| /* |
| * Copyright 2015-2016 Rivoreo |
| * |
| * This program is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License as published by the |
| * Free Software Foundation, either version 2 of the License, or (at your |
| * option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| * more details. |
| */ |
| |
| // This code is translated from the C code which is in the public domain. |
| |
| package org.rivoreo.crypto; |
| |
| import java.io.FileInputStream; |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| import java.security.SecureRandom; |
| |
| public abstract class ECIES { |
| static final int DEGREE_sect163r2 = 163; |
| /* |
| static final byte[] POLY_sect163r2 = { (byte)0xc9, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, }; |
| static final byte[] COEFF_B_sect163r2 = { (byte)0xfd, (byte)0x05, (byte)0x32, (byte)0x4a, (byte)0x74, (byte)0x78, (byte)0x2f, (byte)0x51, (byte)0x10, (byte)0xeb, (byte)0x81, (byte)0x14, (byte)0xca, (byte)0x53, (byte)0xc9, (byte)0xb8, (byte)0x07, (byte)0x19, (byte)0x60, (byte)0x0a, }; |
| static final byte[] BASE_X_sect163r2 = { (byte)0x36, (byte)0x3e, (byte)0x34, (byte)0xe8, (byte)0x37, (byte)0x46, (byte)0x99, (byte)0xd4, (byte)0x68, (byte)0x11, (byte)0x99, (byte)0xa0, (byte)0x7e, (byte)0xd5, (byte)0xa2, (byte)0x86, (byte)0x62, (byte)0xa1, (byte)0xeb, (byte)0xf0, }; |
| static final byte[] BASE_Y_sect163r2 = { (byte)0xf1, (byte)0x24, (byte)0x73, (byte)0x79, (byte)0x0c, (byte)0x5c, (byte)0x1c, (byte)0xb1, (byte)0x45, (byte)0xd5, (byte)0xcd, (byte)0xa2, (byte)0x4f, (byte)0x09, (byte)0xa0, (byte)0x71, (byte)0x6c, (byte)0xbc, (byte)0x1f, (byte)0xd5, }; |
| static final byte[] BASE_ORDER_sect163r2 = { (byte)0x33, (byte)0x4c, (byte)0x23, (byte)0xa4, (byte)0x12, (byte)0x0c, (byte)0xe7, (byte)0x77, (byte)0xfe, (byte)0x92, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, }; |
| */ |
| static final int DEGREE_sect233r1 = 233; |
| /* |
| static final byte[] POLY_sect233r1 = { (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, }; |
| static final byte[] COEFF_B_sect233r1 = { (byte)0xad, (byte)0x90, (byte)0x8f, (byte)0x7d, (byte)0x5f, (byte)0x11, (byte)0xfe, (byte)0x81, (byte)0x42, (byte)0xce, (byte)0xe9, (byte)0x20, (byte)0x3b, (byte)0x33, (byte)0x3b, (byte)0x21, (byte)0x58, (byte)0xbb, (byte)0x23, (byte)0x09, (byte)0x8c, (byte)0x7f, (byte)0x2c, (byte)0x33, (byte)0x6c, (byte)0xde, (byte)0x7e, (byte)0x64, (byte)0x66, }; |
| static final byte[] BASE_X_sect233r1 = { (byte)0x8b, (byte)0x55, (byte)0xfd, (byte)0x71, (byte)0x73, (byte)0xeb, (byte)0xf8, (byte)0xf8, (byte)0x36, (byte)0x8b, (byte)0x1f, (byte)0x39, (byte)0xbc, (byte)0x65, (byte)0xef, (byte)0x5f, (byte)0x75, (byte)0xbb, (byte)0xf1, (byte)0x39, (byte)0x21, (byte)0xbb, (byte)0x13, (byte)0x83, (byte)0xac, (byte)0xcb, (byte)0xdf, (byte)0xc9, (byte)0xfa, }; |
| static final byte[] BASE_Y_sect233r1 = { (byte)0x52, (byte)0x10, (byte)0xf8, (byte)0x01, (byte)0x7e, (byte)0x6f, (byte)0x71, (byte)0x36, (byte)0xca, (byte)0xa7, (byte)0x67, (byte)0xf8, (byte)0xef, (byte)0x0b, (byte)0x8a, (byte)0xbf, (byte)0xbe, (byte)0x28, (byte)0x85, (byte)0xe5, (byte)0x78, (byte)0x06, (byte)0x35, (byte)0x03, (byte)0x19, (byte)0xa4, (byte)0x08, (byte)0x6a, (byte)0x00, }; |
| static final byte[] BASE_ORDER_sect233r1 = { (byte)0xd7, (byte)0xe0, (byte)0xcf, (byte)0x03, (byte)0x26, (byte)0x1d, (byte)0x03, (byte)0x22, (byte)0x69, (byte)0x8a, (byte)0x2f, (byte)0xe7, (byte)0x74, (byte)0xe9, (byte)0x13, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, }; |
| */ |
| static final int DEGREE_sect283r1 = 283; |
| /* |
| static final byte[] POLY_sect283r1 = { (byte)0xA1, (byte)0x10, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, }; |
| static final byte[] COEFF_B_sect283r1 = { (byte)0xf5, (byte)0xa2, (byte)0x79, (byte)0x3b, (byte)0x31, (byte)0x3e, (byte)0x26, (byte)0xf6, (byte)0x5a, (byte)0x48, (byte)0x81, (byte)0xa5, (byte)0xa2, (byte)0x9f, (byte)0x30, (byte)0x45, (byte)0x76, (byte)0xfd, (byte)0x97, (byte)0xca, (byte)0x3f, (byte)0x30, (byte)0xa0, (byte)0x19, (byte)0x8a, (byte)0xaf, (byte)0xa4, (byte)0xa5, (byte)0x6d, (byte)0x59, (byte)0xb8, (byte)0xc8, (byte)0x0a, (byte)0x68, (byte)0x7b, }; |
| static final byte[] BASE_X_sect283r1 = { (byte)0x53, (byte)0x20, (byte)0xb1, (byte)0x86, (byte)0xcd, (byte)0xbe, (byte)0xcd, (byte)0xf8, (byte)0x98, (byte)0xe1, (byte)0xe2, (byte)0x80, (byte)0x9c, (byte)0xac, (byte)0x7e, (byte)0x55, (byte)0xb8, (byte)0x25, (byte)0xed, (byte)0x2e, (byte)0xec, (byte)0xdf, (byte)0xb0, (byte)0x70, (byte)0x8c, (byte)0x4f, (byte)0x93, (byte)0xe1, (byte)0x90, (byte)0xdd, (byte)0xb7, (byte)0x8d, (byte)0x25, (byte)0x39, (byte)0xf9, }; |
| static final byte[] BASE_Y_sect283r1 = { (byte)0xf4, (byte)0x12, (byte)0x81, (byte)0xbe, (byte)0x45, (byte)0xdf, (byte)0xf0, (byte)0x13, (byte)0xc8, (byte)0x79, (byte)0x67, (byte)0x82, (byte)0xb0, (byte)0xdd, (byte)0x0e, (byte)0x35, (byte)0x02, (byte)0xf7, (byte)0x6f, (byte)0x51, (byte)0xb4, (byte)0x02, (byte)0x0d, (byte)0xb2, (byte)0xd4, (byte)0xe6, (byte)0x8f, (byte)0xb9, (byte)0x1c, (byte)0x14, (byte)0x24, (byte)0xfe, (byte)0x54, (byte)0x68, (byte)0x67, }; |
| static final byte[] BASE_ORDER_sect283r1 = { (byte)0x07, (byte)0xb3, (byte)0xad, (byte)0xef, (byte)0x7c, (byte)0x2a, (byte)0x04, (byte)0x5b, (byte)0x16, (byte)0x90, (byte)0x8a, (byte)0x93, (byte)0xfc, (byte)0x60, (byte)0x96, (byte)0x39, (byte)0x90, (byte)0xef, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, }; |
| */ |
| static final int DEGREE_sect409r1 = 409; |
| /* |
| static final byte[] POLY_sect409r1 = { (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x80, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, }; |
| static final byte[] COEFF_B_sect409r1 = { (byte)0x5f, (byte)0x54, (byte)0x13, (byte)0x7b, (byte)0x31, (byte)0xae, (byte)0x50, (byte)0x4f, (byte)0xaa, (byte)0x55, (byte)0x7a, (byte)0xd5, (byte)0x6c, (byte)0x2f, (byte)0x82, (byte)0x72, (byte)0xb2, (byte)0x97, (byte)0xa1, (byte)0xa9, (byte)0xc8, (byte)0x27, (byte)0xac, (byte)0xd6, (byte)0x99, (byte)0xfa, (byte)0x61, (byte)0x47, (byte)0x67, (byte)0xdd, (byte)0xf3, (byte)0xf1, (byte)0x2e, (byte)0x42, (byte)0xd6, (byte)0x7f, (byte)0x6b, (byte)0x47, (byte)0x7b, (byte)0x3b, (byte)0x75, (byte)0x9a, (byte)0x4b, (byte)0x5c, (byte)0xeb, (byte)0x9f, (byte)0xee, (byte)0xc8, (byte)0xc2, (byte)0xa5, (byte)0x21, }; |
| static final byte[] BASE_X_sect409r1 = { (byte)0xa7, (byte)0x96, (byte)0x79, (byte)0xbb, (byte)0x54, (byte)0x4e, (byte)0x79, (byte)0x60, (byte)0xab, (byte)0xae, (byte)0x03, (byte)0x56, (byte)0x51, (byte)0x80, (byte)0x11, (byte)0x8a, (byte)0x86, (byte)0x5a, (byte)0x25, (byte)0xdc, (byte)0x03, (byte)0x97, (byte)0xe5, (byte)0x34, (byte)0x5b, (byte)0xfe, (byte)0x1f, (byte)0xb0, (byte)0x4d, (byte)0x1d, (byte)0x77, (byte)0xf1, (byte)0x4a, (byte)0xde, (byte)0x1c, (byte)0x44, (byte)0x60, (byte)0x62, (byte)0x75, (byte)0x64, (byte)0x60, (byte)0x0c, (byte)0x6b, (byte)0x49, (byte)0xb3, (byte)0xdd, (byte)0x88, (byte)0xd0, (byte)0x60, (byte)0x48, (byte)0x5d, }; |
| static final byte[] BASE_Y_sect409r1 = { (byte)0x06, (byte)0xc7, (byte)0x73, (byte)0x02, (byte)0xba, (byte)0x64, (byte)0xc3, (byte)0x81, (byte)0x36, (byte)0x1b, (byte)0x18, (byte)0xd2, (byte)0x40, (byte)0x4f, (byte)0x4b, (byte)0xdf, (byte)0x1f, (byte)0x4f, (byte)0x51, (byte)0x38, (byte)0x8f, (byte)0xd0, (byte)0x88, (byte)0x54, (byte)0x4f, (byte)0xaa, (byte)0x58, (byte)0x01, (byte)0x8d, (byte)0x19, (byte)0xbd, (byte)0xa7, (byte)0xc5, (byte)0xb9, (byte)0x36, (byte)0x76, (byte)0x6a, (byte)0x10, (byte)0xed, (byte)0x24, (byte)0x83, (byte)0xa7, (byte)0xbf, (byte)0x2b, (byte)0xf3, (byte)0xe5, (byte)0x6b, (byte)0xab, (byte)0xcf, (byte)0xb1, (byte)0x61, }; |
| static final byte[] BASE_ORDER_sect409r1 = { (byte)0x73, (byte)0x11, (byte)0xa2, (byte)0xd9, (byte)0x37, (byte)0xcd, (byte)0x64, (byte)0x81, (byte)0x83, (byte)0x2f, (byte)0x05, (byte)0x9e, (byte)0x3c, (byte)0x7c, (byte)0xa4, (byte)0x5f, (byte)0xbe, (byte)0x07, (byte)0x33, (byte)0xf3, (byte)0x12, (byte)0xa6, (byte)0xd6, (byte)0xaa, (byte)0xe2, (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, }; |
| */ |
| static final int DEGREE_sect571r1 = 571; |
| /* |
| static final byte[] POLY_sect571r1 = { (byte)0x25, (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, }; |
| static final byte[] COEFF_B_sect571r1 = { (byte)0x7a, (byte)0x72, (byte)0x55, (byte)0x29, (byte)0x7f, (byte)0xff, (byte)0xfe, (byte)0x7f, (byte)0x0c, (byte)0xca, (byte)0xba, (byte)0x39, (byte)0xe7, (byte)0x4d, (byte)0x0e, (byte)0x52, (byte)0xaa, (byte)0x12, (byte)0xff, (byte)0x78, (byte)0x5a, (byte)0x18, (byte)0xfd, (byte)0x4a, (byte)0x29, (byte)0x6e, (byte)0xa6, (byte)0x56, (byte)0x67, (byte)0xad, (byte)0xe7, (byte)0x2b, (byte)0x33, (byte)0x59, (byte)0xfa, (byte)0x8e, (byte)0xbd, (byte)0xab, (byte)0xff, (byte)0x84, (byte)0xad, (byte)0x18, (byte)0x9a, (byte)0x4a, (byte)0xce, (byte)0xa8, (byte)0x6b, (byte)0xcd, (byte)0xf1, (byte)0xef, (byte)0x8c, (byte)0xcb, (byte)0xff, (byte)0x97, (byte)0x6a, (byte)0x5c, (byte)0x2f, (byte)0xd6, (byte)0xf3, (byte)0xb7, (byte)0x17, (byte)0x71, (byte)0x29, (byte)0xde, (byte)0x95, (byte)0xf2, (byte)0x21, (byte)0x22, (byte)0x7e, (byte)0x0e, (byte)0xf4, }; |
| static final byte[] BASE_X_sect571r1 = { (byte)0x19, (byte)0x2d, (byte)0xec, (byte)0x8e, (byte)0x9c, (byte)0x76, (byte)0xe7, (byte)0xe1, (byte)0x27, (byte)0xd9, (byte)0x50, (byte)0xc8, (byte)0xb4, (byte)0xa3, (byte)0xbf, (byte)0x4a, (byte)0x39, (byte)0xf1, (byte)0x14, (byte)0x86, (byte)0x03, (byte)0x60, (byte)0xae, (byte)0x99, (byte)0x14, (byte)0xfb, (byte)0x67, (byte)0x5b, (byte)0xa3, (byte)0x11, (byte)0xd7, (byte)0xcd, (byte)0x93, (byte)0xd2, (byte)0xc0, (byte)0xf4, (byte)0x50, (byte)0x39, (byte)0xe5, (byte)0xbd, (byte)0xbd, (byte)0x2a, (byte)0x7b, (byte)0xdb, (byte)0xc8, (byte)0x0f, (byte)0xf4, (byte)0xa5, (byte)0x0a, (byte)0xa8, (byte)0x5f, (byte)0x95, (byte)0xd2, (byte)0xd1, (byte)0x93, (byte)0x0a, (byte)0x75, (byte)0xd7, (byte)0x3c, (byte)0x0d, (byte)0xd4, (byte)0xc0, (byte)0x16, (byte)0x6c, (byte)0x29, (byte)0x56, (byte)0xb8, (byte)0x34, (byte)0x1d, (byte)0x00, (byte)0x03, }; |
| static final byte[] BASE_Y_sect571r1 = { (byte)0x5b, (byte)0xc1, (byte)0x8a, (byte)0x1b, (byte)0xaf, (byte)0x27, (byte)0x48, (byte)0x1a, (byte)0x3c, (byte)0xdd, (byte)0x23, (byte)0x6e, (byte)0x51, (byte)0xf1, (byte)0xe2, (byte)0x16, (byte)0x9b, (byte)0xc1, (byte)0x85, (byte)0x04, (byte)0x2f, (byte)0x1d, (byte)0x53, (byte)0xb3, (byte)0xa8, (byte)0xb2, (byte)0x1b, (byte)0x46, (byte)0x8f, (byte)0xaf, (byte)0x91, (byte)0x62, (byte)0x57, (byte)0x8a, (byte)0xb0, (byte)0xba, (byte)0x43, (byte)0x3e, (byte)0x42, (byte)0x84, (byte)0xa6, (byte)0xe8, (byte)0x21, (byte)0x39, (byte)0x53, (byte)0xf8, (byte)0x80, (byte)0x19, (byte)0xca, (byte)0xbb, (byte)0x9c, (byte)0x00, (byte)0xa6, (byte)0x27, (byte)0x6c, (byte)0x8c, (byte)0xd7, (byte)0x69, (byte)0x3d, (byte)0xb7, (byte)0xfe, (byte)0xff, (byte)0xcc, (byte)0x6d, (byte)0x9b, (byte)0x63, (byte)0xda, (byte)0x42, (byte)0x73, (byte)0xf2, (byte)0x7b, }; |
| static final byte[] BASE_ORDER_sect571r1 = { (byte)0x47, (byte)0x4e, (byte)0xe8, (byte)0x2f, (byte)0xbb, (byte)0xe9, (byte)0x82, (byte)0x83, (byte)0x6e, (byte)0xd6, (byte)0x74, (byte)0x51, (byte)0x3d, (byte)0xe9, (byte)0x1d, (byte)0x16, (byte)0xa1, (byte)0x9c, (byte)0xdd, (byte)0xc7, (byte)0x1e, (byte)0x85, (byte)0x23, (byte)0x68, (byte)0x18, (byte)0x9b, (byte)0x05, (byte)0x08, (byte)0x73, (byte)0x98, (byte)0x55, (byte)0xff, (byte)0x18, (byte)0xce, (byte)0x61, (byte)0xe6, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, }; |
| */ |
| |
| static final int[] POLY_sect163r2 = { 0x000000c9, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8 }; |
| static final int[] COEFF_B_sect163r2 = { 0x4a3205fd, 0x512f7874, 0x1481eb10, 0xb8c953ca, 0x0a601907, 0x2 }; |
| static final int[] BASE_X_sect163r2 = { 0xe8343e36, 0xd4994637, 0xa0991168, 0x86a2d57e, 0xf0eba162, 0x3 }; |
| static final int[] BASE_Y_sect163r2 = { 0x797324f1, 0xb11c5c0c, 0xa2cdd545, 0x71a0094f, 0xd51fbc6c, 0x0 }; |
| static final int[] BASE_ORDER_sect163r2 = { 0xa4234c33, 0x77e70c12, 0x000292fe, 0x00000000, 0x00000000, 0x4 }; |
| static final int[] POLY_sect233r1 = { 0x00000001, 0x00000000, 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x200 }; |
| static final int[] COEFF_B_sect233r1 = { 0x7d8f90ad, 0x81fe115f, 0x20e9ce42, 0x213b333b, 0x0923bb58, 0x332c7f8c, 0x647ede6c, 0x066 }; |
| static final int[] BASE_X_sect233r1 = { 0x71fd558b, 0xf8f8eb73, 0x391f8b36, 0x5fef65bc, 0x39f1bb75, 0x8313bb21, 0xc9dfcbac, 0x0fa }; |
| static final int[] BASE_Y_sect233r1 = { 0x01f81052, 0x36716f7e, 0xf867a7ca, 0xbf8a0bef, 0xe58528be, 0x03350678, 0x6a08a419, 0x100 }; |
| static final int[] BASE_ORDER_sect233r1 = { 0x03cfe0d7, 0x22031d26, 0xe72f8a69, 0x0013e974, 0x00000000, 0x00000000, 0x00000000, 0x100 }; |
| static final int[] POLY_sect283r1 = { 0x000010A1, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8000000 }; |
| static final int[] COEFF_B_sect283r1 = { 0x3b79a2f5, 0xf6263e31, 0xa581485a, 0x45309fa2, 0xca97fd76, 0x19a0303f, 0xa5a4af8a, 0xc8b8596d, 0x27b680a }; |
| static final int[] BASE_X_sect283r1 = { 0x86b12053, 0xf8cdbecd, 0x80e2e198, 0x557eac9c, 0x2eed25b8, 0x70b0dfec, 0xe1934f8c, 0x8db7dd90, 0x5f93925 }; |
| static final int[] BASE_Y_sect283r1 = { 0xbe8112f4, 0x13f0df45, 0x826779c8, 0x350eddb0, 0x516ff702, 0xb20d02b4, 0xb98fe6d4, 0xfe24141c, 0x3676854 }; |
| static final int[] BASE_ORDER_sect283r1 = { 0xefadb307, 0x5b042a7c, 0x938a9016, 0x399660fc, 0xffffef90, 0xffffffff, 0xffffffff, 0xffffffff, 0x3ffffff }; |
| static final int[] POLY_sect409r1 = { 0x00000001, 0x00000000, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x2000000 }; |
| static final int[] COEFF_B_sect409r1 = { 0x7b13545f, 0x4f50ae31, 0xd57a55aa, 0x72822f6c, 0xa9a197b2, 0xd6ac27c8, 0x4761fa99, 0xf1f3dd67, 0x7fd6422e, 0x3b7b476b, 0x5c4b9a75, 0xc8ee9feb, 0x021a5c2 }; |
| static final int[] BASE_X_sect409r1 = { 0xbb7996a7, 0x60794e54, 0x5603aeab, 0x8a118051, 0xdc255a86, 0x34e59703, 0xb01ffe5b, 0xf1771d4d, 0x441cde4a, 0x64756260, 0x496b0c60, 0xd088ddb3, 0x15d4860 }; |
| static final int[] BASE_Y_sect409r1 = { 0x0273c706, 0x81c364ba, 0xd2181b36, 0xdf4b4f40, 0x38514f1f, 0x5488d08f, 0x0158aa4f, 0xa7bd198d, 0x7636b9c5, 0x24ed106a, 0x2bbfa783, 0xab6be5f3, 0x061b1cf }; |
| static final int[] BASE_ORDER_sect409r1 = { 0xd9a21173, 0x8164cd37, 0x9e052f83, 0x5fa47c3c, 0xf33307be, 0xaad6a612, 0x000001e2, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1000000 }; |
| static final int[] POLY_sect571r1 = { 0x00000425, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8000000 }; |
| static final int[] COEFF_B_sect571r1 = { 0x2955727a, 0x7ffeff7f, 0x39baca0c, 0x520e4de7, 0x78ff12aa, 0x4afd185a, 0x56a66e29, 0x2be7ad67, 0x8efa5933, 0x84ffabbd, 0x4a9a18ad, 0xcd6ba8ce, 0xcb8ceff1, 0x5c6a97ff, 0xb7f3d62f, 0xde297117, 0x2221f295, 0x2f40e7e }; |
| static final int[] BASE_X_sect571r1 = { 0x8eec2d19, 0xe1e7769c, 0xc850d927, 0x4abfa3b4, 0x8614f139, 0x99ae6003, 0x5b67fb14, 0xcdd711a3, 0xf4c0d293, 0xbde53950, 0xdb7b2abd, 0xa5f40fc8, 0x955fa80a, 0x0a93d1d2, 0x0d3cd775, 0x6c16c0d4, 0x34b85629, 0x303001d }; |
| static final int[] BASE_Y_sect571r1 = { 0x1b8ac15b, 0x1a4827af, 0x6e23dd3c, 0x16e2f151, 0x0485c19b, 0xb3531d2f, 0x461bb2a8, 0x6291af8f, 0xbab08a57, 0x84423e43, 0x3921e8a6, 0x1980f853, 0x009cbbca, 0x8c6c27a6, 0xb73d69d7, 0x6dccfffe, 0x42da639b, 0x37bf273 }; |
| static final int[] BASE_ORDER_sect571r1 = { 0x2fe84e47, 0x8382e9bb, 0x5174d66e, 0x161de93d, 0xc7dd9ca1, 0x6823851e, 0x08059b18, 0xff559873, 0xe661ce18, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x3ffffff }; |
| |
| |
| public enum SECTDomainParameters { |
| sect163r2, |
| sect233r1, |
| sect283r1, |
| sect409r1, |
| sect571r1 |
| } |
| |
| public ECIES(SECTDomainParameters dp) { |
| switch(dp) { |
| case sect163r2: |
| DEGREE = 163; |
| poly = POLY_sect163r2; |
| coeff_b = COEFF_B_sect163r2; |
| base_x = BASE_X_sect163r2; |
| base_y = BASE_Y_sect163r2; |
| base_order = BASE_ORDER_sect163r2; |
| break; |
| case sect233r1: |
| DEGREE = 233; |
| poly = POLY_sect233r1; |
| coeff_b = COEFF_B_sect233r1; |
| base_x = BASE_X_sect233r1; |
| base_y = BASE_Y_sect233r1; |
| base_order = BASE_ORDER_sect233r1; |
| break; |
| case sect283r1: |
| DEGREE = 283; |
| poly = POLY_sect283r1; |
| coeff_b = COEFF_B_sect283r1; |
| base_x = BASE_X_sect283r1; |
| base_y = BASE_Y_sect283r1; |
| base_order = BASE_ORDER_sect283r1; |
| break; |
| case sect409r1: |
| DEGREE = 409; |
| poly = POLY_sect409r1; |
| coeff_b = COEFF_B_sect409r1; |
| base_x = BASE_X_sect409r1; |
| base_y = BASE_Y_sect409r1; |
| base_order = BASE_ORDER_sect409r1; |
| break; |
| case sect571r1: |
| DEGREE = 571; |
| poly = POLY_sect571r1; |
| coeff_b = COEFF_B_sect571r1; |
| base_x = BASE_X_sect571r1; |
| base_y = BASE_Y_sect571r1; |
| base_order = BASE_ORDER_sect571r1; |
| break; |
| default: |
| throw new IllegalArgumentException(); |
| } |
| NUMWORDS = (DEGREE + MARGIN + 31) / 32; |
| OVERHEAD = 8 * NUMWORDS + 8; |
| KEY_SIZE = (DEGREE + 7) / 8; |
| ECIES_START_OVERHEAD = 8 * NUMWORDS; |
| ECIES_CHUNK_OVERHEAD = 8; |
| } |
| |
| final int DEGREE; |
| |
| final int[] poly; |
| final int[] coeff_b; |
| final int[] base_x; |
| final int[] base_y; |
| final int[] base_order; |
| |
| final int MARGIN = 3; |
| final int NUMWORDS; |
| public final int OVERHEAD; |
| public final int KEY_SIZE; |
| |
| public class PublicKey { |
| public PublicKey() { |
| x = new byte[KEY_SIZE]; |
| y = new byte[KEY_SIZE]; |
| } |
| public final byte[] x, y; |
| } |
| |
| public class PrivateKey { |
| public PrivateKey() { |
| k = new byte[KEY_SIZE]; |
| } |
| public PrivateKey(byte[] a) { |
| if(a.length != KEY_SIZE) throw new IllegalArgumentException("a.length should be " + KEY_SIZE); |
| k = a; |
| } |
| public final byte[] k; |
| } |
| |
| // typedef int[NUMWORDS] elem_t |
| // typedef int[NUMWORDS] exp_t |
| |
| private static int compare_bytes(final byte[] a, final byte[] b) { |
| int i = 0; |
| while(i < a.length && i < b.length) { |
| if(a[i] < b[i]) return -1; |
| else if(a[i] > b[i]) return 1; |
| i++; |
| } |
| if(a.length < b.length) return -1; |
| else if(a.length > b.length) return 1; |
| return 0; |
| } |
| |
| private static int compare_integers(final int[] a, final int[] b) { |
| int i = 0; |
| while(i < a.length && i < b.length) { |
| if(a[i] < b[i]) return -1; |
| else if(a[i] > b[i]) return 1; |
| i++; |
| } |
| if(a.length < b.length) return -1; |
| else if(a.length > b.length) return 1; |
| return 0; |
| } |
| |
| private static int compare_bytes(final byte[] a, final byte[] b, int maxlen) { |
| if(maxlen < 0) throw new IllegalArgumentException("maxlen < 0"); |
| if(maxlen == 0) return 0; |
| int i = 0; |
| while(i < a.length && i < b.length) { |
| if(a[i] < b[i]) return -1; |
| else if(a[i] > b[i]) return 1; |
| if(++i == maxlen) return 0; |
| } |
| if(a.length < b.length) return -1; |
| else if(a.length > b.length) return 1; |
| return 0; |
| } |
| |
| protected static byte[] sub_byte_array(final byte[] a, int start) { |
| if(start < 0) throw new IllegalArgumentException("start < 0"); |
| if(start == 0) return a.clone(); |
| if(start > a.length) return new byte[0]; |
| byte[] r = new byte[a.length - start]; |
| for(int i=0; i<r.length; i++) r[i] = a[start + i]; |
| return r; |
| } |
| |
| private static int unsigned_byte_to_int(byte v) { |
| return v < 0 ? (int)v + 256 : v; |
| } |
| |
| protected static long unsigned_int_to_long(int v) { |
| return v < 0 ? (long)v + 4294967296l : v; |
| } |
| |
| protected int unsigned_bytes_to_int(byte[] a, int offset) { |
| if(a.length + offset < 4) throw new IllegalArgumentException("a.length + offset < 4"); |
| return unsigned_byte_to_int(a[offset]) << 24 | |
| unsigned_byte_to_int(a[offset + 1]) << 16 | |
| unsigned_byte_to_int(a[offset + 2]) << 8 | |
| unsigned_byte_to_int(a[offset + 3]); |
| } |
| |
| protected void int_to_bytes(byte[] dest, int offset, int n) { |
| if(dest.length + offset < 4) throw new IllegalArgumentException("dest.length + offset < 4"); |
| dest[offset] = (byte)((n >>> 24) & 0xff); |
| dest[offset + 1] = (byte)((n >>> 16) & 0xff); |
| dest[offset + 2] = (byte)((n >>> 8) & 0xff); |
| dest[offset + 3] = (byte)((n) & 0xff); |
| } |
| |
| public PublicKey create_publickey() { |
| return new PublicKey(); |
| } |
| |
| public PrivateKey create_privatekey() { |
| return new PrivateKey(); |
| } |
| |
| private void bitstr_import(int[] x, final byte[] s) { |
| if(x.length != NUMWORDS) throw new IllegalArgumentException("x.length should be " + NUMWORDS); |
| //for(x += NUMWORDS, int i = 0; i < NUMWORDS; i++, s += 4) *--x = CHARS2INT(s); |
| for(int i = 0, xi = NUMWORDS, si = 0; i < NUMWORDS; i++, si += 4) { |
| //x[--xi] = (int)s[si] | |
| // (int)s[si + 1] << 8 | |
| // (int)s[si + 2] << 16 | |
| // (int)s[si + 3] << 24; |
| //x[--xi] = to_unsigned_int(s[si]) | |
| // to_unsigned_int(s[si + 1]) << 8 | |
| // to_unsigned_int(s[si + 2]) << 16 | |
| // to_unsigned_int(s[si + 3]) << 24; |
| //x[--xi] = to_unsigned_int(s[si]) << 24 | |
| // to_unsigned_int(s[si + 1]) << 16 | |
| // to_unsigned_int(s[si + 2]) << 8 | |
| // to_unsigned_int(s[si + 3]); |
| x[--xi] = unsigned_bytes_to_int(s, si); |
| } |
| } |
| |
| private int[] bitstr_import(final byte[] s) { |
| int[] r = new int[NUMWORDS]; |
| bitstr_import(r, s); |
| return r; |
| } |
| |
| private void bitstr_export(byte[] s, int offset, final int[] x) { |
| if(offset < 0) throw new IllegalArgumentException("offset < 0"); |
| if(x.length != NUMWORDS) throw new IllegalArgumentException("x.length should be " + NUMWORDS); |
| //for(x += ECIES_NUMWORDS, i = 0; i < ECIES_NUMWORDS; i++, s += 4) |
| for(int i = 0, xi = NUMWORDS, si = offset; i < NUMWORDS; i++, si += 4) { |
| int v = x[--xi]; |
| //s[si] = (byte)(v & 0xff); |
| //s[si + 1] = (byte)((v >> 8) & 0xff); |
| //s[si + 2] = (byte)((v >> 16) & 0xff); |
| //s[si + 3] = (byte)((v >> 24) & 0xff); |
| s[si] = (byte)((v >>> 24) & 0xff); |
| s[si + 1] = (byte)((v >>> 16) & 0xff); |
| s[si + 2] = (byte)((v >>> 8) & 0xff); |
| s[si + 3] = (byte)((v) & 0xff); |
| //int_to_bytes(s, si, v); |
| } |
| } |
| |
| private int bitstr_sizeinbits(final int[] x) { |
| int i, xi; |
| //for(x += ECIES_NUMWORDS, i = 32 * ECIES_NUMWORDS; i > 0 && ! *--x; i -= 32); |
| for(i = 32 * NUMWORDS, xi = NUMWORDS; i > 0 && x[--xi] == 0; i -= 32); |
| if(i != 0) for(int mask = 1 << 31; (x[xi] & mask) == 0; mask >>>= 1, i--); |
| return i; |
| } |
| |
| /* left-shift by 'count' digits */ |
| private void bitstr_lshift(int[] a, final int[] b, int count) { |
| /* |
| int i, offs = 4 * (count / 32); |
| memmove((char*)A + offs, B, sizeof(bitstr_t) - offs); |
| memset(A, 0, offs); |
| if (count %= 32) { |
| for(i = ECIES_NUMWORDS - 1; i > 0; i--) |
| A[i] = (A[i] << count) | (A[i - 1] >> (32 - count)); |
| A[0] <<= count; |
| } |
| */ |
| if(a.length != NUMWORDS) throw new IllegalArgumentException("a.length should be " + NUMWORDS); |
| if(b.length != NUMWORDS) throw new IllegalArgumentException("b.length should be " + NUMWORDS); |
| if(count > NUMWORDS * 32) throw new IllegalArgumentException("count too large"); |
| int i; |
| int shift_items = count / 32; // count / sizeof(int) |
| for(i=0; i<NUMWORDS-shift_items; i++) a[shift_items + i] = b[i]; |
| for(i=0; i<shift_items; i++) a[i] = 0; |
| if((count %= 32) != 0) { |
| for(i = NUMWORDS - 1; i > 0; i--) { |
| a[i] = (a[i] << count) | (a[i - 1] >>> (32 - count)); |
| } |
| a[0] <<= count; |
| } |
| } |
| |
| private void bitstr_load(int[] bstr, final byte[] data, int len) { |
| //System.err.printf("method: org.rivoreo.crypto.ECIES::bitstr_load(int[%d], final byte[%d], %d)\n", bstr.length, data.length, len); |
| //uint32_t *bptr = bstr + ((len + 3) / 4) - 1; |
| int i = (len + 3) / 4 - 1; |
| int di = 0; |
| |
| len %= 4; |
| |
| if(len > 0) { |
| //*bptr = 0; |
| bstr[i] = 0; |
| if(len > 1) { |
| if(len > 2) { |
| //*bptr |= (uint32_t)(*data++) << 16; |
| //bstr[i] |= (int)data[di++] << 16; |
| bstr[i] |= unsigned_byte_to_int(data[di++]) << 16; |
| } |
| //*bptr |= (uint32_t)(*data++) << 8; |
| //bstr[i] |= (int)data[di++] << 8; |
| bstr[i] |= unsigned_byte_to_int(data[di++]) << 8; |
| } |
| //*bptr |= (uint32_t)(*data++); |
| //bptr--; |
| //bstr[i--] |= (int)data[di++]; |
| bstr[i--] |= unsigned_byte_to_int(data[di++]); |
| } |
| /* |
| for(; bptr >= bstr; bptr--){ |
| *bptr = (uint32_t)(*data++) << 24; |
| *bptr |= (uint32_t)(*data++) << 16; |
| *bptr |= (uint32_t)(*data++) << 8; |
| *bptr |= (uint32_t)(*data++); |
| }*/ |
| while(i >= 0) { |
| /* |
| bstr[i] = (int)data[di++] << 24; |
| bstr[i] |= (int)data[di++] << 16; |
| bstr[i] |= (int)data[di++] << 8; |
| bstr[i] |= (int)data[di++]; |
| */ |
| /* |
| bstr[i] = to_unsigned_int(data[di++]) << 24; |
| bstr[i] |= to_unsigned_int(data[di++]) << 16; |
| bstr[i] |= to_unsigned_int(data[di++]) << 8; |
| bstr[i] |= to_unsigned_int(data[di++]); |
| i--; |
| */ |
| bstr[i--] = unsigned_bytes_to_int(data, di); |
| di += 4; |
| } |
| } |
| |
| private void bitstr_dump(byte[] data, int len, final int[] bstr) { |
| //const uint32_t *bptr = bstr + ((len + 3) / 4) - 1; |
| int i = (len + 3) / 4 - 1; |
| int di = 0; |
| |
| len %= 4; |
| |
| if(len > 0){ |
| if(len > 1){ |
| if(len > 2){ |
| //*data++ = *bptr >> 16; |
| data[di++] = (byte)(bstr[i] >>> 16); |
| } |
| //*data++ = *bptr >> 8; |
| data[di++] = (byte)(bstr[i] >>> 8); |
| } |
| //*data++ = *bptr; |
| //bptr--; |
| data[di++] = (byte)(bstr[i--]); |
| } |
| |
| /* |
| for(; bptr >= bstr; bptr--){ |
| *data++ = *bptr >> 24; |
| *data++ = *bptr >> 16; |
| *data++ = *bptr >> 8; |
| *data++ = *bptr; |
| }*/ |
| while(i >= 0) { |
| data[di++] = (byte)(bstr[i] >>> 24); |
| data[di++] = (byte)(bstr[i] >>> 16); |
| data[di++] = (byte)(bstr[i] >>> 8); |
| data[di++] = (byte)(bstr[i--]); |
| } |
| } |
| |
| private boolean bitstr_is_clear(final int[] x) { |
| int i; |
| for(i = 0; i < NUMWORDS && x[i] == 0; i++); |
| return i == NUMWORDS; |
| } |
| |
| private byte bitstr_getbit(int[] x, int i) { |
| return (byte)((x[i / 32] >>> (i % 32)) & 1); |
| } |
| |
| private void bitstr_setbit(int[] x, int i) { |
| x[i / 32] |= 1 << (i % 32); |
| } |
| |
| private void bitstr_clrbit(int[] x, int i) { |
| x[i / 32] &= ~(1 << (i % 32)); |
| } |
| |
| private void bitstr_clear(int[] x) { |
| if(x.length != NUMWORDS) throw new IllegalArgumentException("x.length should be " + NUMWORDS); |
| for(int i=0; i<NUMWORDS; i++) x[i] = 0; |
| } |
| |
| private void bitstr_copy(int[] dest, final int[] src) { |
| if(dest.length != NUMWORDS) throw new IllegalArgumentException("dest.length should be " + NUMWORDS); |
| if(src.length != NUMWORDS) throw new IllegalArgumentException("src.length should be " + NUMWORDS); |
| for(int i=0; i<NUMWORDS; i++) dest[i] = src[i]; |
| } |
| |
| private void bitstr_swap(int[] a, int[] b) { |
| if(a.length != NUMWORDS) throw new IllegalArgumentException("a.length should be " + NUMWORDS); |
| if(b.length != NUMWORDS) throw new IllegalArgumentException("b.length should be " + NUMWORDS); |
| int[] t = a.clone(); |
| bitstr_copy(a, b); |
| bitstr_copy(b, t); |
| } |
| |
| private void field_set1(int[] x) { |
| x[0] = 1; |
| for(int i = 1; i < NUMWORDS; i++) x[i] = 0; |
| } |
| |
| private boolean field_is1(final int[] x) { |
| int i; |
| if(x[0] != 1) return false; |
| for(i = 1; i < NUMWORDS && x[i] == 0; i++); |
| return i == NUMWORDS; |
| } |
| |
| private void field_add1(int[] a) { |
| //a[0] ^= 1; |
| a[0] = (int)(unsigned_int_to_long(a[0]) ^ 1); |
| } |
| |
| /* field addition */ |
| private void field_add(int[] z, final int[] x, final int[] y) { |
| //for(int i = 0; i < NUMWORDS; i++) z[i] = x[i] ^ y[i]; |
| for(int i = 0; i < NUMWORDS; i++) { |
| z[i] = (int)(unsigned_int_to_long(x[i]) ^ unsigned_int_to_long(y[i])); |
| } |
| } |
| |
| /* field multiplication */ |
| private void field_mult(int[] z, final int[] x, final int[] y) { |
| int[] b = new int[NUMWORDS]; |
| /* assert(z != y); */ |
| bitstr_copy(b, x); |
| if(bitstr_getbit(y, 0) != 0) bitstr_copy(z, x); |
| else bitstr_clear(z); |
| for(int i = 1; i < DEGREE; i++) { |
| for(int j = NUMWORDS - 1; j > 0; j--) b[j] = (b[j] << 1) | (b[j - 1] >>> 31); |
| b[0] <<= 1; |
| if(bitstr_getbit(b, DEGREE) != 0) field_add(b, b, poly); |
| if(bitstr_getbit(y, i) != 0) field_add(z, z, b); |
| } |
| } |
| |
| private void debug_print_bitstr(int[] a) { |
| for(int i=0; i<a.length; i++) System.err.printf("0x%x\n", a[i]); |
| } |
| protected void debug_print_bytes(byte[] a, int len) { |
| for(int i=0; i<len; i++) System.err.printf("0x%x, ", a[i]); |
| System.err.println(); |
| } |
| |
| /* field inversion */ |
| private void field_invert(int[] z, final int[] x) { |
| //System.err.printf("method: org.rivoreo.crypto.ECIES::field_invert(int[%d], final int[%d])\n", z.length, x.length); |
| //debug_print_bitstr(x); |
| //elem_t u, v, g, h; |
| int[] u = new int[NUMWORDS]; |
| int[] v = new int[NUMWORDS]; |
| int[] g = new int[NUMWORDS]; |
| int[] h = new int[NUMWORDS]; |
| bitstr_copy(u, x); |
| bitstr_copy(v, poly); |
| bitstr_clear(g); |
| field_set1(z); |
| //debug_print_bitstr(z); |
| //System.err.printf("%d, %d\n", bitstr_sizeinbits(u), bitstr_sizeinbits(v)); |
| while(!field_is1(u)) { |
| //System.err.printf("u[0] = %d\n", u[0]); |
| int i = bitstr_sizeinbits(u) - bitstr_sizeinbits(v); |
| //System.err.printf("field_invert: i = %d\n", i); |
| if(i < 0) { |
| bitstr_swap(u, v); |
| bitstr_swap(g, z); |
| i = -i; |
| } |
| bitstr_lshift(h, v, i); |
| //debug_print_bitstr(h); |
| field_add(u, u, h); |
| bitstr_lshift(h, g, i); |
| field_add(z, z, h); |
| } |
| } |
| |
| private boolean point_is_zero(final int[] x, final int[] y) { |
| return bitstr_is_clear(x) && bitstr_is_clear(y); |
| } |
| |
| private void point_set_zero(int[] x, int[] y) { |
| bitstr_clear(x); |
| bitstr_clear(y); |
| } |
| |
| private void point_copy(int[] dest_x, int[] dest_y, final int[] src_x, final int[] src_y) { |
| bitstr_copy(dest_x, src_x); |
| bitstr_copy(dest_y, src_y); |
| } |
| |
| private boolean is_point_on_curve(final int[] x, final int[] y) { |
| int[] a = new int[NUMWORDS]; |
| int[] b = new int[NUMWORDS]; |
| if(point_is_zero(x, y)) return true; |
| field_mult(a, x, x); |
| field_mult(b, a, x); |
| field_add(a, a, b); |
| field_add(a, a, coeff_b); |
| field_mult(b, y, y); |
| field_add(a, a, b); |
| field_mult(b, x, y); |
| //return bitstr_is_equal(a, b); |
| //return a.equals(b); |
| return compare_integers(a, b) == 0; |
| } |
| |
| private void point_double(int[] x, int[] y) { |
| //System.err.printf("method: org.rivoreo.crypto.ECIES::point_double(int[%d], int[%d])\n", x.length, y.length); |
| //debug_print_bitstr(x); |
| if(bitstr_is_clear(x)) { |
| bitstr_clear(y); |
| return; |
| } |
| int[] a = new int[NUMWORDS]; |
| field_invert(a, x); |
| field_mult(a, a, y); |
| field_add(a, a, x); |
| field_mult(y, x, x); |
| field_mult(x, a, a); |
| field_add1(a); |
| field_add(x, x, a); |
| field_mult(a, a, x); |
| field_add(y, y, a); |
| } |
| |
| /* add two points together (x1, y1) := (x1, y1) + (x2, y2) */ |
| private void point_add(int[] x1, int[] y1, final int[] x2, final int[] y2) { |
| if(point_is_zero(x2, y2)) return; |
| if(point_is_zero(x1, y1)) { |
| point_copy(x1, y1, x2, y2); |
| return; |
| } |
| //if(bitstr_is_equal(x1, x2)) { |
| if(compare_integers(x1, x2) == 0) { |
| //if(bitstr_is_equal(y1, y2)) point_double(x1, y1); |
| if(compare_integers(y1, y2) == 0) point_double(x1, y1); |
| else point_set_zero(x1, y1); |
| } else { |
| //elem_t a, b, c, d; |
| int[] a = new int[NUMWORDS]; |
| int[] b = new int[NUMWORDS]; |
| int[] c = new int[NUMWORDS]; |
| int[] d = new int[NUMWORDS]; |
| field_add(a, y1, y2); |
| field_add(b, x1, x2); |
| field_invert(c, b); |
| field_mult(c, c, a); |
| field_mult(d, c, c); |
| field_add(d, d, c); |
| field_add(d, d, b); |
| field_add1(d); |
| field_add(x1, x1, d); |
| field_mult(a, x1, c); |
| field_add(a, a, d); |
| field_add(y1, y1, a); |
| bitstr_copy(x1, d); |
| } |
| } |
| |
| private void point_mult(int[] x, int[] y, final int[] exp) { |
| //System.err.printf("method: org.rivoreo.crypto.ECIES::point_mult(int[%d], int[%d], final int[%d])\n", x.length, y.length, exp.length); |
| //elem_t X, Y; |
| int[] X = new int[NUMWORDS]; |
| int[] Y = new int[NUMWORDS]; |
| point_set_zero(X, Y); |
| for(int i = bitstr_sizeinbits(exp) - 1; i >= 0; i--) { |
| //System.err.printf("point_mult: i = %d\n", i); |
| point_double(X, Y); |
| if(bitstr_getbit(exp, i) != 0) point_add(X, Y, x, y); |
| } |
| point_copy(x, y, X, Y); |
| } |
| |
| private int internal_validate_pubkey(final int[] Px, final int[] Py) { |
| //System.err.printf("DEGREE = %d\nbitstr_sizeinbits(Px) = %d\nbitstr_sizeinbits(Py) = %d\n", |
| // DEGREE, bitstr_sizeinbits(Px), bitstr_sizeinbits(Py)); |
| return (bitstr_sizeinbits(Px) > DEGREE) || (bitstr_sizeinbits(Py) > DEGREE) || |
| point_is_zero(Px, Py) || ! is_point_on_curve(Px, Py) ? -1 : 1; |
| } |
| |
| public void generate_keys(PrivateKey priv, PublicKey pub) { |
| //System.err.println("method: org.rivoreo.crypto.ECIES::generate_keys(PrivateKey, PublicKey)"); |
| |
| int[] x = new int[NUMWORDS]; |
| int[] y = new int[NUMWORDS]; |
| int[] k = new int[NUMWORDS]; |
| |
| get_random_exponent(k); |
| point_copy(x, y, base_x, base_y); |
| point_mult(x, y, k); |
| |
| bitstr_dump(pub.x, KEY_SIZE, x); |
| bitstr_dump(pub.y, KEY_SIZE, y); |
| bitstr_dump(priv.k, KEY_SIZE, k); |
| } |
| |
| public int validate_pubkey(final PublicKey pubkey) { |
| int[] x = new int[NUMWORDS]; |
| int[] y = new int[NUMWORDS]; |
| bitstr_load(x, pubkey.x, KEY_SIZE); |
| bitstr_load(y, pubkey.y, KEY_SIZE); |
| if(internal_validate_pubkey(x, y) < 0) return -1; |
| point_mult(x, y, base_order); |
| return point_is_zero(x, y) ? 1 : -1; |
| } |
| |
| private void get_random_exponent(int[] exp) { |
| byte[] buffer = new byte[4 * NUMWORDS]; |
| //int i = buffer.length - 1; |
| FileInputStream fis = null; |
| SecureRandom sr = null; |
| try { |
| fis = new FileInputStream("/dev/urandom"); |
| } catch(FileNotFoundException e) { |
| e.printStackTrace(); |
| sr = new SecureRandom(); |
| } |
| do { |
| try { |
| if(fis == null) throw new IOException("/dev/urandom"); |
| fis.read(buffer); |
| } catch(IOException e) { |
| if(sr == null) sr = new SecureRandom(); |
| sr.nextBytes(buffer); |
| } |
| bitstr_import(exp, buffer); |
| for(int i = bitstr_sizeinbits(base_order) - 1; i < NUMWORDS * 32; i++) { |
| bitstr_clrbit(exp, i); |
| } |
| } while(bitstr_is_clear(exp)); |
| if(fis != null) try { |
| fis.close(); |
| } catch(IOException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| /* |
| private void get_random_exponent(int[] exp) { |
| byte[] buffer = new byte[4 * NUMWORDS]; |
| do { |
| get_random(buffer); |
| bitstr_import(exp, buffer); |
| for(int i = bitstr_sizeinbits(base_order) - 1; i < NUMWORDS * 32; i++) { |
| bitstr_clrbit(exp, i); |
| } |
| } while(bitstr_is_clear(exp)); |
| } |
| */ |
| |
| protected abstract int get_symmetric_key_bytes(); |
| protected abstract void ctr_crypt(byte[] data, int len, final byte[] key); |
| protected abstract void cbc_mac(byte[] mac, final byte[] data, int len, final byte[] key); |
| protected abstract void davies_meyer(byte[] out, final byte[] in, int ilen); |
| |
| protected interface NonceListener { |
| void set_nonce(byte[] nonce); |
| } |
| |
| private NonceListener symmetric_crypt_nonce_listener = null; |
| private int symmetric_crypt_nonce_length = 0; |
| |
| protected void set_symmetric_crypt_nonce_listener(NonceListener l, int nonce_len) { |
| symmetric_crypt_nonce_listener = l; |
| symmetric_crypt_nonce_length = nonce_len; |
| } |
| |
| /* a non-standard KDF */ |
| private void kdf(byte[] k1, byte[] k2, final int[] Zx, final int[] Rx, final int[] Ry) { |
| System.err.printf("method: org.rivoreo.crypto.ECIES::kdf(byte[%d], byte[%d], final int[%d], final int[%d], final int[%d])\n", k1.length, k2.length, Zx.length, Rx.length, Ry.length); |
| int key_bytes = get_symmetric_key_bytes(); |
| int bufsize = (3 * (4 * NUMWORDS) + 1 + key_bytes - 1) & ~(key_bytes - 1); |
| byte[] buffer = new byte[bufsize]; |
| byte[] kbuffer = new byte[key_bytes / 2]; |
| //memset(buffer, 0, bufsize); |
| bitstr_export(buffer, 0, Zx); |
| bitstr_export(buffer, 4 * NUMWORDS, Rx); |
| bitstr_export(buffer, 8 * NUMWORDS, Ry); |
| int i; |
| buffer[12 * NUMWORDS] = 0; |
| davies_meyer(kbuffer, buffer, bufsize / key_bytes); |
| //debug_print_bytes(kbuffer, 8); |
| for(i = 0; i < kbuffer.length; i++) k1[i] = kbuffer[i]; |
| buffer[12 * NUMWORDS] = 1; |
| davies_meyer(kbuffer, buffer, bufsize / key_bytes); |
| for(i = 0; i < kbuffer.length; i++) k1[kbuffer.length + i] = kbuffer[i]; |
| buffer[12 * NUMWORDS] = 2; |
| davies_meyer(kbuffer, buffer, bufsize / key_bytes); |
| for(i = 0; i < kbuffer.length; i++) k2[i] = kbuffer[i]; |
| buffer[12 * NUMWORDS] = 3; |
| davies_meyer(kbuffer, buffer, bufsize / key_bytes); |
| for(i = 0; i < kbuffer.length; i++) k2[kbuffer.length + i] = kbuffer[i]; |
| } |
| |
| public void encrypt(byte[] msg, final byte[] raw, final PublicKey pubkey) { |
| if(msg.length < raw.length + OVERHEAD) throw new IllegalArgumentException(String.format("%d bytes needed for msg", raw.length + OVERHEAD)); |
| Stream stm = new Stream(); |
| encrypt_start(stm, msg, pubkey); |
| //for(int i=0; i<raw.length; i++) msg[ECIES_START_OVERHEAD + i] = raw[i]; |
| //byte[] buffer = new byte[msg.length - ECIES_START_OVERHEAD]; |
| byte[] buffer = new byte[raw.length + ECIES_CHUNK_OVERHEAD]; |
| encrypt_chunk(stm, buffer, raw.length); |
| for(int i=0; i<buffer.length; i++) msg[ECIES_START_OVERHEAD + i] = buffer[i]; |
| } |
| |
| public int decrypt(byte[] raw, int len, final byte[] msg, final PrivateKey privkey) { |
| if(len > raw.length) throw new IllegalArgumentException("len > raw.length"); |
| if(msg.length != len + OVERHEAD) throw new IllegalArgumentException(String.format("Encrypted data must be %d bytes long.", len + OVERHEAD)); |
| Stream stm = new Stream(); |
| byte[] mac = new byte[ECIES_CHUNK_OVERHEAD]; |
| int r = decrypt_start(stm, msg, privkey); |
| if(r < 0) return r; |
| |
| //byte[] buffer = new byte[msg.length - ECIES_START_OVERHEAD]; |
| cbc_mac(mac, sub_byte_array(msg, ECIES_START_OVERHEAD), len, stm.k2); |
| if(compare_bytes(mac, sub_byte_array(msg, ECIES_START_OVERHEAD + len), ECIES_CHUNK_OVERHEAD) != 0) return -2; |
| |
| for(int i=0; i<len; i++) raw[i] = msg[ECIES_START_OVERHEAD + i]; |
| //for(int i = 0; i < msg.length - ECIES_START_OVERHEAD; i++) raw[i] = msg[ECIES_START_OVERHEAD + i]; |
| ctr_crypt(raw, len, stm.k1); |
| return 1; |
| } |
| |
| public int decrypt(byte[] raw, final byte[] msg, final PrivateKey privkey) { |
| return decrypt(raw, raw.length, msg, privkey); |
| } |
| |
| public final int ECIES_START_OVERHEAD; |
| public final int ECIES_CHUNK_OVERHEAD; |
| |
| public class Stream { |
| public Stream() { |
| int key_bytes = get_symmetric_key_bytes(); |
| k1 = new byte[key_bytes]; |
| k2 = new byte[key_bytes]; |
| } |
| private final byte[] k1, k2; |
| } |
| |
| public void encrypt_start(Stream stm, byte[] msg, final PublicKey pubkey) { |
| int[] Rx = new int[NUMWORDS]; |
| int[] Ry = new int[NUMWORDS]; |
| int[] Zx = new int[NUMWORDS]; |
| int[] Zy = new int[NUMWORDS]; |
| int[] k = new int[NUMWORDS]; |
| do { |
| get_random_exponent(k); |
| bitstr_load(Zx, pubkey.x, KEY_SIZE); |
| bitstr_load(Zy, pubkey.y, KEY_SIZE); |
| point_mult(Zx, Zy, k); |
| point_double(Zx, Zy); // cofactor h = 2 on all supported curves |
| } while(point_is_zero(Zx, Zy)); |
| point_copy(Rx, Ry, base_x, base_y); |
| point_mult(Rx, Ry, k); |
| |
| if(symmetric_crypt_nonce_listener != null && symmetric_crypt_nonce_length > 0) { |
| byte[] buffer = new byte[symmetric_crypt_nonce_length]; |
| bitstr_dump(buffer, buffer.length, Ry); |
| symmetric_crypt_nonce_listener.set_nonce(buffer); |
| } |
| |
| kdf(stm.k1, stm.k2, Zx, Rx, Ry); |
| |
| bitstr_export(msg, 0, Rx); |
| bitstr_export(msg, 4 * NUMWORDS, Ry); |
| } |
| |
| public void encrypt_chunk(final Stream stm, byte[] msg, int len) { |
| //System.err.printf("method: org.rivoreo.crypto.ECIES::generate_keys(Stream, byte[%d], %d)\n", msg.length, len); |
| ctr_crypt(msg, len, stm.k1); |
| byte[] mac = new byte[ECIES_CHUNK_OVERHEAD]; |
| cbc_mac(mac, msg, len, stm.k2); |
| for(int i=0; i<mac.length; i++) msg[len + i] = mac[i]; |
| } |
| |
| public int decrypt_start(Stream stm, final byte[] msg, final PrivateKey privkey) { |
| //System.err.printf("method: org.rivoreo.crypto.ECIES::decrypt_start(Stream, byte[%d], PrivateKey)\n", msg.length); |
| int[] Rx = new int[NUMWORDS]; |
| int[] Ry = new int[NUMWORDS]; |
| int[] Zx = new int[NUMWORDS]; |
| int[] Zy = new int[NUMWORDS]; |
| int[] d = new int[NUMWORDS]; |
| bitstr_import(Rx, msg); |
| bitstr_import(Ry, sub_byte_array(msg, 4 * NUMWORDS)); |
| if(internal_validate_pubkey(Rx, Ry) < 0) { |
| System.err.println("debug: internal_validate_pubkey failed"); |
| return -1; |
| } |
| |
| if(symmetric_crypt_nonce_listener != null && symmetric_crypt_nonce_length > 0) { |
| byte[] buffer = new byte[symmetric_crypt_nonce_length]; |
| bitstr_dump(buffer, buffer.length, Ry); |
| symmetric_crypt_nonce_listener.set_nonce(buffer); |
| } |
| |
| bitstr_load(d, privkey.k, KEY_SIZE); |
| point_copy(Zx, Zy, Rx, Ry); |
| point_mult(Zx, Zy, d); |
| point_double(Zx, Zy); // cofactor h = 2 on all supported curves |
| if(point_is_zero(Zx, Zy)) return -1; |
| kdf(stm.k1, stm.k2, Zx, Rx, Ry); |
| return 1; |
| } |
| |
| public int decrypt_chunk(final Stream stm, byte[] msg, int len) { |
| //System.err.printf("method: org.rivoreo.crypto.ECIES::decrypt_chunk(Stream, byte[%d], %d)\n", msg.length, len); |
| byte[] mac = new byte[ECIES_CHUNK_OVERHEAD]; |
| cbc_mac(mac, msg, len, stm.k2); |
| if(compare_bytes(mac, sub_byte_array(msg, len), ECIES_CHUNK_OVERHEAD) != 0) return -2; |
| ctr_crypt(msg, len, stm.k1); |
| return 1; |
| } |
| |
| /* |
| public static void main(String[] a) { |
| ECIES ecies = new ECIES(SECTDomainParameters.sect233r1); |
| byte[] a = { (byte)0xad, (byte)0x90, (byte)0x8f, (byte)0x7d, (byte)0x5f, (byte)0x11, (byte)0xfe, (byte)0x81, (byte)0x42, (byte)0xce, (byte)0xe9, (byte)0x20, (byte)0x3b, (byte)0x33, (byte)0x3b, (byte)0x21, (byte)0x58, (byte)0xbb, (byte)0x23, (byte)0x09, (byte)0x8c, (byte)0x7f, (byte)0x2c, (byte)0x33, (byte)0x6c, (byte)0xde, (byte)0x7e, (byte)0x64, (byte)0x66 }; |
| int[] bs = new int[NUMWORDS]; |
| bitstr_import(bs, a); |
| } |
| */ |
| } |