Merge pull request #60

c259a7c Set precomputation table late and unset early. (Pieter Wuille)
04e34d1 Split up signing and verification initialization (Pieter Wuille)
This commit is contained in:
Pieter Wuille 2014-09-28 05:58:59 +02:00
commit b00982fdbd
No known key found for this signature in database
GPG Key ID: 57896D2FF8F0B657
5 changed files with 69 additions and 12 deletions

View File

@ -5,12 +5,16 @@
extern "C" { extern "C" {
#endif #endif
/** Flags to pass to secp256k1_start. */
#define SECP256K1_START_VERIFY (1 << 0)
#define SECP256K1_START_SIGN (1 << 1)
/** Initialize the library. This may take some time (10-100 ms). /** Initialize the library. This may take some time (10-100 ms).
* You need to call this before calling any other function. * You need to call this before calling any other function.
* It cannot run in parallel with any other functions, but once * It cannot run in parallel with any other functions, but once
* secp256k1_start() returns, all other functions are thread-safe. * secp256k1_start() returns, all other functions are thread-safe.
*/ */
void secp256k1_start(void); void secp256k1_start(unsigned int flags);
/** Free all memory associated with this library. After this, no /** Free all memory associated with this library. After this, no
* functions can be called anymore, except secp256k1_start() * functions can be called anymore, except secp256k1_start()
@ -22,6 +26,7 @@ void secp256k1_stop(void);
* 0: incorrect signature * 0: incorrect signature
* -1: invalid public key * -1: invalid public key
* -2: invalid signature * -2: invalid signature
* Requires starting using SECP256K1_START_VERIFY.
*/ */
int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen, int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen,
const unsigned char *sig, int siglen, const unsigned char *sig, int siglen,
@ -36,6 +41,7 @@ int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen,
* nonce: pointer to a 32-byte nonce (generated with a cryptographic PRNG) * nonce: pointer to a 32-byte nonce (generated with a cryptographic PRNG)
* Out: sig: pointer to a 72-byte array where the signature will be placed. * Out: sig: pointer to a 72-byte array where the signature will be placed.
* siglen: pointer to an int, which will be updated to the signature length (<=72). * siglen: pointer to an int, which will be updated to the signature length (<=72).
* Requires starting using SECP256K1_START_SIGN.
*/ */
int secp256k1_ecdsa_sign(const unsigned char *msg, int msglen, int secp256k1_ecdsa_sign(const unsigned char *msg, int msglen,
unsigned char *sig, int *siglen, unsigned char *sig, int *siglen,
@ -51,6 +57,7 @@ int secp256k1_ecdsa_sign(const unsigned char *msg, int msglen,
* nonce: pointer to a 32-byte nonce (generated with a cryptographic PRNG) * nonce: pointer to a 32-byte nonce (generated with a cryptographic PRNG)
* Out: sig: pointer to a 64-byte array where the signature will be placed. * Out: sig: pointer to a 64-byte array where the signature will be placed.
* recid: pointer to an int, which will be updated to contain the recovery id. * recid: pointer to an int, which will be updated to contain the recovery id.
* Requires starting using SECP256K1_START_SIGN.
*/ */
int secp256k1_ecdsa_sign_compact(const unsigned char *msg, int msglen, int secp256k1_ecdsa_sign_compact(const unsigned char *msg, int msglen,
unsigned char *sig64, unsigned char *sig64,
@ -68,8 +75,8 @@ int secp256k1_ecdsa_sign_compact(const unsigned char *msg, int msglen,
* recid: the recovery id (as returned by ecdsa_sign_compact) * recid: the recovery id (as returned by ecdsa_sign_compact)
* Out: pubkey: pointer to a 33 or 65 byte array to put the pubkey. * Out: pubkey: pointer to a 33 or 65 byte array to put the pubkey.
* pubkeylen: pointer to an int that will contain the pubkey length. * pubkeylen: pointer to an int that will contain the pubkey length.
* Requires starting using SECP256K1_START_VERIFY.
*/ */
int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen, int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen,
const unsigned char *sig64, const unsigned char *sig64,
unsigned char *pubkey, int *pubkeylen, unsigned char *pubkey, int *pubkeylen,
@ -97,6 +104,7 @@ int secp256k1_ecdsa_pubkey_verify(const unsigned char *pubkey, int pubkeylen);
* length. * length.
* Returns: 1: secret was valid, public key stores * Returns: 1: secret was valid, public key stores
* 0: secret was invalid, try again. * 0: secret was invalid, try again.
* Requires starting using SECP256K1_START_SIGN.
*/ */
int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed); int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed);

View File

@ -69,7 +69,9 @@ typedef struct {
// For accelerating the computation of a*P + b*G: // For accelerating the computation of a*P + b*G:
secp256k1_ge_t pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; // odd multiples of the generator secp256k1_ge_t pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; // odd multiples of the generator
secp256k1_ge_t pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; // odd multiples of 2^128*generator secp256k1_ge_t pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; // odd multiples of 2^128*generator
} secp256k1_ecmult_consts_t;
typedef struct {
// For accelerating the computation of a*G: // For accelerating the computation of a*G:
// To harden against timing attacks, use the following mechanism: // To harden against timing attacks, use the following mechanism:
// * Break up the multiplicand into groups of 4 bits, called n_0, n_1, n_2, ..., n_63. // * Break up the multiplicand into groups of 4 bits, called n_0, n_1, n_2, ..., n_63.
@ -83,16 +85,17 @@ typedef struct {
// the intermediate sums while computing a*G. // the intermediate sums while computing a*G.
// To make memory access uniform, the bytes of prec(i, n_i) are sliced per value of n_i. // To make memory access uniform, the bytes of prec(i, n_i) are sliced per value of n_i.
unsigned char prec[64][sizeof(secp256k1_ge_t)][16]; // prec[j][k][i] = k'th byte of (16^j * i * G + U_i) unsigned char prec[64][sizeof(secp256k1_ge_t)][16]; // prec[j][k][i] = k'th byte of (16^j * i * G + U_i)
} secp256k1_ecmult_consts_t; } secp256k1_ecmult_gen_consts_t;
static const secp256k1_ecmult_consts_t *secp256k1_ecmult_consts = NULL; static const secp256k1_ecmult_consts_t *secp256k1_ecmult_consts = NULL;
static const secp256k1_ecmult_gen_consts_t *secp256k1_ecmult_gen_consts = NULL;
static void secp256k1_ecmult_start(void) { static void secp256k1_ecmult_start(void) {
if (secp256k1_ecmult_consts != NULL) if (secp256k1_ecmult_consts != NULL)
return; return;
// Allocate the precomputation table.
secp256k1_ecmult_consts_t *ret = (secp256k1_ecmult_consts_t*)malloc(sizeof(secp256k1_ecmult_consts_t)); secp256k1_ecmult_consts_t *ret = (secp256k1_ecmult_consts_t*)malloc(sizeof(secp256k1_ecmult_consts_t));
secp256k1_ecmult_consts = ret;
// get the generator // get the generator
const secp256k1_ge_t *g = &secp256k1_ge_consts->g; const secp256k1_ge_t *g = &secp256k1_ge_consts->g;
@ -107,6 +110,21 @@ static void secp256k1_ecmult_start(void) {
secp256k1_ecmult_table_precomp_ge(ret->pre_g, &gj, WINDOW_G); secp256k1_ecmult_table_precomp_ge(ret->pre_g, &gj, WINDOW_G);
secp256k1_ecmult_table_precomp_ge(ret->pre_g_128, &g_128j, WINDOW_G); secp256k1_ecmult_table_precomp_ge(ret->pre_g_128, &g_128j, WINDOW_G);
// Set the global pointer to the precomputation table.
secp256k1_ecmult_consts = ret;
}
static void secp256k1_ecmult_gen_start(void) {
if (secp256k1_ecmult_gen_consts != NULL)
return;
// Allocate the precomputation table.
secp256k1_ecmult_gen_consts_t *ret = (secp256k1_ecmult_gen_consts_t*)malloc(sizeof(secp256k1_ecmult_gen_consts_t));
// get the generator
const secp256k1_ge_t *g = &secp256k1_ge_consts->g;
secp256k1_gej_t gj; secp256k1_gej_set_ge(&gj, g);
// Construct a group element with no known corresponding scalar (nothing up my sleeve). // Construct a group element with no known corresponding scalar (nothing up my sleeve).
secp256k1_gej_t nums_gej; secp256k1_gej_t nums_gej;
{ {
@ -154,6 +172,9 @@ static void secp256k1_ecmult_start(void) {
ret->prec[j][k][i] = raw[k]; ret->prec[j][k][i] = raw[k];
} }
} }
// Set the global pointer to the precomputation table.
secp256k1_ecmult_gen_consts = ret;
} }
static void secp256k1_ecmult_stop(void) { static void secp256k1_ecmult_stop(void) {
@ -161,8 +182,17 @@ static void secp256k1_ecmult_stop(void) {
return; return;
secp256k1_ecmult_consts_t *c = (secp256k1_ecmult_consts_t*)secp256k1_ecmult_consts; secp256k1_ecmult_consts_t *c = (secp256k1_ecmult_consts_t*)secp256k1_ecmult_consts;
free(c);
secp256k1_ecmult_consts = NULL; secp256k1_ecmult_consts = NULL;
free(c);
}
static void secp256k1_ecmult_gen_stop(void) {
if (secp256k1_ecmult_gen_consts == NULL)
return;
secp256k1_ecmult_gen_consts_t *c = (secp256k1_ecmult_gen_consts_t*)secp256k1_ecmult_gen_consts;
secp256k1_ecmult_gen_consts = NULL;
free(c);
} }
/** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits), /** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits),
@ -209,7 +239,7 @@ void static secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_num_t *gn)
secp256k1_num_t n; secp256k1_num_t n;
secp256k1_num_init(&n); secp256k1_num_init(&n);
secp256k1_num_copy(&n, gn); secp256k1_num_copy(&n, gn);
const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts; const secp256k1_ecmult_gen_consts_t *c = secp256k1_ecmult_gen_consts;
secp256k1_gej_set_infinity(r); secp256k1_gej_set_infinity(r);
secp256k1_ge_t add; secp256k1_ge_t add;
int bits; int bits;

View File

@ -15,7 +15,7 @@ static void __javasecp256k1_attach(void) __attribute__((constructor));
static void __javasecp256k1_detach(void) __attribute__((destructor)); static void __javasecp256k1_detach(void) __attribute__((destructor));
static void __javasecp256k1_attach(void) { static void __javasecp256k1_attach(void) {
secp256k1_start(); secp256k1_start(SECP256K1_START_VERIFY);
} }
static void __javasecp256k1_detach(void) { static void __javasecp256k1_detach(void) {

View File

@ -2,6 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying // Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "include/secp256k1.h"
#include <assert.h> #include <assert.h>
#include "util.h" #include "util.h"
#include "num_impl.h" #include "num_impl.h"
@ -10,19 +12,26 @@
#include "ecmult_impl.h" #include "ecmult_impl.h"
#include "ecdsa_impl.h" #include "ecdsa_impl.h"
void secp256k1_start(void) { void secp256k1_start(unsigned int flags) {
secp256k1_fe_start(); secp256k1_fe_start();
secp256k1_ge_start(); secp256k1_ge_start();
secp256k1_ecmult_start(); if (flags & SECP256K1_START_SIGN) {
secp256k1_ecmult_gen_start();
}
if (flags & SECP256K1_START_VERIFY) {
secp256k1_ecmult_start();
}
} }
void secp256k1_stop(void) { void secp256k1_stop(void) {
secp256k1_ecmult_stop(); secp256k1_ecmult_stop();
secp256k1_ecmult_gen_stop();
secp256k1_ge_stop(); secp256k1_ge_stop();
secp256k1_fe_stop(); secp256k1_fe_stop();
} }
int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen, const unsigned char *sig, int siglen, const unsigned char *pubkey, int pubkeylen) { int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen, const unsigned char *sig, int siglen, const unsigned char *pubkey, int pubkeylen) {
DEBUG_CHECK(secp256k1_ecmult_consts != NULL);
DEBUG_CHECK(msg != NULL); DEBUG_CHECK(msg != NULL);
DEBUG_CHECK(msglen <= 32); DEBUG_CHECK(msglen <= 32);
DEBUG_CHECK(sig != NULL); DEBUG_CHECK(sig != NULL);
@ -56,6 +65,7 @@ end:
} }
int secp256k1_ecdsa_sign(const unsigned char *message, int messagelen, unsigned char *signature, int *signaturelen, const unsigned char *seckey, const unsigned char *nonce) { int secp256k1_ecdsa_sign(const unsigned char *message, int messagelen, unsigned char *signature, int *signaturelen, const unsigned char *seckey, const unsigned char *nonce) {
DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL);
DEBUG_CHECK(message != NULL); DEBUG_CHECK(message != NULL);
DEBUG_CHECK(messagelen <= 32); DEBUG_CHECK(messagelen <= 32);
DEBUG_CHECK(signature != NULL); DEBUG_CHECK(signature != NULL);
@ -91,6 +101,7 @@ int secp256k1_ecdsa_sign(const unsigned char *message, int messagelen, unsigned
} }
int secp256k1_ecdsa_sign_compact(const unsigned char *message, int messagelen, unsigned char *sig64, const unsigned char *seckey, const unsigned char *nonce, int *recid) { int secp256k1_ecdsa_sign_compact(const unsigned char *message, int messagelen, unsigned char *sig64, const unsigned char *seckey, const unsigned char *nonce, int *recid) {
DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL);
DEBUG_CHECK(message != NULL); DEBUG_CHECK(message != NULL);
DEBUG_CHECK(messagelen <= 32); DEBUG_CHECK(messagelen <= 32);
DEBUG_CHECK(sig64 != NULL); DEBUG_CHECK(sig64 != NULL);
@ -126,6 +137,7 @@ int secp256k1_ecdsa_sign_compact(const unsigned char *message, int messagelen, u
} }
int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen, const unsigned char *sig64, unsigned char *pubkey, int *pubkeylen, int compressed, int recid) { int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen, const unsigned char *sig64, unsigned char *pubkey, int *pubkeylen, int compressed, int recid) {
DEBUG_CHECK(secp256k1_ecmult_consts != NULL);
DEBUG_CHECK(msg != NULL); DEBUG_CHECK(msg != NULL);
DEBUG_CHECK(msglen <= 32); DEBUG_CHECK(msglen <= 32);
DEBUG_CHECK(sig64 != NULL); DEBUG_CHECK(sig64 != NULL);
@ -173,6 +185,7 @@ int secp256k1_ecdsa_pubkey_verify(const unsigned char *pubkey, int pubkeylen) {
} }
int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed) { int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed) {
DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL);
DEBUG_CHECK(pubkey != NULL); DEBUG_CHECK(pubkey != NULL);
DEBUG_CHECK(pubkeylen != NULL); DEBUG_CHECK(pubkeylen != NULL);
DEBUG_CHECK(seckey != NULL); DEBUG_CHECK(seckey != NULL);
@ -230,6 +243,7 @@ int secp256k1_ecdsa_privkey_tweak_add(unsigned char *seckey, const unsigned char
} }
int secp256k1_ecdsa_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { int secp256k1_ecdsa_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) {
DEBUG_CHECK(secp256k1_ecmult_consts != NULL);
DEBUG_CHECK(pubkey != NULL); DEBUG_CHECK(pubkey != NULL);
DEBUG_CHECK(tweak != NULL); DEBUG_CHECK(tweak != NULL);
@ -246,8 +260,12 @@ int secp256k1_ecdsa_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const
} }
if (ret) { if (ret) {
secp256k1_gej_t pt; secp256k1_gej_t pt;
secp256k1_ecmult_gen(&pt, &term); secp256k1_gej_set_ge(&pt, &p);
secp256k1_gej_add_ge(&pt, &pt, &p); secp256k1_num_t one;
secp256k1_num_init(&one);
secp256k1_num_set_int(&one, 1);
secp256k1_ecmult(&pt, &pt, &one, &term);
secp256k1_num_free(&one);
if (secp256k1_gej_is_infinity(&pt)) if (secp256k1_gej_is_infinity(&pt))
ret = 0; ret = 0;
secp256k1_ge_set_gej(&p, &pt); secp256k1_ge_set_gej(&p, &pt);
@ -285,6 +303,7 @@ int secp256k1_ecdsa_privkey_tweak_mul(unsigned char *seckey, const unsigned char
} }
int secp256k1_ecdsa_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { int secp256k1_ecdsa_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) {
DEBUG_CHECK(secp256k1_ecmult_consts != NULL);
DEBUG_CHECK(pubkey != NULL); DEBUG_CHECK(pubkey != NULL);
DEBUG_CHECK(tweak != NULL); DEBUG_CHECK(tweak != NULL);

View File

@ -704,7 +704,7 @@ int main(int argc, char **argv) {
printf("test count = %i\n", count); printf("test count = %i\n", count);
// initialize // initialize
secp256k1_start(); secp256k1_start(SECP256K1_START_SIGN | SECP256K1_START_VERIFY);
// num tests // num tests
run_num_smalltests(); run_num_smalltests();