Skip to content

Commit e454fa7

Browse files
authored
Merge pull request #2545 from Lrifton92/fix/wif-private-key-range-validation
btcutil: reject out-of-range private keys in DecodeWIF
2 parents 263ac0e + f10224d commit e454fa7

2 files changed

Lines changed: 40 additions & 0 deletions

File tree

btcutil/wif.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,22 @@ func DecodeWIF(wif string) (*WIF, error) {
118118

119119
netID := decoded[0]
120120
privKeyBytes := decoded[1 : 1+btcec.PrivKeyBytesLen]
121+
122+
// Ensure the private key is within the valid range for a secp256k1
123+
// private key, that is [1, N-1]. Without this check, a WIF encoding a
124+
// key of zero or one greater than or equal to the group order N is
125+
// silently accepted: btcec.PrivKeyFromBytes reduces the scalar modulo
126+
// N, so DecodeWIF would otherwise return a private key that differs from
127+
// the one actually encoded in the WIF (or the all-zero key) without
128+
// reporting an error.
129+
var keyScalar btcec.ModNScalar
130+
defer keyScalar.Zero()
131+
if overflow := keyScalar.SetByteSlice(privKeyBytes); overflow ||
132+
keyScalar.IsZero() {
133+
134+
return nil, ErrMalformedPrivateKey
135+
}
136+
121137
privKey, _ := btcec.PrivKeyFromBytes(privKeyBytes)
122138
return &WIF{privKey, compress, netID}, nil
123139
}

btcutil/wif_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,30 @@ func TestEncodeDecodeWIF(t *testing.T) {
122122
wif: "5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTj",
123123
err: address.ErrChecksumMismatch,
124124
},
125+
{
126+
// A WIF encoding a private key of zero, which is
127+
// outside the valid range [1, N-1] for a secp256k1
128+
// private key.
129+
name: "decodeZeroPrivKeyWif",
130+
wif: "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAbuatmU",
131+
err: ErrMalformedPrivateKey,
132+
},
133+
{
134+
// A WIF encoding a private key equal to the group order
135+
// N, which is outside the valid range [1, N-1].
136+
name: "decodeOrderNPrivKeyWif",
137+
wif: "5Km2kuu7vtFDPpxywn4u3NLpbr5jKpTB3jsuDU2KYEqetwr388P",
138+
err: ErrMalformedPrivateKey,
139+
},
140+
{
141+
// A WIF encoding a private key of N+5, which is outside
142+
// the valid range [1, N-1]. Before validation was
143+
// added, this was silently reduced modulo N and decoded
144+
// to a different private key (5) without any error.
145+
name: "decodeAboveOrderNPrivKeyWif",
146+
wif: "5Km2kuu7vtFDPpxywn4u3NLpbr5jKpTB3jsuDU2KYEqeuVhzTbv",
147+
err: ErrMalformedPrivateKey,
148+
},
125149
}
126150

127151
for _, invalidCase := range invalidDecodeCases {

0 commit comments

Comments
 (0)