blob: e626109f6ede985a456c65bc3d0ad39468fe5ca5 [file] [log] [blame] [raw]
/*
* 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);
}
*/
}