btcec: validate R and S signature components in RecoverCompact

This commit is contained in:
Anirudha Bose 2021-02-03 21:01:10 +01:00 committed by John C. Vernaleo
parent fa683a69dc
commit 31b66488b4
2 changed files with 54 additions and 1 deletions

View file

@ -284,6 +284,25 @@ func hashToInt(hash []byte, c elliptic.Curve) *big.Int {
// format and thus we match bitcoind's behaviour here.
func recoverKeyFromSignature(curve *KoblitzCurve, sig *Signature, msg []byte,
iter int, doChecks bool) (*PublicKey, error) {
// Parse and validate the R and S signature components.
//
// Fail if r and s are not in [1, N-1].
if sig.R.Cmp(curve.Params().N) != -1 {
return nil, errors.New("signature R is >= curve order")
}
if sig.R.Sign() == 0 {
return nil, errors.New("signature R is 0")
}
if sig.S.Cmp(curve.Params().N) != -1 {
return nil, errors.New("signature S is >= curve order")
}
if sig.S.Sign() == 0 {
return nil, errors.New("signature S is 0")
}
// 1.1 x = (n * i) + r
Rx := new(big.Int).Mul(curve.Params().N,
new(big.Int).SetInt64(int64(iter/2)))
@ -393,7 +412,7 @@ func SignCompact(curve *KoblitzCurve, key *PrivateKey,
// RecoverCompact verifies the compact signature "signature" of "hash" for the
// Koblitz curve in "curve". If the signature matches then the recovered public
// key will be returned as well as a boolen if the original key was compressed
// key will be returned as well as a boolean if the original key was compressed
// or not, else an error will be returned.
func RecoverCompact(curve *KoblitzCurve, signature,
hash []byte) (*PublicKey, bool, error) {

View file

@ -555,6 +555,40 @@ var recoveryTests = []struct {
sig: "00000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000004",
pub: "04A7640409AA2083FDAD38B2D8DE1263B2251799591D840653FB02DBBA503D7745FCB83D80E08A1E02896BE691EA6AFFB8A35939A646F1FC79052A744B1C82EDC3",
},
{
// Zero R value
//
// Test case contributed by Ethereum Swarm: GH-1651
msg: "3060d2c77c1e192d62ad712fb400e04e6f779914a6876328ff3b213fa85d2012",
sig: "65000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037a3",
err: fmt.Errorf("signature R is 0"),
},
{
// Zero R value
//
// Test case contributed by Ethereum Swarm: GH-1651
msg: "2bcebac60d8a78e520ae81c2ad586792df495ed429bd730dcd897b301932d054",
sig: "060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007c",
err: fmt.Errorf("signature R is 0"),
},
{
// R = N (curve order of secp256k1)
msg: "2bcebac60d8a78e520ae81c2ad586792df495ed429bd730dcd897b301932d054",
sig: "65fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036414100000000000000000000000000000000000000000000000000000000000037a3",
err: fmt.Errorf("signature R is >= curve order"),
},
{
// Zero S value
msg: "ce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008",
sig: "0190f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e549980000000000000000000000000000000000000000000000000000000000000000",
err: fmt.Errorf("signature S is 0"),
},
{
// S = N (curve order of secp256k1)
msg: "ce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008",
sig: "0190f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e54998fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141",
err: fmt.Errorf("signature S is >= curve order"),
},
}
func TestRecoverCompact(t *testing.T) {