key: Fix PublicKey::from_slice compressed key prefix check
What changed, and why it matters
This commit fixes a bug in how the library reads Bitcoin public keys from raw bytes. Previously, when a caller said the key was 'compressed', the code did not verify that the first byte was a valid compressed-key prefix (2 or 3). That meant invalid or even attacker-chosen prefix bytes could be accepted for compressed keys, while uncompressed keys were already checked. The fix now rejects any compressed key whose first byte is not 2 or 3, matching the Bitcoin protocol rules.
Upgrade to a version containing this commit. If upgrading is not possible, validate public-key bytes before passing them to PublicKey::from_slice, ensuring compressed keys begin with 0x02 or 0x03 and uncompressed keys begin with 0x04.
Security signals we found
Missing input validation on compressed public-key prefix byte
Protocol rule enforcement gap in cryptographic deserialization
Potential acceptance of malformed secp256k1 public key inputs
Evidence from the diff
PublicKey::from_slice in bitcoin/src/crypto/key.rs previously only validated the 0x04 prefix for uncompressed keys. For compressed keys it skipped prefix validation entirely, relying on downstream secp256k1 parsing. The patch adds an explicit match on (compressed, data[0]) allowing only 0x02/0x03 for compressed and 0x04 for uncompressed, returning InvalidKeyPrefix otherwise. This is a correctness fix for Bitcoin public-key deserialization and prevents acceptance of malformed compressed public keys.
Changed components
bitcoin/src/crypto/key.rsPublicKey::from_sliceFromSliceError::InvalidKeyPrefixInspect captured patch +6 / −2
diff --git a/bitcoin/src/crypto/key.rs b/bitcoin/src/crypto/key.rs
index b0f09d23..4567cabb 100644
--- a/bitcoin/src/crypto/key.rs
+++ b/bitcoin/src/crypto/key.rs
@@ -621,8 +621,12 @@ impl PublicKey {
}
};
- if !compressed && data[0] != 0x04 {
- return Err(FromSliceError::InvalidKeyPrefix(data[0]));
+ // Compressed keys must have a prefix byte of 2 or 3. Uncompressed must be 4
+ match (compressed, data[0]) {
+ (true, 0x02) => (),
+ (true, 0x03) => (),
+ (false, 0x04) => (),
+ (_, byte) => return Err(FromSliceError::InvalidKeyPrefix(byte)),
}
Ok(match compressed {
Why this scored 60/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.