Make endomorphism optimization optional

This commit is contained in:
Pieter Wuille 2013-12-01 21:06:20 +01:00
parent ad52495d72
commit 399c03f227
4 changed files with 53 additions and 19 deletions

7
configure vendored
View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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);