0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-08 10:31:50 -05:00

Separate recoverable and normal signatures

This commit is contained in:
Pieter Wuille 2015-08-27 03:09:23 +02:00
parent a7b046e554
commit 439d34adc6
5 changed files with 203 additions and 73 deletions

View file

@ -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);

View file

@ -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++) {

View file

@ -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];
}
}
}

View file

@ -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)) {

View file

@ -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]));
}