Browse Source

[API BREAK] Introduce explicit contexts

master
Pieter Wuille 8 years ago
parent
commit
a9b6595ef8
  1. 118
      include/secp256k1.h
  2. 8
      src/bench_recover.c
  3. 8
      src/bench_sign.c
  4. 11
      src/bench_verify.c
  5. 7
      src/ecdsa.h
  6. 12
      src/ecdsa_impl.h
  7. 8
      src/eckey.h
  8. 12
      src/eckey_impl.h
  9. 16
      src/ecmult.h
  10. 24
      src/ecmult_gen.h
  11. 53
      src/ecmult_gen_impl.h
  12. 57
      src/ecmult_impl.h
  13. 104
      src/secp256k1.c
  14. 181
      src/tests.c

118
include/secp256k1.h

@ -40,42 +40,52 @@ extern "C" { @@ -40,42 +40,52 @@ extern "C" {
# define SECP256K1_ARG_NONNULL(_x)
# endif
/** Opaque data structure that holds context information (precomputed tables etc.).
* Only functions that take a pointer to a non-const context require exclusive
* access to it. Multiple functions that take a pointer to a const context may
* run simultaneously.
*/
typedef struct secp256k1_context_struct secp256k1_context_t;
/** Flags to pass to secp256k1_start. */
# define SECP256K1_START_VERIFY (1 << 0)
# define SECP256K1_START_SIGN (1 << 1)
/** Flags to pass to secp256k1_context_create. */
# define SECP256K1_CONTEXT_VERIFY (1 << 0)
# define SECP256K1_CONTEXT_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.
/** Create a secp256k1 context object.
* Returns: a newly created context object.
* In: flags: which parts of the context to initialize.
*/
void secp256k1_start(unsigned int flags);
secp256k1_context_t* secp256k1_context_create(
int flags
) SECP256K1_WARN_UNUSED_RESULT;
/** Free all memory associated with this library. After this, no
* functions can be called anymore, except secp256k1_start()
/** Destroy a secp256k1 context object.
* The context pointer may not be used afterwards.
*/
void secp256k1_stop(void);
void secp256k1_context_destroy(
secp256k1_context_t* ctx
) SECP256K1_ARG_NONNULL(1);
/** Verify an ECDSA signature.
* Returns: 1: correct signature
* 0: incorrect signature
* -1: invalid public key
* -2: invalid signature
* In: msg32: the 32-byte message hash being verified (cannot be NULL)
* In: ctx: a secp256k1 context object, initialized for verification.
* msg32: the 32-byte message hash being verified (cannot be NULL)
* sig: the signature being verified (cannot be NULL)
* siglen: the length of the signature
* pubkey: the public key to verify with (cannot be NULL)
* pubkeylen: the length of pubkey
* Requires starting using SECP256K1_START_VERIFY.
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(
const secp256k1_context_t* ctx,
const unsigned char *msg32,
const unsigned char *sig,
int siglen,
const unsigned char *pubkey,
int pubkeylen
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5);
/** A pointer to a function to deterministically generate a nonce.
* Returns: 1 if a nonce was successfully generated. 0 will cause signing to fail.
@ -111,15 +121,14 @@ extern const secp256k1_nonce_function_t secp256k1_nonce_function_default; @@ -111,15 +121,14 @@ extern const secp256k1_nonce_function_t secp256k1_nonce_function_default;
* Returns: 1: signature created
* 0: the nonce generation function failed, the private key was invalid, or there is not
* enough space in the signature (as indicated by siglen).
* In: msg32: the 32-byte message hash being signed (cannot be NULL)
* In: ctx: pointer to a context object, initialized for signing (cannot be NULL)
* msg32: the 32-byte message hash being signed (cannot be NULL)
* seckey: pointer to a 32-byte secret key (cannot be NULL)
* noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL)
* In/Out: siglen: pointer to an int with the length of sig, which will be updated
* to contain the actual signature length (<=72). If 0 is returned, this will be
* set to zero.
* Requires starting using SECP256K1_START_SIGN.
* to contain the actual signature length (<=72).
*
* The sig always has an s value in the lower half of the range (From 0x1
* to 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,
@ -148,72 +157,85 @@ extern const secp256k1_nonce_function_t secp256k1_nonce_function_default; @@ -148,72 +157,85 @@ extern const secp256k1_nonce_function_t secp256k1_nonce_function_default;
* be taken when this property is required for an application.
*/
int secp256k1_ecdsa_sign(
const secp256k1_context_t* ctx,
const unsigned char *msg32,
unsigned char *sig,
int *siglen,
const unsigned char *seckey,
secp256k1_nonce_function_t noncefp,
const void *ndata
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
/** Create a compact ECDSA signature (64 byte + recovery id).
* Returns: 1: signature created
* 0: the nonce generation function failed, or the secret key was invalid.
* In: msg32: the 32-byte message hash being signed (cannot be NULL)
* In: ctx: pointer to a context object, initialized for signing (cannot be NULL)
* msg32: the 32-byte message hash being signed (cannot be NULL)
* seckey: pointer to a 32-byte secret key (cannot be NULL)
* noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
* Out: sig: pointer to a 64-byte array where the signature will be placed (cannot be NULL)
* In case 0 is returned, the returned signature length will be zero.
* recid: pointer to an int, which will be updated to contain the recovery id (can be NULL)
* Requires starting using SECP256K1_START_SIGN.
*/
int secp256k1_ecdsa_sign_compact(
const secp256k1_context_t* ctx,
const unsigned char *msg32,
unsigned char *sig64,
const unsigned char *seckey,
secp256k1_nonce_function_t noncefp,
const void *ndata,
int *recid
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Recover an ECDSA public key from a compact signature.
* Returns: 1: public key successfully recovered (which guarantees a correct signature).
* 0: otherwise.
* In: msg32: the 32-byte message hash assumed to be signed (cannot be NULL)
* In: ctx: pointer to a context object, initialized for verification (cannot be NULL)
* msg32: the 32-byte message hash assumed to be signed (cannot be NULL)
* sig64: signature as 64 byte array (cannot be NULL)
* compressed: whether to recover a compressed or uncompressed pubkey
* recid: the recovery id (0-3, as returned by ecdsa_sign_compact)
* Out: pubkey: pointer to a 33 or 65 byte array to put the pubkey (cannot be NULL)
* pubkeylen: pointer to an int that will contain the pubkey length (cannot be NULL)
* Requires starting using SECP256K1_START_VERIFY.
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover_compact(
const secp256k1_context_t* ctx,
const unsigned char *msg32,
const unsigned char *sig64,
unsigned char *pubkey,
int *pubkeylen,
int compressed,
int recid
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
/** Verify an ECDSA secret key.
* Returns: 1: secret key is valid
* 0: secret key is invalid
* In: seckey: pointer to a 32-byte secret key (cannot be NULL)
* In: ctx: pointer to a context object (cannot be NULL)
* seckey: pointer to a 32-byte secret key (cannot be NULL)
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(const unsigned char *seckey) SECP256K1_ARG_NONNULL(1);
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(
const secp256k1_context_t* ctx,
const unsigned char *seckey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
/** Verify an ECDSA public key.
/** Just validate a public key.
* Returns: 1: public key is valid
* 0: public key is invalid
* In: pubkey: pointer to a 33-byte or 65-byte public key (cannot be NULL).
* In: ctx: pointer to a context object (cannot be NULL)
* pubkey: pointer to a 33-byte or 65-byte public key (cannot be NULL).
* pubkeylen: length of pubkey
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_verify(const unsigned char *pubkey, int pubkeylen) SECP256K1_ARG_NONNULL(1);
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_verify(
const secp256k1_context_t* ctx,
const unsigned char *pubkey,
int pubkeylen
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
/** Compute the public key for a secret key.
* In: compressed: whether the computed public key should be compressed
* In: ctx: pointer to a context object, initialized for signing (cannot be NULL)
* compressed: whether the computed public key should be compressed
* seckey: pointer to a 32-byte private key (cannot be NULL)
* Out: pubkey: pointer to a 33-byte (if compressed) or 65-byte (if uncompressed)
* area to store the public key (cannot be NULL)
@ -221,16 +243,17 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_verify(const unsigned char @@ -221,16 +243,17 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_verify(const unsigned char
* length (cannot be NULL)
* Returns: 1: secret was valid, public key stores
* 0: secret was invalid, try again
* Requires starting using SECP256K1_START_SIGN.
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
const secp256k1_context_t* ctx,
unsigned char *pubkey,
int *pubkeylen,
const unsigned char *seckey,
int compressed
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Decompress a public key.
* In: ctx: pointer to a context object (cannot be NULL)
* In/Out: pubkey: pointer to a 65-byte array to put the decompressed public key.
* It must contain a 33-byte or 65-byte public key already (cannot be NULL)
* pubkeylen: pointer to the size of the public key pointed to by pubkey (cannot be NULL)
@ -239,54 +262,63 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create( @@ -239,54 +262,63 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
* 1: pubkey was valid, and was replaced with its decompressed version
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_decompress(
const secp256k1_context_t* ctx,
unsigned char *pubkey,
int *pubkeylen
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Export a private key in DER format. */
/** Export a private key in DER format.
* In: ctx: pointer to a context object, initialized for signing (cannot be NULL)
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_export(
const secp256k1_context_t* ctx,
const unsigned char *seckey,
unsigned char *privkey,
int *privkeylen,
int compressed
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Import a private key in DER format. */
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_import(
const secp256k1_context_t* ctx,
unsigned char *seckey,
const unsigned char *privkey,
int privkeylen
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Tweak a private key by adding tweak to it. */
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add(
const secp256k1_context_t* ctx,
unsigned char *seckey,
const unsigned char *tweak
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Tweak a public key by adding tweak times the generator to it.
* Requires starting with SECP256K1_START_VERIFY.
* In: ctx: pointer to a context object, initialized for verification (cannot be NULL)
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add(
const secp256k1_context_t* ctx,
unsigned char *pubkey,
int pubkeylen,
const unsigned char *tweak
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3);
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);
/** Tweak a private key by multiplying it with tweak. */
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul(
const secp256k1_context_t* ctx,
unsigned char *seckey,
const unsigned char *tweak
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Tweak a public key by multiplying it with tweak.
* Requires starting with SECP256K1_START_VERIFY.
* In: ctx: pointer to a context object, initialized for verification (cannot be NULL)
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
const secp256k1_context_t* ctx,
unsigned char *pubkey,
int pubkeylen,
const unsigned char *tweak
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3);
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);
# ifdef __cplusplus
}

8
src/bench_recover.c

@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
#include "bench.h"
typedef struct {
secp256k1_context_t *ctx;
unsigned char msg[32];
unsigned char sig[64];
} bench_recover_t;
@ -21,7 +22,7 @@ void bench_recover(void* arg) { @@ -21,7 +22,7 @@ void bench_recover(void* arg) {
for (i = 0; i < 20000; i++) {
int j;
int pubkeylen = 33;
CHECK(secp256k1_ecdsa_recover_compact(data->msg, data->sig, pubkey, &pubkeylen, 1, i % 2));
CHECK(secp256k1_ecdsa_recover_compact(data->ctx, data->msg, data->sig, pubkey, &pubkeylen, 1, i % 2));
for (j = 0; j < 32; j++) {
data->sig[j + 32] = data->msg[j]; /* Move former message to S. */
data->msg[j] = data->sig[j]; /* Move former R to message. */
@ -40,10 +41,11 @@ void bench_recover_setup(void* arg) { @@ -40,10 +41,11 @@ void bench_recover_setup(void* arg) {
int main(void) {
bench_recover_t data;
secp256k1_start(SECP256K1_START_VERIFY);
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
run_benchmark("ecdsa_recover", bench_recover, bench_recover_setup, NULL, &data, 10, 20000);
secp256k1_stop();
secp256k1_context_destroy(data.ctx);
return 0;
}

8
src/bench_sign.c

@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
#include "bench.h"
typedef struct {
secp256k1_context_t* ctx;
unsigned char msg[32];
unsigned char key[32];
} bench_sign_t;
@ -29,7 +30,7 @@ static void bench_sign(void* arg) { @@ -29,7 +30,7 @@ static void bench_sign(void* arg) {
for (i = 0; i < 20000; i++) {
int j;
int recid = 0;
CHECK(secp256k1_ecdsa_sign_compact(data->msg, sig, data->key, NULL, NULL, &recid));
CHECK(secp256k1_ecdsa_sign_compact(data->ctx, data->msg, sig, data->key, NULL, NULL, &recid));
for (j = 0; j < 32; j++) {
data->msg[j] = sig[j]; /* Move former R to message. */
data->key[j] = sig[j + 32]; /* Move former S to key. */
@ -39,10 +40,11 @@ static void bench_sign(void* arg) { @@ -39,10 +40,11 @@ static void bench_sign(void* arg) {
int main(void) {
bench_sign_t data;
secp256k1_start(SECP256K1_START_SIGN);
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
run_benchmark("ecdsa_sign", bench_sign, bench_sign_setup, NULL, &data, 10, 20000);
secp256k1_stop();
secp256k1_context_destroy(data.ctx);
return 0;
}

11
src/bench_verify.c

@ -12,6 +12,7 @@ @@ -12,6 +12,7 @@
#include "bench.h"
typedef struct {
secp256k1_context_t *ctx;
unsigned char msg[32];
unsigned char key[32];
unsigned char sig[72];
@ -28,7 +29,7 @@ static void benchmark_verify(void* arg) { @@ -28,7 +29,7 @@ static void benchmark_verify(void* arg) {
data->sig[data->siglen - 1] ^= (i & 0xFF);
data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
CHECK(secp256k1_ecdsa_verify(data->msg, data->sig, data->siglen, data->pubkey, data->pubkeylen) == (i == 0));
CHECK(secp256k1_ecdsa_verify(data->ctx, data->msg, data->sig, data->siglen, data->pubkey, data->pubkeylen) == (i == 0));
data->sig[data->siglen - 1] ^= (i & 0xFF);
data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF);
data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF);
@ -39,17 +40,17 @@ int main(void) { @@ -39,17 +40,17 @@ int main(void) {
int i;
benchmark_verify_t data;
secp256k1_start(SECP256K1_START_VERIFY | SECP256K1_START_SIGN);
data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
for (i = 0; i < 32; i++) data.msg[i] = 1 + i;
for (i = 0; i < 32; i++) data.key[i] = 33 + i;
data.siglen = 72;
secp256k1_ecdsa_sign(data.msg, data.sig, &data.siglen, data.key, NULL, NULL);
secp256k1_ecdsa_sign(data.ctx, data.msg, data.sig, &data.siglen, data.key, NULL, NULL);
data.pubkeylen = 33;
CHECK(secp256k1_ec_pubkey_create(data.pubkey, &data.pubkeylen, data.key, 1));
CHECK(secp256k1_ec_pubkey_create(data.ctx, data.pubkey, &data.pubkeylen, data.key, 1));
run_benchmark("ecdsa_verify", benchmark_verify, NULL, NULL, &data, 10, 20000);
secp256k1_stop();
secp256k1_context_destroy(data.ctx);
return 0;
}

7
src/ecdsa.h

@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
#include "scalar.h"
#include "group.h"
#include "ecmult.h"
typedef struct {
secp256k1_scalar_t r, s;
@ -16,8 +17,8 @@ typedef struct { @@ -16,8 +17,8 @@ typedef struct {
static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size);
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a);
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message);
static int secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid);
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid);
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context_t *ctx, const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message);
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context_t *ctx, secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid);
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context_t *ctx, const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid);
#endif

12
src/ecdsa_impl.h

@ -132,7 +132,7 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const se @@ -132,7 +132,7 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const se
return 1;
}
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message) {
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context_t *ctx, const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message) {
unsigned char c[32];
secp256k1_scalar_t sn, u1, u2;
secp256k1_fe_t xr;
@ -147,7 +147,7 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const se @@ -147,7 +147,7 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const se
secp256k1_scalar_mul(&u1, &sn, message);
secp256k1_scalar_mul(&u2, &sn, &sig->r);
secp256k1_gej_set_ge(&pubkeyj, pubkey);
secp256k1_ecmult(&pr, &pubkeyj, &u2, &u1);
secp256k1_ecmult(ctx, &pr, &pubkeyj, &u2, &u1);
if (secp256k1_gej_is_infinity(&pr)) {
return 0;
}
@ -186,7 +186,7 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const se @@ -186,7 +186,7 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const se
return 0;
}
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid) {
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context_t *ctx, const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid) {
unsigned char brx[32];
secp256k1_fe_t fx;
secp256k1_ge_t x;
@ -214,19 +214,19 @@ static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256 @@ -214,19 +214,19 @@ static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256
secp256k1_scalar_mul(&u1, &rn, message);
secp256k1_scalar_negate(&u1, &u1);
secp256k1_scalar_mul(&u2, &rn, &sig->s);
secp256k1_ecmult(&qj, &xj, &u2, &u1);
secp256k1_ecmult(ctx, &qj, &xj, &u2, &u1);
secp256k1_ge_set_gej_var(pubkey, &qj);
return !secp256k1_gej_is_infinity(&qj);
}
static int secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid) {
static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context_t *ctx, secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid) {
unsigned char b[32];
secp256k1_gej_t rp;
secp256k1_ge_t r;
secp256k1_scalar_t n;
int overflow = 0;
secp256k1_ecmult_gen(&rp, nonce);
secp256k1_ecmult_gen(ctx, &rp, nonce);
secp256k1_ge_set_gej(&r, &rp);
secp256k1_fe_normalize(&r.x);
secp256k1_fe_normalize(&r.y);

8
src/eckey.h

@ -9,16 +9,18 @@ @@ -9,16 +9,18 @@
#include "group.h"
#include "scalar.h"
#include "ecmult.h"
#include "ecmult_gen.h"
static int secp256k1_eckey_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size);
static int secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed);
static int secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned char *privkey, int privkeylen);
static int secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_scalar_t *key, int compressed);
static int secp256k1_eckey_privkey_serialize(const secp256k1_ecmult_gen_context_t *ctx, unsigned char *privkey, int *privkeylen, const secp256k1_scalar_t *key, int compressed);
static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak);
static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_scalar_t *tweak);
static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context_t *ctx, secp256k1_ge_t *key, const secp256k1_scalar_t *tweak);
static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak);
static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_scalar_t *tweak);
static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context_t *ctx, secp256k1_ge_t *key, const secp256k1_scalar_t *tweak);
#endif

12
src/eckey_impl.h

@ -94,11 +94,11 @@ static int secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned @@ -94,11 +94,11 @@ static int secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned
return !overflow;
}
static int secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_scalar_t *key, int compressed) {
static int secp256k1_eckey_privkey_serialize(const secp256k1_ecmult_gen_context_t *ctx, unsigned char *privkey, int *privkeylen, const secp256k1_scalar_t *key, int compressed) {
secp256k1_gej_t rp;
secp256k1_ge_t r;
int pubkeylen = 0;
secp256k1_ecmult_gen(&rp, key);
secp256k1_ecmult_gen(ctx, &rp, key);
secp256k1_ge_set_gej(&r, &rp);
if (compressed) {
static const unsigned char begin[] = {
@ -162,12 +162,12 @@ static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar_t *key, const secp @@ -162,12 +162,12 @@ static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar_t *key, const secp
return 1;
}
static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_scalar_t *tweak) {
static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context_t *ctx, secp256k1_ge_t *key, const secp256k1_scalar_t *tweak) {
secp256k1_gej_t pt;
secp256k1_scalar_t one;
secp256k1_gej_set_ge(&pt, key);
secp256k1_scalar_set_int(&one, 1);
secp256k1_ecmult(&pt, &pt, &one, tweak);
secp256k1_ecmult(ctx, &pt, &pt, &one, tweak);
if (secp256k1_gej_is_infinity(&pt)) {
return 0;
@ -185,7 +185,7 @@ static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar_t *key, const secp @@ -185,7 +185,7 @@ static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar_t *key, const secp
return 1;
}
static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_scalar_t *tweak) {
static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context_t *ctx, secp256k1_ge_t *key, const secp256k1_scalar_t *tweak) {
secp256k1_scalar_t zero;
secp256k1_gej_t pt;
if (secp256k1_scalar_is_zero(tweak)) {
@ -194,7 +194,7 @@ static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1 @@ -194,7 +194,7 @@ static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1
secp256k1_scalar_set_int(&zero, 0);
secp256k1_gej_set_ge(&pt, key);
secp256k1_ecmult(&pt, &pt, tweak, &zero);
secp256k1_ecmult(ctx, &pt, &pt, tweak, &zero);
secp256k1_ge_set_gej(key, &pt);
return 1;
}

16
src/ecmult.h

@ -10,10 +10,20 @@ @@ -10,10 +10,20 @@
#include "num.h"
#include "group.h"
static void secp256k1_ecmult_start(void);
static void secp256k1_ecmult_stop(void);
typedef struct {
/* For accelerating the computation of a*P + b*G: */
secp256k1_ge_storage_t (*pre_g)[]; /* odd multiples of the generator */
#ifdef USE_ENDOMORPHISM
secp256k1_ge_storage_t (*pre_g_128)[]; /* odd multiples of 2^128*generator */
#endif
} secp256k1_ecmult_context_t;
static void secp256k1_ecmult_context_init(secp256k1_ecmult_context_t *ctx);
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context_t *ctx);
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context_t *ctx);
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context_t *ctx);
/** Double multiply: R = na*A + ng*G */
static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_scalar_t *na, const secp256k1_scalar_t *ng);
static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_scalar_t *na, const secp256k1_scalar_t *ng);
#endif

24
src/ecmult_gen.h

@ -10,10 +10,28 @@ @@ -10,10 +10,28 @@
#include "scalar.h"
#include "group.h"
static void secp256k1_ecmult_gen_start(void);
static void secp256k1_ecmult_gen_stop(void);
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.
* * Compute sum(n_i * 16^i * G + U_i, i=0..63), where:
* * U_i = U * 2^i (for i=0..62)
* * U_i = U * (1-2^63) (for i=63)
* where U is a point with no known corresponding scalar. Note that sum(U_i, i=0..63) = 0.
* For each i, and each of the 16 possible values of n_i, (n_i * 16^i * G + U_i) is
* precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0..63).
* None of the resulting prec group elements have a known scalar, and neither do any of
* the intermediate sums while computing a*G.
*/
secp256k1_ge_storage_t (*prec)[64][16]; /* prec[j][i] = 16^j * i * G + U_i */
} secp256k1_ecmult_gen_context_t;
static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context_t* ctx);
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context_t* ctx);
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context_t* ctx);
static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context_t* ctx);
/** Multiply with the generator: R = a*G */
static void secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_scalar_t *a);
static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context_t* ctx, secp256k1_gej_t *r, const secp256k1_scalar_t *a);
#endif

53
src/ecmult_gen_impl.h

@ -11,36 +11,21 @@ @@ -11,36 +11,21 @@
#include "group.h"
#include "ecmult_gen.h"
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.
* * Compute sum(n_i * 16^i * G + U_i, i=0..63), where:
* * U_i = U * 2^i (for i=0..62)
* * U_i = U * (1-2^63) (for i=63)
* where U is a point with no known corresponding scalar. Note that sum(U_i, i=0..63) = 0.
* For each i, and each of the 16 possible values of n_i, (n_i * 16^i * G + U_i) is
* precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0..63).
* None of the resulting prec group elements have a known scalar, and neither do any of
* the intermediate sums while computing a*G.
*/
secp256k1_ge_storage_t prec[64][16]; /* prec[j][i] = 16^j * i * G + U_i */
} secp256k1_ecmult_gen_consts_t;
static const secp256k1_ecmult_gen_consts_t *secp256k1_ecmult_gen_consts = NULL;
static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context_t *ctx) {
ctx->prec = NULL;
}
static void secp256k1_ecmult_gen_start(void) {
static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context_t *ctx) {
secp256k1_ge_t prec[1024];
secp256k1_gej_t gj;
secp256k1_gej_t nums_gej;
secp256k1_ecmult_gen_consts_t *ret;
int i, j;
if (secp256k1_ecmult_gen_consts != NULL) {
if (ctx->prec != NULL) {
return;
}
/* Allocate the precomputation table. */
ret = (secp256k1_ecmult_gen_consts_t*)checked_malloc(sizeof(secp256k1_ecmult_gen_consts_t));
ctx->prec = (secp256k1_ge_storage_t (*)[64][16])checked_malloc(sizeof(*ctx->prec));
/* get the generator */
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
@ -86,27 +71,21 @@ static void secp256k1_ecmult_gen_start(void) { @@ -86,27 +71,21 @@ static void secp256k1_ecmult_gen_start(void) {
}
for (j = 0; j < 64; j++) {
for (i = 0; i < 16; i++) {
secp256k1_ge_to_storage(&ret->prec[j][i], &prec[j*16 + i]);
secp256k1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*16 + i]);
}
}
/* Set the global pointer to the precomputation table. */
secp256k1_ecmult_gen_consts = ret;
}
static void secp256k1_ecmult_gen_stop(void) {
secp256k1_ecmult_gen_consts_t *c;
if (secp256k1_ecmult_gen_consts == NULL) {
return;
}
static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context_t* ctx) {
return ctx->prec != NULL;
}
c = (secp256k1_ecmult_gen_consts_t*)secp256k1_ecmult_gen_consts;
secp256k1_ecmult_gen_consts = NULL;
free(c);
static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context_t *ctx) {
free(ctx->prec);
ctx->prec = NULL;
}
static void secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_scalar_t *gn) {
const secp256k1_ecmult_gen_consts_t *c = secp256k1_ecmult_gen_consts;
static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context_t *ctx, secp256k1_gej_t *r, const secp256k1_scalar_t *gn) {
secp256k1_ge_t add;
secp256k1_ge_storage_t adds;
int bits;
@ -127,7 +106,7 @@ static void secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_scalar_t *g @@ -127,7 +106,7 @@ static void secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_scalar_t *g
* by Dag Arne Osvik, Adi Shamir, and Eran Tromer
* (http://www.tau.ac.il/~tromer/papers/cache.pdf)
*/
secp256k1_ge_storage_cmov(&adds, &c->prec[j][i], i == bits);
secp256k1_ge_storage_cmov(&adds, &(*ctx->prec)[j][i], i == bits);
}
secp256k1_ge_from_storage(&add, &adds);
secp256k1_gej_add_ge(r, r, &add);

57
src/ecmult_impl.h

@ -92,59 +92,55 @@ static void secp256k1_ecmult_table_precomp_ge_storage_var(secp256k1_ge_storage_t @@ -92,59 +92,55 @@ static void secp256k1_ecmult_table_precomp_ge_storage_var(secp256k1_ge_storage_t
} \
} while(0)
typedef struct {
/* For accelerating the computation of a*P + b*G: */
secp256k1_ge_storage_t pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; /* odd multiples of the generator */
static void secp256k1_ecmult_context_init(secp256k1_ecmult_context_t *ctx) {
ctx->pre_g = NULL;
#ifdef USE_ENDOMORPHISM
secp256k1_ge_storage_t pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; /* odd multiples of 2^128*generator */
ctx->pre_g_128 = NULL;
#endif
} secp256k1_ecmult_consts_t;
static const secp256k1_ecmult_consts_t *secp256k1_ecmult_consts = NULL;
}
static void secp256k1_ecmult_start(void) {
static void secp256k1_ecmult_context_build(secp256k1_ecmult_context_t *ctx) {
secp256k1_gej_t gj;
secp256k1_ecmult_consts_t *ret;
if (secp256k1_ecmult_consts != NULL) {
if (ctx->pre_g != NULL) {
return;
}
/* Allocate the precomputation table. */
ret = (secp256k1_ecmult_consts_t*)checked_malloc(sizeof(secp256k1_ecmult_consts_t));
/* get the generator */
secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g);
ctx->pre_g = (secp256k1_ge_storage_t (*)[])checked_malloc(sizeof((*ctx->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G));
/* precompute the tables with odd multiples */
secp256k1_ecmult_table_precomp_ge_storage_var(ret->pre_g, &gj, WINDOW_G);
secp256k1_ecmult_table_precomp_ge_storage_var(*ctx->pre_g, &gj, WINDOW_G);
#ifdef USE_ENDOMORPHISM
{
secp256k1_gej_t g_128j;
int i;
ctx->pre_g_128 = (secp256k1_ge_storage_t (*)[])checked_malloc(sizeof((*ctx->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G));
/* calculate 2^128*generator */
g_128j = gj;
for (i = 0; i < 128; i++) {
secp256k1_gej_double_var(&g_128j, &g_128j);
}
secp256k1_ecmult_table_precomp_ge_storage_var(ret->pre_g_128, &g_128j, WINDOW_G);
secp256k1_ecmult_table_precomp_ge_storage_var(*ctx->pre_g_128, &g_128j, WINDOW_G);
}
#endif
/* Set the global pointer to the precomputation table. */
secp256k1_ecmult_consts = ret;
}
static void secp256k1_ecmult_stop(void) {
secp256k1_ecmult_consts_t *c;
if (secp256k1_ecmult_consts == NULL) {
return;
}
static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context_t *ctx) {
return ctx->pre_g != NULL;
}
c = (secp256k1_ecmult_consts_t*)secp256k1_ecmult_consts;
secp256k1_ecmult_consts = NULL;
free(c);
static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context_t *ctx) {
free(ctx->pre_g);
#ifdef USE_ENDOMORPHISM
free(ctx->pre_g_128);
#endif
secp256k1_ecmult_context_init(ctx);
}
/** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits),
@ -191,11 +187,10 @@ static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_scalar_t *a, int w) @@ -191,11 +187,10 @@ static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_scalar_t *a, int w)
return set_bits;
}
static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_scalar_t *na, const secp256k1_scalar_t *ng) {
static void secp256k1_ecmult(const secp256k1_ecmult_context_t *ctx, secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_scalar_t *na, const secp256k1_scalar_t *ng) {
secp256k1_gej_t tmpj;
secp256k1_gej_t pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
secp256k1_ge_t tmpa;
const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts;
#ifdef USE_ENDOMORPHISM
secp256k1_gej_t pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)];
secp256k1_scalar_t na_1, na_lam;
@ -279,11 +274,11 @@ static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const @@ -279,11 +274,11 @@ static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const
secp256k1_gej_add_var(r, r, &tmpj);
}
if (i < bits_ng_1 && (n = wnaf_ng_1[i])) {
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, c->pre_g, n, WINDOW_G);
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G);
secp256k1_gej_add_ge_var(r, r, &tmpa);
}
if (i < bits_ng_128 && (n = wnaf_ng_128[i])) {
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, c->pre_g_128, n, WINDOW_G);
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g_128, n, WINDOW_G);
secp256k1_gej_add_ge_var(r, r, &tmpa);
}
#else
@ -292,7 +287,7 @@ static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const @@ -292,7 +287,7 @@ static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const
secp256k1_gej_add_var(r, r, &tmpj);
}
if (i < bits_ng && (n = wnaf_ng[i])) {
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, c->pre_g, n, WINDOW_G);
ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G);
secp256k1_gej_add_ge_var(r, r, &tmpa);
}
#endif

104
src/secp256k1.c

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/**********************************************************************
* Copyright (c) 2013, 2014 Pieter Wuille *
* Copyright (c) 2013-2015 Pieter Wuille *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
@ -19,26 +19,39 @@ @@ -19,26 +19,39 @@
#include "eckey_impl.h"
#include "hash_impl.h"
void secp256k1_start(unsigned int flags) {
if (flags & SECP256K1_START_SIGN) {
secp256k1_ecmult_gen_start();
struct secp256k1_context_struct {
secp256k1_ecmult_context_t ecmult_ctx;
secp256k1_ecmult_gen_context_t ecmult_gen_ctx;
};
secp256k1_context_t* secp256k1_context_create(int flags) {
secp256k1_context_t* ret = (secp256k1_context_t*)checked_malloc(sizeof(secp256k1_context_t));
secp256k1_ecmult_context_init(&ret->ecmult_ctx);
secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx);
if (flags & SECP256K1_CONTEXT_SIGN) {
secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx);
}
if (flags & SECP256K1_START_VERIFY) {
secp256k1_ecmult_start();
if (flags & SECP256K1_CONTEXT_VERIFY) {
secp256k1_ecmult_context_build(&ret->ecmult_ctx);
}
return ret;
}
void secp256k1_stop(void) {
secp256k1_ecmult_stop();
secp256k1_ecmult_gen_stop();
void secp256k1_context_destroy(secp256k1_context_t* ctx) {
secp256k1_ecmult_context_clear(&ctx->ecmult_ctx);
secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx);
free(ctx);
}
int secp256k1_ecdsa_verify(const unsigned char *msg32, const unsigned char *sig, int siglen, const unsigned char *pubkey, int pubkeylen) {
int secp256k1_ecdsa_verify(const secp256k1_context_t* ctx, const unsigned char *msg32, const unsigned char *sig, int siglen, const unsigned char *pubkey, int pubkeylen) {
secp256k1_ge_t q;
secp256k1_ecdsa_sig_t s;
secp256k1_scalar_t m;
int ret = -3;
DEBUG_CHECK(secp256k1_ecmult_consts != NULL);
DEBUG_CHECK(msg32 != NULL);
DEBUG_CHECK(sig != NULL);
DEBUG_CHECK(pubkey != NULL);
@ -47,7 +60,7 @@ int secp256k1_ecdsa_verify(const unsigned char *msg32, const unsigned char *sig, @@ -47,7 +60,7 @@ int secp256k1_ecdsa_verify(const unsigned char *msg32, const unsigned char *sig,
if (secp256k1_eckey_pubkey_parse(&q, pubkey, pubkeylen)) {
if (secp256k1_ecdsa_sig_parse(&s, sig, siglen)) {
if (secp256k1_ecdsa_sig_verify(&s, &q, &m)) {
if (secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &s, &q, &m)) {
/* success is 1, all other values are fail */
ret = 1;
} else {
@ -77,13 +90,14 @@ static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *m @@ -77,13 +90,14 @@ static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *m
const secp256k1_nonce_function_t secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979;
const secp256k1_nonce_function_t secp256k1_nonce_function_default = nonce_function_rfc6979;
int secp256k1_ecdsa_sign(const unsigned char *msg32, unsigned char *signature, int *signaturelen, const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void* noncedata) {
int secp256k1_ecdsa_sign(const secp256k1_context_t* ctx, const unsigned char *msg32, unsigned char *signature, int *signaturelen, const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void* noncedata) {
secp256k1_ecdsa_sig_t sig;
secp256k1_scalar_t sec, non, msg;
int ret = 0;
int overflow = 0;
unsigned int count = 0;
DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL);
DEBUG_CHECK(ctx != NULL);
DEBUG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
DEBUG_CHECK(msg32 != NULL);
DEBUG_CHECK(signature != NULL);
DEBUG_CHECK(signaturelen != NULL);
@ -105,7 +119,7 @@ int secp256k1_ecdsa_sign(const unsigned char *msg32, unsigned char *signature, i @@ -105,7 +119,7 @@ int secp256k1_ecdsa_sign(const unsigned char *msg32, unsigned char *signature, i
secp256k1_scalar_set_b32(&non, nonce32, &overflow);
memset(nonce32, 0, 32);
if (!secp256k1_scalar_is_zero(&non) && !overflow) {
if (secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, NULL)) {
if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &sig, &sec, &msg, &non, NULL)) {
break;
}
}
@ -124,13 +138,14 @@ int secp256k1_ecdsa_sign(const unsigned char *msg32, unsigned char *signature, i @@ -124,13 +138,14 @@ int secp256k1_ecdsa_sign(const unsigned char *msg32, unsigned char *signature, i
return ret;
}
int secp256k1_ecdsa_sign_compact(const unsigned char *msg32, unsigned char *sig64, const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void* noncedata, int *recid) {
int secp256k1_ecdsa_sign_compact(const secp256k1_context_t* ctx, const unsigned char *msg32, unsigned char *sig64, const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void* noncedata, int *recid) {
secp256k1_ecdsa_sig_t sig;
secp256k1_scalar_t sec, non, msg;
int ret = 0;
int overflow = 0;
unsigned int count = 0;
DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL);
DEBUG_CHECK(ctx != NULL);
DEBUG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
DEBUG_CHECK(msg32 != NULL);
DEBUG_CHECK(sig64 != NULL);
DEBUG_CHECK(seckey != NULL);
@ -151,7 +166,7 @@ int secp256k1_ecdsa_sign_compact(const unsigned char *msg32, unsigned char *sig6 @@ -151,7 +166,7 @@ int secp256k1_ecdsa_sign_compact(const unsigned char *msg32, unsigned char *sig6
secp256k1_scalar_set_b32(&non, nonce32, &overflow);
memset(nonce32, 0, 32);
if (!secp256k1_scalar_is_zero(&non) && !overflow) {
if (secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, recid)) {
if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &sig, &sec, &msg, &non, recid)) {
break;
}
}
@ -171,13 +186,14 @@ int secp256k1_ecdsa_sign_compact(const unsigned char *msg32, unsigned char *sig6 @@ -171,13 +186,14 @@ int secp256k1_ecdsa_sign_compact(const unsigned char *msg32, unsigned char *sig6
return ret;
}
int secp256k1_ecdsa_recover_compact(const unsigned char *msg32, const unsigned char *sig64, unsigned char *pubkey, int *pubkeylen, int compressed, int recid) {
int secp256k1_ecdsa_recover_compact(const secp256k1_context_t* ctx, const unsigned char *msg32, const unsigned char *sig64, unsigned char *pubkey, int *pubkeylen, int compressed, int recid) {
secp256k1_ge_t q;
secp256k1_ecdsa_sig_t sig;
secp256k1_scalar_t m;
int ret = 0;
int overflow = 0;
DEBUG_CHECK(secp256k1_ecmult_consts != NULL);
DEBUG_CHECK(ctx != NULL);
DEBUG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
DEBUG_CHECK(msg32 != NULL);
DEBUG_CHECK(sig64 != NULL);
DEBUG_CHECK(pubkey != NULL);
@ -190,7 +206,7 @@ int secp256k1_ecdsa_recover_compact(const unsigned char *msg32, const unsigned c @@ -190,7 +206,7 @@ int secp256k1_ecdsa_recover_compact(const unsigned char *msg32, const unsigned c
if (!overflow) {
secp256k1_scalar_set_b32(&m, msg32, NULL);
if (secp256k1_ecdsa_sig_recover(&sig, &q, &m, recid)) {
if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &sig, &q, &m, recid)) {
ret = secp256k1_eckey_pubkey_serialize(&q, pubkey, pubkeylen, compressed);
}
}
@ -198,11 +214,13 @@ int secp256k1_ecdsa_recover_compact(const unsigned char *msg32, const unsigned c @@ -198,11 +214,13 @@ int secp256k1_ecdsa_recover_compact(const unsigned char *msg32, const unsigned c
return ret;
}
int secp256k1_ec_seckey_verify(const unsigned char *seckey) {
int secp256k1_ec_seckey_verify(const secp256k1_context_t* ctx, const unsigned char *seckey) {
secp256k1_scalar_t sec;
int ret;
int overflow;
DEBUG_CHECK(ctx != NULL);
DEBUG_CHECK(seckey != NULL);
(void)ctx;
secp256k1_scalar_set_b32(&sec, seckey, &overflow);
ret = !secp256k1_scalar_is_zero(&sec) && !overflow;
@ -210,27 +228,28 @@ int secp256k1_ec_seckey_verify(const unsigned char *seckey) { @@ -210,27 +228,28 @@ int secp256k1_ec_seckey_verify(const unsigned char *seckey) {
return ret;
}
int secp256k1_ec_pubkey_verify(const unsigned char *pubkey, int pubkeylen) {
int secp256k1_ec_pubkey_verify(const secp256k1_context_t* ctx, const unsigned char *pubkey, int pubkeylen) {
secp256k1_ge_t q;
DEBUG_CHECK(ctx != NULL);
DEBUG_CHECK(pubkey != NULL);
(void)ctx;
return secp256k1_eckey_pubkey_parse(&q, pubkey, pubkeylen);
}
int secp256k1_ec_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed) {
int secp256k1_ec_pubkey_create(const secp256k1_context_t* ctx, unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed) {
secp256k1_gej_t pj;
secp256k1_ge_t p;
secp256k1_scalar_t sec;
int overflow;
int ret = 0;
DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL);
DEBUG_CHECK(pubkey != NULL);
DEBUG_CHECK(pubkeylen != NULL);
DEBUG_CHECK(seckey != NULL);
secp256k1_scalar_set_b32(&sec, seckey, &overflow);
if (!overflow) {
secp256k1_ecmult_gen(&pj, &sec);
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec);
secp256k1_scalar_clear(&sec);
secp256k1_ge_set_gej(&p, &pj);
ret = secp256k1_eckey_pubkey_serialize(&p, pubkey, pubkeylen, compressed);
@ -241,11 +260,12 @@ int secp256k1_ec_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsi @@ -241,11 +260,12 @@ int secp256k1_ec_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsi
return ret;
}
int secp256k1_ec_pubkey_decompress(unsigned char *pubkey, int *pubkeylen) {
int secp256k1_ec_pubkey_decompress(const secp256k1_context_t* ctx, unsigned char *pubkey, int *pubkeylen) {
secp256k1_ge_t p;
int ret = 0;
DEBUG_CHECK(pubkey != NULL);
DEBUG_CHECK(pubkeylen != NULL);
(void)ctx;
if (secp256k1_eckey_pubkey_parse(&p, pubkey, *pubkeylen)) {
ret = secp256k1_eckey_pubkey_serialize(&p, pubkey, pubkeylen, 0);
@ -253,13 +273,15 @@ int secp256k1_ec_pubkey_decompress(unsigned char *pubkey, int *pubkeylen) { @@ -253,13 +273,15 @@ int secp256k1_ec_pubkey_decompress(unsigned char *pubkey, int *pubkeylen) {
return ret;
}
int secp256k1_ec_privkey_tweak_add(unsigned char *seckey, const unsigned char *tweak) {
int secp256k1_ec_privkey_tweak_add(const secp256k1_context_t* ctx, unsigned char *seckey, const unsigned char *tweak) {
secp256k1_scalar_t term;
secp256k1_scalar_t sec;
int ret = 0;
int overflow = 0;
DEBUG_CHECK(ctx != NULL);
DEBUG_CHECK(seckey != NULL);
DEBUG_CHECK(tweak != NULL);
(void)ctx;
secp256k1_scalar_set_b32(&term, tweak, &overflow);
secp256k1_scalar_set_b32(&sec, seckey, NULL);
@ -274,12 +296,13 @@ int secp256k1_ec_privkey_tweak_add(unsigned char *seckey, const unsigned char *t @@ -274,12 +296,13 @@ int secp256k1_ec_privkey_tweak_add(unsigned char *seckey, const unsigned char *t
return ret;
}
int secp256k1_ec_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) {
int secp256k1_ec_pubkey_tweak_add(const secp256k1_context_t* ctx, unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) {
secp256k1_ge_t p;
secp256k1_scalar_t term;
int ret = 0;
int overflow = 0;
DEBUG_CHECK(secp256k1_ecmult_consts != NULL);
DEBUG_CHECK(ctx != NULL);
DEBUG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
DEBUG_CHECK(pubkey != NULL);
DEBUG_CHECK(tweak != NULL);
@ -287,7 +310,7 @@ int secp256k1_ec_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const un @@ -287,7 +310,7 @@ int secp256k1_ec_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const un
if (!overflow) {
ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen);
if (ret) {
ret = secp256k1_eckey_pubkey_tweak_add(&p, &term);
ret = secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term);
}
if (ret) {
int oldlen = pubkeylen;
@ -299,13 +322,15 @@ int secp256k1_ec_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const un @@ -299,13 +322,15 @@ int secp256k1_ec_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const un
return ret;
}
int secp256k1_ec_privkey_tweak_mul(unsigned char *seckey, const unsigned char *tweak) {
int secp256k1_ec_privkey_tweak_mul(const secp256k1_context_t* ctx, unsigned char *seckey, const unsigned char *tweak) {
secp256k1_scalar_t factor;
secp256k1_scalar_t sec;
int ret = 0;
int overflow = 0;
DEBUG_CHECK(ctx != NULL);
DEBUG_CHECK(seckey != NULL);
DEBUG_CHECK(tweak != NULL);
(void)ctx;
secp256k1_scalar_set_b32(&factor, tweak, &overflow);
secp256k1_scalar_set_b32(&sec, seckey, NULL);
@ -319,12 +344,13 @@ int secp256k1_ec_privkey_tweak_mul(unsigned char *seckey, const unsigned char *t @@ -319,12 +344,13 @@ int secp256k1_ec_privkey_tweak_mul(unsigned char *seckey, const unsigned char *t
return ret;
}
int secp256k1_ec_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) {
int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context_t* ctx, unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) {
secp256k1_ge_t p;
secp256k1_scalar_t factor;
int ret = 0;
int overflow = 0;
DEBUG_CHECK(secp256k1_ecmult_consts != NULL);
DEBUG_CHECK(ctx != NULL);
DEBUG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx));
DEBUG_CHECK(pubkey != NULL);
DEBUG_CHECK(tweak != NULL);
@ -332,7 +358,7 @@ int secp256k1_ec_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const un @@ -332,7 +358,7 @@ int secp256k1_ec_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const un
if (!overflow) {
ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen);
if (ret) {
ret = secp256k1_eckey_pubkey_tweak_mul(&p, &factor);
ret = secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor);
}
if (ret) {
int oldlen = pubkeylen;
@ -344,24 +370,26 @@ int secp256k1_ec_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const un @@ -344,24 +370,26 @@ int secp256k1_ec_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const un
return ret;
}
int secp256k1_ec_privkey_export(const unsigned char *seckey, unsigned char *privkey, int *privkeylen, int compressed) {
int secp256k1_ec_privkey_export(const secp256k1_context_t* ctx, const unsigned char *seckey, unsigned char *privkey, int *privkeylen, int compressed) {
secp256k1_scalar_t key;
int ret = 0;
DEBUG_CHECK(seckey != NULL);
DEBUG_CHECK(privkey != NULL);
DEBUG_CHECK(privkeylen != NULL);
DEBUG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
secp256k1_scalar_set_b32(&key, seckey, NULL);
ret = secp256k1_eckey_privkey_serialize(privkey, privkeylen, &key, compressed);
ret = secp256k1_eckey_privkey_serialize(&ctx->ecmult_gen_ctx, privkey, privkeylen, &key, compressed);
secp256k1_scalar_clear(&key);
return ret;
}
int secp256k1_ec_privkey_import(unsigned char *seckey, const unsigned char *privkey, int privkeylen) {
int secp256k1_ec_privkey_import(const secp256k1_context_t* ctx, unsigned char *seckey, const unsigned char *privkey, int privkeylen) {
secp256k1_scalar_t key;
int ret = 0;
DEBUG_CHECK(seckey != NULL);
DEBUG_CHECK(privkey != NULL);
(void)ctx;
ret = secp256k1_eckey_privkey_parse(&key, privkey, privkeylen);
if (ret) {

181
src/tests.c

@ -24,6 +24,7 @@ @@ -24,6 +24,7 @@
#endif
static int count = 64;
static secp256k1_context_t *ctx = NULL;
void random_field_element_test(secp256k1_fe_t *fe) {
do {
@ -1035,7 +1036,7 @@ void run_ecmult_chain(void) { @@ -1035,7 +1036,7 @@ void run_ecmult_chain(void) {
x = a;
for (i = 0; i < 200*count; i++) {
/* in each iteration, compute X = xn*X + gn*G; */
secp256k1_ecmult(&x, &x, &xn, &gn);
secp256k1_ecmult(&ctx->ecmult_ctx, &x, &x, &xn, &gn);
/* also compute ae and ge: the actual accumulated factors for A and G */
/* if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G) */
secp256k1_scalar_mul(&ae, &ae, &xn);
@ -1061,7 +1062,7 @@ void run_ecmult_chain(void) { @@ -1061,7 +1062,7 @@ void run_ecmult_chain(void) {
}
}
/* redo the computation, but directly with the resulting ae and ge coefficients: */
secp256k1_ecmult(&x2, &a, &ae, &ge);
secp256k1_ecmult(&ctx->ecmult_ctx, &x2, &a, &ae, &ge);
secp256k1_gej_neg(&x2, &x2);
secp256k1_gej_add_var(&x2, &x2, &x);
CHECK(secp256k1_gej_is_infinity(&x2));
@ -1077,8 +1078,8 @@ void test_point_times_order(const secp256k1_gej_t *point) { @@ -1077,8 +1078,8 @@ void test_point_times_order(const secp256k1_gej_t *point) {
int psize = 65;
random_scalar_order_test(&x);
secp256k1_scalar_negate(&nx, &x);
secp256k1_ecmult(&res1, point, &x, &x); /* calc res1 = x * point + x * G; */
secp256k1_ecmult(&res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */
secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &x, &x); /* calc res1 = x * point + x * G; */
secp256k1_ecmult(&ctx->ecmult_ctx, &res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */
secp256k1_gej_add_var(&res1, &res1, &res2);
CHECK(secp256k1_gej_is_infinity(&res1));
CHECK(secp256k1_gej_is_valid_var(&res1) == 0);
@ -1159,7 +1160,7 @@ void random_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *key, cons @@ -1159,7 +1160,7 @@ void random_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *key, cons
secp256k1_scalar_t nonce;
do {
random_scalar_order_test(&nonce);
} while(!secp256k1_ecdsa_sig_sign(sig, key, msg, &nonce, recid));
} while(!secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, sig, key, msg, &nonce, recid));
}
void test_ecdsa_sign_verify(void) {
@ -1172,17 +1173,17 @@ void test_ecdsa_sign_verify(void) { @@ -1172,17 +1173,17 @@ void test_ecdsa_sign_verify(void) {
int getrec;
random_scalar_order_test(&msg);
random_scalar_order_test(&key);
secp256k1_ecmult_gen(&pubj, &key);
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubj, &key);
secp256k1_ge_set_gej(&pub, &pubj);
getrec = secp256k1_rand32()&1;
random_sign(&sig, &key, &msg, getrec?&recid:NULL);
if (getrec) {
CHECK(recid >= 0 && recid < 4);
}
CHECK(secp256k1_ecdsa_sig_verify(&sig, &pub, &msg));
CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sig, &pub, &msg));
secp256k1_scalar_set_int(&one, 1);
secp256k1_scalar_add(&msg, &msg, &one);
CHECK(!secp256k1_ecdsa_sig_verify(&sig, &pub, &msg));
CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sig, &pub, &msg));
}
void run_ecdsa_sign_verify(void) {
@ -1275,16 +1276,16 @@ void test_ecdsa_end_to_end(void) { @@ -1275,16 +1276,16 @@ void test_ecdsa_end_to_end(void) {
}
/* Construct and verify corresponding public key. */
CHECK(secp256k1_ec_seckey_verify(privkey) == 1);
CHECK(secp256k1_ec_pubkey_create(pubkey, &pubkeylen, privkey, (secp256k1_rand32() & 3) != 0) == 1);
CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1);
CHECK(secp256k1_ec_pubkey_create(ctx, pubkey, &pubkeylen, privkey, (secp256k1_rand32() & 3) != 0) == 1);
if (secp256k1_rand32() & 1) {
CHECK(secp256k1_ec_pubkey_decompress(pubkey, &pubkeylen));
CHECK(secp256k1_ec_pubkey_decompress(ctx, pubkey, &pubkeylen));
}
CHECK(secp256k1_ec_pubkey_verify(pubkey, pubkeylen));
CHECK(secp256k1_ec_pubkey_verify(ctx, pubkey, pubkeylen));
/* Verify private key import and export. */
CHECK(secp256k1_ec_privke