diff --git a/JCMathLib/src/opencrypto/jcmathlib/ECPoint.java b/JCMathLib/src/opencrypto/jcmathlib/ECPoint.java index 41270cb3..06ebc841 100644 --- a/JCMathLib/src/opencrypto/jcmathlib/ECPoint.java +++ b/JCMathLib/src/opencrypto/jcmathlib/ECPoint.java @@ -175,6 +175,8 @@ public void makeDouble() { public void add(ECPoint other) { PM.check(PM.TRAP_ECPOINT_ADD_1); + boolean samePoint = this == other || isEqual(other); + ech.lock(ech.uncompressed_point_arr1); this.thePoint.getW(ech.uncompressed_point_arr1, (short) 0); ech.fnc_add_x_p.lock(); @@ -194,7 +196,7 @@ public void add(ECPoint other) { // P+Q=R ech.fnc_add_nominator.lock(); ech.fnc_add_denominator.lock(); - if (this == other) { + if (samePoint) { //lambda = (3(x_p^2)+a)/(2y_p) //(3(x_p^2)+a) ech.fnc_add_nominator.clone(ech.fnc_add_x_p); @@ -245,7 +247,7 @@ public void add(ECPoint other) { //x_r=lambda^2-x_p-x_q ech.fnc_add_x_r.lock(); - if (this == other) { + if (samePoint) { short len = this.multiplication_x(Bignat_Helper.TWO, ech.fnc_add_x_r.as_byte_array(), (short) 0); ech.fnc_add_x_r.set_size(len); } else { @@ -422,7 +424,65 @@ public void negate() { ech.unlock(ech.uncompressed_point_arr1); PM.check(PM.TRAP_ECPOINT_NEGATE_5); } - + + /** + * Restore point from X coordinate. Stores one of the two results into this point. + * + * @param xCoord byte array containing the X coordinate + * @param xOffset offset in the byte array + * @param xLen length of the X coordinate + */ + public void from_x(byte[] xCoord, short xOffset, short xLen) { + ech.fnc_from_x_x.lock(); + ech.fnc_from_x_x.set_size(xLen); + ech.fnc_from_x_x.from_byte_array(xLen, (short) 0, xCoord, xOffset); + from_x(ech.fnc_from_x_x); + ech.fnc_from_x_x.unlock(); + } + + /** + * Restore point from X coordinate. Stores one of the two results into this point. + * + * @param x the x coordinate + */ + private void from_x(Bignat x) { + //Y^2 = X^3 + XA + B = x(x^2+A)+B + ech.fnc_from_x_y_sq.lock(); + ech.fnc_from_x_y_sq.clone(x); + ech.fnc_from_x_y_sq.mod_exp(Bignat_Helper.TWO, this.theCurve.pBN); + ech.fnc_from_x_y_sq.mod_add(this.theCurve.aBN, this.theCurve.pBN); + ech.fnc_from_x_y_sq.mod_mult(ech.fnc_from_x_y_sq, x, this.theCurve.pBN); + ech.fnc_from_x_y_sq.mod_add(this.theCurve.bBN, this.theCurve.pBN); + ech.fnc_from_x_y.lock(); + ech.fnc_from_x_y.clone(ech.fnc_from_x_y_sq); + ech.fnc_from_x_y_sq.unlock(); + ech.fnc_from_x_y.sqrt_FP(this.theCurve.pBN); + + // Construct public key with + ech.lock(ech.uncompressed_point_arr1); + ech.uncompressed_point_arr1[0] = 0x04; + x.prepend_zeros(this.theCurve.COORD_SIZE, ech.uncompressed_point_arr1, (short) 1); + ech.fnc_from_x_y.prepend_zeros(this.theCurve.COORD_SIZE, ech.uncompressed_point_arr1, (short) (1 + theCurve.COORD_SIZE)); + ech.fnc_from_x_y.unlock(); + this.setW(ech.uncompressed_point_arr1, (short) 0, theCurve.POINT_SIZE); + ech.unlock(ech.uncompressed_point_arr1); + } + + /** + * Returns true if Y coordinate is even; false otherwise. + * + * @return true if Y coordinate is even; false otherwise + */ + public boolean is_y_even() { + ech.fnc_is_y.lock(); + ech.lock(ech.uncompressed_point_arr1); + thePoint.getW(ech.uncompressed_point_arr1, (short) 0); + boolean result = ech.uncompressed_point_arr1[(short)(theCurve.POINT_SIZE - 1)] % 2 == 0; + ech.unlock(ech.uncompressed_point_arr1); + ech.fnc_is_y.unlock(); + return result; + } + /** * Compares this and provided point for equality. The comparison is made using hash of both values to prevent leak of position of mismatching byte. * @param other second point for comparison diff --git a/JCMathLib/src/opencrypto/jcmathlib/ECPoint_Helper.java b/JCMathLib/src/opencrypto/jcmathlib/ECPoint_Helper.java index d4ab7479..452f1824 100644 --- a/JCMathLib/src/opencrypto/jcmathlib/ECPoint_Helper.java +++ b/JCMathLib/src/opencrypto/jcmathlib/ECPoint_Helper.java @@ -6,7 +6,7 @@ /** * -* @author Petr Svenda + * @author Petr Svenda */ public class ECPoint_Helper extends Base_Helper { // Selected constants missing from older JC API specs @@ -15,15 +15,15 @@ public class ECPoint_Helper extends Base_Helper { public static final byte Signature_ALG_ECDSA_SHA_256 = (byte) 33; /** - * I true, fast multiplication of ECPoints via KeyAgreement can be used Is + * If true, fast multiplication of ECPoints via KeyAgreement can be used. Is * set automatically after successful allocation of required engines */ public boolean FLAG_FAST_EC_MULT_VIA_KA = false; - + byte[] uncompressed_point_arr1; byte[] fnc_isEqual_hashArray; byte[] fnc_multiplication_resultArray; - + // These Bignats are just pointing to some helperEC_BN_? so reasonable naming is preserved yet no need to actually allocated whole Bignat object Bignat fnc_add_x_r; // frequent write Bignat fnc_add_y_r; // frequent write @@ -33,21 +33,27 @@ public class ECPoint_Helper extends Base_Helper { Bignat fnc_add_lambda; // write mod_mul (but only final result) Bignat fnc_add_nominator; // frequent write Bignat fnc_add_denominator; // frequent write - + Bignat fnc_multiplication_x; // result write Bignat fnc_multiplication_y_sq; // frequent write Bignat fnc_multiplication_scalar; // write once, read Bignat fnc_multiplication_y1; // mostly just read, write inside sqrt_FP Bignat fnc_multiplication_y2; // mostly just read, result write Bignat fnc_negate_yBN; // mostly just read, result write - + + Bignat fnc_from_x_x; + Bignat fnc_from_x_y_sq; + Bignat fnc_from_x_y; + + Bignat fnc_is_y; + KeyAgreement fnc_multiplication_x_keyAgreement; Signature fnc_SignVerifyECDSA_signEngine; MessageDigest fnc_isEqual_hashEngine; - + public ECPoint_Helper(ResourceManager rm) { super(rm); - + FLAG_FAST_EC_MULT_VIA_KA = false; // set true only if succesfully allocated and tested below try { //fnc_multiplication_x_keyAgreement = KeyAgreement.getInstance(KeyAgreement.ALG_EC_SVDP_DHC, false); @@ -57,9 +63,9 @@ public ECPoint_Helper(ResourceManager rm) { fnc_SignVerifyECDSA_signEngine = Signature.getInstance(Signature_ALG_ECDSA_SHA_256, false); FLAG_FAST_EC_MULT_VIA_KA = true; } catch (Exception ignored) { - } // Discard any exception + } // Discard any exception } - + void initialize() { // Important: assignment of helper BNs is made according to two criteria: // 1. Correctness: same BN must not be assigned to overlapping operations (guarded by lock/unlock) @@ -74,21 +80,25 @@ void initialize() { fnc_add_nominator = rm.helperEC_BN_B; fnc_add_denominator = rm.helperEC_BN_C; fnc_add_lambda = rm.helperEC_BN_A; - + fnc_multiplication_scalar = rm.helperEC_BN_F; fnc_multiplication_x = rm.helperEC_BN_B; fnc_multiplication_y_sq = rm.helperEC_BN_C; fnc_multiplication_y1 = rm.helperEC_BN_D; fnc_multiplication_y2 = rm.helperEC_BN_B; fnc_multiplication_resultArray = rm.helper_BN_array1; - + fnc_negate_yBN = rm.helperEC_BN_C; - + + Bignat fnc_from_x_x; + Bignat fnc_from_x_y_sq; + Bignat fnc_from_x_y; + + fnc_is_y = rm.helperEC_BN_C; + fnc_isEqual_hashArray = rm.helper_hashArray; fnc_isEqual_hashEngine = rm.hashEngine; uncompressed_point_arr1 = rm.helper_uncompressed_point_arr1; - } - } diff --git a/JCMathLib/src/opencrypto/jcmathlib/SecP256k1.java b/JCMathLib/src/opencrypto/jcmathlib/SecP256k1.java new file mode 100644 index 00000000..f21d7724 --- /dev/null +++ b/JCMathLib/src/opencrypto/jcmathlib/SecP256k1.java @@ -0,0 +1,72 @@ +package opencrypto.jcmathlib; + +public class SecP256k1 { + + public final static short KEY_LENGTH = 256; // Bits + public final static short POINT_SIZE = 65; // Bytes + public final static short COORD_SIZE = 32; // Bytes + + public final static byte[] p = { + (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) 0xfe, + (byte) 0xff, (byte) 0xff, (byte) 0xfc, (byte) 0x2f + }; + + public final static byte[] a = { + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 + }; + + public final static byte[] b = { + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x07 + }; + + public final static byte[] G = { + (byte) 0x04, + (byte) 0x79, (byte) 0xbe, (byte) 0x66, (byte) 0x7e, + (byte) 0xf9, (byte) 0xdc, (byte) 0xbb, (byte) 0xac, + (byte) 0x55, (byte) 0xa0, (byte) 0x62, (byte) 0x95, + (byte) 0xce, (byte) 0x87, (byte) 0x0b, (byte) 0x07, + (byte) 0x02, (byte) 0x9b, (byte) 0xfc, (byte) 0xdb, + (byte) 0x2d, (byte) 0xce, (byte) 0x28, (byte) 0xd9, + (byte) 0x59, (byte) 0xf2, (byte) 0x81, (byte) 0x5b, + (byte) 0x16, (byte) 0xf8, (byte) 0x17, (byte) 0x98, + (byte) 0x48, (byte) 0x3a, (byte) 0xda, (byte) 0x77, + (byte) 0x26, (byte) 0xa3, (byte) 0xc4, (byte) 0x65, + (byte) 0x5d, (byte) 0xa4, (byte) 0xfb, (byte) 0xfc, + (byte) 0x0e, (byte) 0x11, (byte) 0x08, (byte) 0xa8, + (byte) 0xfd, (byte) 0x17, (byte) 0xb4, (byte) 0x48, + (byte) 0xa6, (byte) 0x85, (byte) 0x54, (byte) 0x19, + (byte) 0x9c, (byte) 0x47, (byte) 0xd0, (byte) 0x8f, + (byte) 0xfb, (byte) 0x10, (byte) 0xd4, (byte) 0xb8 + }; + + public final static byte[] r = { + (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) 0xfe, + (byte) 0xba, (byte) 0xae, (byte) 0xdc, (byte) 0xe6, + (byte) 0xaf, (byte) 0x48, (byte) 0xa0, (byte) 0x3b, + (byte) 0xbf, (byte) 0xd2, (byte) 0x5e, (byte) 0x8c, + (byte) 0xd0, (byte) 0x36, (byte) 0x41, (byte) 0x41, + }; +}