From 23cfa914d2d17dfc3d28ae3b10d95385dac5d835 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 20 Jul 2015 13:36:55 -0400 Subject: [PATCH 1/3] Introduce secp256k1_pubkey_t type --- include/secp256k1.h | 141 +++++++++++++++++-------------------- src/bench_recover.c | 8 ++- src/bench_verify.c | 9 ++- src/secp256k1.c | 167 +++++++++++++++++++++++--------------------- src/tests.c | 141 +++++++++++++++---------------------- 5 files changed, 216 insertions(+), 250 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index f725d3b..73d80b9 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -74,25 +74,70 @@ void secp256k1_context_destroy( secp256k1_context_t* ctx ) SECP256K1_ARG_NONNULL(1); +/** Data type to hold a parsed and valid public key. + This data type should be considered opaque to the user, and only created + through API functions. It is not guaranteed to be compatible between + different implementations. If you need to convert to a format suitable + for storage or transmission, use secp256k1_ec_pubkey_serialize and + secp256k1_ec_pubkey_parse. + */ +typedef struct { + unsigned char data[64]; +} secp256k1_pubkey_t; + +/** Parse a variable-length public key into the pubkey object. + * Returns: 1 if the public key was fully valid. + * 0 if the public key could not be parsed or is invalid. + * In: ctx: a secp256k1 context object. + * input: pointer to a serialized public key + * inputlen: length of the array pointed to by input + * Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a + * parsed version of input. If not, its value is undefined. + * This function supports parsing compressed (33 bytes, header byte 0x02 or + * 0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes, header + * byte 0x06 or 0x07) format public keys. + */ +SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse( + const secp256k1_context_t* ctx, + secp256k1_pubkey_t* pubkey, + const unsigned char *input, + int inputlen +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Serialize a pubkey object into a serialized byte sequence. + * Returns: 1 always. + * In: ctx: a secp256k1 context object. + * pubkey: a pointer to a secp256k1_pubkey_t containing an initialized + * public key. + * compressed: whether to serialize in compressed format. + * Out: output: a pointer to a 65-byte (if compressed==0) or 33-byte (if + * compressed==1) byte array to place the serialized key in. + * outputlen: a pointer to an integer which will contain the serialized + * size. + */ +int secp256k1_ec_pubkey_serialize( + const secp256k1_context_t* ctx, + unsigned char *output, + int *outputlen, + const secp256k1_pubkey_t* pubkey, + int compressed +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + /** Verify an ECDSA signature. * Returns: 1: correct signature - * 0: incorrect signature - * -1: invalid public key - * -2: invalid signature + * 0: incorrect or unparseable signature * 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 + * pubkey: pointer to an initialized public key to verify with (cannot be NULL) */ 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 + const secp256k1_pubkey_t *pubkey ) 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. @@ -124,7 +169,6 @@ extern const secp256k1_nonce_function_t secp256k1_nonce_function_rfc6979; /** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */ extern const secp256k1_nonce_function_t secp256k1_nonce_function_default; - /** Create an ECDSA signature. * Returns: 1: signature created * 0: the nonce generation function failed, the private key was invalid, or there is not @@ -202,20 +246,16 @@ int secp256k1_ecdsa_sign_compact( * 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) + * Out: pubkey: pointer to the recoved public key (cannot be NULL) */ 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, + secp256k1_pubkey_t *pubkey, int recid -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5); +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Verify an ECDSA secret key. * Returns: 1: secret key is valid @@ -228,71 +268,18 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify( const unsigned char *seckey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); -/** Just validate a public key. - * Returns: 1: public key is valid - * 0: public key is invalid - * 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 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: 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) - * pubkeylen: pointer to int that will be updated to contains the pubkey's - * length (cannot be NULL) + * Out: pubkey: pointer to the created public key (cannot be NULL) * Returns: 1: secret was valid, public key stores * 0: secret was invalid, try again */ 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(4); - -/** Compress a public key. - * In: ctx: pointer to a context object (cannot be NULL) - * pubkeyin: pointer to a 33-byte or 65-byte public key (cannot be NULL) - * Out: pubkeyout: pointer to a 33-byte array to put the compressed public key (cannot be NULL) - * May alias pubkeyin. - * pubkeylen: pointer to the size of the public key pointed to by pubkeyin (cannot be NULL) - * It will be updated to reflect the size of the public key in pubkeyout. - * Returns: 0: pubkeyin was invalid - * 1: pubkeyin was valid, and pubkeyout is its compressed version - */ -SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_compress( - const secp256k1_context_t* ctx, - const unsigned char *pubkeyin, - unsigned char *pubkeyout, - int *pubkeylen -) 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) - * pubkeyin: pointer to a 33-byte or 65-byte public key (cannot be NULL) - * Out: pubkeyout: pointer to a 65-byte array to put the decompressed public key (cannot be NULL) - * May alias pubkeyin. - * pubkeylen: pointer to the size of the public key pointed to by pubkeyin (cannot be NULL) - * It will be updated to reflect the size of the public key in pubkeyout. - * Returns: 0: pubkeyin was invalid - * 1: pubkeyin was valid, and pubkeyout is its decompressed version - */ -SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_decompress( - const secp256k1_context_t* ctx, - const unsigned char *pubkeyin, - unsigned char *pubkeyout, - int *pubkeylen -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + secp256k1_pubkey_t *pubkey, + const unsigned char *seckey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Export a private key in DER format. * In: ctx: pointer to a context object, initialized for signing (cannot be NULL) @@ -325,10 +312,9 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add( */ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add( const secp256k1_context_t* ctx, - unsigned char *pubkey, - int pubkeylen, + secp256k1_pubkey_t *pubkey, const unsigned char *tweak -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4); +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Tweak a private key by multiplying it with tweak. */ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul( @@ -342,10 +328,9 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul( */ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul( const secp256k1_context_t* ctx, - unsigned char *pubkey, - int pubkeylen, + secp256k1_pubkey_t *pubkey, const unsigned char *tweak -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4); +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Updates the context randomization. * Returns: 1: randomization successfully updated diff --git a/src/bench_recover.c b/src/bench_recover.c index 56faed1..700f154 100644 --- a/src/bench_recover.c +++ b/src/bench_recover.c @@ -17,16 +17,18 @@ typedef struct { void bench_recover(void* arg) { int i; bench_recover_t *data = (bench_recover_t*)arg; - unsigned char pubkey[33]; + secp256k1_pubkey_t pubkey; + unsigned char pubkeyc[33]; for (i = 0; i < 20000; i++) { int j; int pubkeylen = 33; - CHECK(secp256k1_ecdsa_recover_compact(data->ctx, data->msg, data->sig, pubkey, &pubkeylen, 1, i % 2)); + CHECK(secp256k1_ecdsa_recover_compact(data->ctx, data->msg, data->sig, &pubkey, i % 2)); + CHECK(secp256k1_ec_pubkey_serialize(data->ctx, pubkeyc, &pubkeylen, &pubkey, 1)); 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. */ - data->sig[j] = pubkey[j + 1]; /* Move recovered pubkey X coordinate to R (which must be a valid X coordinate). */ + data->sig[j] = pubkeyc[j + 1]; /* Move recovered pubkey X coordinate to R (which must be a valid X coordinate). */ } } } diff --git a/src/bench_verify.c b/src/bench_verify.c index c8c8275..795847b 100644 --- a/src/bench_verify.c +++ b/src/bench_verify.c @@ -26,10 +26,12 @@ static void benchmark_verify(void* arg) { benchmark_verify_t* data = (benchmark_verify_t*)arg; for (i = 0; i < 20000; i++) { + secp256k1_pubkey_t pubkey; 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->ctx, data->msg, data->sig, data->siglen, data->pubkey, data->pubkeylen) == (i == 0)); + CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1); + CHECK(secp256k1_ecdsa_verify(data->ctx, data->msg, data->sig, data->siglen, &pubkey) == (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); @@ -38,6 +40,7 @@ static void benchmark_verify(void* arg) { int main(void) { int i; + secp256k1_pubkey_t pubkey; benchmark_verify_t data; data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); @@ -46,8 +49,8 @@ int main(void) { for (i = 0; i < 32; i++) data.key[i] = 33 + i; data.siglen = 72; secp256k1_ecdsa_sign(data.ctx, data.msg, data.sig, &data.siglen, data.key, NULL, NULL); - data.pubkeylen = 33; - CHECK(secp256k1_ec_pubkey_create(data.ctx, data.pubkey, &data.pubkeylen, data.key, 1)); + CHECK(secp256k1_ec_pubkey_create(data.ctx, &pubkey, data.key)); + CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, 1) == 1); run_benchmark("ecdsa_verify", benchmark_verify, NULL, NULL, &data, 10, 20000); diff --git a/src/secp256k1.c b/src/secp256k1.c index a7f2754..f3ac831 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -54,11 +54,65 @@ void secp256k1_context_destroy(secp256k1_context_t* ctx) { free(ctx); } -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) { +static void secp256k1_pubkey_load(secp256k1_ge_t* ge, const secp256k1_pubkey_t* pubkey) { + if (sizeof(secp256k1_ge_storage_t) == 64) { + /* When the secp256k1_ge_storage_t type is exactly 64 byte, use its + * representation inside secp256k1_pubkey_t, as conversion is very fast. + * Note that secp256k1_pubkey_save must use the same representation. */ + secp256k1_ge_storage_t s; + memcpy(&s, &pubkey->data[0], 64); + secp256k1_ge_from_storage(ge, &s); + DEBUG_CHECK(!secp256k1_fe_is_zero(&ge->x)); + } else { + /* Otherwise, fall back to 32-byte big endian for X and Y. */ + secp256k1_fe_t x, y; + secp256k1_fe_set_b32(&x, pubkey->data); + DEBUG_CHECK(!secp256k1_fe_is_zero(&x)); + secp256k1_fe_set_b32(&y, pubkey->data + 32); + secp256k1_ge_set_xy(ge, &x, &y); + } +} + +static void secp256k1_pubkey_save(secp256k1_pubkey_t* pubkey, secp256k1_ge_t* ge) { + if (sizeof(secp256k1_ge_storage_t) == 64) { + secp256k1_ge_storage_t s; + secp256k1_ge_to_storage(&s, ge); + memcpy(&pubkey->data[0], &s, 64); + } else { + VERIFY_CHECK(!secp256k1_ge_is_infinity(ge)); + secp256k1_fe_normalize_var(&ge->x); + secp256k1_fe_normalize_var(&ge->y); + secp256k1_fe_get_b32(pubkey->data, &ge->x); + secp256k1_fe_get_b32(pubkey->data + 32, &ge->y); + } +} + +int secp256k1_ec_pubkey_parse(const secp256k1_context_t* ctx, secp256k1_pubkey_t* pubkey, const unsigned char *input, int inputlen) { + secp256k1_ge_t Q; + + (void)ctx; + if (!secp256k1_eckey_pubkey_parse(&Q, input, inputlen)) { + memset(pubkey, 0, sizeof(*pubkey)); + return 0; + } + secp256k1_pubkey_save(pubkey, &Q); + secp256k1_ge_clear(&Q); + return 1; +} + +int secp256k1_ec_pubkey_serialize(const secp256k1_context_t* ctx, unsigned char *output, int *outputlen, const secp256k1_pubkey_t* pubkey, int compressed) { + secp256k1_ge_t Q; + + (void)ctx; + secp256k1_pubkey_load(&Q, pubkey); + return secp256k1_eckey_pubkey_serialize(&Q, output, outputlen, compressed); +} + +int secp256k1_ecdsa_verify(const secp256k1_context_t* ctx, const unsigned char *msg32, const unsigned char *sig, int siglen, const secp256k1_pubkey_t *pubkey) { secp256k1_ge_t q; secp256k1_ecdsa_sig_t s; secp256k1_scalar_t m; - int ret = -3; + int ret = 0; DEBUG_CHECK(ctx != NULL); DEBUG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); DEBUG_CHECK(msg32 != NULL); @@ -67,19 +121,12 @@ int secp256k1_ecdsa_verify(const secp256k1_context_t* ctx, const unsigned char * secp256k1_scalar_set_b32(&m, msg32, NULL); - if (secp256k1_eckey_pubkey_parse(&q, pubkey, pubkeylen)) { - if (secp256k1_ecdsa_sig_parse(&s, sig, siglen)) { - if (secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &s, &q, &m)) { - /* success is 1, all other values are fail */ - ret = 1; - } else { - ret = 0; - } - } else { - ret = -2; + secp256k1_pubkey_load(&q, pubkey); + if (secp256k1_ecdsa_sig_parse(&s, sig, siglen)) { + if (secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &s, &q, &m)) { + /* success is 1, all other values are fail */ + ret = 1; } - } else { - ret = -1; } return ret; @@ -206,7 +253,7 @@ int secp256k1_ecdsa_sign_compact(const secp256k1_context_t* ctx, const unsigned return ret; } -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) { +int secp256k1_ecdsa_recover_compact(const secp256k1_context_t* ctx, const unsigned char *msg32, const unsigned char *sig64, secp256k1_pubkey_t *pubkey, int recid) { secp256k1_ge_t q; secp256k1_ecdsa_sig_t sig; secp256k1_scalar_t m; @@ -217,7 +264,6 @@ int secp256k1_ecdsa_recover_compact(const secp256k1_context_t* ctx, const unsign DEBUG_CHECK(msg32 != NULL); DEBUG_CHECK(sig64 != NULL); DEBUG_CHECK(pubkey != NULL); - DEBUG_CHECK(pubkeylen != NULL); DEBUG_CHECK(recid >= 0 && recid <= 3); secp256k1_scalar_set_b32(&sig.r, sig64, &overflow); @@ -226,8 +272,11 @@ int secp256k1_ecdsa_recover_compact(const secp256k1_context_t* ctx, const unsign if (!overflow) { secp256k1_scalar_set_b32(&m, msg32, NULL); - if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &sig, &q, &m, recid)) { - ret = secp256k1_eckey_pubkey_serialize(&q, pubkey, pubkeylen, compressed); + ret = secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &sig, &q, &m, recid); + if (ret) { + secp256k1_pubkey_save(pubkey, &q); + } else { + memset(pubkey, 0, sizeof(*pubkey)); } } } @@ -248,16 +297,7 @@ int secp256k1_ec_seckey_verify(const secp256k1_context_t* ctx, const unsigned ch return ret; } -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(const secp256k1_context_t* ctx, unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed) { +int secp256k1_ec_pubkey_create(const secp256k1_context_t* ctx, secp256k1_pubkey_t *pubkey, const unsigned char *seckey) { secp256k1_gej_t pj; secp256k1_ge_t p; secp256k1_scalar_t sec; @@ -266,51 +306,20 @@ int secp256k1_ec_pubkey_create(const secp256k1_context_t* ctx, unsigned char *pu DEBUG_CHECK(ctx != NULL); DEBUG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); DEBUG_CHECK(pubkey != NULL); - DEBUG_CHECK(pubkeylen != NULL); DEBUG_CHECK(seckey != NULL); secp256k1_scalar_set_b32(&sec, seckey, &overflow); - if (!overflow) { - 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); - } + ret = !overflow & !secp256k1_scalar_is_zero(&sec); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec); + secp256k1_ge_set_gej(&p, &pj); + secp256k1_pubkey_save(pubkey, &p); + secp256k1_scalar_clear(&sec); if (!ret) { - *pubkeylen = 0; + memset(pubkey, 0, sizeof(*pubkey)); } return ret; } -int secp256k1_ec_pubkey_decompress(const secp256k1_context_t* ctx, const unsigned char *pubkeyin, unsigned char *pubkeyout, int *pubkeylen) { - secp256k1_ge_t p; - int ret = 0; - DEBUG_CHECK(pubkeyin != NULL); - DEBUG_CHECK(pubkeyout != NULL); - DEBUG_CHECK(pubkeylen != NULL); - (void)ctx; - - if (secp256k1_eckey_pubkey_parse(&p, pubkeyin, *pubkeylen)) { - ret = secp256k1_eckey_pubkey_serialize(&p, pubkeyout, pubkeylen, 0); - } - return ret; -} - -int secp256k1_ec_pubkey_compress(const secp256k1_context_t* ctx, const unsigned char *pubkeyin, unsigned char *pubkeyout, int *pubkeylen) { - secp256k1_ge_t p; - int ret = 0; - DEBUG_CHECK(pubkeyin != NULL); - DEBUG_CHECK(pubkeyout != NULL); - DEBUG_CHECK(pubkeylen != NULL); - (void)ctx; - - if (secp256k1_eckey_pubkey_parse(&p, pubkeyin, *pubkeylen)) { - ret = secp256k1_eckey_pubkey_serialize(&p, pubkeyout, pubkeylen, 1); - } - - return ret; -} - 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; @@ -334,7 +343,7 @@ int secp256k1_ec_privkey_tweak_add(const secp256k1_context_t* ctx, unsigned char return ret; } -int secp256k1_ec_pubkey_tweak_add(const secp256k1_context_t* ctx, unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { +int secp256k1_ec_pubkey_tweak_add(const secp256k1_context_t* ctx, secp256k1_pubkey_t *pubkey, const unsigned char *tweak) { secp256k1_ge_t p; secp256k1_scalar_t term; int ret = 0; @@ -345,15 +354,13 @@ int secp256k1_ec_pubkey_tweak_add(const secp256k1_context_t* ctx, unsigned char DEBUG_CHECK(tweak != NULL); secp256k1_scalar_set_b32(&term, tweak, &overflow); + secp256k1_pubkey_load(&p, pubkey); if (!overflow) { - ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen); + ret = secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term); if (ret) { - ret = secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term); - } - if (ret) { - int oldlen = pubkeylen; - ret = secp256k1_eckey_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33); - VERIFY_CHECK(pubkeylen == oldlen); + secp256k1_pubkey_save(pubkey, &p); + } else { + memset(pubkey, 0, sizeof(*pubkey)); } } @@ -382,7 +389,7 @@ int secp256k1_ec_privkey_tweak_mul(const secp256k1_context_t* ctx, unsigned char return ret; } -int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context_t* ctx, unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) { +int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context_t* ctx, secp256k1_pubkey_t *pubkey, const unsigned char *tweak) { secp256k1_ge_t p; secp256k1_scalar_t factor; int ret = 0; @@ -393,15 +400,13 @@ int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context_t* ctx, unsigned char DEBUG_CHECK(tweak != NULL); secp256k1_scalar_set_b32(&factor, tweak, &overflow); + secp256k1_pubkey_load(&p, pubkey); if (!overflow) { - ret = secp256k1_eckey_pubkey_parse(&p, pubkey, pubkeylen); + ret = secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor); if (ret) { - ret = secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor); - } - if (ret) { - int oldlen = pubkeylen; - ret = secp256k1_eckey_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33); - VERIFY_CHECK(pubkeylen == oldlen); + secp256k1_pubkey_save(pubkey, &p); + } else { + memset(pubkey, 0, sizeof(*pubkey)); } } diff --git a/src/tests.c b/src/tests.c index dea1735..df9adec 100644 --- a/src/tests.c +++ b/src/tests.c @@ -1585,16 +1585,16 @@ void test_ecdsa_end_to_end(void) { unsigned char signature2[72]; unsigned char signature3[72]; unsigned char signature4[72]; - unsigned char pubkey[65]; - unsigned char recpubkey[65]; + unsigned char pubkeyc[65]; + int pubkeyclen = 65; + secp256k1_pubkey_t pubkey; + secp256k1_pubkey_t recpubkey; unsigned char seckey[300]; int signaturelen = 72; int signaturelen2 = 72; int signaturelen3 = 72; int signaturelen4 = 72; int recid = 0; - int recpubkeylen = 0; - int pubkeylen = 65; int seckeylen = 300; /* Generate a random key and message. */ @@ -1608,31 +1608,12 @@ void test_ecdsa_end_to_end(void) { /* Construct and verify corresponding public key. */ 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) { - unsigned char pubkey2[65] = {0}; - unsigned char pubkey3RE[33] = {0}; - int pubkey2len = pubkeylen, pubkey3len = pubkeylen; + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); - /* Decompress into a new array */ - CHECK(secp256k1_ec_pubkey_decompress(ctx, pubkey, pubkey2, &pubkey2len)); - - /* Compress into a new array */ - CHECK(secp256k1_ec_pubkey_compress(ctx, pubkey, pubkey3RE, &pubkey3len)); - - /* Check that the key was changed iff it was originally compressed */ - if (pubkeylen == 65) { - CHECK(memcmp(pubkey, pubkey2, 65) == 0); /* Values should be the same */ - CHECK(memcmp(pubkey3RE, pubkey, 33) != 0); /* Means it should have been compressed */ - } else { - CHECK(memcmp(pubkey, pubkey2, 65) != 0); /* Should have been decompressed */ - CHECK(memcmp(pubkey3RE, pubkey, 33) == 0); /* Therefore compressed key should equal initial pubkey */ - } - /* Decompress in place */ - CHECK(secp256k1_ec_pubkey_decompress(ctx, pubkey, pubkey, &pubkeylen)); - CHECK(memcmp(pubkey, pubkey2, 65) == 0); - } - CHECK(secp256k1_ec_pubkey_verify(ctx, pubkey, pubkeylen)); + /* Verify exporting and importing public key. */ + CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyc, &pubkeyclen, &pubkey, secp256k1_rand32() % 2) == 1); + memset(&pubkey, 0, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1); /* Verify private key import and export. */ CHECK(secp256k1_ec_privkey_export(ctx, privkey, seckey, &seckeylen, secp256k1_rand32() % 2) == 1); @@ -1644,17 +1625,16 @@ void test_ecdsa_end_to_end(void) { int ret1; int ret2; unsigned char rnd[32]; - unsigned char pubkey2[65]; - int pubkeylen2 = 65; + secp256k1_pubkey_t pubkey2; secp256k1_rand256_test(rnd); ret1 = secp256k1_ec_privkey_tweak_add(ctx, privkey, rnd); - ret2 = secp256k1_ec_pubkey_tweak_add(ctx, pubkey, pubkeylen, rnd); + ret2 = secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, rnd); CHECK(ret1 == ret2); if (ret1 == 0) { return; } - CHECK(secp256k1_ec_pubkey_create(ctx, pubkey2, &pubkeylen2, privkey, pubkeylen == 33) == 1); - CHECK(memcmp(pubkey, pubkey2, pubkeylen) == 0); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1); + CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); } /* Optionally tweak the keys using multiplication. */ @@ -1662,17 +1642,16 @@ void test_ecdsa_end_to_end(void) { int ret1; int ret2; unsigned char rnd[32]; - unsigned char pubkey2[65]; - int pubkeylen2 = 65; + secp256k1_pubkey_t pubkey2; secp256k1_rand256_test(rnd); ret1 = secp256k1_ec_privkey_tweak_mul(ctx, privkey, rnd); - ret2 = secp256k1_ec_pubkey_tweak_mul(ctx, pubkey, pubkeylen, rnd); + ret2 = secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, rnd); CHECK(ret1 == ret2); if (ret1 == 0) { return; } - CHECK(secp256k1_ec_pubkey_create(ctx, pubkey2, &pubkeylen2, privkey, pubkeylen == 33) == 1); - CHECK(memcmp(pubkey, pubkey2, pubkeylen) == 0); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1); + CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); } /* Sign. */ @@ -1694,27 +1673,24 @@ void test_ecdsa_end_to_end(void) { CHECK((signaturelen4 != signaturelen2) || (memcmp(signature4, signature2, signaturelen4) != 0)); CHECK((signaturelen4 != signaturelen) || (memcmp(signature4, signature, signaturelen4) != 0)); /* Verify. */ - CHECK(secp256k1_ecdsa_verify(ctx, message, signature, signaturelen, pubkey, pubkeylen) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, message, signature2, signaturelen2, pubkey, pubkeylen) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, message, signature3, signaturelen3, pubkey, pubkeylen) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, message, signature4, signaturelen4, pubkey, pubkeylen) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, message, signature, signaturelen, &pubkey) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, message, signature2, signaturelen2, &pubkey) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, message, signature3, signaturelen3, &pubkey) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, message, signature4, signaturelen4, &pubkey) == 1); /* Destroy signature and verify again. */ signature[signaturelen - 1 - secp256k1_rand32() % 20] += 1 + (secp256k1_rand32() % 255); - CHECK(secp256k1_ecdsa_verify(ctx, message, signature, signaturelen, pubkey, pubkeylen) != 1); + CHECK(secp256k1_ecdsa_verify(ctx, message, signature, signaturelen, &pubkey) != 1); /* Compact sign. */ CHECK(secp256k1_ecdsa_sign_compact(ctx, message, csignature, privkey, NULL, NULL, &recid) == 1); CHECK(!is_empty_compact_signature(csignature)); /* Recover. */ - CHECK(secp256k1_ecdsa_recover_compact(ctx, message, csignature, recpubkey, &recpubkeylen, pubkeylen == 33, recid) == 1); - CHECK(recpubkeylen == pubkeylen); - CHECK(memcmp(pubkey, recpubkey, pubkeylen) == 0); + CHECK(secp256k1_ecdsa_recover_compact(ctx, message, csignature, &recpubkey, recid) == 1); + CHECK(memcmp(&pubkey, &recpubkey, sizeof(pubkey)) == 0); /* Destroy signature and verify again. */ csignature[secp256k1_rand32() % 64] += 1 + (secp256k1_rand32() % 255); - CHECK(secp256k1_ecdsa_recover_compact(ctx, message, csignature, recpubkey, &recpubkeylen, pubkeylen == 33, recid) != 1 || - memcmp(pubkey, recpubkey, pubkeylen) != 0); - CHECK(recpubkeylen == pubkeylen); - + CHECK(secp256k1_ecdsa_recover_compact(ctx, message, csignature, &recpubkey, recid) != 1 || + memcmp(&pubkey, &recpubkey, sizeof(pubkey)) != 0); } void test_random_pubkeys(void) { @@ -1816,9 +1792,8 @@ void test_ecdsa_edge_cases(void) { 0x7D, 0xD7, 0x3E, 0x38, 0x7E, 0xE4, 0xFC, 0x86, 0x6E, 0x1B, 0xE8, 0xEC, 0xC7, 0xDD, 0x95, 0x57 }; - unsigned char pubkey[65]; + secp256k1_pubkey_t pubkey; int t; - int pubkeylen = 65; /* signature (r,s) = (4,4), which can be recovered with all 4 recids. */ const unsigned char sigb64[64] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -1830,14 +1805,13 @@ void test_ecdsa_edge_cases(void) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, }; - unsigned char pubkeyb[33]; - int pubkeyblen = 33; + secp256k1_pubkey_t pubkeyb; int recid; - CHECK(!secp256k1_ecdsa_recover_compact(ctx, msg32, sig64, pubkey, &pubkeylen, 0, 0)); - CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sig64, pubkey, &pubkeylen, 0, 1)); - CHECK(!secp256k1_ecdsa_recover_compact(ctx, msg32, sig64, pubkey, &pubkeylen, 0, 2)); - CHECK(!secp256k1_ecdsa_recover_compact(ctx, msg32, sig64, pubkey, &pubkeylen, 0, 3)); + CHECK(!secp256k1_ecdsa_recover_compact(ctx, msg32, sig64, &pubkey, 0)); + CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sig64, &pubkey, 1)); + CHECK(!secp256k1_ecdsa_recover_compact(ctx, msg32, sig64, &pubkey, 2)); + CHECK(!secp256k1_ecdsa_recover_compact(ctx, msg32, sig64, &pubkey, 3)); for (recid = 0; recid < 4; recid++) { int i; @@ -1882,34 +1856,33 @@ void test_ecdsa_edge_cases(void) { 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x45, 0x02, 0x01, 0x04 }; - CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigb64, pubkeyb, &pubkeyblen, 1, recid)); - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, sizeof(sigbder), pubkeyb, pubkeyblen) == 1); + CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigb64, &pubkeyb, recid)); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, sizeof(sigbder), &pubkeyb) == 1); for (recid2 = 0; recid2 < 4; recid2++) { - unsigned char pubkey2b[33]; - int pubkey2blen = 33; - CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigb64, pubkey2b, &pubkey2blen, 1, recid2)); + secp256k1_pubkey_t pubkey2b; + CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigb64, &pubkey2b, recid2)); /* Verifying with (order + r,4) should always fail. */ - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderlong, sizeof(sigbderlong), pubkey2b, pubkey2blen) != 1); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderlong, sizeof(sigbderlong), &pubkey2b) != 1); } /* DER parsing tests. */ /* Zero length r/s. */ - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder_zr, sizeof(sigcder_zr), pubkeyb, pubkeyblen) == -2); - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder_zs, sizeof(sigcder_zs), pubkeyb, pubkeyblen) == -2); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder_zr, sizeof(sigcder_zr), &pubkeyb) != 1); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder_zs, sizeof(sigcder_zs), &pubkeyb) != 1); /* Leading zeros. */ - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt1, sizeof(sigbderalt1), pubkeyb, pubkeyblen) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt2, sizeof(sigbderalt2), pubkeyb, pubkeyblen) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt3, sizeof(sigbderalt3), pubkeyb, pubkeyblen) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt4, sizeof(sigbderalt4), pubkeyb, pubkeyblen) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt1, sizeof(sigbderalt1), &pubkeyb) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt2, sizeof(sigbderalt2), &pubkeyb) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt3, sizeof(sigbderalt3), &pubkeyb) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt4, sizeof(sigbderalt4), &pubkeyb) == 1); sigbderalt3[4] = 1; - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt3, sizeof(sigbderalt3), pubkeyb, pubkeyblen) == -2); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt3, sizeof(sigbderalt3), &pubkeyb) != 1); sigbderalt4[7] = 1; - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt4, sizeof(sigbderalt4), pubkeyb, pubkeyblen) == -2); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt4, sizeof(sigbderalt4), &pubkeyb) != 1); /* Damage signature. */ sigbder[7]++; - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, sizeof(sigbder), pubkeyb, pubkeyblen) == 0); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, sizeof(sigbder), &pubkeyb) == 0); sigbder[7]--; - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, 6, pubkeyb, pubkeyblen) == -2); - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, sizeof(sigbder)-1, pubkeyb, pubkeyblen) == -2); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, 6, &pubkeyb) != 1); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, sizeof(sigbder)-1, &pubkeyb) != 1); for(i = 0; i < 8; i++) { int c; unsigned char orig = sigbder[i]; @@ -1919,8 +1892,7 @@ void test_ecdsa_edge_cases(void) { continue; } sigbder[i] = c; - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, sizeof(sigbder), pubkeyb, pubkeyblen) == - (i==4 || i==7) ? 0 : -2 ); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, sizeof(sigbder), &pubkeyb) != 1); } sigbder[i] = orig; } @@ -1956,20 +1928,19 @@ void test_ecdsa_edge_cases(void) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }; - unsigned char pubkeyc[65]; - int pubkeyclen = 65; - CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigc64, pubkeyc, &pubkeyclen, 0, 0) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder, sizeof(sigcder), pubkeyc, pubkeyclen) == 1); + secp256k1_pubkey_t pubkeyc; + CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigc64, &pubkeyc, 0) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder, sizeof(sigcder), &pubkeyc) == 1); sigcder[4] = 0; sigc64[31] = 0; - CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigc64, pubkeyb, &pubkeyblen, 1, 0) == 0); - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder, sizeof(sigcder), pubkeyc, pubkeyclen) == 0); + CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigc64, &pubkeyb, 0) == 0); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder, sizeof(sigcder), &pubkeyc) == 0); sigcder[4] = 1; sigcder[7] = 0; sigc64[31] = 1; sigc64[63] = 0; - CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigc64, pubkeyb, &pubkeyblen, 1, 0) == 0); - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder, sizeof(sigcder), pubkeyc, pubkeyclen) == 0); + CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigc64, &pubkeyb, 0) == 0); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder, sizeof(sigcder), &pubkeyc) == 0); } /*Signature where s would be zero.*/ From 74a2acdb8a3d3899877343f4b3fbfa15ba31fc1e Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 26 Jul 2015 16:00:55 +0200 Subject: [PATCH 2/3] Add a secp256k1_ecdsa_signature_t type --- include/secp256k1.h | 129 +++++++++++++++------- src/bench_recover.c | 4 +- src/bench_sign.c | 4 +- src/bench_verify.c | 8 +- src/ecdsa_impl.h | 1 + src/secp256k1.c | 203 +++++++++++++++++++--------------- src/tests.c | 263 ++++++++++++++++++++++---------------------- 7 files changed, 353 insertions(+), 259 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index 73d80b9..d265e4d 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -123,22 +123,99 @@ int secp256k1_ec_pubkey_serialize( int compressed ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); +/** Data type to hold a parsed ECDSA signature, optionally supporting pubkey + * recovery. + This data type should be considered opaque to the user, and only created + through API functions. It is not guaranteed to be compatible between + different implementations. If you need to convert to a format suitable + for storage or transmission, use secp256k1_ecdsa_signature_serialize_* and + secp256k1_ecdsa_signature_parse_* functions. */ +typedef struct { + unsigned char data[65]; +} secp256k1_ecdsa_signature_t; + +/** Parse a DER ECDSA signature. + * Returns: 1 when the signature could be parsed, 0 otherwise. + * In: ctx: a secp256k1 context object + * input: a pointer to the signature to be parsed + * inputlen: the length of the array pointed to be input + * Out: sig: a pointer to a signature object + * + * Note that this function also supports some violations of DER. + * + * The resulting signature object will not support pubkey recovery. + */ +int secp256k1_ecdsa_signature_parse_der( + const secp256k1_context_t* ctx, + secp256k1_ecdsa_signature_t* sig, + const unsigned char *input, + int inputlen +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Parse a compact ECDSA signature (64 bytes + recovery id). + * Returns: 1 when the signature could be parsed, 0 otherwise + * In: ctx: a secp256k1 context object + * input64: a pointer to a 64-byte compact signature + * recid: the recovery id (0, 1, 2 or 3, or -1 for unknown) + * Out: sig: a pointer to a signature object + * + * If recid is not -1, the resulting signature object will support pubkey + * recovery. + */ +int secp256k1_ecdsa_signature_parse_compact( + const secp256k1_context_t* ctx, + secp256k1_ecdsa_signature_t* sig, + const unsigned char *input64, + int recid +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Serialize an ECDSA signature in DER format. + * Returns: 1 if enough space was available to serialize, 0 otherwise + * In: ctx: a secp256k1 context object + * sig: a pointer to an initialized signature object + * Out: output: a pointer to an array to store the DER serialization + * In/Out: outputlen: a pointer to a length integer. Initially, this integer + * should be set to the length of output. After the call + * it will be set to the length of the serialization (even + * if 0 was returned). + */ +int secp256k1_ecdsa_signature_serialize_der( + const secp256k1_context_t* ctx, + unsigned char *output, + int *outputlen, + const secp256k1_ecdsa_signature_t* sig +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Serialize an ECDSA signature in compact format (64 bytes + recovery id). + * Returns: 1 + * In: ctx: a secp256k1 context object + * sig: a pointer to an initialized signature object (cannot be NULL) + * Out: output64: a pointer to a 64-byte array of the compact signature (cannot be NULL) + * recid: a pointer to an integer to hold the recovery id (can be NULL). + * + * If recid is not NULL, the signature must support pubkey recovery. + */ +int secp256k1_ecdsa_signature_serialize_compact( + const secp256k1_context_t* ctx, + unsigned char *output64, + int *recid, + const secp256k1_ecdsa_signature_t* sig +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4); + /** Verify an ECDSA signature. * Returns: 1: correct signature * 0: incorrect or unparseable signature * 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: pointer to an initialized public key to verify with (cannot be NULL) */ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify( const secp256k1_context_t* ctx, const unsigned char *msg32, - const unsigned char *sig, - int siglen, + const secp256k1_ecdsa_signature_t *sig, const secp256k1_pubkey_t *pubkey -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5); +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** A pointer to a function to deterministically generate a nonce. * Returns: 1 if a nonce was successfully generated. 0 will cause signing to fail. @@ -171,16 +248,15 @@ extern const secp256k1_nonce_function_t secp256k1_nonce_function_default; /** Create an ECDSA signature. * 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). + * 0: the nonce generation function failed, or the private key was invalid. * 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). + * + * The resulting signature will support pubkey recovery. * * The sig always has an s value in the lower half of the range (From 0x1 * to 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, @@ -211,50 +287,25 @@ extern const secp256k1_nonce_function_t secp256k1_nonce_function_default; int secp256k1_ecdsa_sign( const secp256k1_context_t* ctx, const unsigned char *msg32, - unsigned char *sig, - int *siglen, + secp256k1_ecdsa_signature_t *sig, 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(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: 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) - */ -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(4); -/** Recover an ECDSA public key from a compact signature. +/** Recover an ECDSA public key from a signature. * Returns: 1: public key successfully recovered (which guarantees a correct signature). * 0: otherwise. * 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) - * recid: the recovery id (0-3, as returned by ecdsa_sign_compact) + * sig64: pointer to initialized signature that supports pubkey recovery (cannot be NULL) * Out: pubkey: pointer to the recoved public key (cannot be NULL) */ -SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover_compact( +SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover( const secp256k1_context_t* ctx, const unsigned char *msg32, - const unsigned char *sig64, - secp256k1_pubkey_t *pubkey, - int recid + const secp256k1_ecdsa_signature_t *sig, + secp256k1_pubkey_t *pubkey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Verify an ECDSA secret key. diff --git a/src/bench_recover.c b/src/bench_recover.c index 700f154..1b198ec 100644 --- a/src/bench_recover.c +++ b/src/bench_recover.c @@ -23,7 +23,9 @@ void bench_recover(void* arg) { for (i = 0; i < 20000; i++) { int j; int pubkeylen = 33; - CHECK(secp256k1_ecdsa_recover_compact(data->ctx, data->msg, data->sig, &pubkey, i % 2)); + secp256k1_ecdsa_signature_t sig; + CHECK(secp256k1_ecdsa_signature_parse_compact(data->ctx, &sig, data->sig, i % 2)); + CHECK(secp256k1_ecdsa_recover(data->ctx, data->msg, &sig, &pubkey)); CHECK(secp256k1_ec_pubkey_serialize(data->ctx, pubkeyc, &pubkeylen, &pubkey, 1)); for (j = 0; j < 32; j++) { data->sig[j + 32] = data->msg[j]; /* Move former message to S. */ diff --git a/src/bench_sign.c b/src/bench_sign.c index 072a37a..e625da0 100644 --- a/src/bench_sign.c +++ b/src/bench_sign.c @@ -30,7 +30,9 @@ static void bench_sign(void* arg) { for (i = 0; i < 20000; i++) { int j; int recid = 0; - CHECK(secp256k1_ecdsa_sign_compact(data->ctx, data->msg, sig, data->key, NULL, NULL, &recid)); + secp256k1_ecdsa_signature_t signature; + CHECK(secp256k1_ecdsa_sign(data->ctx, data->msg, &signature, data->key, NULL, NULL)); + CHECK(secp256k1_ecdsa_signature_serialize_compact(data->ctx, sig, &recid, &signature)); 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. */ diff --git a/src/bench_verify.c b/src/bench_verify.c index 795847b..b8c5bdf 100644 --- a/src/bench_verify.c +++ b/src/bench_verify.c @@ -27,11 +27,13 @@ static void benchmark_verify(void* arg) { for (i = 0; i < 20000; i++) { secp256k1_pubkey_t pubkey; + secp256k1_ecdsa_signature_t sig; 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_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1); - CHECK(secp256k1_ecdsa_verify(data->ctx, data->msg, data->sig, data->siglen, &pubkey) == (i == 0)); + CHECK(secp256k1_ecdsa_signature_parse_der(data->ctx, &sig, data->sig, data->siglen) == 1); + CHECK(secp256k1_ecdsa_verify(data->ctx, data->msg, &sig, &pubkey) == (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); @@ -41,6 +43,7 @@ static void benchmark_verify(void* arg) { int main(void) { int i; secp256k1_pubkey_t pubkey; + secp256k1_ecdsa_signature_t sig; benchmark_verify_t data; data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); @@ -48,7 +51,8 @@ int main(void) { 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.ctx, data.msg, data.sig, &data.siglen, data.key, NULL, NULL); + CHECK(secp256k1_ecdsa_sign(data.ctx, data.msg, &sig, data.key, NULL, NULL)); + CHECK(secp256k1_ecdsa_signature_serialize_der(data.ctx, data.sig, &data.siglen, &sig)); CHECK(secp256k1_ec_pubkey_create(data.ctx, &pubkey, data.key)); CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, 1) == 1); diff --git a/src/ecdsa_impl.h b/src/ecdsa_impl.h index ed1d228..7278c93 100644 --- a/src/ecdsa_impl.h +++ b/src/ecdsa_impl.h @@ -118,6 +118,7 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const se while (lenR > 1 && rp[0] == 0 && rp[1] < 0x80) { lenR--; rp++; } while (lenS > 1 && sp[0] == 0 && sp[1] < 0x80) { lenS--; sp++; } if (*size < 6+lenS+lenR) { + *size = 6 + lenS + lenR; return 0; } *size = 6 + lenS + lenR; diff --git a/src/secp256k1.c b/src/secp256k1.c index f3ac831..61bc8b9 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -108,11 +108,105 @@ int secp256k1_ec_pubkey_serialize(const secp256k1_context_t* ctx, unsigned char return secp256k1_eckey_pubkey_serialize(&Q, output, outputlen, compressed); } -int secp256k1_ecdsa_verify(const secp256k1_context_t* ctx, const unsigned char *msg32, const unsigned char *sig, int siglen, const secp256k1_pubkey_t *pubkey) { +static void secp256k1_ecdsa_signature_load(secp256k1_ecdsa_sig_t* s, int* recid, const secp256k1_ecdsa_signature_t* sig) { + if (sizeof(secp256k1_scalar_t) == 32) { + /* When the secp256k1_scalar_t type is exactly 32 byte, use its + * representation inside secp256k1_ecdsa_signature_t, as conversion is very fast. + * Note that secp256k1_ecdsa_signature_save must use the same representation. */ + memcpy(&s->r, &sig->data[0], 32); + memcpy(&s->s, &sig->data[32], 32); + } else { + secp256k1_scalar_set_b32(&s->r, &sig->data[0], NULL); + secp256k1_scalar_set_b32(&s->s, &sig->data[32], NULL); + } + if (recid) { + *recid = sig->data[64]; + } +} + +static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature_t* sig, const secp256k1_ecdsa_sig_t* s, int recid) { + if (sizeof(secp256k1_scalar_t) == 32) { + memcpy(&sig->data[0], &s->r, 32); + memcpy(&sig->data[32], &s->s, 32); + } else { + secp256k1_scalar_get_b32(&sig->data[0], &s->r); + secp256k1_scalar_get_b32(&sig->data[32], &s->s); + } + sig->data[64] = recid; +} + +int secp256k1_ecdsa_signature_parse_der(const secp256k1_context_t* ctx, secp256k1_ecdsa_signature_t* sig, const unsigned char *input, int inputlen) { + secp256k1_ecdsa_sig_t s; + + (void)ctx; + DEBUG_CHECK(sig != NULL); + DEBUG_CHECK(input != NULL); + + if (secp256k1_ecdsa_sig_parse(&s, input, inputlen)) { + secp256k1_ecdsa_signature_save(sig, &s, -1); + return 1; + } else { + memset(sig, 0, sizeof(*sig)); + return 0; + } +} + +int secp256k1_ecdsa_signature_parse_compact(const secp256k1_context_t* ctx, secp256k1_ecdsa_signature_t* sig, const unsigned char *input64, int recid) { + secp256k1_ecdsa_sig_t s; + int ret = 1; + int overflow = 0; + + (void)ctx; + DEBUG_CHECK(sig != NULL); + DEBUG_CHECK(input64 != NULL); + + secp256k1_scalar_set_b32(&s.r, &input64[0], &overflow); + ret &= !overflow; + secp256k1_scalar_set_b32(&s.s, &input64[32], &overflow); + ret &= !overflow; + ret &= (recid == -1 || (recid >= 0 && recid < 4)); + if (ret) { + secp256k1_ecdsa_signature_save(sig, &s, recid); + } else { + memset(sig, 0, sizeof(*sig)); + } + return ret; +} + +int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context_t* ctx, unsigned char *output, int *outputlen, const secp256k1_ecdsa_signature_t* sig) { + secp256k1_ecdsa_sig_t s; + + (void)ctx; + DEBUG_CHECK(output != NULL); + DEBUG_CHECK(outputlen != NULL); + DEBUG_CHECK(sig != NULL); + + secp256k1_ecdsa_signature_load(&s, NULL, sig); + return secp256k1_ecdsa_sig_serialize(output, outputlen, &s); +} + +int secp256k1_ecdsa_signature_serialize_compact(const secp256k1_context_t* ctx, unsigned char *output64, int *recid, const secp256k1_ecdsa_signature_t* sig) { + secp256k1_ecdsa_sig_t s; + int rec; + + (void)ctx; + DEBUG_CHECK(output64 != NULL); + DEBUG_CHECK(sig != NULL); + + secp256k1_ecdsa_signature_load(&s, &rec, sig); + secp256k1_scalar_get_b32(&output64[0], &s.r); + secp256k1_scalar_get_b32(&output64[32], &s.s); + if (recid) { + DEBUG_CHECK(rec >= 0 && rec < 4); + *recid = rec; + } + return 1; +} + +int secp256k1_ecdsa_verify(const secp256k1_context_t* ctx, const unsigned char *msg32, const secp256k1_ecdsa_signature_t *sig, const secp256k1_pubkey_t *pubkey) { secp256k1_ge_t q; secp256k1_ecdsa_sig_t s; secp256k1_scalar_t m; - int ret = 0; DEBUG_CHECK(ctx != NULL); DEBUG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); DEBUG_CHECK(msg32 != NULL); @@ -120,16 +214,9 @@ int secp256k1_ecdsa_verify(const secp256k1_context_t* ctx, const unsigned char * DEBUG_CHECK(pubkey != NULL); secp256k1_scalar_set_b32(&m, msg32, NULL); - secp256k1_pubkey_load(&q, pubkey); - if (secp256k1_ecdsa_sig_parse(&s, sig, siglen)) { - if (secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &s, &q, &m)) { - /* success is 1, all other values are fail */ - ret = 1; - } - } - - return ret; + secp256k1_ecdsa_signature_load(&s, NULL, sig); + return secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &s, &q, &m); } static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int counter, const void *data) { @@ -157,9 +244,10 @@ 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 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) { +int secp256k1_ecdsa_sign(const secp256k1_context_t* ctx, const unsigned char *msg32, secp256k1_ecdsa_signature_t *signature, const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void* noncedata) { secp256k1_ecdsa_sig_t sig; secp256k1_scalar_t sec, non, msg; + int recid; int ret = 0; int overflow = 0; unsigned int count = 0; @@ -167,7 +255,6 @@ int secp256k1_ecdsa_sign(const secp256k1_context_t* ctx, const unsigned char *ms DEBUG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); DEBUG_CHECK(msg32 != NULL); DEBUG_CHECK(signature != NULL); - DEBUG_CHECK(signaturelen != NULL); DEBUG_CHECK(seckey != NULL); if (noncefp == NULL) { noncefp = secp256k1_nonce_function_default; @@ -186,101 +273,45 @@ int secp256k1_ecdsa_sign(const secp256k1_context_t* ctx, const unsigned char *ms secp256k1_scalar_set_b32(&non, nonce32, &overflow); memset(nonce32, 0, 32); if (!secp256k1_scalar_is_zero(&non) && !overflow) { - if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &sig, &sec, &msg, &non, NULL)) { + if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &sig, &sec, &msg, &non, &recid)) { break; } } count++; } - if (ret) { - ret = secp256k1_ecdsa_sig_serialize(signature, signaturelen, &sig); - } secp256k1_scalar_clear(&msg); secp256k1_scalar_clear(&non); secp256k1_scalar_clear(&sec); } - if (!ret) { - *signaturelen = 0; + if (ret) { + secp256k1_ecdsa_signature_save(signature, &sig, recid); + } else { + memset(signature, 0, sizeof(*signature)); } return ret; } -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(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); - if (noncefp == NULL) { - noncefp = secp256k1_nonce_function_default; - } - - secp256k1_scalar_set_b32(&sec, seckey, &overflow); - /* Fail if the secret key is invalid. */ - if (!overflow && !secp256k1_scalar_is_zero(&sec)) { - secp256k1_scalar_set_b32(&msg, msg32, NULL); - while (1) { - unsigned char nonce32[32]; - ret = noncefp(nonce32, msg32, seckey, count, noncedata); - if (!ret) { - break; - } - secp256k1_scalar_set_b32(&non, nonce32, &overflow); - memset(nonce32, 0, 32); - if (!secp256k1_scalar_is_zero(&non) && !overflow) { - if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &sig, &sec, &msg, &non, recid)) { - break; - } - } - count++; - } - if (ret) { - secp256k1_scalar_get_b32(sig64, &sig.r); - secp256k1_scalar_get_b32(sig64 + 32, &sig.s); - } - secp256k1_scalar_clear(&msg); - secp256k1_scalar_clear(&non); - secp256k1_scalar_clear(&sec); - } - if (!ret) { - memset(sig64, 0, 64); - } - return ret; -} - -int secp256k1_ecdsa_recover_compact(const secp256k1_context_t* ctx, const unsigned char *msg32, const unsigned char *sig64, secp256k1_pubkey_t *pubkey, int recid) { +int secp256k1_ecdsa_recover(const secp256k1_context_t* ctx, const unsigned char *msg32, const secp256k1_ecdsa_signature_t *signature, secp256k1_pubkey_t *pubkey) { secp256k1_ge_t q; secp256k1_ecdsa_sig_t sig; secp256k1_scalar_t m; - int ret = 0; - int overflow = 0; + int recid; DEBUG_CHECK(ctx != NULL); DEBUG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); DEBUG_CHECK(msg32 != NULL); - DEBUG_CHECK(sig64 != NULL); + DEBUG_CHECK(signature != NULL); DEBUG_CHECK(pubkey != NULL); - DEBUG_CHECK(recid >= 0 && recid <= 3); - secp256k1_scalar_set_b32(&sig.r, sig64, &overflow); - if (!overflow) { - secp256k1_scalar_set_b32(&sig.s, sig64 + 32, &overflow); - if (!overflow) { - secp256k1_scalar_set_b32(&m, msg32, NULL); - - ret = secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &sig, &q, &m, recid); - if (ret) { - secp256k1_pubkey_save(pubkey, &q); - } else { - memset(pubkey, 0, sizeof(*pubkey)); - } - } + secp256k1_ecdsa_signature_load(&sig, &recid, signature); + DEBUG_CHECK(recid >= 0 && recid < 4); + secp256k1_scalar_set_b32(&m, msg32, NULL); + if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &sig, &q, &m, recid)) { + secp256k1_pubkey_save(pubkey, &q); + return 1; + } else { + memset(pubkey, 0, sizeof(*pubkey)); + return 0; } - return ret; } int secp256k1_ec_seckey_verify(const secp256k1_context_t* ctx, const unsigned char *seckey) { diff --git a/src/tests.c b/src/tests.c index df9adec..0f53227 100644 --- a/src/tests.c +++ b/src/tests.c @@ -13,6 +13,7 @@ #include +#include "include/secp256k1.h" #include "secp256k1.c" #include "testrand_impl.h" @@ -1570,9 +1571,9 @@ static int nonce_function_test_retry(unsigned char *nonce32, const unsigned char return nonce_function_rfc6979(nonce32, msg32, key32, counter - 5, data); } -int is_empty_compact_signature(const unsigned char *sig64) { - static const unsigned char res[64] = {0}; - return memcmp(sig64, res, 64) == 0; +int is_empty_signature(const secp256k1_ecdsa_signature_t *sig) { + static const unsigned char res[sizeof(secp256k1_ecdsa_signature_t)] = {0}; + return memcmp(sig, res, sizeof(secp256k1_ecdsa_signature_t)) == 0; } void test_ecdsa_end_to_end(void) { @@ -1580,20 +1581,14 @@ void test_ecdsa_end_to_end(void) { unsigned char privkey[32]; unsigned char message[32]; unsigned char privkey2[32]; - unsigned char csignature[64]; - unsigned char signature[72]; - unsigned char signature2[72]; - unsigned char signature3[72]; - unsigned char signature4[72]; + secp256k1_ecdsa_signature_t signature[5]; + unsigned char sig[74]; + int siglen = 74; unsigned char pubkeyc[65]; int pubkeyclen = 65; secp256k1_pubkey_t pubkey; secp256k1_pubkey_t recpubkey; unsigned char seckey[300]; - int signaturelen = 72; - int signaturelen2 = 72; - int signaturelen3 = 72; - int signaturelen4 = 72; int recid = 0; int seckeylen = 300; @@ -1655,41 +1650,56 @@ void test_ecdsa_end_to_end(void) { } /* Sign. */ - CHECK(secp256k1_ecdsa_sign(ctx, message, signature, &signaturelen, privkey, NULL, NULL) == 1); - CHECK(signaturelen > 0); - CHECK(secp256k1_ecdsa_sign(ctx, message, signature2, &signaturelen2, privkey, NULL, extra) == 1); - CHECK(signaturelen2 > 0); + CHECK(secp256k1_ecdsa_sign(ctx, message, &signature[0], privkey, NULL, NULL) == 1); + CHECK(secp256k1_ecdsa_sign(ctx, message, &signature[4], privkey, NULL, NULL) == 1); + CHECK(secp256k1_ecdsa_sign(ctx, message, &signature[1], privkey, NULL, extra) == 1); extra[31] = 1; - CHECK(secp256k1_ecdsa_sign(ctx, message, signature3, &signaturelen3, privkey, NULL, extra) == 1); - CHECK(signaturelen3 > 0); + CHECK(secp256k1_ecdsa_sign(ctx, message, &signature[2], privkey, NULL, extra) == 1); extra[31] = 0; extra[0] = 1; - CHECK(secp256k1_ecdsa_sign(ctx, message, signature4, &signaturelen4, privkey, NULL, extra) == 1); - CHECK(signaturelen4 > 0); - CHECK((signaturelen != signaturelen2) || (memcmp(signature, signature2, signaturelen) != 0)); - CHECK((signaturelen != signaturelen3) || (memcmp(signature, signature3, signaturelen) != 0)); - CHECK((signaturelen3 != signaturelen2) || (memcmp(signature3, signature2, signaturelen3) != 0)); - CHECK((signaturelen4 != signaturelen3) || (memcmp(signature4, signature3, signaturelen4) != 0)); - CHECK((signaturelen4 != signaturelen2) || (memcmp(signature4, signature2, signaturelen4) != 0)); - CHECK((signaturelen4 != signaturelen) || (memcmp(signature4, signature, signaturelen4) != 0)); + CHECK(secp256k1_ecdsa_sign(ctx, message, &signature[3], privkey, NULL, extra) == 1); + CHECK(memcmp(&signature[0], &signature[4], sizeof(signature[0])) == 0); + CHECK(memcmp(&signature[0], &signature[1], sizeof(signature[0])) != 0); + CHECK(memcmp(&signature[0], &signature[2], sizeof(signature[0])) != 0); + CHECK(memcmp(&signature[0], &signature[3], sizeof(signature[0])) != 0); + CHECK(memcmp(&signature[1], &signature[2], sizeof(signature[0])) != 0); + CHECK(memcmp(&signature[1], &signature[3], sizeof(signature[0])) != 0); + CHECK(memcmp(&signature[2], &signature[3], sizeof(signature[0])) != 0); /* Verify. */ - CHECK(secp256k1_ecdsa_verify(ctx, message, signature, signaturelen, &pubkey) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, message, signature2, signaturelen2, &pubkey) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, message, signature3, signaturelen3, &pubkey) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, message, signature4, signaturelen4, &pubkey) == 1); - /* Destroy signature and verify again. */ - signature[signaturelen - 1 - secp256k1_rand32() % 20] += 1 + (secp256k1_rand32() % 255); - CHECK(secp256k1_ecdsa_verify(ctx, message, signature, signaturelen, &pubkey) != 1); + CHECK(secp256k1_ecdsa_verify(ctx, message, &signature[0], &pubkey) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, message, &signature[1], &pubkey) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, message, &signature[2], &pubkey) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, message, &signature[3], &pubkey) == 1); - /* Compact sign. */ - CHECK(secp256k1_ecdsa_sign_compact(ctx, message, csignature, privkey, NULL, NULL, &recid) == 1); - CHECK(!is_empty_compact_signature(csignature)); - /* Recover. */ - CHECK(secp256k1_ecdsa_recover_compact(ctx, message, csignature, &recpubkey, recid) == 1); + /* Serialize/parse DER and verify again */ + CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature[0]) == 1); + memset(&signature[0], 0, sizeof(signature[0])); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &signature[0], sig, siglen) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, message, &signature[0], &pubkey) == 1); + /* Serialize/destroy/parse DER and verify again. */ + CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature[0]) == 1); + sig[secp256k1_rand32() % siglen] += 1 + (secp256k1_rand32() % 255); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &signature[0], sig, siglen) == 0 || + secp256k1_ecdsa_verify(ctx, message, &signature[0], &pubkey) == 0); + + /* Serialize/parse compact (without recovery id) and verify again. */ + CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, sig, &recid, &signature[4]) == 1); + CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, sig, NULL, &signature[4]) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, message, &signature[4], &pubkey) == 1); + memset(&signature[4], 0, sizeof(signature[4])); + CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &signature[4], sig, -1) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, message, &signature[4], &pubkey) == 1); + /* Parse compact (with recovery id) and recover. */ + CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &signature[4], sig, recid) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, message, &signature[4], &recpubkey) == 1); CHECK(memcmp(&pubkey, &recpubkey, sizeof(pubkey)) == 0); - /* Destroy signature and verify again. */ - csignature[secp256k1_rand32() % 64] += 1 + (secp256k1_rand32() % 255); - CHECK(secp256k1_ecdsa_recover_compact(ctx, message, csignature, &recpubkey, recid) != 1 || + /* Serialize/destroy/parse signature and verify again. */ + CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, sig, &recid, &signature[4]) == 1); + sig[secp256k1_rand32() % 64] += 1 + (secp256k1_rand32() % 255); + CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &signature[4], sig, recid) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, message, &signature[4], &pubkey) == 0); + /* Recover again */ + CHECK(secp256k1_ecdsa_recover(ctx, message, &signature[4], &recpubkey) == 0 || memcmp(&pubkey, &recpubkey, sizeof(pubkey)) != 0); } @@ -1806,12 +1816,17 @@ void test_ecdsa_edge_cases(void) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, }; secp256k1_pubkey_t pubkeyb; + secp256k1_ecdsa_signature_t sig; int recid; - CHECK(!secp256k1_ecdsa_recover_compact(ctx, msg32, sig64, &pubkey, 0)); - CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sig64, &pubkey, 1)); - CHECK(!secp256k1_ecdsa_recover_compact(ctx, msg32, sig64, &pubkey, 2)); - CHECK(!secp256k1_ecdsa_recover_compact(ctx, msg32, sig64, &pubkey, 3)); + CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, sig64, 0)); + CHECK(!secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkey)); + CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, sig64, 1)); + CHECK(secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkey)); + CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, sig64, 2)); + CHECK(!secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkey)); + CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, sig64, 3)); + CHECK(!secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkey)); for (recid = 0; recid < 4; recid++) { int i; @@ -1856,33 +1871,41 @@ void test_ecdsa_edge_cases(void) { 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x45, 0x02, 0x01, 0x04 }; - CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigb64, &pubkeyb, recid)); - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, sizeof(sigbder), &pubkeyb) == 1); + CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, sigb64, recid) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkeyb) == 1); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, &sig, &pubkeyb) == 1); for (recid2 = 0; recid2 < 4; recid2++) { secp256k1_pubkey_t pubkey2b; - CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigb64, &pubkey2b, recid2)); + CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, sigb64, recid2) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkey2b) == 1); /* Verifying with (order + r,4) should always fail. */ - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderlong, sizeof(sigbderlong), &pubkey2b) != 1); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderlong, sizeof(sigbderlong)) == 0); } /* DER parsing tests. */ /* Zero length r/s. */ - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder_zr, sizeof(sigcder_zr), &pubkeyb) != 1); - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder_zs, sizeof(sigcder_zs), &pubkeyb) != 1); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder_zr, sizeof(sigcder_zr)) == 0); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder_zs, sizeof(sigcder_zs)) == 0); /* Leading zeros. */ - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt1, sizeof(sigbderalt1), &pubkeyb) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt2, sizeof(sigbderalt2), &pubkeyb) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt3, sizeof(sigbderalt3), &pubkeyb) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt4, sizeof(sigbderalt4), &pubkeyb) == 1); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt1, sizeof(sigbderalt1)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, &sig, &pubkeyb) == 1); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt2, sizeof(sigbderalt2)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, &sig, &pubkeyb) == 1); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt3, sizeof(sigbderalt3)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, &sig, &pubkeyb) == 1); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt4, sizeof(sigbderalt4)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, &sig, &pubkeyb) == 1); sigbderalt3[4] = 1; - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt3, sizeof(sigbderalt3), &pubkeyb) != 1); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt3, sizeof(sigbderalt3)) == 0); sigbderalt4[7] = 1; - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbderalt4, sizeof(sigbderalt4), &pubkeyb) != 1); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt4, sizeof(sigbderalt4)) == 0); /* Damage signature. */ sigbder[7]++; - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, sizeof(sigbder), &pubkeyb) == 0); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, &sig, &pubkeyb) == 0); sigbder[7]--; - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, 6, &pubkeyb) != 1); - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, sizeof(sigbder)-1, &pubkeyb) != 1); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, 6) == 0); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder) - 1) == 0); for(i = 0; i < 8; i++) { int c; unsigned char orig = sigbder[i]; @@ -1892,7 +1915,7 @@ void test_ecdsa_edge_cases(void) { continue; } sigbder[i] = c; - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigbder, sizeof(sigbder), &pubkeyb) != 1); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 0 || secp256k1_ecdsa_verify(ctx, msg32, &sig, &pubkeyb) == 0); } sigbder[i] = orig; } @@ -1903,15 +1926,15 @@ void test_ecdsa_edge_cases(void) { secp256k1_gej_t keyj; secp256k1_ge_t key; secp256k1_scalar_t msg; - secp256k1_ecdsa_sig_t sig; - secp256k1_scalar_set_int(&sig.s, 1); - secp256k1_scalar_negate(&sig.s, &sig.s); - secp256k1_scalar_inverse(&sig.s, &sig.s); - secp256k1_scalar_set_int(&sig.r, 1); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &keyj, &sig.r); + secp256k1_ecdsa_sig_t s; + secp256k1_scalar_set_int(&s.s, 1); + secp256k1_scalar_negate(&s.s, &s.s); + secp256k1_scalar_inverse(&s.s, &s.s); + secp256k1_scalar_set_int(&s.r, 1); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &keyj, &s.r); secp256k1_ge_set_gej(&key, &keyj); - msg = sig.s; - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sig, &key, &msg) == 0); + msg = s.s; + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &s, &key, &msg) == 0); } /* Test r/s equal to zero */ @@ -1929,22 +1952,30 @@ void test_ecdsa_edge_cases(void) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }; secp256k1_pubkey_t pubkeyc; - CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigc64, &pubkeyc, 0) == 1); - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder, sizeof(sigcder), &pubkeyc) == 1); + CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, sigc64, 0) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkeyc) == 1); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, &sig, &pubkeyc) == 1); sigcder[4] = 0; sigc64[31] = 0; - CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigc64, &pubkeyb, 0) == 0); - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder, sizeof(sigcder), &pubkeyc) == 0); + CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, sigc64, 0) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkeyb) == 0); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, &sig, &pubkeyc) == 0); sigcder[4] = 1; sigcder[7] = 0; sigc64[31] = 1; sigc64[63] = 0; - CHECK(secp256k1_ecdsa_recover_compact(ctx, msg32, sigc64, &pubkeyb, 0) == 0); - CHECK(secp256k1_ecdsa_verify(ctx, msg32, sigcder, sizeof(sigcder), &pubkeyc) == 0); + CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, sigc64, 0) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkeyb) == 0); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, msg32, &sig, &pubkeyc) == 0); } /*Signature where s would be zero.*/ { + unsigned char signature[72]; + int siglen; const unsigned char nonce[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -1969,21 +2000,15 @@ void test_ecdsa_edge_cases(void) { 0xb8, 0x12, 0xe0, 0x0b, 0x81, 0x7a, 0x77, 0x62, 0x65, 0xdf, 0xdd, 0x31, 0xb9, 0x3e, 0x29, 0xa9, }; - unsigned char sig[72]; - int siglen = 72; - CHECK(secp256k1_ecdsa_sign(ctx, msg, sig, &siglen, key, precomputed_nonce_function, nonce) == 0); - CHECK(siglen == 0); - CHECK(secp256k1_ecdsa_sign(ctx, msg, sig, &siglen, key, precomputed_nonce_function, nonce2) == 0); - CHECK(siglen == 0); + CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig, key, precomputed_nonce_function, nonce) == 0); + CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig, key, precomputed_nonce_function, nonce2) == 0); msg[31] = 0xaa; + CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig, key, precomputed_nonce_function, nonce) == 1); + CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig, key, precomputed_nonce_function, nonce2) == 1); siglen = 72; - CHECK(secp256k1_ecdsa_sign(ctx, msg, sig, &siglen, key, precomputed_nonce_function, nonce) == 1); - CHECK(siglen > 0); - CHECK(secp256k1_ecdsa_sign(ctx, msg, sig, &siglen, key, precomputed_nonce_function, nonce2) == 1); - CHECK(siglen > 0); + CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, &sig) == 1); siglen = 10; - CHECK(secp256k1_ecdsa_sign(ctx, msg, sig, &siglen, key, precomputed_nonce_function, nonce) != 1); - CHECK(siglen == 0); + CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, &sig) == 0); } /* Nonce function corner cases. */ @@ -1992,63 +2017,41 @@ void test_ecdsa_edge_cases(void) { int i; unsigned char key[32]; unsigned char msg[32]; - unsigned char sig[72]; - unsigned char sig2[72]; + secp256k1_ecdsa_signature_t sig2; secp256k1_ecdsa_sig_t s[512]; - int siglen = 72; - int siglen2 = 72; - int recid2; const unsigned char *extra; extra = t == 0 ? NULL : zero; memset(msg, 0, 32); msg[31] = 1; /* High key results in signature failure. */ memset(key, 0xFF, 32); - CHECK(secp256k1_ecdsa_sign(ctx, msg, sig, &siglen, key, NULL, extra) == 0); - CHECK(siglen == 0); + CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig, key, NULL, extra) == 0); + CHECK(is_empty_signature(&sig)); /* Zero key results in signature failure. */ memset(key, 0, 32); - CHECK(secp256k1_ecdsa_sign(ctx, msg, sig, &siglen, key, NULL, extra) == 0); - CHECK(siglen == 0); + CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig, key, NULL, extra) == 0); + CHECK(is_empty_signature(&sig)); /* Nonce function failure results in signature failure. */ key[31] = 1; - CHECK(secp256k1_ecdsa_sign(ctx, msg, sig, &siglen, key, nonce_function_test_fail, extra) == 0); - CHECK(siglen == 0); - CHECK(secp256k1_ecdsa_sign_compact(ctx, msg, sig, key, nonce_function_test_fail, extra, &recid) == 0); - CHECK(is_empty_compact_signature(sig)); + CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig, key, nonce_function_test_fail, extra) == 0); + CHECK(is_empty_signature(&sig)); /* The retry loop successfully makes its way to the first good value. */ - siglen = 72; - CHECK(secp256k1_ecdsa_sign(ctx, msg, sig, &siglen, key, nonce_function_test_retry, extra) == 1); - CHECK(siglen > 0); - CHECK(secp256k1_ecdsa_sign(ctx, msg, sig2, &siglen2, key, nonce_function_rfc6979, extra) == 1); - CHECK(siglen > 0); - CHECK((siglen == siglen2) && (memcmp(sig, sig2, siglen) == 0)); - CHECK(secp256k1_ecdsa_sign_compact(ctx, msg, sig, key, nonce_function_test_retry, extra, &recid) == 1); - CHECK(!is_empty_compact_signature(sig)); - CHECK(secp256k1_ecdsa_sign_compact(ctx, msg, sig2, key, nonce_function_rfc6979, extra, &recid2) == 1); - CHECK(!is_empty_compact_signature(sig2)); - CHECK((recid == recid2) && (memcmp(sig, sig2, 64) == 0)); + CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig, key, nonce_function_test_retry, extra) == 1); + CHECK(!is_empty_signature(&sig)); + CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig2, key, nonce_function_rfc6979, extra) == 1); + CHECK(!is_empty_signature(&sig2)); + CHECK(memcmp(&sig, &sig2, sizeof(sig)) == 0); /* The default nonce function is determinstic. */ - siglen = 72; - siglen2 = 72; - CHECK(secp256k1_ecdsa_sign(ctx, msg, sig, &siglen, key, NULL, extra) == 1); - CHECK(siglen > 0); - CHECK(secp256k1_ecdsa_sign(ctx, msg, sig2, &siglen2, key, NULL, extra) == 1); - CHECK(siglen2 > 0); - CHECK((siglen == siglen2) && (memcmp(sig, sig2, siglen) == 0)); - CHECK(secp256k1_ecdsa_sign_compact(ctx, msg, sig, key, NULL, extra, &recid) == 1); - CHECK(!is_empty_compact_signature(sig)); - CHECK(secp256k1_ecdsa_sign_compact(ctx, msg, sig2, key, NULL, extra, &recid2) == 1); - CHECK(!is_empty_compact_signature(sig)); - CHECK((recid == recid2) && (memcmp(sig, sig2, 64) == 0)); + CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig2, key, NULL, extra) == 1); + CHECK(!is_empty_signature(&sig2)); + CHECK(memcmp(&sig, &sig2, sizeof(sig)) == 0); /* The default nonce function changes output with different messages. */ for(i = 0; i < 256; i++) { int j; - siglen2 = 72; msg[0] = i; - CHECK(secp256k1_ecdsa_sign(ctx, msg, sig2, &siglen2, key, NULL, extra) == 1); - CHECK(!is_empty_compact_signature(sig)); - CHECK(secp256k1_ecdsa_sig_parse(&s[i], sig2, siglen2)); + CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig2, key, NULL, extra) == 1); + CHECK(!is_empty_signature(&sig2)); + secp256k1_ecdsa_signature_load(&s[i], NULL, &sig2); for (j = 0; j < i; j++) { CHECK(!secp256k1_scalar_eq(&s[i].r, &s[j].r)); } @@ -2058,10 +2061,10 @@ void test_ecdsa_edge_cases(void) { /* The default nonce function changes output with different keys. */ for(i = 256; i < 512; i++) { int j; - siglen2 = 72; key[0] = i - 256; - CHECK(secp256k1_ecdsa_sign(ctx, msg, sig2, &siglen2, key, NULL, extra) == 1); - CHECK(secp256k1_ecdsa_sig_parse(&s[i], sig2, siglen2)); + CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig2, key, NULL, extra) == 1); + CHECK(!is_empty_signature(&sig2)); + secp256k1_ecdsa_signature_load(&s[i], NULL, &sig2); for (j = 0; j < i; j++) { CHECK(!secp256k1_scalar_eq(&s[i].r, &s[j].r)); } From 18c329c5067f96dac4ee127ae51a9742e8e26c91 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 26 Jul 2015 16:51:58 +0200 Subject: [PATCH 3/3] Remove the internal secp256k1_ecdsa_sig_t type --- src/ecdsa.h | 14 ++++------ src/ecdsa_impl.h | 50 ++++++++++++++++++------------------ src/secp256k1.c | 66 ++++++++++++++++++++++++------------------------ src/tests.c | 62 ++++++++++++++++++++++----------------------- 4 files changed, 94 insertions(+), 98 deletions(-) diff --git a/src/ecdsa.h b/src/ecdsa.h index 4ef78e8..c361728 100644 --- a/src/ecdsa.h +++ b/src/ecdsa.h @@ -11,14 +11,10 @@ #include "group.h" #include "ecmult.h" -typedef struct { - secp256k1_scalar_t r, s; -} secp256k1_ecdsa_sig_t; - -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_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); +static int secp256k1_ecdsa_sig_parse(secp256k1_scalar_t *r, secp256k1_scalar_t *s, const unsigned char *sig, int size); +static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_scalar_t *r, const secp256k1_scalar_t *s); +static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context_t *ctx, const secp256k1_scalar_t* r, const secp256k1_scalar_t* s, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message); +static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context_t *ctx, secp256k1_scalar_t* r, secp256k1_scalar_t* s, 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_scalar_t* r, const secp256k1_scalar_t* s, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid); #endif diff --git a/src/ecdsa_impl.h b/src/ecdsa_impl.h index 7278c93..c0c44fa 100644 --- a/src/ecdsa_impl.h +++ b/src/ecdsa_impl.h @@ -46,7 +46,7 @@ static const secp256k1_fe_t secp256k1_ecdsa_const_p_minus_order = SECP256K1_FE_C 0, 0, 0, 1, 0x45512319UL, 0x50B75FC4UL, 0x402DA172UL, 0x2FC9BAEEUL ); -static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size) { +static int secp256k1_ecdsa_sig_parse(secp256k1_scalar_t *rr, secp256k1_scalar_t *rs, const unsigned char *sig, int size) { unsigned char ra[32] = {0}, sa[32] = {0}; const unsigned char *rp; const unsigned char *sp; @@ -98,23 +98,23 @@ static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned ch memcpy(ra + 32 - lenr, rp, lenr); memcpy(sa + 32 - lens, sp, lens); overflow = 0; - secp256k1_scalar_set_b32(&r->r, ra, &overflow); + secp256k1_scalar_set_b32(rr, ra, &overflow); if (overflow) { return 0; } - secp256k1_scalar_set_b32(&r->s, sa, &overflow); + secp256k1_scalar_set_b32(rs, sa, &overflow); if (overflow) { return 0; } return 1; } -static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a) { +static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_scalar_t* ar, const secp256k1_scalar_t* as) { unsigned char r[33] = {0}, s[33] = {0}; unsigned char *rp = r, *sp = s; int lenR = 33, lenS = 33; - secp256k1_scalar_get_b32(&r[1], &a->r); - secp256k1_scalar_get_b32(&s[1], &a->s); + secp256k1_scalar_get_b32(&r[1], ar); + secp256k1_scalar_get_b32(&s[1], as); while (lenR > 1 && rp[0] == 0 && rp[1] < 0x80) { lenR--; rp++; } while (lenS > 1 && sp[0] == 0 && sp[1] < 0x80) { lenS--; sp++; } if (*size < 6+lenS+lenR) { @@ -133,26 +133,26 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const se return 1; } -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_verify(const secp256k1_ecmult_context_t *ctx, const secp256k1_scalar_t *sigr, const secp256k1_scalar_t *sigs, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message) { unsigned char c[32]; secp256k1_scalar_t sn, u1, u2; secp256k1_fe_t xr; secp256k1_gej_t pubkeyj; secp256k1_gej_t pr; - if (secp256k1_scalar_is_zero(&sig->r) || secp256k1_scalar_is_zero(&sig->s)) { + if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) { return 0; } - secp256k1_scalar_inverse_var(&sn, &sig->s); + secp256k1_scalar_inverse_var(&sn, sigs); secp256k1_scalar_mul(&u1, &sn, message); - secp256k1_scalar_mul(&u2, &sn, &sig->r); + secp256k1_scalar_mul(&u2, &sn, sigr); secp256k1_gej_set_ge(&pubkeyj, pubkey); secp256k1_ecmult(ctx, &pr, &pubkeyj, &u2, &u1); if (secp256k1_gej_is_infinity(&pr)) { return 0; } - secp256k1_scalar_get_b32(c, &sig->r); + secp256k1_scalar_get_b32(c, sigr); secp256k1_fe_set_b32(&xr, c); /** We now have the recomputed R point in pr, and its claimed x coordinate (modulo n) @@ -187,7 +187,7 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context_t *ctx, con return 0; } -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) { +static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context_t *ctx, const secp256k1_scalar_t *sigr, const secp256k1_scalar_t* sigs, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid) { unsigned char brx[32]; secp256k1_fe_t fx; secp256k1_ge_t x; @@ -195,11 +195,11 @@ static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context_t *ctx, co secp256k1_scalar_t rn, u1, u2; secp256k1_gej_t qj; - if (secp256k1_scalar_is_zero(&sig->r) || secp256k1_scalar_is_zero(&sig->s)) { + if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) { return 0; } - secp256k1_scalar_get_b32(brx, &sig->r); + secp256k1_scalar_get_b32(brx, sigr); VERIFY_CHECK(secp256k1_fe_set_b32(&fx, brx)); /* brx comes from a scalar, so is less than the order; certainly less than p */ if (recid & 2) { if (secp256k1_fe_cmp_var(&fx, &secp256k1_ecdsa_const_p_minus_order) >= 0) { @@ -211,16 +211,16 @@ static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context_t *ctx, co return 0; } secp256k1_gej_set_ge(&xj, &x); - secp256k1_scalar_inverse_var(&rn, &sig->r); + secp256k1_scalar_inverse_var(&rn, sigr); secp256k1_scalar_mul(&u1, &rn, message); secp256k1_scalar_negate(&u1, &u1); - secp256k1_scalar_mul(&u2, &rn, &sig->s); + secp256k1_scalar_mul(&u2, &rn, sigs); 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(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_sign(const secp256k1_ecmult_gen_context_t *ctx, secp256k1_scalar_t *sigr, secp256k1_scalar_t *sigs, 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; @@ -232,8 +232,8 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context_t *ctx, s secp256k1_fe_normalize(&r.x); secp256k1_fe_normalize(&r.y); secp256k1_fe_get_b32(b, &r.x); - secp256k1_scalar_set_b32(&sig->r, b, &overflow); - if (secp256k1_scalar_is_zero(&sig->r)) { + secp256k1_scalar_set_b32(sigr, b, &overflow); + if (secp256k1_scalar_is_zero(sigr)) { /* P.x = order is on the curve, so technically sig->r could end up zero, which would be an invalid signature. */ secp256k1_gej_clear(&rp); secp256k1_ge_clear(&r); @@ -242,18 +242,18 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context_t *ctx, s if (recid) { *recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0); } - secp256k1_scalar_mul(&n, &sig->r, seckey); + secp256k1_scalar_mul(&n, sigr, seckey); secp256k1_scalar_add(&n, &n, message); - secp256k1_scalar_inverse(&sig->s, nonce); - secp256k1_scalar_mul(&sig->s, &sig->s, &n); + secp256k1_scalar_inverse(sigs, nonce); + secp256k1_scalar_mul(sigs, sigs, &n); secp256k1_scalar_clear(&n); secp256k1_gej_clear(&rp); secp256k1_ge_clear(&r); - if (secp256k1_scalar_is_zero(&sig->s)) { + if (secp256k1_scalar_is_zero(sigs)) { return 0; } - if (secp256k1_scalar_is_high(&sig->s)) { - secp256k1_scalar_negate(&sig->s, &sig->s); + if (secp256k1_scalar_is_high(sigs)) { + secp256k1_scalar_negate(sigs, sigs); if (recid) { *recid ^= 1; } diff --git a/src/secp256k1.c b/src/secp256k1.c index 61bc8b9..7247c0f 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -108,42 +108,42 @@ int secp256k1_ec_pubkey_serialize(const secp256k1_context_t* ctx, unsigned char return secp256k1_eckey_pubkey_serialize(&Q, output, outputlen, compressed); } -static void secp256k1_ecdsa_signature_load(secp256k1_ecdsa_sig_t* s, int* recid, const secp256k1_ecdsa_signature_t* sig) { +static void secp256k1_ecdsa_signature_load(secp256k1_scalar_t* r, secp256k1_scalar_t* s, int* recid, const secp256k1_ecdsa_signature_t* sig) { if (sizeof(secp256k1_scalar_t) == 32) { /* When the secp256k1_scalar_t type is exactly 32 byte, use its * representation inside secp256k1_ecdsa_signature_t, as conversion is very fast. * Note that secp256k1_ecdsa_signature_save must use the same representation. */ - memcpy(&s->r, &sig->data[0], 32); - memcpy(&s->s, &sig->data[32], 32); + memcpy(r, &sig->data[0], 32); + memcpy(s, &sig->data[32], 32); } else { - secp256k1_scalar_set_b32(&s->r, &sig->data[0], NULL); - secp256k1_scalar_set_b32(&s->s, &sig->data[32], NULL); + secp256k1_scalar_set_b32(r, &sig->data[0], NULL); + secp256k1_scalar_set_b32(s, &sig->data[32], NULL); } if (recid) { *recid = sig->data[64]; } } -static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature_t* sig, const secp256k1_ecdsa_sig_t* s, int recid) { +static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature_t* sig, const secp256k1_scalar_t* r, const secp256k1_scalar_t* s, int recid) { if (sizeof(secp256k1_scalar_t) == 32) { - memcpy(&sig->data[0], &s->r, 32); - memcpy(&sig->data[32], &s->s, 32); + memcpy(&sig->data[0], r, 32); + memcpy(&sig->data[32], s, 32); } else { - secp256k1_scalar_get_b32(&sig->data[0], &s->r); - secp256k1_scalar_get_b32(&sig->data[32], &s->s); + secp256k1_scalar_get_b32(&sig->data[0], r); + secp256k1_scalar_get_b32(&sig->data[32], s); } sig->data[64] = recid; } int secp256k1_ecdsa_signature_parse_der(const secp256k1_context_t* ctx, secp256k1_ecdsa_signature_t* sig, const unsigned char *input, int inputlen) { - secp256k1_ecdsa_sig_t s; + secp256k1_scalar_t r, s; (void)ctx; DEBUG_CHECK(sig != NULL); DEBUG_CHECK(input != NULL); - if (secp256k1_ecdsa_sig_parse(&s, input, inputlen)) { - secp256k1_ecdsa_signature_save(sig, &s, -1); + if (secp256k1_ecdsa_sig_parse(&r, &s, input, inputlen)) { + secp256k1_ecdsa_signature_save(sig, &r, &s, -1); return 1; } else { memset(sig, 0, sizeof(*sig)); @@ -152,7 +152,7 @@ int secp256k1_ecdsa_signature_parse_der(const secp256k1_context_t* ctx, secp256k } int secp256k1_ecdsa_signature_parse_compact(const secp256k1_context_t* ctx, secp256k1_ecdsa_signature_t* sig, const unsigned char *input64, int recid) { - secp256k1_ecdsa_sig_t s; + secp256k1_scalar_t r, s; int ret = 1; int overflow = 0; @@ -160,13 +160,13 @@ int secp256k1_ecdsa_signature_parse_compact(const secp256k1_context_t* ctx, secp DEBUG_CHECK(sig != NULL); DEBUG_CHECK(input64 != NULL); - secp256k1_scalar_set_b32(&s.r, &input64[0], &overflow); + secp256k1_scalar_set_b32(&r, &input64[0], &overflow); ret &= !overflow; - secp256k1_scalar_set_b32(&s.s, &input64[32], &overflow); + secp256k1_scalar_set_b32(&s, &input64[32], &overflow); ret &= !overflow; ret &= (recid == -1 || (recid >= 0 && recid < 4)); if (ret) { - secp256k1_ecdsa_signature_save(sig, &s, recid); + secp256k1_ecdsa_signature_save(sig, &r, &s, recid); } else { memset(sig, 0, sizeof(*sig)); } @@ -174,28 +174,28 @@ int secp256k1_ecdsa_signature_parse_compact(const secp256k1_context_t* ctx, secp } int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context_t* ctx, unsigned char *output, int *outputlen, const secp256k1_ecdsa_signature_t* sig) { - secp256k1_ecdsa_sig_t s; + secp256k1_scalar_t r, s; (void)ctx; DEBUG_CHECK(output != NULL); DEBUG_CHECK(outputlen != NULL); DEBUG_CHECK(sig != NULL); - secp256k1_ecdsa_signature_load(&s, NULL, sig); - return secp256k1_ecdsa_sig_serialize(output, outputlen, &s); + secp256k1_ecdsa_signature_load(&r, &s, NULL, sig); + return secp256k1_ecdsa_sig_serialize(output, outputlen, &r, &s); } int secp256k1_ecdsa_signature_serialize_compact(const secp256k1_context_t* ctx, unsigned char *output64, int *recid, const secp256k1_ecdsa_signature_t* sig) { - secp256k1_ecdsa_sig_t s; + secp256k1_scalar_t r, s; int rec; (void)ctx; DEBUG_CHECK(output64 != NULL); DEBUG_CHECK(sig != NULL); - secp256k1_ecdsa_signature_load(&s, &rec, sig); - secp256k1_scalar_get_b32(&output64[0], &s.r); - secp256k1_scalar_get_b32(&output64[32], &s.s); + secp256k1_ecdsa_signature_load(&r, &s, &rec, sig); + secp256k1_scalar_get_b32(&output64[0], &r); + secp256k1_scalar_get_b32(&output64[32], &s); if (recid) { DEBUG_CHECK(rec >= 0 && rec < 4); *recid = rec; @@ -205,7 +205,7 @@ int secp256k1_ecdsa_signature_serialize_compact(const secp256k1_context_t* ctx, int secp256k1_ecdsa_verify(const secp256k1_context_t* ctx, const unsigned char *msg32, const secp256k1_ecdsa_signature_t *sig, const secp256k1_pubkey_t *pubkey) { secp256k1_ge_t q; - secp256k1_ecdsa_sig_t s; + secp256k1_scalar_t r, s; secp256k1_scalar_t m; DEBUG_CHECK(ctx != NULL); DEBUG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); @@ -215,8 +215,8 @@ int secp256k1_ecdsa_verify(const secp256k1_context_t* ctx, const unsigned char * secp256k1_scalar_set_b32(&m, msg32, NULL); secp256k1_pubkey_load(&q, pubkey); - secp256k1_ecdsa_signature_load(&s, NULL, sig); - return secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &s, &q, &m); + secp256k1_ecdsa_signature_load(&r, &s, NULL, sig); + return secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m); } static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int counter, const void *data) { @@ -245,7 +245,7 @@ const secp256k1_nonce_function_t secp256k1_nonce_function_rfc6979 = nonce_functi const secp256k1_nonce_function_t secp256k1_nonce_function_default = nonce_function_rfc6979; int secp256k1_ecdsa_sign(const secp256k1_context_t* ctx, const unsigned char *msg32, secp256k1_ecdsa_signature_t *signature, const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void* noncedata) { - secp256k1_ecdsa_sig_t sig; + secp256k1_scalar_t r, s; secp256k1_scalar_t sec, non, msg; int recid; int ret = 0; @@ -273,7 +273,7 @@ int secp256k1_ecdsa_sign(const secp256k1_context_t* ctx, const unsigned char *ms secp256k1_scalar_set_b32(&non, nonce32, &overflow); memset(nonce32, 0, 32); if (!secp256k1_scalar_is_zero(&non) && !overflow) { - if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &sig, &sec, &msg, &non, &recid)) { + if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, &recid)) { break; } } @@ -284,7 +284,7 @@ int secp256k1_ecdsa_sign(const secp256k1_context_t* ctx, const unsigned char *ms secp256k1_scalar_clear(&sec); } if (ret) { - secp256k1_ecdsa_signature_save(signature, &sig, recid); + secp256k1_ecdsa_signature_save(signature, &r, &s, recid); } else { memset(signature, 0, sizeof(*signature)); } @@ -293,7 +293,7 @@ int secp256k1_ecdsa_sign(const secp256k1_context_t* ctx, const unsigned char *ms int secp256k1_ecdsa_recover(const secp256k1_context_t* ctx, const unsigned char *msg32, const secp256k1_ecdsa_signature_t *signature, secp256k1_pubkey_t *pubkey) { secp256k1_ge_t q; - secp256k1_ecdsa_sig_t sig; + secp256k1_scalar_t r, s; secp256k1_scalar_t m; int recid; DEBUG_CHECK(ctx != NULL); @@ -302,10 +302,10 @@ int secp256k1_ecdsa_recover(const secp256k1_context_t* ctx, const unsigned char DEBUG_CHECK(signature != NULL); DEBUG_CHECK(pubkey != NULL); - secp256k1_ecdsa_signature_load(&sig, &recid, signature); + secp256k1_ecdsa_signature_load(&r, &s, &recid, signature); DEBUG_CHECK(recid >= 0 && recid < 4); secp256k1_scalar_set_b32(&m, msg32, NULL); - if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &sig, &q, &m, recid)) { + if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &r, &s, &q, &m, recid)) { secp256k1_pubkey_save(pubkey, &q); return 1; } else { diff --git a/src/tests.c b/src/tests.c index 0f53227..6fa7bf8 100644 --- a/src/tests.c +++ b/src/tests.c @@ -111,7 +111,7 @@ void run_context_tests(void) { secp256k1_gej_t pubj; secp256k1_ge_t pub; secp256k1_scalar_t msg, key, nonce; - secp256k1_ecdsa_sig_t sig; + secp256k1_scalar_t sigr, sigs; /*** clone and destroy all of them to make sure cloning was complete ***/ { @@ -132,15 +132,15 @@ void run_context_tests(void) { /* obtain a working nonce */ do { random_scalar_order_test(&nonce); - } while(!secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sig, &key, &msg, &nonce, NULL)); + } while(!secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); /* try signing */ - CHECK(secp256k1_ecdsa_sig_sign(&sign->ecmult_gen_ctx, &sig, &key, &msg, &nonce, NULL)); - CHECK(secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sig, &key, &msg, &nonce, NULL)); + CHECK(secp256k1_ecdsa_sig_sign(&sign->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); + CHECK(secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); /* try verifying */ - CHECK(secp256k1_ecdsa_sig_verify(&vrfy->ecmult_ctx, &sig, &pub, &msg)); - CHECK(secp256k1_ecdsa_sig_verify(&both->ecmult_ctx, &sig, &pub, &msg)); + CHECK(secp256k1_ecdsa_sig_verify(&vrfy->ecmult_ctx, &sigr, &sigs, &pub, &msg)); + CHECK(secp256k1_ecdsa_sig_verify(&both->ecmult_ctx, &sigr, &sigs, &pub, &msg)); /* cleanup */ secp256k1_context_destroy(none); @@ -1488,11 +1488,11 @@ void run_ecmult_gen_blind(void) { } -void random_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *key, const secp256k1_scalar_t *msg, int *recid) { +void random_sign(secp256k1_scalar_t *sigr, secp256k1_scalar_t *sigs, const secp256k1_scalar_t *key, const secp256k1_scalar_t *msg, int *recid) { secp256k1_scalar_t nonce; do { random_scalar_order_test(&nonce); - } while(!secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, sig, key, msg, &nonce, recid)); + } while(!secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, sigr, sigs, key, msg, &nonce, recid)); } void test_ecdsa_sign_verify(void) { @@ -1500,7 +1500,7 @@ void test_ecdsa_sign_verify(void) { secp256k1_ge_t pub; secp256k1_scalar_t one; secp256k1_scalar_t msg, key; - secp256k1_ecdsa_sig_t sig; + secp256k1_scalar_t sigr, sigs; int recid; int getrec; random_scalar_order_test(&msg); @@ -1508,14 +1508,14 @@ void test_ecdsa_sign_verify(void) { 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); + random_sign(&sigr, &sigs, &key, &msg, getrec?&recid:NULL); if (getrec) { CHECK(recid >= 0 && recid < 4); } - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sig, &pub, &msg)); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg)); secp256k1_scalar_set_int(&one, 1); secp256k1_scalar_add(&msg, &msg, &one); - CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sig, &pub, &msg)); + CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg)); } void run_ecdsa_sign_verify(void) { @@ -1926,15 +1926,15 @@ void test_ecdsa_edge_cases(void) { secp256k1_gej_t keyj; secp256k1_ge_t key; secp256k1_scalar_t msg; - secp256k1_ecdsa_sig_t s; - secp256k1_scalar_set_int(&s.s, 1); - secp256k1_scalar_negate(&s.s, &s.s); - secp256k1_scalar_inverse(&s.s, &s.s); - secp256k1_scalar_set_int(&s.r, 1); - secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &keyj, &s.r); + secp256k1_scalar_t sr, ss; + secp256k1_scalar_set_int(&ss, 1); + secp256k1_scalar_negate(&ss, &ss); + secp256k1_scalar_inverse(&ss, &ss); + secp256k1_scalar_set_int(&sr, 1); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &keyj, &sr); secp256k1_ge_set_gej(&key, &keyj); - msg = s.s; - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &s, &key, &msg) == 0); + msg = ss; + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); } /* Test r/s equal to zero */ @@ -2018,7 +2018,7 @@ void test_ecdsa_edge_cases(void) { unsigned char key[32]; unsigned char msg[32]; secp256k1_ecdsa_signature_t sig2; - secp256k1_ecdsa_sig_t s[512]; + secp256k1_scalar_t sr[512], ss; const unsigned char *extra; extra = t == 0 ? NULL : zero; memset(msg, 0, 32); @@ -2051,9 +2051,9 @@ void test_ecdsa_edge_cases(void) { msg[0] = i; CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig2, key, NULL, extra) == 1); CHECK(!is_empty_signature(&sig2)); - secp256k1_ecdsa_signature_load(&s[i], NULL, &sig2); + secp256k1_ecdsa_signature_load(&sr[i], &ss, NULL, &sig2); for (j = 0; j < i; j++) { - CHECK(!secp256k1_scalar_eq(&s[i].r, &s[j].r)); + CHECK(!secp256k1_scalar_eq(&sr[i], &sr[j])); } } msg[0] = 0; @@ -2064,9 +2064,9 @@ void test_ecdsa_edge_cases(void) { key[0] = i - 256; CHECK(secp256k1_ecdsa_sign(ctx, msg, &sig2, key, NULL, extra) == 1); CHECK(!is_empty_signature(&sig2)); - secp256k1_ecdsa_signature_load(&s[i], NULL, &sig2); + secp256k1_ecdsa_signature_load(&sr[i], &ss, NULL, &sig2); for (j = 0; j < i; j++) { - CHECK(!secp256k1_scalar_eq(&s[i].r, &s[j].r)); + CHECK(!secp256k1_scalar_eq(&sr[i], &sr[j])); } } key[0] = 0; @@ -2107,7 +2107,7 @@ EC_KEY *get_openssl_key(const secp256k1_scalar_t *key) { void test_ecdsa_openssl(void) { secp256k1_gej_t qj; secp256k1_ge_t q; - secp256k1_ecdsa_sig_t sig; + secp256k1_scalar_t sigr, sigs; secp256k1_scalar_t one; secp256k1_scalar_t msg2; secp256k1_scalar_t key, msg; @@ -2124,14 +2124,14 @@ void test_ecdsa_openssl(void) { ec_key = get_openssl_key(&key); CHECK(ec_key); CHECK(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key)); - CHECK(secp256k1_ecdsa_sig_parse(&sig, signature, sigsize)); - CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sig, &q, &msg)); + CHECK(secp256k1_ecdsa_sig_parse(&sigr, &sigs, signature, sigsize)); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &q, &msg)); secp256k1_scalar_set_int(&one, 1); secp256k1_scalar_add(&msg2, &msg, &one); - CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sig, &q, &msg2)); + CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &q, &msg2)); - random_sign(&sig, &key, &msg, NULL); - CHECK(secp256k1_ecdsa_sig_serialize(signature, &secp_sigsize, &sig)); + random_sign(&sigr, &sigs, &key, &msg, NULL); + CHECK(secp256k1_ecdsa_sig_serialize(signature, &secp_sigsize, &sigr, &sigs)); CHECK(ECDSA_verify(0, message, sizeof(message), signature, secp_sigsize, ec_key) == 1); EC_KEY_free(ec_key);