mirror of
https://github.com/bitcoin/bitcoin.git
synced 2024-11-20 10:38:42 +01:00
Compact signatures/pubkey recovery
This commit is contained in:
parent
764332d05d
commit
50eb498ece
@ -42,6 +42,26 @@ int secp256k1_ecdsa_sign(const unsigned char *msg, int msglen,
|
||||
const unsigned char *seckey,
|
||||
const unsigned char *nonce);
|
||||
|
||||
/** Create a compact ECDSA signature (64 byte + recovery id).
|
||||
* 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 64-byte array where the signature will be placed.
|
||||
* recid: pointer to an int, which will be updated to contain the recovery id.
|
||||
*/
|
||||
int secp256k1_ecdsa_sign_compact(const unsigned char *msg, int msglen,
|
||||
unsigned char *sig64,
|
||||
const unsigned char *seckey,
|
||||
const unsigned char *nonce,
|
||||
int *recid);
|
||||
|
||||
int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen,
|
||||
const unsigned char *sig64,
|
||||
unsigned char *pubkey, int *pubkeylen,
|
||||
int compressed, int recid);
|
||||
|
||||
/** Verify an ECDSA secret key.
|
||||
* Returns: 1: secret key is valid
|
||||
|
@ -15,7 +15,8 @@ void static secp256k1_ecdsa_pubkey_serialize(secp256k1_ge_t *elem, unsigned char
|
||||
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_ge_t *pubkey, const secp256k1_num_t *message);
|
||||
int static secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *seckey, const secp256k1_num_t *message, const secp256k1_num_t *nonce);
|
||||
int static secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *seckey, const secp256k1_num_t *message, const secp256k1_num_t *nonce, int *recid);
|
||||
int static secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_num_t *message, int recid);
|
||||
void static secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s);
|
||||
|
||||
#endif
|
||||
|
@ -106,6 +106,49 @@ int static secp256k1_ecdsa_sig_recompute(secp256k1_num_t *r2, const secp256k1_ec
|
||||
return ret;
|
||||
}
|
||||
|
||||
int static secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_num_t *message, int recid) {
|
||||
const secp256k1_ge_consts_t *c = secp256k1_ge_consts;
|
||||
|
||||
if (secp256k1_num_is_neg(&sig->r) || secp256k1_num_is_neg(&sig->s))
|
||||
return 0;
|
||||
if (secp256k1_num_is_zero(&sig->r) || secp256k1_num_is_zero(&sig->s))
|
||||
return 0;
|
||||
if (secp256k1_num_cmp(&sig->r, &c->order) >= 0 || secp256k1_num_cmp(&sig->s, &c->order) >= 0)
|
||||
return 0;
|
||||
|
||||
secp256k1_num_t rx;
|
||||
secp256k1_num_init(&rx);
|
||||
secp256k1_num_copy(&rx, &sig->r);
|
||||
if (recid & 2)
|
||||
secp256k1_num_add(&rx, &rx, &c->order);
|
||||
unsigned char brx[32];
|
||||
secp256k1_num_get_bin(brx, 32, &rx);
|
||||
secp256k1_num_free(&rx);
|
||||
secp256k1_fe_t fx;
|
||||
secp256k1_fe_set_b32(&fx, brx);
|
||||
secp256k1_ge_t x;
|
||||
secp256k1_ge_set_xo(&x, &fx, recid & 1);
|
||||
if (!secp256k1_ge_is_valid(&x))
|
||||
return 0;
|
||||
secp256k1_gej_t xj;
|
||||
secp256k1_gej_set_ge(&xj, &x);
|
||||
secp256k1_num_t rn, u1, u2;
|
||||
secp256k1_num_init(&rn);
|
||||
secp256k1_num_init(&u1);
|
||||
secp256k1_num_init(&u2);
|
||||
secp256k1_num_mod_inverse(&rn, &sig->r, &c->order);
|
||||
secp256k1_num_mod_mul(&u1, &rn, message, &c->order);
|
||||
secp256k1_num_sub(&u1, &c->order, &u1);
|
||||
secp256k1_num_mod_mul(&u2, &rn, &sig->s, &c->order);
|
||||
secp256k1_gej_t qj;
|
||||
secp256k1_ecmult(&qj, &xj, &u2, &u1);
|
||||
secp256k1_ge_set_gej(pubkey, &qj);
|
||||
secp256k1_num_free(&rn);
|
||||
secp256k1_num_free(&u1);
|
||||
secp256k1_num_free(&u2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int static secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message) {
|
||||
secp256k1_num_t r2;
|
||||
secp256k1_num_init(&r2);
|
||||
@ -115,17 +158,20 @@ int static secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const se
|
||||
return ret;
|
||||
}
|
||||
|
||||
int static secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *seckey, const secp256k1_num_t *message, const secp256k1_num_t *nonce) {
|
||||
int static secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *seckey, const secp256k1_num_t *message, const secp256k1_num_t *nonce, int *recid) {
|
||||
const secp256k1_ge_consts_t *c = secp256k1_ge_consts;
|
||||
|
||||
secp256k1_gej_t rp;
|
||||
secp256k1_ecmult_gen(&rp, nonce);
|
||||
secp256k1_fe_t rx;
|
||||
secp256k1_gej_get_x(&rx, &rp);
|
||||
secp256k1_ge_t r;
|
||||
secp256k1_ge_set_gej(&r, &rp);
|
||||
unsigned char b[32];
|
||||
secp256k1_fe_normalize(&rx);
|
||||
secp256k1_fe_get_b32(b, &rx);
|
||||
secp256k1_fe_normalize(&r.x);
|
||||
secp256k1_fe_normalize(&r.y);
|
||||
secp256k1_fe_get_b32(b, &r.x);
|
||||
secp256k1_num_set_bin(&sig->r, b, 32);
|
||||
if (recid)
|
||||
*recid = (secp256k1_num_cmp(&sig->r, &c->order) >= 0 ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0);
|
||||
secp256k1_num_mod(&sig->r, &c->order);
|
||||
secp256k1_num_t n;
|
||||
secp256k1_num_init(&n);
|
||||
@ -137,8 +183,11 @@ int static secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_
|
||||
secp256k1_num_free(&n);
|
||||
if (secp256k1_num_is_zero(&sig->s))
|
||||
return 0;
|
||||
if (secp256k1_num_is_odd(&sig->s))
|
||||
if (secp256k1_num_is_odd(&sig->s)) {
|
||||
secp256k1_num_sub(&sig->s, &c->order, &sig->s);
|
||||
if (recid)
|
||||
*recid ^= 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ int secp256k1_ecdsa_sign(const unsigned char *message, int messagelen, unsigned
|
||||
secp256k1_num_set_bin(&msg, message, messagelen);
|
||||
secp256k1_ecdsa_sig_t sig;
|
||||
secp256k1_ecdsa_sig_init(&sig);
|
||||
int ret = secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non);
|
||||
int ret = secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, NULL);
|
||||
if (ret) {
|
||||
secp256k1_ecdsa_sig_serialize(signature, signaturelen, &sig);
|
||||
}
|
||||
@ -65,6 +65,48 @@ int secp256k1_ecdsa_sign(const unsigned char *message, int messagelen, unsigned
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_sign_compact(const unsigned char *message, int messagelen, unsigned char *sig64, const unsigned char *seckey, const unsigned char *nonce, int *recid) {
|
||||
secp256k1_num_t sec, non, msg;
|
||||
secp256k1_num_init(&sec);
|
||||
secp256k1_num_init(&non);
|
||||
secp256k1_num_init(&msg);
|
||||
secp256k1_num_set_bin(&sec, seckey, 32);
|
||||
secp256k1_num_set_bin(&non, nonce, 32);
|
||||
secp256k1_num_set_bin(&msg, message, messagelen);
|
||||
secp256k1_ecdsa_sig_t sig;
|
||||
secp256k1_ecdsa_sig_init(&sig);
|
||||
int ret = secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, recid);
|
||||
if (ret) {
|
||||
secp256k1_num_get_bin(sig64, 32, &sig.r);
|
||||
secp256k1_num_get_bin(sig64 + 32, 32, &sig.s);
|
||||
}
|
||||
secp256k1_ecdsa_sig_free(&sig);
|
||||
secp256k1_num_free(&msg);
|
||||
secp256k1_num_free(&non);
|
||||
secp256k1_num_free(&sec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen, const unsigned char *sig64, unsigned char *pubkey, int *pubkeylen, int compressed, int recid) {
|
||||
int ret = 0;
|
||||
secp256k1_num_t m;
|
||||
secp256k1_num_init(&m);
|
||||
secp256k1_ecdsa_sig_t sig;
|
||||
secp256k1_ecdsa_sig_init(&sig);
|
||||
secp256k1_num_set_bin(&sig.r, sig64, 32);
|
||||
secp256k1_num_set_bin(&sig.s, sig64 + 32, 32);
|
||||
secp256k1_num_set_bin(&m, msg, msglen);
|
||||
|
||||
secp256k1_ge_t q;
|
||||
if (secp256k1_ecdsa_sig_recover(&sig, &q, &m, recid)) {
|
||||
secp256k1_ecdsa_pubkey_serialize(&q, pubkey, pubkeylen, compressed);
|
||||
ret = 1;
|
||||
}
|
||||
secp256k1_ecdsa_sig_free(&sig);
|
||||
secp256k1_num_free(&m);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256k1_ecdsa_seckey_verify(const unsigned char *seckey) {
|
||||
secp256k1_num_t sec;
|
||||
secp256k1_num_init(&sec);
|
||||
|
@ -344,7 +344,7 @@ void test_ecdsa_sign_verify() {
|
||||
secp256k1_ecdsa_sig_init(&sig);
|
||||
do {
|
||||
random_num_order_test(&nonce);
|
||||
} while(!secp256k1_ecdsa_sig_sign(&sig, &key, &msg, &nonce));
|
||||
} while(!secp256k1_ecdsa_sig_sign(&sig, &key, &msg, &nonce, NULL));
|
||||
assert(secp256k1_ecdsa_sig_verify(&sig, &pub, &msg));
|
||||
secp256k1_num_inc(&msg);
|
||||
assert(!secp256k1_ecdsa_sig_verify(&sig, &pub, &msg));
|
||||
|
Loading…
Reference in New Issue
Block a user