pub fn verify_batch(
    messages: &[&[u8]],
    signatures: &[Signature],
    verifying_keys: &[VerifyingKey]
) -> Result<(), SignatureError>
Available on crate feature batch only.
Expand description

Verify a batch of signatures on messages with their respective verifying_keys.

§Inputs

  • messages is a slice of byte slices, one per signed message.
  • signatures is a slice of Signatures.
  • verifying_keys is a slice of VerifyingKeys.

§Returns

  • A Result whose Ok value is an empty tuple and whose Err value is a SignatureError containing 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 s components 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());