diff --git a/include/secp256k1.h b/include/secp256k1.h index 4fbd15f84f..266f55d463 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -40,7 +40,23 @@ typedef struct { unsigned char data[64]; } secp256k1_pubkey_t; -/** Opaque data structured that holds a parsed ECDSA signature, optionally +/** Opaque data structured that holds a parsed ECDSA signature. + * + * The exact representation of data inside is implementation defined and not + * guaranteed to be portable between different platforms or versions. It is + * however guaranteed to be 64 bytes in size, and can be safely copied/moved. + * If you need to convert to a format suitable for storage or transmission, use + * the secp256k1_ecdsa_signature_serialize_* and + * secp256k1_ecdsa_signature_serialize_* functions. + * + * Furthermore, it is guaranteed to identical signatures will have identical + * representation, so they can be memcmp'ed. + */ +typedef struct { + unsigned char data[64]; +} secp256k1_ecdsa_signature_t; + +/** Opaque data structured that holds a parsed ECDSA signature, * supporting pubkey recovery. * * The exact representation of data inside is implementation defined and not @@ -56,7 +72,7 @@ typedef struct { */ typedef struct { unsigned char data[65]; -} secp256k1_ecdsa_signature_t; +} secp256k1_ecdsa_recoverable_signature_t; /** A pointer to a function to deterministically generate a nonce. * @@ -246,8 +262,6 @@ int secp256k1_ec_pubkey_serialize( * Out: sig: a pointer to a signature object * * Note that this function also supports some violations of DER and even BER. - * - * The resulting signature object will not support pubkey recovery. */ int secp256k1_ecdsa_signature_parse_der( const secp256k1_context_t* ctx, @@ -261,19 +275,28 @@ int secp256k1_ecdsa_signature_parse_der( * 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) + * recid: the recovery id (0, 1, 2 or 3) * 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( +int secp256k1_ecdsa_recoverable_signature_parse_compact( const secp256k1_context_t* ctx, - secp256k1_ecdsa_signature_t* sig, + secp256k1_ecdsa_recoverable_signature_t* sig, const unsigned char *input64, int recid ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); +/** Convert a recoverable signature into a normal signature. + * + * Returns: 1 + * In: sigin: a pointer to a recoverable signature (cannot be NULL). + * Out: sig: a pointer to a normal signature (cannot be NULL). + */ +int secp256k1_ecdsa_recoverable_signature_convert( + const secp256k1_context_t* ctx, + secp256k1_ecdsa_signature_t* sig, + const secp256k1_ecdsa_recoverable_signature_t* sigin +) 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 @@ -299,14 +322,12 @@ int secp256k1_ecdsa_signature_serialize_der( * 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( +int secp256k1_ecdsa_recoverable_signature_serialize_compact( const secp256k1_context_t* ctx, unsigned char *output64, int *recid, - const secp256k1_ecdsa_signature_t* sig + const secp256k1_ecdsa_recoverable_signature_t* sig ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4); /** Verify an ECDSA signature. @@ -383,6 +404,26 @@ int secp256k1_ecdsa_sign( const void *ndata ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); +/** Create a recoverable ECDSA signature. + * + * Returns: 1: signature created + * 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) + */ +int secp256k1_ecdsa_sign_recoverable( + const secp256k1_context_t* ctx, + const unsigned char *msg32, + secp256k1_ecdsa_recoverable_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); + /** Recover an ECDSA public key from a signature. * * Returns: 1: public key successfully recovered (which guarantees a correct signature). @@ -395,7 +436,7 @@ int secp256k1_ecdsa_sign( SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover( const secp256k1_context_t* ctx, const unsigned char *msg32, - const secp256k1_ecdsa_signature_t *sig, + const secp256k1_ecdsa_recoverable_signature_t *sig, secp256k1_pubkey_t *pubkey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); diff --git a/src/bench_recover.c b/src/bench_recover.c index 1b198ec346..c123b62d39 100644 --- a/src/bench_recover.c +++ b/src/bench_recover.c @@ -23,8 +23,8 @@ void bench_recover(void* arg) { for (i = 0; i < 20000; i++) { int j; int pubkeylen = 33; - secp256k1_ecdsa_signature_t sig; - CHECK(secp256k1_ecdsa_signature_parse_compact(data->ctx, &sig, data->sig, i % 2)); + secp256k1_ecdsa_recoverable_signature_t sig; + CHECK(secp256k1_ecdsa_recoverable_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++) { diff --git a/src/bench_sign.c b/src/bench_sign.c index e625da07a4..d705f7c0f2 100644 --- a/src/bench_sign.c +++ b/src/bench_sign.c @@ -26,16 +26,16 @@ static void bench_sign(void* arg) { int i; bench_sign_t *data = (bench_sign_t*)arg; - unsigned char sig[64]; + unsigned char sig[74]; + int siglen = 74; for (i = 0; i < 20000; i++) { int j; - int recid = 0; 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)); + CHECK(secp256k1_ecdsa_signature_serialize_der(data->ctx, sig, &siglen, &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. */ + data->msg[j] = sig[j]; + data->key[j] = sig[j + 32]; } } } diff --git a/src/secp256k1.c b/src/secp256k1.c index 4699bff802..37a7882409 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -155,7 +155,7 @@ int secp256k1_ec_pubkey_serialize(const secp256k1_context_t* ctx, unsigned char secp256k1_eckey_pubkey_serialize(&Q, output, outputlen, compressed)); } -static void secp256k1_ecdsa_signature_load(const secp256k1_context_t* ctx, secp256k1_scalar_t* r, secp256k1_scalar_t* s, int* recid, const secp256k1_ecdsa_signature_t* sig) { +static void secp256k1_ecdsa_recoverable_signature_load(const secp256k1_context_t* ctx, secp256k1_scalar_t* r, secp256k1_scalar_t* s, int* recid, const secp256k1_ecdsa_recoverable_signature_t* sig) { (void)ctx; if (sizeof(secp256k1_scalar_t) == 32) { /* When the secp256k1_scalar_t type is exactly 32 byte, use its @@ -167,12 +167,10 @@ static void secp256k1_ecdsa_signature_load(const secp256k1_context_t* ctx, secp2 secp256k1_scalar_set_b32(r, &sig->data[0], NULL); secp256k1_scalar_set_b32(s, &sig->data[32], NULL); } - if (recid) { - *recid = sig->data[64]; - } + *recid = sig->data[64]; } -static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature_t* sig, const secp256k1_scalar_t* r, const secp256k1_scalar_t* s, int recid) { +static void secp256k1_ecdsa_recoverable_signature_save(secp256k1_ecdsa_recoverable_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], r, 32); memcpy(&sig->data[32], s, 32); @@ -183,6 +181,30 @@ static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature_t* sig, con sig->data[64] = recid; } +static void secp256k1_ecdsa_signature_load(const secp256k1_context_t* ctx, secp256k1_scalar_t* r, secp256k1_scalar_t* s, const secp256k1_ecdsa_signature_t* sig) { + (void)ctx; + 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(r, &sig->data[0], 32); + memcpy(s, &sig->data[32], 32); + } else { + secp256k1_scalar_set_b32(r, &sig->data[0], NULL); + secp256k1_scalar_set_b32(s, &sig->data[32], NULL); + } +} + +static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature_t* sig, const secp256k1_scalar_t* r, const secp256k1_scalar_t* s) { + if (sizeof(secp256k1_scalar_t) == 32) { + memcpy(&sig->data[0], r, 32); + memcpy(&sig->data[32], s, 32); + } else { + secp256k1_scalar_get_b32(&sig->data[0], r); + secp256k1_scalar_get_b32(&sig->data[32], s); + } +} + int secp256k1_ecdsa_signature_parse_der(const secp256k1_context_t* ctx, secp256k1_ecdsa_signature_t* sig, const unsigned char *input, int inputlen) { secp256k1_scalar_t r, s; @@ -191,7 +213,7 @@ int secp256k1_ecdsa_signature_parse_der(const secp256k1_context_t* ctx, secp256k ARG_CHECK(input != NULL); if (secp256k1_ecdsa_sig_parse(&r, &s, input, inputlen)) { - secp256k1_ecdsa_signature_save(sig, &r, &s, -1); + secp256k1_ecdsa_signature_save(sig, &r, &s); return 1; } else { memset(sig, 0, sizeof(*sig)); @@ -199,7 +221,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) { +int secp256k1_ecdsa_recoverable_signature_parse_compact(const secp256k1_context_t* ctx, secp256k1_ecdsa_recoverable_signature_t* sig, const unsigned char *input64, int recid) { secp256k1_scalar_t r, s; int ret = 1; int overflow = 0; @@ -207,14 +229,14 @@ int secp256k1_ecdsa_signature_parse_compact(const secp256k1_context_t* ctx, secp (void)ctx; ARG_CHECK(sig != NULL); ARG_CHECK(input64 != NULL); + ARG_CHECK(recid >= 0 && recid <= 3); secp256k1_scalar_set_b32(&r, &input64[0], &overflow); ret &= !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, &r, &s, recid); + secp256k1_ecdsa_recoverable_signature_save(sig, &r, &s, recid); } else { memset(sig, 0, sizeof(*sig)); } @@ -229,25 +251,33 @@ int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context_t* ctx, unsi ARG_CHECK(outputlen != NULL); ARG_CHECK(sig != NULL); - secp256k1_ecdsa_signature_load(ctx, &r, &s, NULL, sig); + secp256k1_ecdsa_signature_load(ctx, &r, &s, 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) { +int secp256k1_ecdsa_recoverable_signature_serialize_compact(const secp256k1_context_t* ctx, unsigned char *output64, int *recid, const secp256k1_ecdsa_recoverable_signature_t* sig) { secp256k1_scalar_t r, s; - int rec; (void)ctx; ARG_CHECK(output64 != NULL); ARG_CHECK(sig != NULL); - secp256k1_ecdsa_signature_load(ctx, &r, &s, &rec, sig); + secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, recid, sig); secp256k1_scalar_get_b32(&output64[0], &r); secp256k1_scalar_get_b32(&output64[32], &s); - if (recid) { - ARG_CHECK(rec >= 0 && rec < 4); - *recid = rec; - } + return 1; +} + +int secp256k1_ecdsa_recoverable_signature_convert(const secp256k1_context_t* ctx, secp256k1_ecdsa_signature_t* sig, const secp256k1_ecdsa_recoverable_signature_t* sigin) { + secp256k1_scalar_t r, s; + int recid; + + (void)ctx; + ARG_CHECK(sig != NULL); + ARG_CHECK(sigin != NULL); + + secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, sigin); + secp256k1_ecdsa_signature_save(sig, &r, &s); return 1; } @@ -262,7 +292,7 @@ int secp256k1_ecdsa_verify(const secp256k1_context_t* ctx, const unsigned char * ARG_CHECK(pubkey != NULL); secp256k1_scalar_set_b32(&m, msg32, NULL); - secp256k1_ecdsa_signature_load(ctx, &r, &s, NULL, sig); + secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); return (secp256k1_pubkey_load(ctx, &q, pubkey) && secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m)); } @@ -302,6 +332,52 @@ 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_scalar_t r, s; + secp256k1_scalar_t sec, non, msg; + int ret = 0; + int overflow = 0; + unsigned int count = 0; + ARG_CHECK(ctx != NULL); + ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(msg32 != NULL); + ARG_CHECK(signature != NULL); + ARG_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, NULL, 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, &r, &s, &sec, &msg, &non, NULL)) { + break; + } + } + count++; + } + secp256k1_scalar_clear(&msg); + secp256k1_scalar_clear(&non); + secp256k1_scalar_clear(&sec); + } + if (ret) { + secp256k1_ecdsa_signature_save(signature, &r, &s); + } else { + memset(signature, 0, sizeof(*signature)); + } + return ret; +} + +int secp256k1_ecdsa_sign_recoverable(const secp256k1_context_t* ctx, const unsigned char *msg32, secp256k1_ecdsa_recoverable_signature_t *signature, const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void* noncedata) { secp256k1_scalar_t r, s; secp256k1_scalar_t sec, non, msg; int recid; @@ -341,14 +417,14 @@ int secp256k1_ecdsa_sign(const secp256k1_context_t* ctx, const unsigned char *ms secp256k1_scalar_clear(&sec); } if (ret) { - secp256k1_ecdsa_signature_save(signature, &r, &s, recid); + secp256k1_ecdsa_recoverable_signature_save(signature, &r, &s, recid); } else { memset(signature, 0, sizeof(*signature)); } return ret; } -int secp256k1_ecdsa_recover(const secp256k1_context_t* ctx, const unsigned char *msg32, const secp256k1_ecdsa_signature_t *signature, secp256k1_pubkey_t *pubkey) { +int secp256k1_ecdsa_recover(const secp256k1_context_t* ctx, const unsigned char *msg32, const secp256k1_ecdsa_recoverable_signature_t *signature, secp256k1_pubkey_t *pubkey) { secp256k1_ge_t q; secp256k1_scalar_t r, s; secp256k1_scalar_t m; @@ -359,7 +435,7 @@ int secp256k1_ecdsa_recover(const secp256k1_context_t* ctx, const unsigned char ARG_CHECK(signature != NULL); ARG_CHECK(pubkey != NULL); - secp256k1_ecdsa_signature_load(ctx, &r, &s, &recid, signature); + secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, signature); ARG_CHECK(recid >= 0 && recid < 4); secp256k1_scalar_set_b32(&m, msg32, NULL); if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &r, &s, &q, &m, recid)) { diff --git a/src/tests.c b/src/tests.c index ca055c4809..053e8c05ba 100644 --- a/src/tests.c +++ b/src/tests.c @@ -1844,6 +1844,7 @@ void test_ecdsa_end_to_end(void) { unsigned char message[32]; unsigned char privkey2[32]; secp256k1_ecdsa_signature_t signature[5]; + secp256k1_ecdsa_recoverable_signature_t rsignature[5]; unsigned char sig[74]; int siglen = 74; unsigned char pubkeyc[65]; @@ -1944,24 +1945,35 @@ void test_ecdsa_end_to_end(void) { 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); + /* Serialize/parse compact and verify/recover. */ + extra[0] = 0; + CHECK(secp256k1_ecdsa_sign_recoverable(ctx, message, &rsignature[0], privkey, NULL, NULL) == 1); + CHECK(secp256k1_ecdsa_sign_recoverable(ctx, message, &rsignature[4], privkey, NULL, NULL) == 1); + CHECK(secp256k1_ecdsa_sign_recoverable(ctx, message, &rsignature[1], privkey, NULL, extra) == 1); + extra[31] = 1; + CHECK(secp256k1_ecdsa_sign_recoverable(ctx, message, &rsignature[2], privkey, NULL, extra) == 1); + extra[31] = 0; + extra[0] = 1; + CHECK(secp256k1_ecdsa_sign_recoverable(ctx, message, &rsignature[3], privkey, NULL, extra) == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &rsignature[4]) == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[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); + memset(&rsignature[4], 0, sizeof(rsignature[4])); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 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(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, message, &rsignature[4], &recpubkey) == 1); CHECK(memcmp(&pubkey, &recpubkey, sizeof(pubkey)) == 0); /* Serialize/destroy/parse signature and verify again. */ - CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, sig, &recid, &signature[4]) == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &rsignature[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_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); CHECK(secp256k1_ecdsa_verify(ctx, message, &signature[4], &pubkey) == 0); /* Recover again */ - CHECK(secp256k1_ecdsa_recover(ctx, message, &signature[4], &recpubkey) == 0 || + CHECK(secp256k1_ecdsa_recover(ctx, message, &rsignature[4], &recpubkey) == 0 || memcmp(&pubkey, &recpubkey, sizeof(pubkey)) != 0); } @@ -2078,17 +2090,18 @@ void test_ecdsa_edge_cases(void) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, }; secp256k1_pubkey_t pubkeyb; + secp256k1_ecdsa_recoverable_signature_t rsig; secp256k1_ecdsa_signature_t sig; int recid; - 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)); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 0)); + CHECK(!secp256k1_ecdsa_recover(ctx, msg32, &rsig, &pubkey)); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 1)); + CHECK(secp256k1_ecdsa_recover(ctx, msg32, &rsig, &pubkey)); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 2)); + CHECK(!secp256k1_ecdsa_recover(ctx, msg32, &rsig, &pubkey)); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 3)); + CHECK(!secp256k1_ecdsa_recover(ctx, msg32, &rsig, &pubkey)); for (recid = 0; recid < 4; recid++) { int i; @@ -2133,14 +2146,14 @@ 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_signature_parse_compact(ctx, &sig, sigb64, recid) == 1); - CHECK(secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkeyb) == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigb64, recid) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, msg32, &rsig, &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_signature_parse_compact(ctx, &sig, sigb64, recid2) == 1); - CHECK(secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkey2b) == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigb64, recid2) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, msg32, &rsig, &pubkey2b) == 1); /* Verifying with (order + r,4) should always fail. */ CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderlong, sizeof(sigbderlong)) == 0); } @@ -2214,22 +2227,22 @@ void test_ecdsa_edge_cases(void) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }; secp256k1_pubkey_t pubkeyc; - CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, sigc64, 0) == 1); - CHECK(secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkeyc) == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, msg32, &rsig, &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_signature_parse_compact(ctx, &sig, sigc64, 0) == 1); - CHECK(secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkeyb) == 0); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, msg32, &rsig, &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_signature_parse_compact(ctx, &sig, sigc64, 0) == 1); - CHECK(secp256k1_ecdsa_recover(ctx, msg32, &sig, &pubkeyb) == 0); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, msg32, &rsig, &pubkeyb) == 0); CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); CHECK(secp256k1_ecdsa_verify(ctx, msg32, &sig, &pubkeyc) == 0); } @@ -2313,7 +2326,7 @@ 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(ctx, &sr[i], &ss, NULL, &sig2); + secp256k1_ecdsa_signature_load(ctx, &sr[i], &ss, &sig2); for (j = 0; j < i; j++) { CHECK(!secp256k1_scalar_eq(&sr[i], &sr[j])); } @@ -2326,7 +2339,7 @@ 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(ctx, &sr[i], &ss, NULL, &sig2); + secp256k1_ecdsa_signature_load(ctx, &sr[i], &ss, &sig2); for (j = 0; j < i; j++) { CHECK(!secp256k1_scalar_eq(&sr[i], &sr[j])); }