mirror of
https://github.com/status-im/secp256k1.git
synced 2025-02-24 03:38:12 +00:00
Add a secp256k1_ecdsa_signature_t type
This commit is contained in:
parent
23cfa914d2
commit
74a2acdb8a
@ -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.
|
||||
|
@ -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. */
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
193
src/secp256k1.c
193
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,102 +273,46 @@ 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;
|
||||
}
|
||||
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);
|
||||
secp256k1_ecdsa_signature_save(signature, &sig, recid);
|
||||
} else {
|
||||
memset(signature, 0, sizeof(*signature));
|
||||
}
|
||||
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_ecdsa_signature_load(&sig, &recid, signature);
|
||||
DEBUG_CHECK(recid >= 0 && recid < 4);
|
||||
secp256k1_scalar_set_b32(&m, msg32, NULL);
|
||||
|
||||
ret = secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &sig, &q, &m, recid);
|
||||
if (ret) {
|
||||
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) {
|
||||
secp256k1_scalar_t sec;
|
||||
|
263
src/tests.c
263
src/tests.c
@ -13,6 +13,7 @@
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#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));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user