Test off curve pubkey (bp #11299) (#11317)

* Allow inspection of signature verification failures

(cherry picked from commit 251f974b50)

* Test that off-curve pubkeys fail signature verify

(cherry picked from commit c421d7f1b8)

Co-authored-by: Trent Nelson <trent@solana.com>
This commit is contained in:
mergify[bot]
2020-07-31 23:39:56 +00:00
committed by GitHub
parent e33f9ea6b5
commit 158f6f3725
3 changed files with 34 additions and 9 deletions

1
Cargo.lock generated
View File

@ -4688,6 +4688,7 @@ dependencies = [
"bv", "bv",
"byteorder", "byteorder",
"chrono", "chrono",
"curve25519-dalek 2.1.0",
"ed25519-dalek", "ed25519-dalek",
"generic-array 0.14.2", "generic-array 0.14.2",
"hex 0.4.2", "hex 0.4.2",

View File

@ -59,6 +59,7 @@ solana-sdk-macro = { path = "macro", version = "1.2.16" }
rustversion = "1.0.3" rustversion = "1.0.3"
[dev-dependencies] [dev-dependencies]
curve25519-dalek = "2.1.0"
tiny-bip39 = "0.7.0" tiny-bip39 = "0.7.0"
[package.metadata.docs.rs] [package.metadata.docs.rs]

View File

@ -57,16 +57,18 @@ impl Signature {
Self(GenericArray::clone_from_slice(&signature_slice)) Self(GenericArray::clone_from_slice(&signature_slice))
} }
pub fn verify(&self, pubkey_bytes: &[u8], message_bytes: &[u8]) -> bool { pub(self) fn verify_verbose(
let pubkey = ed25519_dalek::PublicKey::from_bytes(pubkey_bytes); &self,
let signature = ed25519_dalek::Signature::from_bytes(self.0.as_slice()); pubkey_bytes: &[u8],
if pubkey.is_err() || signature.is_err() { message_bytes: &[u8],
return false; ) -> Result<(), ed25519_dalek::SignatureError> {
let publickey = ed25519_dalek::PublicKey::from_bytes(pubkey_bytes)?;
let signature = ed25519_dalek::Signature::from_bytes(self.0.as_slice())?;
publickey.verify_strict(message_bytes, &signature)
} }
pubkey
.unwrap() pub fn verify(&self, pubkey_bytes: &[u8], message_bytes: &[u8]) -> bool {
.verify_strict(message_bytes, &signature.unwrap()) self.verify_verbose(pubkey_bytes, message_bytes).is_ok()
.is_ok()
} }
} }
@ -573,4 +575,25 @@ mod tests {
pubkeys(&[&alice, &bob]) pubkeys(&[&alice, &bob])
); );
} }
#[test]
fn test_off_curve_pubkey_verify_fails() {
// Golden point off the ed25519 curve
let off_curve_bytes = bs58::decode("9z5nJyQar1FUxVJxpBXzon6kHehbomeYiDaLi9WAMhCq")
.into_vec()
.unwrap();
// Confirm golden's off-curvedness
let mut off_curve_bits = [0u8; 32];
off_curve_bits.copy_from_slice(&off_curve_bytes);
let off_curve_point = curve25519_dalek::edwards::CompressedEdwardsY(off_curve_bits);
assert_eq!(off_curve_point.decompress(), None);
let pubkey = Pubkey::new(&off_curve_bytes);
let signature = Signature::default();
// Unfortunately, ed25519-dalek doesn't surface the internal error types that we'd ideally
// `source()` out of the `SignatureError` returned by `verify_strict()`. So the best we
// can do is `is_err()` here.
assert!(signature.verify_verbose(pubkey.as_ref(), &[0u8]).is_err());
}
} }