wallet: always create signatures with low r-value

This commit is contained in:
gorazdko 2019-10-28 01:03:19 +01:00 committed by neil saitug
parent 67ce27aac7
commit a3851f2943
2 changed files with 27 additions and 5 deletions

View File

@ -75,16 +75,38 @@ static void dump_tx(const char *msg UNUSED,
}
#endif
/* Taken from https://github.com/bitcoin/bitcoin/blob/master/src/key.cpp */
/* Check that the sig has a low R value and will be less than 71 bytes */
static bool sig_has_low_r(const secp256k1_ecdsa_signature* sig)
{
unsigned char compact_sig[64];
secp256k1_ecdsa_signature_serialize_compact(secp256k1_ctx, compact_sig, sig);
/* In DER serialization, all values are interpreted as big-endian, signed
* integers. The highest bit in the integer indicates its signed-ness; 0 is
* positive, 1 is negative. When the value is interpreted as a negative
* integer, it must be converted to a positive value by prepending a 0x00
* byte so that the highest bit is 0. We can avoid this prepending by
* ensuring that our highest bit is always 0, and thus we must check that
* the first byte is less than 0x80. */
return compact_sig[0] < 0x80;
}
void sign_hash(const struct privkey *privkey,
const struct sha256_double *h,
secp256k1_ecdsa_signature *s)
{
bool ok;
unsigned char extra_entropy[32] = {0};
ok = secp256k1_ecdsa_sign(secp256k1_ctx,
s,
h->sha.u.u8,
privkey->secret.data, NULL, NULL);
/* Grind for low R */
do {
ok = secp256k1_ecdsa_sign(secp256k1_ctx,
s,
h->sha.u.u8,
privkey->secret.data, NULL, extra_entropy);
((u32 *)extra_entropy)[0]++;
} while (!sig_has_low_r(s));
assert(ok);
}

View File

@ -47,7 +47,7 @@ struct bitcoin_signature {
};
/**
* sign_hash - produce a raw secp256k1 signature.
* sign_hash - produce a raw secp256k1 signature (with low R value).
* @p: secret key
* @h: hash to sign.
* @sig: signature to fill in and return.