This commit is contained in:
eschorn1 2024-02-10 14:26:37 -06:00
parent 6cec1182c7
commit 6bab551ffb
6 changed files with 630 additions and 47 deletions

View file

@ -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

22
dudect/Cargo.toml Normal file
View file

@ -0,0 +1,22 @@
[package]
name = "fips205-dudect"
version = "0.1.0"
authors = ["Eric Schorn <eschorn@integritychain.com>"]
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

25
dudect/README.md Normal file
View file

@ -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
~~~

36
dudect/src/main.rs Normal file
View file

@ -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<slh_dsa_shake_128s::PrivateKey> = 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);

View file

@ -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 <https://csrc.nist.gov/pubs/fips/205/ipd>
/// 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<N>);
// ----- 'EXTERNAL' DATA TYPES -----
#[derive(Zeroize, ZeroizeOnDrop)]
/// Correctly sized private key specific to the target security parameter set. <br>
/// Implements the [`crate::traits::Signer`] and [`crate::traits::SerDes`] traits.
#[derive(Clone, Zeroize, ZeroizeOnDrop)]
pub struct PrivateKey(SlhPrivateKey<N>);
/// Correctly sized public key specific to the target security parameter set. <br>
/// Implements the [`crate::traits::Verifier`] and [`crate::traits::SerDes`] traits.
#[derive(Clone, Zeroize, ZeroizeOnDrop)]
pub struct PublicKey(SlhPublicKey<N>);
/// Empty struct to enable `KeyGen` trait objects across security parameter sets. <br>
/// 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. <br>
/// 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<dyn Error>> {
///
/// 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. <br>
/// 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<dyn Error>> {
///
/// 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<bool, &'static str> {
@ -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<Prod<U2, N>, 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<K, Len, M, N> =
Hashers::<K, Len, M, N> { 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<Prod<U2, N>, 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<K, Len, M, N> =
Hashers::<K, Len, M, N> { 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<Prod<U2, N>, 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<K, Len, M, N> =
Hashers::<K, Len, M, N> { 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<Prod<U2, N>, 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<K, Len, M, N> =
Hashers::<K, Len, M, N> { 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<Prod<U2, N>, 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<K, Len, M, N> =
Hashers::<K, Len, M, N> { 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<Prod<U2, N>, 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<K, Len, M, N> =
Hashers::<K, Len, M, N> { 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<Prod<U2, N>, 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<K, Len, M, N> =
Hashers::<K, Len, M, N> { 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<Prod<U2, N>, 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<K, Len, M, N> =
Hashers::<K, Len, M, N> { 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<Prod<U2, N>, 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<K, Len, M, N> =
Hashers::<K, Len, M, N> { 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<Prod<U2, N>, 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<K, Len, M, N> =
Hashers::<K, Len, M, N> { 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<Prod<U2, N>, 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<K, Len, M, N> =
Hashers::<K, Len, M, N> { 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<Prod<U2, N>, 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<K, Len, M, N> =
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };

View file

@ -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<dyn Error>> {
///
/// 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<dyn Error>> {
///
/// 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<Self, &'static str>
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. <br>
@ -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<dyn Error>> {
///
/// 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<dyn Error>> {
///
/// 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<dyn Error>> {
///
/// 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<dyn Error>> {
///
/// 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<dyn Error>> {
///
/// 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,