pub fn verify_batch(
messages: &[&[u8]],
signatures: &[Signature],
verifying_keys: &[VerifyingKey],
) -> Result<(), SignatureError>Expand description
Verify a batch of signatures on messages with their respective verifying_keys.
§Inputs
messagesis a slice of byte slices, one per signed message.signaturesis a slice ofSignatures.verifying_keysis a slice ofVerifyingKeys.
§Returns
- A
ResultwhoseOkvalue is an empty tuple and whoseErrvalue is aSignatureErrorcontaining a description of the internal error which occurred.
§On Deterministic Nonces
The nonces for batch signature verification are derived purely from the inputs to this function themselves.
In any sigma protocol it is wise to include as much context pertaining to the public state in the protocol as possible, to avoid malleability attacks where an adversary alters publics in an algebraic manner that manages to satisfy the equations for the protocol in question.
For ed25519 batch verification we include the following as scalars in the protocol transcript:
- All of the computed
H(R||A||M)s to the protocol transcript, and - All of the
scomponents of each signature.
The former, while not quite as elegant as adding the Rs, As, and
Ms separately, saves us a bit of context hashing since the
H(R||A||M)s need to be computed for the verification equation anyway.
The latter prevents a malleability attack wherein an adversary, without access
to the signing key(s), can take any valid signature, (s,R), and swap
s with s' = -z1. This doesn’t constitute a signature forgery, merely
a vulnerability, as the resulting signature will not pass single
signature verification. (Thanks to Github users @real_or_random and
@jonasnick for pointing out this malleability issue.)
§Examples
use ed25519_dalek::{
verify_batch, SigningKey, VerifyingKey, Signer, Signature,
};
use rand::rngs::OsRng;
let mut csprng = OsRng;
let signing_keys: Vec<_> = (0..64).map(|_| SigningKey::generate(&mut csprng)).collect();
let msg: &[u8] = b"They're good dogs Brant";
let messages: Vec<_> = (0..64).map(|_| msg).collect();
let signatures: Vec<_> = signing_keys.iter().map(|key| key.sign(&msg)).collect();
let verifying_keys: Vec<_> = signing_keys.iter().map(|key| key.verifying_key()).collect();
let result = verify_batch(&messages, &signatures, &verifying_keys);
assert!(result.is_ok());