hashiverse_lib/tools/signing.rs
1//! # Ed25519 signing and verification helpers
2//!
3//! Thin wrappers over `ed25519-dalek` that accept and return hashiverse's newtype-wrapped
4//! [`Signature`], [`SignatureKey`] and [`VerificationKey`] instead of raw byte arrays.
5//!
6//! Three functions cover the common cases:
7//! - [`sign`] — sign a single slice directly.
8//! - [`sign_multiple`] — Blake3-hash a list of slices then sign the 32-byte digest. Used
9//! anywhere the "message" is a tuple of fields (post headers, bucket commitments, peer
10//! announcements) — cheaper and produces a deterministic canonical form regardless of
11//! field sizes.
12//! - [`verify`] — verify an Ed25519 signature against its signed data.
13//!
14//! Post-quantum fallbacks (Falcon, Dilithium) live in [`crate::tools::keys_post_quantum`]
15//! and are invoked only once the network signals a transition away from Ed25519.
16
17use crate::tools::hashing;
18use crate::tools::types::{Signature, SignatureKey, VerificationKey};
19
20pub fn sign(signature_key: &SignatureKey, data: &[u8]) -> Signature {
21 use ed25519_dalek::Signer;
22 let signature = signature_key.0.sign(data);
23 Signature::from_bytes_exact(signature.into())
24}
25
26pub fn sign_multiple(signature_key: &SignatureKey, datas: &[&[u8]]) -> Signature {
27 let hash = hashing::hash_multiple(datas);
28 sign(signature_key, hash.as_ref())
29}
30
31pub fn verify(verification_key: &VerificationKey, signature: &Signature, data: &[u8]) -> anyhow::Result<()> {
32 use ed25519_dalek::{Verifier};
33 let signature = ed25519_dalek::Signature::from_bytes(signature);
34 let verifying_key = verification_key.0;
35 verifying_key.verify(data, &signature)?;
36 Ok(())
37}