1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
use rand_core::CryptoRngCore;
#[cfg(feature = "default-rng")]
use rand_core::OsRng;
/// 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
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
type PrivateKey;
/// An expanded private key containing precomputed elements to increase (repeated) signing performance.
type ExpandedPrivateKey;
/// An expanded public key containing precomputed elements to increase (repeated) verify performance.
type ExpandedPublicKey;
/// 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 std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use fips204::ml_dsa_44; // Could also be ml_dsa_65 or ml_dsa_87.
/// use fips204::traits::{KeyGen, SerDes, Signer, Verifier};
///
/// let message = [0u8, 1, 2, 3, 4, 5, 6, 7];
///
/// // Generate key pair and signature
/// let (pk, sk) = ml_dsa_44::KG::try_keygen_vt()?; // Generate both public and secret keys
/// let sig = sk.try_sign_ct(&message)?; // Use the secret key to generate a message signature
/// # Ok(())}
/// ```
#[cfg(feature = "default-rng")]
fn try_keygen_vt() -> Result<(Self::PublicKey, Self::PrivateKey), &'static str> {
Self::try_keygen_with_rng_vt(&mut OsRng)
}
/// 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 std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use fips204::ml_dsa_44; // Could also be ml_dsa_65 or ml_dsa_87.
/// use fips204::traits::{KeyGen, SerDes, Signer, Verifier};
/// use rand_chacha::rand_core::SeedableRng;
///
/// 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) = ml_dsa_44::KG::try_keygen_with_rng_vt(&mut rng)?; // Generate both public and secret keys
/// let sig = sk.try_sign_ct(&message)?; // Use the secret key to generate a message signature
/// # Ok(())}
/// ```
fn try_keygen_with_rng_vt(
rng: &mut impl CryptoRngCore,
) -> Result<(Self::PublicKey, Self::PrivateKey), &'static str>;
/// Generates an expanded private key from the normal/compressed private key.
///
/// # Errors
/// Propagates internal errors; potential for additional validation as FIPS 204 evolves.
fn gen_expanded_private_vt(
sk: &Self::PrivateKey,
) -> Result<Self::ExpandedPrivateKey, &'static str>;
/// Generates an expanded public key from the normal/compressed public key.
///
/// # Errors
/// Propagates internal errors; potential for additional validation as FIPS 204 evolves.
fn gen_expanded_public_vt(
pk: &Self::PublicKey,
) -> Result<Self::ExpandedPublicKey, &'static str>;
}
// /// The `PreGen` trait is defined to allow pre-computation of private key material to speed signing.
// pub trait PreGen: Signer + SerDes {
// /// A private (secret) precompute specific to the chosen security parameter set, e.g., ml-dsa-44, ml-dsa-65 or ml-dsa-87
// type PreCompute;
//
// /// # Examples
// /// ```rust
// /// # use std::error::Error;
// /// # fn main() -> Result<(), Box<dyn Error>> {
// /// use fips204::ml_dsa_44; // Could also be ml_dsa_65 or ml_dsa_87.
// /// use fips204::traits::{KeyGen, PreGen, SerDes, Signer, Verifier};
// /// ///
// /// let message = [0u8, 1, 2, 3, 4, 5, 6, 7];
// ///
// /// // Generate key pair and signature
// /// let (pk, sk) = ml_dsa_44::KG::try_keygen_vt()?; // Generate both public and secret keys
// /// let pre = sk.gen_precompute();
// /// let sig = pre.try_sign_ct(&message)?; // Use the secret key to generate a message signature
// /// # Ok(())}
// /// ```
// fn gen_precompute(&self) -> Self::PreCompute;
// }
/// 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
type Signature;
/// Attempt to sign the given message, returning a digital signature on success, or an error if
/// something went wrong. This function utilizes the default OS RNG and operates in constant time
/// with respect to the `PrivateKey` only (not including rejection loop; work in progress).
///
/// # Errors
/// Returns an error when the random number generator fails; propagates internal errors.
/// # Examples
/// ```rust
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use fips204::ml_dsa_65; // Could also be ml_dsa_44 or ml_dsa_87.
/// use fips204::traits::{KeyGen, SerDes, Signer, Verifier};
///
/// let message = [0u8, 1, 2, 3, 4, 5, 6, 7];
///
/// // Generate key pair and signature
/// let (pk, sk) = ml_dsa_65::KG::try_keygen_vt()?; // Generate both public and secret keys
/// let sig = sk.try_sign_ct(&message)?; // Use the secret key to generate a message signature
/// # Ok(())}
/// ```
#[cfg(feature = "default-rng")]
fn try_sign_ct(&self, message: &[u8]) -> Result<Self::Signature, &'static str> {
self.try_sign_with_rng_ct(&mut OsRng, message)
}
/// Attempt to sign the given message, returning a digital signature on success, or an error if
/// something went wrong. This function utilizes a supplied RNG and operates in constant time
/// with respect to the `PrivateKey` only (not including rejection loop; work in progress).
///
/// # Errors
/// Returns an error when the random number generator fails; propagates internal errors.
/// # Examples
/// ```rust
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use fips204::ml_dsa_65; // Could also be ml_dsa_44 or ml_dsa_87.
/// use fips204::traits::{KeyGen, SerDes, Signer, Verifier};
/// use rand_chacha::rand_core::SeedableRng;
///
/// 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) = ml_dsa_65::KG::try_keygen_with_rng_vt(&mut rng)?; // Generate both public and secret keys
/// let sig = sk.try_sign_with_rng_ct(&mut rng, &message)?; // Use the secret key to generate a message signature
/// # Ok(())}
/// ```
fn try_sign_with_rng_ct(
&self, rng: &mut impl CryptoRngCore, message: &[u8],
) -> Result<Self::Signature, &'static str>;
}
/// 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
type Signature;
/// Verifies a digital signature with respect to a `PublicKey`. This function operates in
/// variable time.
///
/// # Errors
/// Returns an error on a malformed signature; propagates internal errors.
/// # Examples
/// ```rust
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use fips204::ml_dsa_65; // Could also be ml_dsa_44 or ml_dsa_87.
/// use fips204::traits::{KeyGen, SerDes, Signer, Verifier};
///
/// let message = [0u8, 1, 2, 3, 4, 5, 6, 7];
///
/// // Generate key pair and signature
/// let (pk, sk) = ml_dsa_65::KG::try_keygen_vt()?; // Generate both public and secret keys
/// let sig = sk.try_sign_ct(&message)?; // Use the secret key to generate a message signature
/// let v = pk.try_verify_vt(&message, &sig)?; // Use the public to verify message signature
/// # Ok(())}
/// ```
fn try_verify_vt(
&self, message: &[u8], signature: &Self::Signature,
) -> Result<bool, &'static str>;
}
/// The `SerDes` trait provides for validated serialization and deserialization of fixed size elements
pub trait SerDes {
/// The fixed-size byte array to be serialized or deserialized
type ByteArray;
/// Produces a byte array of fixed-size specific to the struct being serialized.
/// # Examples
/// ```rust
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use fips204::ml_dsa_65; // Could also be ml_dsa_44 or ml_dsa_87.
/// use fips204::traits::{KeyGen, SerDes, Signer, Verifier};
///
/// let message = [0u8, 1, 2, 3, 4, 5, 6, 7];
///
/// // Generate key pair and signature
/// let (pk, sk) = ml_dsa_65::KG::try_keygen_vt()?; // Generate both public and secret keys
/// let sig = sk.try_sign_ct(&message)?; // Use the secret key to generate a message signature
/// let pk_bytes = pk.into_bytes(); // Serialize the public key
/// let sk_bytes = sk.into_bytes(); // Serialize the private key
/// # Ok(())}
/// ```
fn into_bytes(self) -> Self::ByteArray;
/// Consumes a byte array of fixed-size specific to the struct being deserialized; performs validation
/// # Errors
/// Returns an error on malformed input.
/// # Examples
/// ```rust
/// # use std::error::Error;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// use fips204::ml_dsa_87; // Could also be ml_dsa_44 or ml_dsa_65.
/// use fips204::traits::{KeyGen, SerDes, Signer, Verifier};
///
/// // Generate key pair and signature
/// let (pk, sk) = ml_dsa_87::try_keygen_vt()?; // Generate both public and secret keys
/// let pk_bytes = pk.into_bytes(); // Serialize the public key
/// let sk_bytes = sk.into_bytes(); // Serialize the private key
/// let pk2 = ml_dsa_87::PublicKey::try_from_bytes(pk_bytes)?;
/// let sk2 = ml_dsa_87::PrivateKey::try_from_bytes(sk_bytes)?;
/// # Ok(())}
/// ```
fn try_from_bytes(ba: Self::ByteArray) -> Result<Self, &'static str>
where
Self: Sized;
}