diff --git a/configure b/configure index cb69239..8878561 100755 --- a/configure +++ b/configure @@ -114,6 +114,9 @@ for arg in "$@"; do --use-5x64) HAVE_LIMB=64 ;; + --use-endomorphism) + USE_ENDOMORPHISM=1 + ;; esac done @@ -163,7 +166,9 @@ CFLAGS_TEST_EXTRA="" if [ "$HAVE_OPENSSL_EC" = "1" ]; then CFLAGS_TEST_EXTRA="-DENABLE_OPENSSL_TESTS" fi - +if [ "$USE_ENDOMORPHISM" = "1" ]; then + CFLAGS_EXTRA="$(CFLAGS_EXTRA) -DUSE_ENDOMORPHISM" +fi echo "CC=$CC" > config.mk echo "YASM=$YASM" >>config.mk echo "CFLAGS_EXTRA=$CFLAGS_EXTRA" >> config.mk diff --git a/src/group.h b/src/group.h index ae291c6..fc02a42 100644 --- a/src/group.h +++ b/src/group.h @@ -98,11 +98,13 @@ void static secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, c /** Get a hex representation of a point. *rlen will be overwritten with the real length. */ void static secp256k1_gej_get_hex(char *r, int *rlen, const secp256k1_gej_t *a); +#ifdef USE_ENDOMORPHISM /** Set r to be equal to lambda times a, where lambda is chosen in a way such that this is very fast. */ void static secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *a); /** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (given that a is not more than 256 bits). */ void static secp256k1_gej_split_exp(secp256k1_num_t *r1, secp256k1_num_t *r2, const secp256k1_num_t *a); +#endif #endif diff --git a/src/impl/ecmult.h b/src/impl/ecmult.h index 6acb4c4..c6711ac 100644 --- a/src/impl/ecmult.h +++ b/src/impl/ecmult.h @@ -173,34 +173,46 @@ void static secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_num_t *gn) void static secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_num_t *na, const secp256k1_num_t *ng) { const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts; +#ifdef USE_ENDOMORPHISM secp256k1_num_t na_1, na_lam; - secp256k1_num_t ng_1, ng_128; secp256k1_num_init(&na_1); secp256k1_num_init(&na_lam); - secp256k1_num_init(&ng_1); - secp256k1_num_init(&ng_128); - // split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) secp256k1_gej_split_exp(&na_1, &na_lam, na); - // split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) - secp256k1_num_split(&ng_1, &ng_128, ng, 128); - // build wnaf representation for na_1, na_lam, ng_1, ng_128 + // build wnaf representation for na_1 and na_lam. int wnaf_na_1[129]; int bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, &na_1, WINDOW_A); int wnaf_na_lam[129]; int bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, &na_lam, WINDOW_A); - int wnaf_ng_1[129]; int bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, &ng_1, WINDOW_G); - int wnaf_ng_128[129]; int bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, &ng_128, WINDOW_G); + int bits = bits_na_1; + if (bits_na_lam > bits) bits = bits_na_lam; // calculate a_lam = a*lambda secp256k1_gej_t a_lam; secp256k1_gej_mul_lambda(&a_lam, a); - // calculate odd multiples of a and a_lam - secp256k1_gej_t pre_a_1[ECMULT_TABLE_SIZE(WINDOW_A)], pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; - secp256k1_ecmult_table_precomp_gej(pre_a_1, a, WINDOW_A); + // calculate odd multiples of a_lam + secp256k1_gej_t pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; secp256k1_ecmult_table_precomp_gej(pre_a_lam, &a_lam, WINDOW_A); +#else + // build wnaf representation for na. + int wnaf_na[257]; int bits_na = secp256k1_ecmult_wnaf(wnaf_na, na, WINDOW_A); + int bits = bits_na; +#endif - int bits = bits_na_1; - if (bits_na_lam > bits) bits = bits_na_lam; + // calculate odd multiples of a + secp256k1_gej_t pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; + secp256k1_ecmult_table_precomp_gej(pre_a, a, WINDOW_A); + + // Splitted G factors. + secp256k1_num_t ng_1, ng_128; + secp256k1_num_init(&ng_1); + secp256k1_num_init(&ng_128); + + // split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) + secp256k1_num_split(&ng_1, &ng_128, ng, 128); + + // Build wnaf representation for ng_1 and ng_128 + int wnaf_ng_1[129]; int bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, &ng_1, WINDOW_G); + int wnaf_ng_128[129]; int bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, &ng_128, WINDOW_G); if (bits_ng_1 > bits) bits = bits_ng_1; if (bits_ng_128 > bits) bits = bits_ng_128; @@ -211,14 +223,21 @@ void static secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const for (int i=bits-1; i>=0; i--) { secp256k1_gej_double(r, r); int n; +#ifdef USE_ENDOMORPHISM if (i < bits_na_1 && (n = wnaf_na_1[i])) { - ECMULT_TABLE_GET_GEJ(&tmpj, pre_a_1, n, WINDOW_A); + ECMULT_TABLE_GET_GEJ(&tmpj, pre_a, n, WINDOW_A); secp256k1_gej_add(r, r, &tmpj); } if (i < bits_na_lam && (n = wnaf_na_lam[i])) { ECMULT_TABLE_GET_GEJ(&tmpj, pre_a_lam, n, WINDOW_A); secp256k1_gej_add(r, r, &tmpj); } +#else + if (i < bits_na && (n = wnaf_na[i])) { + ECMULT_TABLE_GET_GEJ(&tmpj, pre_a, n, WINDOW_A); + secp256k1_gej_add(r, r, &tmpj); + } +#endif if (i < bits_ng_1 && (n = wnaf_ng_1[i])) { ECMULT_TABLE_GET_GE(&tmpa, c->pre_g, n, WINDOW_G); secp256k1_gej_add_ge(r, r, &tmpa); @@ -229,8 +248,10 @@ void static secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const } } +#ifdef USE_ENDOMORPHISM secp256k1_num_free(&na_1); secp256k1_num_free(&na_lam); +#endif secp256k1_num_free(&ng_1); secp256k1_num_free(&ng_128); } diff --git a/src/impl/group.h b/src/impl/group.h index ce8d7b2..cfbe800 100644 --- a/src/impl/group.h +++ b/src/impl/group.h @@ -268,6 +268,7 @@ void static secp256k1_gej_get_hex(char *r, int *rlen, const secp256k1_gej_t *a) secp256k1_ge_get_hex(r, rlen, &t); } +#ifdef USE_ENDOMORPHISM void static secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *a) { const secp256k1_fe_t *beta = &secp256k1_ge_consts->beta; *r = *a; @@ -309,6 +310,7 @@ void static secp256k1_gej_split_exp(secp256k1_num_t *r1, secp256k1_num_t *r2, co secp256k1_num_free(&bnt2); secp256k1_num_free(&bnn2); } +#endif void static secp256k1_ge_start(void) { @@ -330,6 +332,7 @@ void static secp256k1_ge_start(void) { 0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19, 0x9C,0x47,0xD0,0x8F,0xFB,0x10,0xD4,0xB8 }; +#ifdef USE_ENDOMORPHISM // properties of secp256k1's efficiently computable endomorphism static const unsigned char secp256k1_ge_consts_lambda[] = { 0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0, @@ -356,22 +359,25 @@ void static secp256k1_ge_start(void) { 0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6, 0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8 }; +#endif if (secp256k1_ge_consts == NULL) { secp256k1_ge_consts_t *ret = (secp256k1_ge_consts_t*)malloc(sizeof(secp256k1_ge_consts_t)); secp256k1_num_init(&ret->order); secp256k1_num_init(&ret->half_order); + secp256k1_num_set_bin(&ret->order, secp256k1_ge_consts_order, sizeof(secp256k1_ge_consts_order)); + secp256k1_num_copy(&ret->half_order, &ret->order); + secp256k1_num_shift(&ret->half_order, 1); +#ifdef USE_ENDOMORPHISM secp256k1_num_init(&ret->lambda); secp256k1_num_init(&ret->a1b2); secp256k1_num_init(&ret->a2); secp256k1_num_init(&ret->b1); - secp256k1_num_set_bin(&ret->order, secp256k1_ge_consts_order, sizeof(secp256k1_ge_consts_order)); secp256k1_num_set_bin(&ret->lambda, secp256k1_ge_consts_lambda, sizeof(secp256k1_ge_consts_lambda)); secp256k1_num_set_bin(&ret->a1b2, secp256k1_ge_consts_a1b2, sizeof(secp256k1_ge_consts_a1b2)); secp256k1_num_set_bin(&ret->a2, secp256k1_ge_consts_a2, sizeof(secp256k1_ge_consts_a2)); secp256k1_num_set_bin(&ret->b1, secp256k1_ge_consts_b1, sizeof(secp256k1_ge_consts_b1)); - secp256k1_num_copy(&ret->half_order, &ret->order); - secp256k1_num_shift(&ret->half_order, 1); secp256k1_fe_set_b32(&ret->beta, secp256k1_ge_consts_beta); +#endif secp256k1_fe_t g_x, g_y; secp256k1_fe_set_b32(&g_x, secp256k1_ge_consts_g_x); secp256k1_fe_set_b32(&g_y, secp256k1_ge_consts_g_y);