#![cfg_attr(not(feature = "alloc"), no_std)]
#![doc = include_str!("../README.md")]
#![warn(clippy::pedantic)] #![allow(clippy::module_name_repetitions)] #![allow(clippy::similar_names)] #![allow(clippy::clone_on_copy)] #![deny(missing_docs)]
pub use signature;
mod address;
mod fors;
mod hashes;
mod hypertree;
mod signature_encoding;
mod signing_key;
mod util;
mod verifying_key;
mod wots;
mod xmss;
pub use signature_encoding::*;
pub use signing_key::*;
pub use verifying_key::*;
use fors::ForsParams;
pub use hashes::*;
#[allow(private_bounds)] pub trait ParameterSet:
ForsParams + SigningKeyLen + VerifyingKeyLen + SignatureLen + PartialEq + Eq
{
const NAME: &'static str;
const ALGORITHM_OID: pkcs8::ObjectIdentifier;
}
#[cfg(test)]
mod tests {
use super::*;
use rand::Rng;
use signature::*;
use util::macros::test_parameter_sets;
fn test_sign_verify<P: ParameterSet>() {
let mut rng = rand::rngs::OsRng;
let sk = SigningKey::<P>::new(&mut rng);
let vk = sk.verifying_key();
let msg = b"Hello, world!";
let sig = sk.try_sign(msg).unwrap();
vk.verify(msg, &sig).unwrap();
}
test_parameter_sets!(test_sign_verify);
#[test]
fn test_sign_verify_shake_128f_fail_on_modified_message() {
let mut rng = rand::rngs::OsRng;
let sk = SigningKey::<Shake128f>::new(&mut rng);
let msg = b"Hello, world!";
let modified_msg = b"Goodbye, world!";
let sig = sk.try_sign(msg).unwrap();
let vk = sk.verifying_key();
assert!(vk.verify(msg, &sig).is_ok());
assert!(vk.verify(modified_msg, &sig).is_err());
}
#[test]
fn test_sign_verify_fail_with_wrong_verifying_key() {
let mut rng = rand::rngs::OsRng;
let sk = SigningKey::<Shake128f>::new(&mut rng);
let wrong_sk = SigningKey::<Shake128f>::new(&mut rng); let msg = b"Hello, world!";
let sig = sk.try_sign(msg).unwrap();
let vk = sk.verifying_key();
let wrong_vk = wrong_sk.verifying_key(); assert!(vk.verify(msg, &sig).is_ok());
assert!(wrong_vk.verify(msg, &sig).is_err()); }
#[test]
fn test_sign_verify_fail_on_modified_signature() {
let mut rng = rand::rngs::OsRng;
let sk = SigningKey::<Shake128f>::new(&mut rng);
let msg = b"Hello, world!";
let mut sig_bytes = sk.try_sign(msg).unwrap().to_bytes();
let sig_len = sig_bytes.len();
let random_byte_index = rng.gen_range(0..sig_len);
sig_bytes[random_byte_index] ^= 0xff; let sig = (&sig_bytes).into();
let vk = sk.verifying_key();
assert!(
vk.verify(msg, &sig).is_err(),
"Verification should fail with a modified signature"
);
}
#[test]
fn test_successive_signatures_not_equal() {
let mut rng = rand::rngs::OsRng;
let sk = SigningKey::<Shake128f>::new(&mut rng);
let msg = b"Hello, world!";
let sig1 = sk.try_sign_with_rng(&mut rng, msg).unwrap();
let sig2 = sk.try_sign_with_rng(&mut rng, msg).unwrap();
assert_ne!(
sig1, sig2,
"Two successive randomized signatures over the same message should not be equal"
);
}
#[test]
fn test_sign_verify_nonempty_context() {
let mut rng = rand::rngs::OsRng;
let sk = SigningKey::<Shake128f>::new(&mut rng);
let vk = sk.verifying_key();
let msg = b"Hello, world!";
let ctx = b"Test context";
let sig = sk.try_sign_with_context(msg, ctx, None).unwrap();
vk.try_verify_with_context(msg, ctx, &sig).unwrap();
}
#[test]
fn test_sign_verify_wrong_context() {
let mut rng = rand::rngs::OsRng;
let sk = SigningKey::<Shake128f>::new(&mut rng);
let vk = sk.verifying_key();
let msg = b"Hello, world!";
let ctx = b"Test context!";
let wrong_ctx = b"Wrong context";
let sig = sk.try_sign_with_context(msg, ctx, None).unwrap();
assert!(vk.try_verify_with_context(msg, wrong_ctx, &sig).is_err());
}
}