use super::*;
impl<N: Network> Signature<N> {
pub fn verify(&self, address: &Address<N>, message: &[Field<N>]) -> bool {
if message.len() > N::MAX_DATA_SIZE_IN_FIELDS as usize {
eprintln!("Cannot sign the signature: the signed message exceeds maximum allowed size");
return false;
}
let pk_sig = self.compute_key.pk_sig();
let pr_sig = self.compute_key.pr_sig();
let g_r = N::g_scalar_multiply(&self.response) + (pk_sig * self.challenge);
let mut preimage = Vec::with_capacity(4 + message.len());
preimage.extend([g_r, pk_sig, pr_sig, **address].map(|point| point.to_x_coordinate()));
preimage.extend(message);
let candidate_challenge = match N::hash_to_scalar_psd8(&preimage) {
Ok(candidate_challenge) => candidate_challenge,
Err(_) => return false,
};
let candidate_address = match Address::try_from(self.compute_key) {
Ok(candidate_address) => candidate_address,
Err(_) => return false,
};
self.challenge == candidate_challenge && *address == candidate_address
}
pub fn verify_bytes(&self, address: &Address<N>, message: &[u8]) -> bool {
self.verify_bits(address, &message.to_bits_le())
}
pub fn verify_bits(&self, address: &Address<N>, message: &[bool]) -> bool {
match message.chunks(Field::<N>::size_in_data_bits()).map(Field::from_bits_le).collect::<Result<Vec<_>>>() {
Ok(fields) => self.verify(address, &fields),
Err(error) => {
eprintln!("Failed to verify signature: {error}");
false
}
}
}
}
#[cfg(test)]
#[cfg(feature = "private_key")]
mod tests {
use super::*;
use snarkvm_console_network::MainnetV0;
type CurrentNetwork = MainnetV0;
const ITERATIONS: u64 = 100;
#[test]
fn test_sign_and_verify() -> Result<()> {
let rng = &mut TestRng::default();
for i in 0..ITERATIONS {
let private_key = PrivateKey::<CurrentNetwork>::new(rng)?;
let address = Address::try_from(&private_key)?;
let message: Vec<_> = (0..i).map(|_| Uniform::rand(rng)).collect();
let signature = Signature::sign(&private_key, &message, rng)?;
assert!(signature.verify(&address, &message));
let failure_message: Vec<_> = (0..i).map(|_| Uniform::rand(rng)).collect();
if message != failure_message {
assert!(!signature.verify(&address, &failure_message));
}
}
Ok(())
}
#[test]
fn test_sign_and_verify_bytes() -> Result<()> {
let rng = &mut TestRng::default();
for i in 0..ITERATIONS {
let private_key = PrivateKey::<CurrentNetwork>::new(rng)?;
let address = Address::try_from(&private_key)?;
let message: Vec<_> = (0..i).map(|_| Uniform::rand(rng)).collect();
let signature = Signature::sign_bytes(&private_key, &message, rng)?;
assert!(signature.verify_bytes(&address, &message));
let failure_message: Vec<_> = (0..i).map(|_| Uniform::rand(rng)).collect();
if message != failure_message {
assert!(!signature.verify_bytes(&address, &failure_message));
}
}
Ok(())
}
#[test]
fn test_sign_and_verify_bits() -> Result<()> {
let rng = &mut TestRng::default();
for i in 0..ITERATIONS {
let private_key = PrivateKey::<CurrentNetwork>::new(rng)?;
let address = Address::try_from(&private_key)?;
let message: Vec<_> = (0..i).map(|_| Uniform::rand(rng)).collect();
let signature = Signature::sign_bits(&private_key, &message, rng)?;
assert!(signature.verify_bits(&address, &message));
let failure_message: Vec<_> = (0..i).map(|_| Uniform::rand(rng)).collect();
if message != failure_message {
assert!(!signature.verify_bits(&address, &failure_message));
}
}
Ok(())
}
}