From 6bab551ffbdcb8704e6601ed8fe7c59eed7c833d Mon Sep 17 00:00:00 2001 From: eschorn1 Date: Sat, 10 Feb 2024 14:26:37 -0600 Subject: [PATCH] dudect --- Cargo.toml | 15 +- dudect/Cargo.toml | 22 +++ dudect/README.md | 25 +++ dudect/src/main.rs | 36 ++++ src/lib.rs | 409 +++++++++++++++++++++++++++++++++++++++++---- src/traits.rs | 170 +++++++++++++++++-- 6 files changed, 630 insertions(+), 47 deletions(-) create mode 100644 dudect/Cargo.toml create mode 100644 dudect/README.md create mode 100644 dudect/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index 9b93351..23670a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,6 @@ hex = "0.4.3" [features] -#default = ["default-rng", "slh_dsa_shake_128s", "slh_dsa_sha2_128s"] default = ["default-rng", "slh_dsa_sha2_128s", "slh_dsa_shake_128s", "slh_dsa_sha2_128f", "slh_dsa_shake_128f", "slh_dsa_sha2_192s", "slh_dsa_shake_192s", "slh_dsa_sha2_192f", "slh_dsa_shake_192f", "slh_dsa_sha2_256s", "slh_dsa_shake_256s", "slh_dsa_sha2_256f", "slh_dsa_shake_256f"] @@ -43,3 +42,17 @@ slh_dsa_shake_256f = [] [profile.dev] opt-level = 3 + + +#[[bench]] +#name = "benchmark" +#harness = false + + +[profile.bench] +debug = true +debug-assertions = false +incremental = false +lto = true +opt-level = 3 +overflow-checks = false \ No newline at end of file diff --git a/dudect/Cargo.toml b/dudect/Cargo.toml new file mode 100644 index 0000000..a691631 --- /dev/null +++ b/dudect/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "fips205-dudect" +version = "0.1.0" +authors = ["Eric Schorn "] +publish = false +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + +[dependencies] +fips205 = { path = ".." } +dudect-bencher = "0.6" + + +[profile.bench] +debug = true +debug-assertions = false +incremental = false +lto = true +opt-level = 3 +overflow-checks = false \ No newline at end of file diff --git a/dudect/README.md b/dudect/README.md new file mode 100644 index 0000000..05ed7a8 --- /dev/null +++ b/dudect/README.md @@ -0,0 +1,25 @@ +This needs work... + +See https://docs.rs/dudect-bencher/latest/dudect_bencher/ + +Dudect can indicate something terribly wrong, but not too much else. + + +~~~ +$ cargo run --release -- --continuous sign + Finished release [optimized] target(s) in 7.34s + Running `target/release/fips205-dudect --continuous sign` +running 1 benchmark continuously +bench sign seeded with 0x2e4df99cf3c2b95b +bench sign ... : n == +0.000M, max t = +1.89036, max tau = +0.56996, (5/tau)^2 = 76 +bench sign ... : n == +0.000M, max t = +3.41458, max tau = +0.72799, (5/tau)^2 = 47 +bench sign ... : n == +0.000M, max t = +3.15437, max tau = +0.56654, (5/tau)^2 = 77 +bench sign ... : n == +0.000M, max t = +3.68377, max tau = +0.57531, (5/tau)^2 = 75 +bench sign ... : n == +0.000M, max t = +4.21598, max tau = +0.48046, (5/tau)^2 = 108 +bench sign ... : n == +0.000M, max t = +3.89742, max tau = +0.39987, (5/tau)^2 = 156 +bench sign ... : n == +0.000M, max t = +4.01349, max tau = +0.37924, (5/tau)^2 = 173 +bench sign ... : n == +0.000M, max t = +3.47164, max tau = +0.30566, (5/tau)^2 = 267 +bench sign ... : n == +0.000M, max t = +3.55797, max tau = +0.29547, (5/tau)^2 = 286 +bench sign ... : n == +0.000M, max t = +2.97639, max tau = +0.23604, (5/tau)^2 = 448 +~~~ + diff --git a/dudect/src/main.rs b/dudect/src/main.rs new file mode 100644 index 0000000..328f004 --- /dev/null +++ b/dudect/src/main.rs @@ -0,0 +1,36 @@ +use dudect_bencher::{ctbench_main, BenchRng, Class, CtRunner}; +use fips205::slh_dsa_shake_128s; // Could use any of the twelve security parameter sets. +use fips205::traits::Signer; + +fn sign(runner: &mut CtRunner, mut _rng: &mut BenchRng) { + const ITERATIONS_OUTER: usize = 10; + const ITERATIONS_INNER: usize = 1; + + let message = [0u8, 1, 2, 3, 4, 5, 6, 7]; + + let (_pk1, sk1) = slh_dsa_shake_128s::try_keygen_vt().unwrap(); // Generate both public and secret keys + let (_pk2, sk2) = slh_dsa_shake_128s::try_keygen_vt().unwrap(); // Generate both public and secret keys + + let mut inputs: Vec = Vec::new(); + let mut classes = Vec::new(); + + for _ in 0..ITERATIONS_OUTER { + inputs.push(sk1.clone()); + classes.push(Class::Left); + } + + for _ in 0..ITERATIONS_OUTER { + inputs.push(sk2.clone()); + classes.push(Class::Right); + } + + for (class, input) in classes.into_iter().zip(inputs.into_iter()) { + runner.run_one(class, || { + for _ in 0..ITERATIONS_INNER { + let _ = input.try_sign_ct(&message, true); + } + }) + } +} + +ctbench_main!(sign); diff --git a/src/lib.rs b/src/lib.rs index 52e03e1..8fc2648 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,24 +1,22 @@ #![no_std] #![deny(clippy::pedantic)] #![deny(warnings)] -//#![deny(missing_docs)] +#![deny(missing_docs)] #![doc = include_str!("../README.md")] /// Implements FIPS 205 draft Stateless Hash-Based Digital Signature Standard. /// See -/// TKTK crate doc -// TODO -// 1. General clean-up -// 7. Doc, of course! +/// All functionality is covered by traits, such that consumers can utilize trait objects as desired. +pub mod traits; + mod fors; mod hashers; mod helpers; mod hypertree; mod slh; -pub mod traits; mod types; mod wots; mod xmss; @@ -30,7 +28,7 @@ const W: u32 = 16; const LEN2: u32 = 3; -/// blah +// This common functionality is injected into each parameter set module macro_rules! functionality { () => { use crate::traits::{KeyGen, SerDes, Signer, Verifier}; @@ -39,18 +37,93 @@ macro_rules! functionality { use zeroize::{Zeroize, ZeroizeOnDrop}; - #[derive(Zeroize, ZeroizeOnDrop)] - pub struct PublicKey(SlhPublicKey); + // ----- 'EXTERNAL' DATA TYPES ----- - #[derive(Zeroize, ZeroizeOnDrop)] + /// Correctly sized private key specific to the target security parameter set.
+ /// Implements the [`crate::traits::Signer`] and [`crate::traits::SerDes`] traits. + #[derive(Clone, Zeroize, ZeroizeOnDrop)] pub struct PrivateKey(SlhPrivateKey); + /// Correctly sized public key specific to the target security parameter set.
+ /// Implements the [`crate::traits::Verifier`] and [`crate::traits::SerDes`] traits. + #[derive(Clone, Zeroize, ZeroizeOnDrop)] + pub struct PublicKey(SlhPublicKey); + + /// Empty struct to enable `KeyGen` trait objects across security parameter sets.
+ /// Implements the [`crate::traits::KeyGen`] trait. #[derive(Zeroize, ZeroizeOnDrop)] pub struct KG(); // Arguable how useful an empty struct+trait is... - /// blah + // ----- PRIMARY FUNCTIONS --- + + /// Generates a public and private key pair specific to this security parameter set.
+ /// This function utilizes the OS default random number generator, and makes no (constant) + /// timing assurances. /// # Errors + /// Returns an error when the random number generator fails; propagates internal errors. + /// # Examples + /// ```rust + /// use fips205::slh_dsa_shake_128s; // Could use any of the twelve security parameter sets. + /// use fips205::traits::{SerDes, Signer, Verifier}; + /// # use std::error::Error; + /// # + /// # fn main() -> Result<(), Box> { + /// + /// let msg_bytes = [0u8, 1, 2, 3, 4, 5, 6, 7]; + /// + /// // Generate public/private key pair and signature + /// let (pk1, sk) = slh_dsa_shake_128s::try_keygen_vt()?; // Generate both public and secret keys + /// let sig_bytes = sk.try_sign_ct(&msg_bytes, true)?; // Use the secret key to generate a msg signature + /// + /// // Serialize the public key, and send with message and signature bytes + /// let (pk_send, msg_send, sig_send) = (pk1.into_bytes(), msg_bytes, sig_bytes); + /// let (pk_recv, msg_recv, sig_recv) = (pk_send, msg_send, sig_send); + /// + /// // Deserialize the public key, then use it to verify the msg signature + /// let pk2 = slh_dsa_shake_128s::PublicKey::try_from_bytes(&pk_recv)?; + /// let v = pk2.try_verify_vt(&msg_recv, &sig_recv)?; + /// assert!(v); + /// # Ok(()) + /// # } + /// ``` + #[cfg(feature = "default-rng")] + pub fn try_keygen_vt() -> Result<(PublicKey, PrivateKey), &'static str> { + KG::try_keygen_vt() + } + + + /// Generates a public and private key pair specific to this security parameter set.
+ /// This function utilizes a supplied random number generator, and makes no (constant) + /// timing assurances. + /// # Errors + /// Returns an error when the random number generator fails; propagates internal errors. + /// # Examples + /// ```rust + /// use fips205::slh_dsa_shake_128s; // Could use any of the twelve security parameter sets. + /// use fips205::traits::{SerDes, Signer, Verifier}; + /// use rand_chacha::rand_core::SeedableRng; + /// # use std::error::Error; + /// # + /// # fn main() -> Result<(), Box> { + /// + /// let message = [0u8, 1, 2, 3, 4, 5, 6, 7]; + /// let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(123); + /// + /// // Generate key pair and signature + /// let (pk, sk) = slh_dsa_shake_128s::try_keygen_with_rng_vt(&mut rng)?; // Generate both public and secret keys + /// let sig = sk.try_sign_ct(&message, true)?; // Use the secret key to generate a message signature /// + /// let v = pk.try_verify_vt(&message, &sig)?; + /// assert!(v); + /// # Ok(())} + /// ``` + pub fn try_keygen_with_rng_vt( + rng: &mut impl CryptoRngCore, + ) -> Result<(PublicKey, PrivateKey), &'static str> { + KG::try_keygen_with_rng_vt(rng) + } + + impl KeyGen for KG { type PrivateKey = PrivateKey; type PublicKey = PublicKey; @@ -64,19 +137,9 @@ macro_rules! functionality { } - /// blah - /// # Errors - #[cfg(feature = "default-rng")] - pub fn try_keygen_vt() -> Result<(PublicKey, PrivateKey), &'static str> { - KG::try_keygen_vt() - } - - impl Signer for PrivateKey { type Signature = [u8; SIG_LEN]; - /// blah - /// # Errors fn try_sign_with_rng_ct( &self, rng: &mut impl CryptoRngCore, m: &[u8], randomize: bool, ) -> Result<[u8; SIG_LEN], &'static str> { @@ -91,7 +154,6 @@ macro_rules! functionality { impl Verifier for PublicKey { type Signature = [u8; SIG_LEN]; - /// blah fn try_verify_vt( &self, m: &[u8], sig_bytes: &[u8; SIG_LEN], ) -> Result { @@ -104,6 +166,8 @@ macro_rules! functionality { } + // ----- SERIALIZATION AND DESERIALIZATION --- + impl SerDes for PublicKey { type ByteArray = [u8; PK_LEN]; @@ -155,6 +219,7 @@ macro_rules! functionality { use super::*; use rand_chacha::rand_core::SeedableRng; + // Test keygen, sign, serDes everything, verify true/false #[test] fn simple_round_trips() { let mut message = [0u8, 1, 2, 3]; @@ -179,7 +244,24 @@ macro_rules! functionality { } -/// TKTK +/// Functionality for the **SLH-DSA-SHA2-128s** security parameter set per FIPS 205 section 10. This includes specific +/// sizes for the public key, secret key, and signature along with a number of internal constants. The +/// SLH-DSA-SHA2-128s parameter set is claimed to be in security strength category 1. +/// +/// **1)** The basic usage is for an originator to start with the [`slh_dsa_sha2_128s::try_keygen_vt`] function below +/// to generate both [`slh_dsa_sha2_128s::PublicKey`] and [`slh_dsa_sha2_128s::PrivateKey`] structs. The resulting +/// [`slh_dsa_sha2_128s::PrivateKey`] struct implements the [`traits::Signer`] trait which supplies several functions +/// to sign byte-array messages, such as [`traits::Signer::try_sign_ct()`], resulting in a Signature byte-array. +/// +/// **2)** Both the `PrivateKey` and `PublicKey` structs implement the [`traits::SerDes`] trait. The originator +/// utilizes the [`traits::SerDes::into_bytes()`] functions to serialize the `PublicKey` struct into a byte-array for +/// distribution. The remote party utilizes the [`traits::SerDes::try_from_bytes()`] function to deserialize the +/// `PublicKey` byte-array into its struct. +/// +/// **3)** Finally, the remote party uses the [`traits::Verifier::try_verify_vt()`] function implemented on the +/// [`slh_dsa_sha2_128s::PublicKey`] struct to verify the message byte-array with the Signature byte-array.. +/// +/// See the top-level [crate] documentation for example code that implements the above flow. #[cfg(feature = "slh_dsa_sha2_128s")] pub mod slh_dsa_sha2_128s { use crate::hashers::sha2_cat_1::{f, h, h_msg, prf, prf_msg, t_l}; @@ -195,9 +277,15 @@ pub mod slh_dsa_sha2_128s { type M = U30; type Len = Sum, U3>; + /// Length of public key pub const PK_LEN: usize = 32; + + /// Length of signature byte-array pub const SIG_LEN: usize = 7856; + + /// Length of private/secret key pub const SK_LEN: usize = PK_LEN * 2; + static HASHERS: Hashers = Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l }; @@ -205,7 +293,24 @@ pub mod slh_dsa_sha2_128s { } -/// TKTK +/// Functionality for the **SLH-DSA-SHAKE-128s** security parameter set per FIPS 205 section 10. This includes specific +/// sizes for the public key, secret key, and signature along with a number of internal constants. The +/// SLH-DSA-SHAKE-128s parameter set is claimed to be in security strength category 1. +/// +/// **1)** The basic usage is for an originator to start with the [`slh_dsa_shake_128s::try_keygen_vt`] function below +/// to generate both [`slh_dsa_shake_128s::PublicKey`] and [`slh_dsa_shake_128s::PrivateKey`] structs. The resulting +/// [`slh_dsa_shake_128s::PrivateKey`] struct implements the [`traits::Signer`] trait which supplies several functions +/// to sign byte-array messages, such as [`traits::Signer::try_sign_ct()`], resulting in a Signature byte-array. +/// +/// **2)** Both the `PrivateKey` and `PublicKey` structs implement the [`traits::SerDes`] trait. The originator +/// utilizes the [`traits::SerDes::into_bytes()`] functions to serialize the `PublicKey` struct into a byte-array for +/// distribution. The remote party utilizes the [`traits::SerDes::try_from_bytes()`] function to deserialize the +/// `PublicKey` byte-array into its struct. +/// +/// **3)** Finally, the remote party uses the [`traits::Verifier::try_verify_vt()`] function implemented on the +/// [`slh_dsa_shake_128s::PublicKey`] struct to verify the message byte-array with the Signature byte-array.. +/// +/// See the top-level [crate] documentation for example code that implements the above flow. #[cfg(feature = "slh_dsa_shake_128s")] pub mod slh_dsa_shake_128s { use crate::hashers::shake::{f, h, h_msg, prf, prf_msg, t_l}; @@ -221,9 +326,15 @@ pub mod slh_dsa_shake_128s { type M = U30; type Len = Sum, U3>; + /// Length of public key pub const PK_LEN: usize = 32; + + /// Length of signature byte-array pub const SIG_LEN: usize = 7856; + + /// Length of private/secret key pub const SK_LEN: usize = PK_LEN * 2; + static HASHERS: Hashers = Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l }; @@ -231,7 +342,24 @@ pub mod slh_dsa_shake_128s { } -/// TKTK +/// Functionality for the **SLH-DSA-SHA2-128f** security parameter set per FIPS 205 section 10. This includes specific +/// sizes for the public key, secret key, and signature along with a number of internal constants. The +/// SLH-DSA-SHA2-128f parameter set is claimed to be in security strength category 1. +/// +/// **1)** The basic usage is for an originator to start with the [`slh_dsa_sha2_128f::try_keygen_vt`] function below +/// to generate both [`slh_dsa_sha2_128f::PublicKey`] and [`slh_dsa_sha2_128f::PrivateKey`] structs. The resulting +/// [`slh_dsa_sha2_128f::PrivateKey`] struct implements the [`traits::Signer`] trait which supplies several functions +/// to sign byte-array messages, such as [`traits::Signer::try_sign_ct()`], resulting in a Signature byte-array. +/// +/// **2)** Both the `PrivateKey` and `PublicKey` structs implement the [`traits::SerDes`] trait. The originator +/// utilizes the [`traits::SerDes::into_bytes()`] functions to serialize the `PublicKey` struct into a byte-array for +/// distribution. The remote party utilizes the [`traits::SerDes::try_from_bytes()`] function to deserialize the +/// `PublicKey` byte-array into its struct. +/// +/// **3)** Finally, the remote party uses the [`traits::Verifier::try_verify_vt()`] function implemented on the +/// [`slh_dsa_sha2_128f::PublicKey`] struct to verify the message byte-array with the Signature byte-array.. +/// +/// See the top-level [crate] documentation for example code that implements the above flow. #[cfg(feature = "slh_dsa_sha2_128f")] pub mod slh_dsa_sha2_128f { use crate::hashers::sha2_cat_1::{f, h, h_msg, prf, prf_msg, t_l}; @@ -247,9 +375,15 @@ pub mod slh_dsa_sha2_128f { type M = U34; type Len = Sum, U3>; + /// Length of public key pub const PK_LEN: usize = 32; + + /// Length of signature byte-array pub const SIG_LEN: usize = 17088; + + /// Length of private/secret key pub const SK_LEN: usize = PK_LEN * 2; + static HASHERS: Hashers = Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l }; @@ -257,7 +391,24 @@ pub mod slh_dsa_sha2_128f { } -/// TKTK +/// Functionality for the **SLH-DSA-SHAKE-128f** security parameter set per FIPS 205 section 10. This includes specific +/// sizes for the public key, secret key, and signature along with a number of internal constants. The +/// SLH-DSA-SHAKE-128f parameter set is claimed to be in security strength category 1. +/// +/// **1)** The basic usage is for an originator to start with the [`slh_dsa_shake_128f::try_keygen_vt`] function below +/// to generate both [`slh_dsa_shake_128f::PublicKey`] and [`slh_dsa_shake_128f::PrivateKey`] structs. The resulting +/// [`slh_dsa_shake_128f::PrivateKey`] struct implements the [`traits::Signer`] trait which supplies several functions +/// to sign byte-array messages, such as [`traits::Signer::try_sign_ct()`], resulting in a Signature byte-array. +/// +/// **2)** Both the `PrivateKey` and `PublicKey` structs implement the [`traits::SerDes`] trait. The originator +/// utilizes the [`traits::SerDes::into_bytes()`] functions to serialize the `PublicKey` struct into a byte-array for +/// distribution. The remote party utilizes the [`traits::SerDes::try_from_bytes()`] function to deserialize the +/// `PublicKey` byte-array into its struct. +/// +/// **3)** Finally, the remote party uses the [`traits::Verifier::try_verify_vt()`] function implemented on the +/// [`slh_dsa_shake_128f::PublicKey`] struct to verify the message byte-array with the Signature byte-array.. +/// +/// See the top-level [crate] documentation for example code that implements the above flow. #[cfg(feature = "slh_dsa_shake_128f")] pub mod slh_dsa_shake_128f { use crate::hashers::shake::{f, h, h_msg, prf, prf_msg, t_l}; @@ -273,9 +424,15 @@ pub mod slh_dsa_shake_128f { type M = U34; type Len = Sum, U3>; + /// Length of public key pub const PK_LEN: usize = 32; + + /// Length of signature byte-array pub const SIG_LEN: usize = 17088; + + /// Length of private/secret key pub const SK_LEN: usize = PK_LEN * 2; + static HASHERS: Hashers = Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l }; @@ -283,7 +440,24 @@ pub mod slh_dsa_shake_128f { } -/// TKTK +/// Functionality for the **SLH-DSA-SHA2-192s** security parameter set per FIPS 205 section 10. This includes specific +/// sizes for the public key, secret key, and signature along with a number of internal constants. The +/// SLH-DSA-SHA2-192s parameter set is claimed to be in security strength category 3. +/// +/// **1)** The basic usage is for an originator to start with the [`slh_dsa_sha2_192s::try_keygen_vt`] function below +/// to generate both [`slh_dsa_sha2_192s::PublicKey`] and [`slh_dsa_sha2_192s::PrivateKey`] structs. The resulting +/// [`slh_dsa_sha2_192s::PrivateKey`] struct implements the [`traits::Signer`] trait which supplies several functions +/// to sign byte-array messages, such as [`traits::Signer::try_sign_ct()`], resulting in a Signature byte-array. +/// +/// **2)** Both the `PrivateKey` and `PublicKey` structs implement the [`traits::SerDes`] trait. The originator +/// utilizes the [`traits::SerDes::into_bytes()`] functions to serialize the `PublicKey` struct into a byte-array for +/// distribution. The remote party utilizes the [`traits::SerDes::try_from_bytes()`] function to deserialize the +/// `PublicKey` byte-array into its struct. +/// +/// **3)** Finally, the remote party uses the [`traits::Verifier::try_verify_vt()`] function implemented on the +/// [`slh_dsa_sha2_192s::PublicKey`] struct to verify the message byte-array with the Signature byte-array.. +/// +/// See the top-level [crate] documentation for example code that implements the above flow. #[cfg(feature = "slh_dsa_sha2_192s")] pub mod slh_dsa_sha2_192s { use crate::hashers::sha2_cat_3_5::{f, h, h_msg, prf, prf_msg, t_l}; @@ -299,9 +473,15 @@ pub mod slh_dsa_sha2_192s { type M = U39; type Len = Sum, U3>; + /// Length of public key pub const PK_LEN: usize = 48; + + /// Length of signature byte-array pub const SIG_LEN: usize = 16224; + + /// Length of private/secret key pub const SK_LEN: usize = PK_LEN * 2; + static HASHERS: Hashers = Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l }; @@ -309,7 +489,24 @@ pub mod slh_dsa_sha2_192s { } -/// TKTK +/// Functionality for the **SLH-DSA-SHAKE-192s** security parameter set per FIPS 205 section 10. This includes specific +/// sizes for the public key, secret key, and signature along with a number of internal constants. The +/// SLH-DSA-SHAKE-192s parameter set is claimed to be in security strength category 3. +/// +/// **1)** The basic usage is for an originator to start with the [`slh_dsa_shake_192s::try_keygen_vt`] function below +/// to generate both [`slh_dsa_shake_192s::PublicKey`] and [`slh_dsa_shake_192s::PrivateKey`] structs. The resulting +/// [`slh_dsa_shake_192s::PrivateKey`] struct implements the [`traits::Signer`] trait which supplies several functions +/// to sign byte-array messages, such as [`traits::Signer::try_sign_ct()`], resulting in a Signature byte-array. +/// +/// **2)** Both the `PrivateKey` and `PublicKey` structs implement the [`traits::SerDes`] trait. The originator +/// utilizes the [`traits::SerDes::into_bytes()`] functions to serialize the `PublicKey` struct into a byte-array for +/// distribution. The remote party utilizes the [`traits::SerDes::try_from_bytes()`] function to deserialize the +/// `PublicKey` byte-array into its struct. +/// +/// **3)** Finally, the remote party uses the [`traits::Verifier::try_verify_vt()`] function implemented on the +/// [`slh_dsa_shake_192s::PublicKey`] struct to verify the message byte-array with the Signature byte-array.. +/// +/// See the top-level [crate] documentation for example code that implements the above flow. #[cfg(feature = "slh_dsa_shake_192s")] pub mod slh_dsa_shake_192s { use crate::hashers::shake::{f, h, h_msg, prf, prf_msg, t_l}; @@ -325,9 +522,15 @@ pub mod slh_dsa_shake_192s { type M = U39; type Len = Sum, U3>; + /// Length of public key pub const PK_LEN: usize = 48; + + /// Length of signature byte-array pub const SIG_LEN: usize = 16224; + + /// Length of private/secret key pub const SK_LEN: usize = PK_LEN * 2; + static HASHERS: Hashers = Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l }; @@ -335,7 +538,24 @@ pub mod slh_dsa_shake_192s { } -/// TKTK +/// Functionality for the **SLH-DSA-SHA2-192f** security parameter set per FIPS 205 section 10. This includes specific +/// sizes for the public key, secret key, and signature along with a number of internal constants. The +/// SLH-DSA-SHA2-192f parameter set is claimed to be in security strength category 3. +/// +/// **1)** The basic usage is for an originator to start with the [`slh_dsa_sha2_192f::try_keygen_vt`] function below +/// to generate both [`slh_dsa_sha2_192f::PublicKey`] and [`slh_dsa_sha2_192f::PrivateKey`] structs. The resulting +/// [`slh_dsa_sha2_192f::PrivateKey`] struct implements the [`traits::Signer`] trait which supplies several functions +/// to sign byte-array messages, such as [`traits::Signer::try_sign_ct()`], resulting in a Signature byte-array. +/// +/// **2)** Both the `PrivateKey` and `PublicKey` structs implement the [`traits::SerDes`] trait. The originator +/// utilizes the [`traits::SerDes::into_bytes()`] functions to serialize the `PublicKey` struct into a byte-array for +/// distribution. The remote party utilizes the [`traits::SerDes::try_from_bytes()`] function to deserialize the +/// `PublicKey` byte-array into its struct. +/// +/// **3)** Finally, the remote party uses the [`traits::Verifier::try_verify_vt()`] function implemented on the +/// [`slh_dsa_sha2_192f::PublicKey`] struct to verify the message byte-array with the Signature byte-array.. +/// +/// See the top-level [crate] documentation for example code that implements the above flow. #[cfg(feature = "slh_dsa_sha2_192f")] pub mod slh_dsa_sha2_192f { use crate::hashers::sha2_cat_3_5::{f, h, h_msg, prf, prf_msg, t_l}; @@ -351,9 +571,15 @@ pub mod slh_dsa_sha2_192f { type M = U42; type Len = Sum, U3>; + /// Length of public key pub const PK_LEN: usize = 48; + + /// Length of signature byte-array pub const SIG_LEN: usize = 35664; + + /// Length of private/secret key pub const SK_LEN: usize = PK_LEN * 2; + static HASHERS: Hashers = Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l }; @@ -361,7 +587,24 @@ pub mod slh_dsa_sha2_192f { } -/// TKTK +/// Functionality for the **SLH-DSA-SHAKE-192f** security parameter set per FIPS 205 section 10. This includes specific +/// sizes for the public key, secret key, and signature along with a number of internal constants. The +/// SLH-DSA-SHAKE-192f parameter set is claimed to be in security strength category 3. +/// +/// **1)** The basic usage is for an originator to start with the [`slh_dsa_shake_192f::try_keygen_vt`] function below +/// to generate both [`slh_dsa_shake_192f::PublicKey`] and [`slh_dsa_shake_192f::PrivateKey`] structs. The resulting +/// [`slh_dsa_shake_192f::PrivateKey`] struct implements the [`traits::Signer`] trait which supplies several functions +/// to sign byte-array messages, such as [`traits::Signer::try_sign_ct()`], resulting in a Signature byte-array. +/// +/// **2)** Both the `PrivateKey` and `PublicKey` structs implement the [`traits::SerDes`] trait. The originator +/// utilizes the [`traits::SerDes::into_bytes()`] functions to serialize the `PublicKey` struct into a byte-array for +/// distribution. The remote party utilizes the [`traits::SerDes::try_from_bytes()`] function to deserialize the +/// `PublicKey` byte-array into its struct. +/// +/// **3)** Finally, the remote party uses the [`traits::Verifier::try_verify_vt()`] function implemented on the +/// [`slh_dsa_shake_192f::PublicKey`] struct to verify the message byte-array with the Signature byte-array.. +/// +/// See the top-level [crate] documentation for example code that implements the above flow. #[cfg(feature = "slh_dsa_shake_192f")] pub mod slh_dsa_shake_192f { use crate::hashers::shake::{f, h, h_msg, prf, prf_msg, t_l}; @@ -377,9 +620,15 @@ pub mod slh_dsa_shake_192f { type M = U42; type Len = Sum, U3>; + /// Length of public key pub const PK_LEN: usize = 48; + + /// Length of signature byte-array pub const SIG_LEN: usize = 35664; + + /// Length of private/secret key pub const SK_LEN: usize = PK_LEN * 2; + static HASHERS: Hashers = Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l }; @@ -387,7 +636,24 @@ pub mod slh_dsa_shake_192f { } -/// TKTK +/// Functionality for the **SLH-DSA-SHA2-256s** security parameter set per FIPS 205 section 10. This includes specific +/// sizes for the public key, secret key, and signature along with a number of internal constants. The +/// SLH-DSA-SHA2-256s parameter set is claimed to be in security strength category 5. +/// +/// **1)** The basic usage is for an originator to start with the [`slh_dsa_sha2_256s::try_keygen_vt`] function below +/// to generate both [`slh_dsa_sha2_256s::PublicKey`] and [`slh_dsa_sha2_256s::PrivateKey`] structs. The resulting +/// [`slh_dsa_sha2_256s::PrivateKey`] struct implements the [`traits::Signer`] trait which supplies several functions +/// to sign byte-array messages, such as [`traits::Signer::try_sign_ct()`], resulting in a Signature byte-array. +/// +/// **2)** Both the `PrivateKey` and `PublicKey` structs implement the [`traits::SerDes`] trait. The originator +/// utilizes the [`traits::SerDes::into_bytes()`] functions to serialize the `PublicKey` struct into a byte-array for +/// distribution. The remote party utilizes the [`traits::SerDes::try_from_bytes()`] function to deserialize the +/// `PublicKey` byte-array into its struct. +/// +/// **3)** Finally, the remote party uses the [`traits::Verifier::try_verify_vt()`] function implemented on the +/// [`slh_dsa_sha2_256s::PublicKey`] struct to verify the message byte-array with the Signature byte-array.. +/// +/// See the top-level [crate] documentation for example code that implements the above flow. #[cfg(feature = "slh_dsa_sha2_256s")] pub mod slh_dsa_sha2_256s { use crate::hashers::sha2_cat_3_5::{f, h, h_msg, prf, prf_msg, t_l}; @@ -403,9 +669,15 @@ pub mod slh_dsa_sha2_256s { type M = U47; type Len = Sum, U3>; + /// Length of public key pub const PK_LEN: usize = 64; + + /// Length of signature byte-array pub const SIG_LEN: usize = 29792; + + /// Length of private/secret key pub const SK_LEN: usize = PK_LEN * 2; + static HASHERS: Hashers = Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l }; @@ -413,7 +685,24 @@ pub mod slh_dsa_sha2_256s { } -/// TKTK +/// Functionality for the **SLH-DSA-SHAKE-256s** security parameter set per FIPS 205 section 10. This includes specific +/// sizes for the public key, secret key, and signature along with a number of internal constants. The +/// SLH-DSA-SHAKE_256s parameter set is claimed to be in security strength category 5. +/// +/// **1)** The basic usage is for an originator to start with the [`slh_dsa_shake_256s::try_keygen_vt`] function below +/// to generate both [`slh_dsa_shake_256s::PublicKey`] and [`slh_dsa_shake_256s::PrivateKey`] structs. The resulting +/// [`slh_dsa_shake_256s::PrivateKey`] struct implements the [`traits::Signer`] trait which supplies several functions +/// to sign byte-array messages, such as [`traits::Signer::try_sign_ct()`], resulting in a Signature byte-array. +/// +/// **2)** Both the `PrivateKey` and `PublicKey` structs implement the [`traits::SerDes`] trait. The originator +/// utilizes the [`traits::SerDes::into_bytes()`] functions to serialize the `PublicKey` struct into a byte-array for +/// distribution. The remote party utilizes the [`traits::SerDes::try_from_bytes()`] function to deserialize the +/// `PublicKey` byte-array into its struct. +/// +/// **3)** Finally, the remote party uses the [`traits::Verifier::try_verify_vt()`] function implemented on the +/// [`slh_dsa_shake_256s::PublicKey`] struct to verify the message byte-array with the Signature byte-array.. +/// +/// See the top-level [crate] documentation for example code that implements the above flow. #[cfg(feature = "slh_dsa_shake_256s")] pub mod slh_dsa_shake_256s { use crate::hashers::shake::{f, h, h_msg, prf, prf_msg, t_l}; @@ -429,9 +718,15 @@ pub mod slh_dsa_shake_256s { type M = U47; type Len = Sum, U3>; + /// Length of public key pub const PK_LEN: usize = 64; + + /// Length of signature byte-array pub const SIG_LEN: usize = 29792; + + /// Length of private/secret key pub const SK_LEN: usize = PK_LEN * 2; + static HASHERS: Hashers = Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l }; @@ -439,7 +734,24 @@ pub mod slh_dsa_shake_256s { } -/// TKTK +/// Functionality for the **SLH-DSA-SHA2-256f** security parameter set per FIPS 205 section 10. This includes specific +/// sizes for the public key, secret key, and signature along with a number of internal constants. The +/// SLH-DSA-SHA2-256f parameter set is claimed to be in security strength category 5. +/// +/// **1)** The basic usage is for an originator to start with the [`slh_dsa_sha2_256f::try_keygen_vt`] function below +/// to generate both [`slh_dsa_sha2_256f::PublicKey`] and [`slh_dsa_sha2_256f::PrivateKey`] structs. The resulting +/// [`slh_dsa_sha2_256f::PrivateKey`] struct implements the [`traits::Signer`] trait which supplies several functions +/// to sign byte-array messages, such as [`traits::Signer::try_sign_ct()`], resulting in a Signature byte-array. +/// +/// **2)** Both the `PrivateKey` and `PublicKey` structs implement the [`traits::SerDes`] trait. The originator +/// utilizes the [`traits::SerDes::into_bytes()`] functions to serialize the `PublicKey` struct into a byte-array for +/// distribution. The remote party utilizes the [`traits::SerDes::try_from_bytes()`] function to deserialize the +/// `PublicKey` byte-array into its struct. +/// +/// **3)** Finally, the remote party uses the [`traits::Verifier::try_verify_vt()`] function implemented on the +/// [`slh_dsa_sha2_256f::PublicKey`] struct to verify the message byte-array with the Signature byte-array.. +/// +/// See the top-level [crate] documentation for example code that implements the above flow. #[cfg(feature = "slh_dsa_sha2_256f")] pub mod slh_dsa_sha2_256f { use crate::hashers::sha2_cat_3_5::{f, h, h_msg, prf, prf_msg, t_l}; @@ -455,9 +767,15 @@ pub mod slh_dsa_sha2_256f { type M = U49; type Len = Sum, U3>; + /// Length of public key pub const PK_LEN: usize = 64; + + /// Length of signature byte-array pub const SIG_LEN: usize = 49856; + + /// Length of private/secret key pub const SK_LEN: usize = PK_LEN * 2; + static HASHERS: Hashers = Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l }; @@ -465,7 +783,24 @@ pub mod slh_dsa_sha2_256f { } -/// TKTK +/// Functionality for the **SLH-DSA-SHAKE-256f** security parameter set per FIPS 205 section 10. This includes specific +/// sizes for the public key, secret key, and signature along with a number of internal constants. The +/// SLH-DSA-SHAKE-256f parameter set is claimed to be in security strength category 5. +/// +/// **1)** The basic usage is for an originator to start with the [`slh_dsa_shake_256f::try_keygen_vt`] function below +/// to generate both [`slh_dsa_shake_256f::PublicKey`] and [`slh_dsa_shake_256f::PrivateKey`] structs. The resulting +/// [`slh_dsa_shake_256f::PrivateKey`] struct implements the [`traits::Signer`] trait which supplies several functions +/// to sign byte-array messages, such as [`traits::Signer::try_sign_ct()`], resulting in a Signature byte-array. +/// +/// **2)** Both the `PrivateKey` and `PublicKey` structs implement the [`traits::SerDes`] trait. The originator +/// utilizes the [`traits::SerDes::into_bytes()`] functions to serialize the `PublicKey` struct into a byte-array for +/// distribution. The remote party utilizes the [`traits::SerDes::try_from_bytes()`] function to deserialize the +/// `PublicKey` byte-array into its struct. +/// +/// **3)** Finally, the remote party uses the [`traits::Verifier::try_verify_vt()`] function implemented on the +/// [`slh_dsa_shake_256f::PublicKey`] struct to verify the message byte-array with the Signature byte-array.. +/// +/// See the top-level [crate] documentation for example code that implements the above flow. #[cfg(feature = "slh_dsa_shake_256f")] pub mod slh_dsa_shake_256f { use crate::hashers::shake::{f, h, h_msg, prf, prf_msg, t_l}; @@ -481,9 +816,15 @@ pub mod slh_dsa_shake_256f { type M = U49; type Len = Sum, U3>; + /// Length of public key pub const PK_LEN: usize = 64; + + /// Length of signature byte-array pub const SIG_LEN: usize = 49856; + + /// Length of private/secret key pub const SK_LEN: usize = PK_LEN * 2; + static HASHERS: Hashers = Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l }; diff --git a/src/traits.rs b/src/traits.rs index 938b6eb..e065d56 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -12,7 +12,28 @@ pub trait SerDes { /// Produces a byte array of fixed-size specific to the struct being serialized. /// # Examples /// ```rust - /// println!("Placeholder"); + /// use fips205::slh_dsa_shake_128s; // Could use any of the twelve security parameter sets. + /// use fips205::traits::{SerDes, Signer, Verifier}; + /// # use std::error::Error; + /// # + /// # fn main() -> Result<(), Box> { + /// + /// let msg_bytes = [0u8, 1, 2, 3, 4, 5, 6, 7]; + /// + /// // Generate public/private key pair and signature + /// let (pk1, sk) = slh_dsa_shake_128s::try_keygen_vt()?; // Generate both public and secret keys + /// let sig_bytes = sk.try_sign_ct(&msg_bytes, true)?; // Use the secret key to generate a msg signature + /// + /// // Serialize the public key, and send with message and signature bytes + /// let (pk_send, msg_send, sig_send) = (pk1.into_bytes(), msg_bytes, sig_bytes); + /// let (pk_recv, msg_recv, sig_recv) = (pk_send, msg_send, sig_send); + /// + /// // Deserialize the public key, then use it to verify the msg signature + /// let pk2 = slh_dsa_shake_128s::PublicKey::try_from_bytes(&pk_recv)?; + /// let v = pk2.try_verify_vt(&msg_recv, &sig_recv)?; + /// assert!(v); + /// # Ok(()) + /// # } /// ``` fn into_bytes(self) -> Self::ByteArray; @@ -21,7 +42,28 @@ pub trait SerDes { /// Returns an error on malformed input. /// # Examples /// ```rust - /// println!("Placeholder"); + /// use fips205::slh_dsa_shake_128s; // Could use any of the twelve security parameter sets. + /// use fips205::traits::{SerDes, Signer, Verifier}; + /// # use std::error::Error; + /// # + /// # fn main() -> Result<(), Box> { + /// + /// let msg_bytes = [0u8, 1, 2, 3, 4, 5, 6, 7]; + /// + /// // Generate public/private key pair and signature + /// let (pk1, sk) = slh_dsa_shake_128s::try_keygen_vt()?; // Generate both public and secret keys + /// let sig_bytes = sk.try_sign_ct(&msg_bytes, true)?; // Use the secret key to generate a msg signature + /// + /// // Serialize the public key, and send with message and signature bytes + /// let (pk_send, msg_send, sig_send) = (pk1.into_bytes(), msg_bytes, sig_bytes); + /// let (pk_recv, msg_recv, sig_recv) = (pk_send, msg_send, sig_send); + /// + /// // Deserialize the public key, then use it to verify the msg signature + /// let pk2 = slh_dsa_shake_128s::PublicKey::try_from_bytes(&pk_recv)?; + /// let v = pk2.try_verify_vt(&msg_recv, &sig_recv)?; + /// assert!(v); + /// # Ok(()) + /// # } /// ``` fn try_from_bytes(bytes: &Self::ByteArray) -> Result where @@ -31,9 +73,9 @@ pub trait SerDes { /// The `KeyGen` trait is defined to allow trait objects. pub trait KeyGen { - /// A public key specific to the chosen security parameter set, e.g., ml-dsa-44, ml-dsa-65 or ml-dsa-87 + /// A public key specific to the chosen security parameter set, e.g., `slh_dsa_shake_128s`, `slh_dsa_sha2_128s` etc type PublicKey; - /// A private (secret) key specific to the chosen security parameter set, e.g., ml-dsa-44, ml-dsa-65 or ml-dsa-87 + /// A private (secret) key specific to the chosen security parameter set, e.g., `slh_dsa_shake_128s`, `slh_dsa_sha2_128s` etc type PrivateKey; /// Generates a public and private key pair specific to this security parameter set.
@@ -43,7 +85,28 @@ pub trait KeyGen { /// Returns an error when the random number generator fails; propagates internal errors. /// # Examples /// ```rust - /// println!("Placeholder"); + /// use fips205::slh_dsa_shake_128s; // Could use any of the twelve security parameter sets. + /// use fips205::traits::{SerDes, Signer, Verifier}; + /// # use std::error::Error; + /// # + /// # fn main() -> Result<(), Box> { + /// + /// let msg_bytes = [0u8, 1, 2, 3, 4, 5, 6, 7]; + /// + /// // Generate public/private key pair and signature + /// let (pk1, sk) = slh_dsa_shake_128s::try_keygen_vt()?; // Generate both public and secret keys + /// let sig_bytes = sk.try_sign_ct(&msg_bytes, true)?; // Use the secret key to generate a msg signature + /// + /// // Serialize the public key, and send with message and signature bytes + /// let (pk_send, msg_send, sig_send) = (pk1.into_bytes(), msg_bytes, sig_bytes); + /// let (pk_recv, msg_recv, sig_recv) = (pk_send, msg_send, sig_send); + /// + /// // Deserialize the public key, then use it to verify the msg signature + /// let pk2 = slh_dsa_shake_128s::PublicKey::try_from_bytes(&pk_recv)?; + /// let v = pk2.try_verify_vt(&msg_recv, &sig_recv)?; + /// assert!(v); + /// # Ok(()) + /// # } /// ``` #[cfg(feature = "default-rng")] fn try_keygen_vt() -> Result<(Self::PublicKey, Self::PrivateKey), &'static str> { @@ -57,7 +120,28 @@ pub trait KeyGen { /// Returns an error when the random number generator fails; propagates internal errors. /// # Examples /// ```rust - /// println!("Placeholder"); + /// use fips205::slh_dsa_shake_128s; // Could use any of the twelve security parameter sets. + /// use fips205::traits::{SerDes, Signer, Verifier}; + /// # use std::error::Error; + /// # + /// # fn main() -> Result<(), Box> { + /// + /// let msg_bytes = [0u8, 1, 2, 3, 4, 5, 6, 7]; + /// + /// // Generate public/private key pair and signature + /// let (pk1, sk) = slh_dsa_shake_128s::try_keygen_vt()?; // Generate both public and secret keys + /// let sig_bytes = sk.try_sign_ct(&msg_bytes, true)?; // Use the secret key to generate a msg signature + /// + /// // Serialize the public key, and send with message and signature bytes + /// let (pk_send, msg_send, sig_send) = (pk1.into_bytes(), msg_bytes, sig_bytes); + /// let (pk_recv, msg_recv, sig_recv) = (pk_send, msg_send, sig_send); + /// + /// // Deserialize the public key, then use it to verify the msg signature + /// let pk2 = slh_dsa_shake_128s::PublicKey::try_from_bytes(&pk_recv)?; + /// let v = pk2.try_verify_vt(&msg_recv, &sig_recv)?; + /// assert!(v); + /// # Ok(()) + /// # } /// ``` fn try_keygen_with_rng_vt( rng: &mut impl CryptoRngCore, @@ -67,7 +151,7 @@ pub trait KeyGen { /// The Signer trait is implemented for the `PrivateKey` struct on each of the security parameter sets pub trait Signer { - /// The signature is specific to the chosen security parameter set, e.g., ml-dsa-44, ml-dsa-65 or ml-dsa-87 + /// The signature is specific to the chosen security parameter set, e.g., `slh_dsa_shake_128s`, `slh_dsa_sha2_128s` etc type Signature; /// Attempt to sign the given message, returning a digital signature on success, or an error if @@ -78,7 +162,28 @@ pub trait Signer { /// Returns an error when the random number generator fails; propagates internal errors. /// # Examples /// ```rust - /// println!("Placeholder"); + /// use fips205::slh_dsa_shake_128s; // Could use any of the twelve security parameter sets. + /// use fips205::traits::{SerDes, Signer, Verifier}; + /// # use std::error::Error; + /// # + /// # fn main() -> Result<(), Box> { + /// + /// let msg_bytes = [0u8, 1, 2, 3, 4, 5, 6, 7]; + /// + /// // Generate public/private key pair and signature + /// let (pk1, sk) = slh_dsa_shake_128s::try_keygen_vt()?; // Generate both public and secret keys + /// let sig_bytes = sk.try_sign_ct(&msg_bytes, true)?; // Use the secret key to generate a msg signature + /// + /// // Serialize the public key, and send with message and signature bytes + /// let (pk_send, msg_send, sig_send) = (pk1.into_bytes(), msg_bytes, sig_bytes); + /// let (pk_recv, msg_recv, sig_recv) = (pk_send, msg_send, sig_send); + /// + /// // Deserialize the public key, then use it to verify the msg signature + /// let pk2 = slh_dsa_shake_128s::PublicKey::try_from_bytes(&pk_recv)?; + /// let v = pk2.try_verify_vt(&msg_recv, &sig_recv)?; + /// assert!(v); + /// # Ok(()) + /// # } /// ``` #[cfg(feature = "default-rng")] fn try_sign_ct( @@ -95,7 +200,28 @@ pub trait Signer { /// Returns an error when the random number generator fails; propagates internal errors. /// # Examples /// ```rust - /// println!("Placeholder"); + /// use fips205::slh_dsa_shake_128s; // Could use any of the twelve security parameter sets. + /// use fips205::traits::{SerDes, Signer, Verifier}; + /// # use std::error::Error; + /// # + /// # fn main() -> Result<(), Box> { + /// + /// let msg_bytes = [0u8, 1, 2, 3, 4, 5, 6, 7]; + /// + /// // Generate public/private key pair and signature + /// let (pk1, sk) = slh_dsa_shake_128s::try_keygen_vt()?; // Generate both public and secret keys + /// let sig_bytes = sk.try_sign_ct(&msg_bytes, true)?; // Use the secret key to generate a msg signature + /// + /// // Serialize the public key, and send with message and signature bytes + /// let (pk_send, msg_send, sig_send) = (pk1.into_bytes(), msg_bytes, sig_bytes); + /// let (pk_recv, msg_recv, sig_recv) = (pk_send, msg_send, sig_send); + /// + /// // Deserialize the public key, then use it to verify the msg signature + /// let pk2 = slh_dsa_shake_128s::PublicKey::try_from_bytes(&pk_recv)?; + /// let v = pk2.try_verify_vt(&msg_recv, &sig_recv)?; + /// assert!(v); + /// # Ok(()) + /// # } /// ``` fn try_sign_with_rng_ct( &self, rng: &mut impl CryptoRngCore, message: &[u8], randomize: bool, @@ -105,8 +231,7 @@ pub trait Signer { /// The Verifier trait is implemented for `PublicKey` on each of the security parameter sets pub trait Verifier { - /// The signature is specific to the chosen security parameter set, e.g., ml-dsa-44, ml-dsa-65 - /// or ml-dsa-87 + /// The signature is specific to the chosen security parameter set, e.g., `slh_dsa_shake_128s`, `slh_dsa_sha2_128s` etc type Signature; /// Verifies a digital signature with respect to a `PublicKey`. This function operates in @@ -116,7 +241,28 @@ pub trait Verifier { /// Returns an error on a malformed signature; propagates internal errors. /// # Examples /// ```rust - /// println!("Placeholder"); + /// use fips205::slh_dsa_shake_128s; // Could use any of the twelve security parameter sets. + /// use fips205::traits::{SerDes, Signer, Verifier}; + /// # use std::error::Error; + /// # + /// # fn main() -> Result<(), Box> { + /// + /// let msg_bytes = [0u8, 1, 2, 3, 4, 5, 6, 7]; + /// + /// // Generate public/private key pair and signature + /// let (pk1, sk) = slh_dsa_shake_128s::try_keygen_vt()?; // Generate both public and secret keys + /// let sig_bytes = sk.try_sign_ct(&msg_bytes, true)?; // Use the secret key to generate a msg signature + /// + /// // Serialize the public key, and send with message and signature bytes + /// let (pk_send, msg_send, sig_send) = (pk1.into_bytes(), msg_bytes, sig_bytes); + /// let (pk_recv, msg_recv, sig_recv) = (pk_send, msg_send, sig_send); + /// + /// // Deserialize the public key, then use it to verify the msg signature + /// let pk2 = slh_dsa_shake_128s::PublicKey::try_from_bytes(&pk_recv)?; + /// let v = pk2.try_verify_vt(&msg_recv, &sig_recv)?; + /// assert!(v); + /// # Ok(()) + /// # } /// ``` fn try_verify_vt( &self, message: &[u8], signature: &Self::Signature,