mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-13 11:25:02 -05:00
145 lines
4.6 KiB
C++
145 lines
4.6 KiB
C++
#include "num.h"
|
|
#include "field.h"
|
|
#include "group.h"
|
|
#include "ecmult.h"
|
|
#include "ecdsa.h"
|
|
|
|
namespace secp256k1 {
|
|
|
|
bool ParsePubKey(GroupElemJac &elem, const unsigned char *pub, int size) {
|
|
if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) {
|
|
secp256k1_fe_t x;
|
|
secp256k1_fe_set_b32(&x, pub+1);
|
|
elem.SetCompressed(x, pub[0] == 0x03);
|
|
} else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) {
|
|
secp256k1_fe_t x,y;
|
|
secp256k1_fe_set_b32(&x, pub+1);
|
|
secp256k1_fe_set_b32(&y, pub+33);
|
|
elem = GroupElem(x,y);
|
|
if ((pub[0] == 0x06 || pub[0] == 0x07) && secp256k1_fe_is_odd(&y) != (pub[0] == 0x07))
|
|
return false;
|
|
} else {
|
|
return false;
|
|
}
|
|
return elem.IsValid();
|
|
}
|
|
|
|
bool Signature::Parse(const unsigned char *sig, int size) {
|
|
if (sig[0] != 0x30) return false;
|
|
int lenr = sig[3];
|
|
if (5+lenr >= size) return false;
|
|
int lens = sig[lenr+5];
|
|
if (sig[1] != lenr+lens+4) return false;
|
|
if (lenr+lens+6 > size) return false;
|
|
if (sig[2] != 0x02) return false;
|
|
if (lenr == 0) return false;
|
|
if (sig[lenr+4] != 0x02) return false;
|
|
if (lens == 0) return false;
|
|
secp256k1_num_set_bin(&r, sig+4, lenr);
|
|
secp256k1_num_set_bin(&s, sig+6+lenr, lens);
|
|
return true;
|
|
}
|
|
|
|
bool Signature::Serialize(unsigned char *sig, int *size) {
|
|
int lenR = (secp256k1_num_bits(&r) + 7)/8;
|
|
if (lenR == 0 || secp256k1_num_get_bit(&r, lenR*8-1))
|
|
lenR++;
|
|
int lenS = (secp256k1_num_bits(&s) + 7)/8;
|
|
if (lenS == 0 || secp256k1_num_get_bit(&s, lenS*8-1))
|
|
lenS++;
|
|
if (*size < 6+lenS+lenR)
|
|
return false;
|
|
*size = 6 + lenS + lenR;
|
|
sig[0] = 0x30;
|
|
sig[1] = 4 + lenS + lenR;
|
|
sig[2] = 0x02;
|
|
sig[3] = lenR;
|
|
secp256k1_num_get_bin(sig+4, lenR, &r);
|
|
sig[4+lenR] = 0x02;
|
|
sig[5+lenR] = lenS;
|
|
secp256k1_num_get_bin(sig+lenR+6, lenS, &s);
|
|
return true;
|
|
}
|
|
|
|
bool Signature::RecomputeR(secp256k1_num_t &r2, const GroupElemJac &pubkey, const secp256k1_num_t &message) const {
|
|
const GroupConstants &c = GetGroupConst();
|
|
|
|
if (secp256k1_num_is_neg(&r) || secp256k1_num_is_neg(&s))
|
|
return false;
|
|
if (secp256k1_num_is_zero(&r) || secp256k1_num_is_zero(&s))
|
|
return false;
|
|
if (secp256k1_num_cmp(&r, &c.order) >= 0 || secp256k1_num_cmp(&s, &c.order) >= 0)
|
|
return false;
|
|
|
|
bool ret = false;
|
|
secp256k1_num_t sn, u1, u2;
|
|
secp256k1_num_init(&sn);
|
|
secp256k1_num_init(&u1);
|
|
secp256k1_num_init(&u2);
|
|
secp256k1_num_mod_inverse(&sn, &s, &c.order);
|
|
secp256k1_num_mod_mul(&u1, &sn, &message, &c.order);
|
|
secp256k1_num_mod_mul(&u2, &sn, &r, &c.order);
|
|
GroupElemJac pr; ECMult(pr, pubkey, u2, u1);
|
|
if (!pr.IsInfinity()) {
|
|
secp256k1_fe_t xr; pr.GetX(xr);
|
|
secp256k1_fe_normalize(&xr);
|
|
unsigned char xrb[32]; secp256k1_fe_get_b32(xrb, &xr);
|
|
secp256k1_num_set_bin(&r2, xrb, 32);
|
|
secp256k1_num_mod(&r2, &r2, &c.order);
|
|
ret = true;
|
|
}
|
|
secp256k1_num_free(&sn);
|
|
secp256k1_num_free(&u1);
|
|
secp256k1_num_free(&u2);
|
|
return ret;
|
|
}
|
|
|
|
bool Signature::Verify(const GroupElemJac &pubkey, const secp256k1_num_t &message) const {
|
|
secp256k1_num_t r2;
|
|
secp256k1_num_init(&r2);
|
|
bool ret = false;
|
|
ret = RecomputeR(r2, pubkey, message) && secp256k1_num_cmp(&r, &r2) == 0;
|
|
secp256k1_num_free(&r2);
|
|
return ret;
|
|
}
|
|
|
|
bool Signature::Sign(const secp256k1_num_t &seckey, const secp256k1_num_t &message, const secp256k1_num_t &nonce) {
|
|
const GroupConstants &c = GetGroupConst();
|
|
|
|
GroupElemJac rp;
|
|
ECMultBase(rp, nonce);
|
|
secp256k1_fe_t rx;
|
|
rp.GetX(rx);
|
|
unsigned char b[32];
|
|
secp256k1_fe_normalize(&rx);
|
|
secp256k1_fe_get_b32(b, &rx);
|
|
secp256k1_num_set_bin(&r, b, 32);
|
|
secp256k1_num_mod(&r, &r, &c.order);
|
|
secp256k1_num_t n;
|
|
secp256k1_num_init(&n);
|
|
secp256k1_num_mod_mul(&n, &r, &seckey, &c.order);
|
|
secp256k1_num_add(&n, &n, &message);
|
|
secp256k1_num_mod_inverse(&s, &nonce, &c.order);
|
|
secp256k1_num_mod_mul(&s, &s, &n, &c.order);
|
|
secp256k1_num_free(&n);
|
|
if (secp256k1_num_is_zero(&s))
|
|
return false;
|
|
if (secp256k1_num_is_odd(&s))
|
|
secp256k1_num_sub(&s, &c.order, &s);
|
|
return true;
|
|
}
|
|
|
|
void Signature::SetRS(const secp256k1_num_t &rin, const secp256k1_num_t &sin) {
|
|
secp256k1_num_copy(&r, &rin);
|
|
secp256k1_num_copy(&s, &sin);
|
|
}
|
|
|
|
std::string Signature::ToString() const {
|
|
char rs[65], ss[65];
|
|
int rl = 65, sl = 65;
|
|
secp256k1_num_get_hex(rs, &rl, &r);
|
|
secp256k1_num_get_hex(ss, &sl, &s);
|
|
return "(" + std::string(rs) + "," + std::string(ss) + ")";
|
|
}
|
|
|
|
}
|