From 69e1efe6846e58877dddcc9f9006562273fb812c Mon Sep 17 00:00:00 2001 From: zz-sol Date: Mon, 22 Jun 2026 09:47:19 -0400 Subject: [PATCH] better error handling for batch verify (#57) --- .../solana-ed25519/src/ed_sigs/batch.rs | 2 +- .../solana-ed25519/src/ed_sigs/tests/batch.rs | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/curve25519/solana-ed25519/src/ed_sigs/batch.rs b/curve25519/solana-ed25519/src/ed_sigs/batch.rs index a43fcc9..4fb87e0 100644 --- a/curve25519/solana-ed25519/src/ed_sigs/batch.rs +++ b/curve25519/solana-ed25519/src/ed_sigs/batch.rs @@ -182,7 +182,7 @@ impl Verifier { for (vk_bytes, sigs) in self.signatures.iter() { let A = CompressedEdwardsY(vk_bytes.0) .decompress() - .ok_or(Error::InvalidSignature)?; + .ok_or(Error::MalformedPublicKey)?; let mut A_coeff = Scalar::ZERO; diff --git a/curve25519/solana-ed25519/src/ed_sigs/tests/batch.rs b/curve25519/solana-ed25519/src/ed_sigs/tests/batch.rs index aee4fe0..b8fde27 100644 --- a/curve25519/solana-ed25519/src/ed_sigs/tests/batch.rs +++ b/curve25519/solana-ed25519/src/ed_sigs/tests/batch.rs @@ -1,6 +1,7 @@ #![cfg(all(feature = "alloc", feature = "rand_core"))] use crate::ed_sigs::*; +use crate::edwards::CompressedEdwardsY; use alloc::vec::Vec; #[test] @@ -47,3 +48,37 @@ fn batch_verify_with_one_bad_sig() { } } } + +#[test] +fn batch_verify_with_malformed_verification_key() { + let seed = [1u8; 32]; + let sk = SigningKey::from(seed); + let msg = b"BatchVerifyTest"; + let sig = sk.sign(&msg[..]); + let malformed_key = VerificationKeyBytes::from(first_undecodable_compressed_edwards_y()); + + assert_eq!( + VerificationKey::try_from(malformed_key), + Err(Error::MalformedPublicKey) + ); + + let mut batch = batch::Verifier::new(); + batch.queue((malformed_key, sig, msg)); + + assert_eq!( + batch.verify(rand::thread_rng()), + Err(Error::MalformedPublicKey) + ); +} + +fn first_undecodable_compressed_edwards_y() -> [u8; 32] { + for candidate in 0u16..=u16::MAX { + let mut bytes = [0u8; 32]; + bytes[..2].copy_from_slice(&candidate.to_le_bytes()); + if CompressedEdwardsY(bytes).decompress().is_none() { + return bytes; + } + } + + panic!("failed to find an undecodable compressed Edwards-Y encoding"); +}