diff --git a/include/secp256k1.h b/include/secp256k1.h index e9944e5..369a95e 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -27,18 +27,33 @@ int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen, const unsigned char *sig, int siglen, const unsigned char *pubkey, int pubkeylen); +/** Create an ECDSA signature. + * Returns: 1: signature created + * 0: nonce invalid, try another one + * In: msg: the message being signed + * msglen: the length of the message being signed + * seckey: pointer to a 32-byte secret key (assumed to be valid) + * nonce: pointer to a 32-byte nonce (generated with a cryptographic PRNG) + * Out: sig: pointer to a 72-byte array where the signature will be placed. + * siglen: pointer to an int, which will be updated to the signature length (<=72). + */ int secp256k1_ecdsa_sign(const unsigned char *msg, int msglen, - unsigned char *sig, int* siglen, + unsigned char *sig, int *siglen, const unsigned char *seckey, const unsigned char *nonce); + +/** Verify an ECDSA secret key. + * Returns: 1: secret key is valid + * 0: secret key is invalid + * In: seckey: pointer to a 32-byte secret key + */ int secp256j1_ecdsa_seckey_verify(const unsigned char *seckey); /** Just validate a public key. * Returns: 1: valid public key * 0: invalid public key */ -/* NOT YET IMPLEMENTED */ int secp256k1_ecdsa_pubkey_verify(const unsigned char *pubkey, int pubkeylen); /** Compute the public key for a secret key. @@ -51,8 +66,7 @@ int secp256k1_ecdsa_pubkey_verify(const unsigned char *pubkey, int pubkeylen); * Returns: 1: secret was valid, public key stores * 0: secret was invalid, try again. */ -/* NOT YET IMPLEMENTED */ -int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed) +int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed); int secp256k1_ecdsa_pubkey_decompress(unsigned char *pubkey, int *pubkeylen); diff --git a/src/ecdsa.h b/src/ecdsa.h index f6f3642..5ddbf65 100644 --- a/src/ecdsa.h +++ b/src/ecdsa.h @@ -11,6 +11,7 @@ void static secp256k1_ecdsa_sig_init(secp256k1_ecdsa_sig_t *r); void static secp256k1_ecdsa_sig_free(secp256k1_ecdsa_sig_t *r); int static secp256k1_ecdsa_pubkey_parse(secp256k1_gej_t *elem, const unsigned char *pub, int size); +void static secp256k1_ecdsa_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed); int static secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size); int static secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a); int static secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_gej_t *pubkey, const secp256k1_num_t *message); diff --git a/src/impl/ecdsa.h b/src/impl/ecdsa.h index 1e98a75..e7dfba4 100644 --- a/src/impl/ecdsa.h +++ b/src/impl/ecdsa.h @@ -146,4 +146,18 @@ void static secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256 secp256k1_num_copy(&sig->s, s); } +void static secp256k1_ecdsa_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed) { + secp256k1_fe_normalize(&elem->x); + secp256k1_fe_normalize(&elem->y); + secp256k1_fe_get_b32(&pub[1], &elem->x); + if (compressed) { + *size = 33; + pub[0] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00); + } else { + *size = 65; + pub[0] = 0x04; + secp256k1_fe_get_b32(&pub[33], &elem->y); + } +} + #endif diff --git a/src/secp256k1.c b/src/secp256k1.c index abe1df4..be896a9 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -64,3 +64,40 @@ int secp256k1_ecdsa_sign(const unsigned char *message, int messagelen, unsigned secp256k1_num_free(&sec); return ret; } + +int secp256k1_ecdsa_seckey_verify(const unsigned char *seckey) { + secp256k1_num_t sec; + secp256k1_num_init(&sec); + secp256k1_num_set_bin(&sec, seckey, 32); + int ret = secp256k1_num_is_zero(&sec) || + (secp256k1_num_cmp(&sec, &secp256k1_ge_consts->order) >= 0); + secp256k1_num_free(&sec); + return ret; +} + +int secp256k1_ecdsa_pubkey_verify(const unsigned char *pubkey, int pubkeylen) { + secp256k1_gej_t q; + return secp256k1_ecdsa_pubkey_parse(&q, pubkey, pubkeylen); +} + +int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed) { + secp256k1_num_t sec; + secp256k1_num_init(&sec); + secp256k1_num_set_bin(&sec, seckey, 32); + secp256k1_gej_t pj; + secp256k1_ecmult_gen(&pj, &sec); + secp256k1_ge_t p; + secp256k1_ge_set_gej(&p, &pj); + secp256k1_ecdsa_pubkey_serialize(&p, pubkey, pubkeylen, compressed); + return 1; +} + +int secp256k1_ecdsa_pubkey_decompress(unsigned char *pubkey, int *pubkeylen) { + secp256k1_gej_t pj; + if (!secp256k1_ecdsa_pubkey_parse(&pj, pubkey, *pubkeylen)) + return 0; + secp256k1_ge_t p; + secp256k1_ge_set_gej(&p, &pj); + secp256k1_ecdsa_pubkey_serialize(&p, pubkey, pubkeylen, 0); + return 1; +}