Browse Source

Split up signing and verification initialization

master
Pieter Wuille 8 years ago
parent
commit
04e34d18c3
  1. 12
      include/secp256k1.h
  2. 28
      src/ecmult_impl.h
  3. 2
      src/java/org_bitcoin_NativeSecp256k1.c
  4. 27
      src/secp256k1.c
  5. 2
      src/tests.c

12
include/secp256k1.h

@ -5,12 +5,16 @@ @@ -5,12 +5,16 @@
extern "C" {
#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).
* You need to call this before calling any other function.
* It cannot run in parallel with any other functions, but once
* 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
* functions can be called anymore, except secp256k1_start()
@ -22,6 +26,7 @@ void secp256k1_stop(void); @@ -22,6 +26,7 @@ void secp256k1_stop(void);
* 0: incorrect signature
* -1: invalid public key
* -2: invalid signature
* Requires starting using SECP256K1_START_VERIFY.
*/
int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen,
const unsigned char *sig, int siglen,
@ -36,6 +41,7 @@ int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen, @@ -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)
* 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).
* Requires starting using SECP256K1_START_SIGN.
*/
int secp256k1_ecdsa_sign(const unsigned char *msg, int msglen,
unsigned char *sig, int *siglen,
@ -51,6 +57,7 @@ int secp256k1_ecdsa_sign(const unsigned char *msg, int msglen, @@ -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)
* 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.
* Requires starting using SECP256K1_START_SIGN.
*/
int secp256k1_ecdsa_sign_compact(const unsigned char *msg, int msglen,
unsigned char *sig64,
@ -68,8 +75,8 @@ int secp256k1_ecdsa_sign_compact(const unsigned char *msg, int msglen, @@ -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)
* 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.
* Requires starting using SECP256K1_START_VERIFY.
*/
int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen,
const unsigned char *sig64,
unsigned char *pubkey, int *pubkeylen,
@ -97,6 +104,7 @@ int secp256k1_ecdsa_pubkey_verify(const unsigned char *pubkey, int pubkeylen); @@ -97,6 +104,7 @@ int secp256k1_ecdsa_pubkey_verify(const unsigned char *pubkey, int pubkeylen);
* length.
* Returns: 1: secret was valid, public key stores
* 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);

28
src/ecmult_impl.h

@ -69,7 +69,9 @@ typedef struct { @@ -69,7 +69,9 @@ typedef struct {
// 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_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:
// 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.
@ -83,9 +85,10 @@ typedef struct { @@ -83,9 +85,10 @@ typedef struct {
// 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.
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_gen_consts_t *secp256k1_ecmult_gen_consts = NULL;
static void secp256k1_ecmult_start(void) {
if (secp256k1_ecmult_consts != NULL)
@ -106,6 +109,18 @@ static void secp256k1_ecmult_start(void) { @@ -106,6 +109,18 @@ static void secp256k1_ecmult_start(void) {
// precompute the tables with odd multiples
secp256k1_ecmult_table_precomp_ge(ret->pre_g, &gj, WINDOW_G);
secp256k1_ecmult_table_precomp_ge(ret->pre_g_128, &g_128j, WINDOW_G);
}
static void secp256k1_ecmult_gen_start(void) {
if (secp256k1_ecmult_gen_consts != NULL)
return;
secp256k1_ecmult_gen_consts_t *ret = (secp256k1_ecmult_gen_consts_t*)malloc(sizeof(secp256k1_ecmult_gen_consts_t));
secp256k1_ecmult_gen_consts = ret;
// 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).
secp256k1_gej_t nums_gej;
@ -165,6 +180,15 @@ static void secp256k1_ecmult_stop(void) { @@ -165,6 +180,15 @@ static void secp256k1_ecmult_stop(void) {
secp256k1_ecmult_consts = NULL;
}
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;
free(c);
secp256k1_ecmult_gen_consts = NULL;
}
/** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits),
* with the following guarantees:
* - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1)
@ -209,7 +233,7 @@ void static secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_num_t *gn) @@ -209,7 +233,7 @@ void static secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_num_t *gn)
secp256k1_num_t n;
secp256k1_num_init(&n);
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_ge_t add;
int bits;

2
src/java/org_bitcoin_NativeSecp256k1.c

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

27
src/secp256k1.c

@ -2,6 +2,8 @@ @@ -2,6 +2,8 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "include/secp256k1.h"
#include <assert.h>
#include "util.h"
#include "num_impl.h"
@ -10,19 +12,26 @@ @@ -10,19 +12,26 @@
#include "ecmult_impl.h"
#include "ecdsa_impl.h"
void secp256k1_start(void) {
void secp256k1_start(unsigned int flags) {
secp256k1_fe_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) {
secp256k1_ecmult_stop();
secp256k1_ecmult_gen_stop();
secp256k1_ge_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) {
DEBUG_CHECK(secp256k1_ecmult_consts != NULL);
DEBUG_CHECK(msg != NULL);
DEBUG_CHECK(msglen <= 32);
DEBUG_CHECK(sig != NULL);
@ -56,6 +65,7 @@ end: @@ -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) {
DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL);
DEBUG_CHECK(message != NULL);
DEBUG_CHECK(messagelen <= 32);
DEBUG_CHECK(signature != NULL);
@ -91,6 +101,7 @@ int secp256k1_ecdsa_sign(const unsigned char *message, int messagelen, unsigned @@ -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) {
DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL);
DEBUG_CHECK(message != NULL);
DEBUG_CHECK(messagelen <= 32);
DEBUG_CHECK(sig64 != NULL);
@ -126,6 +137,7 @@ int secp256k1_ecdsa_sign_compact(const unsigned char *message, int messagelen, u @@ -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) {
DEBUG_CHECK(secp256k1_ecmult_consts != NULL);
DEBUG_CHECK(msg != NULL);
DEBUG_CHECK(msglen <= 32);
DEBUG_CHECK(sig64 != NULL);
@ -173,6 +185,7 @@ int secp256k1_ecdsa_pubkey_verify(const unsigned char *pubkey, int pubkeylen) { @@ -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) {
DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL);
DEBUG_CHECK(pubkey != NULL);
DEBUG_CHECK(pubkeylen != NULL);
DEBUG_CHECK(seckey != NULL);
@ -230,6 +243,7 @@ int secp256k1_ecdsa_privkey_tweak_add(unsigned char *seckey, const unsigned char @@ -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) {
DEBUG_CHECK(secp256k1_ecmult_consts != NULL);
DEBUG_CHECK(pubkey != NULL);
DEBUG_CHECK(tweak != NULL);
@ -246,8 +260,12 @@ int secp256k1_ecdsa_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const @@ -246,8 +260,12 @@ int secp256k1_ecdsa_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const
}
if (ret) {
secp256k1_gej_t pt;
secp256k1_ecmult_gen(&pt, &term);
secp256k1_gej_add_ge(&pt, &pt, &p);
secp256k1_gej_set_ge(&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))
ret = 0;
secp256k1_ge_set_gej(&p, &pt);
@ -285,6 +303,7 @@ int secp256k1_ecdsa_privkey_tweak_mul(unsigned char *seckey, const unsigned char @@ -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) {
DEBUG_CHECK(secp256k1_ecmult_consts != NULL);
DEBUG_CHECK(pubkey != NULL);
DEBUG_CHECK(tweak != NULL);

2
src/tests.c

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

Loading…
Cancel
Save