1
1
use crate :: types:: Ph ;
2
- use rand_core:: CryptoRngCore ;
2
+ use rand_core:: { CryptoRng , CryptoRngCore , RngCore } ;
3
3
#[ cfg( feature = "default-rng" ) ]
4
4
use rand_core:: OsRng ;
5
5
@@ -132,7 +132,7 @@ pub trait Signer {
132
132
/// <https://pq-crystals.org/dilithium/data/dilithium-specification-round3-20210208.pdf>).
133
133
///
134
134
/// # Errors
135
- /// Returns an error when the random number generator fails; propagates internal errors.
135
+ /// Returns an error when the random number generator fails or the `ctx` is longer than 255 bytes ; propagates internal errors.
136
136
///
137
137
/// # Examples
138
138
/// ```rust
@@ -167,7 +167,7 @@ pub trait Signer {
167
167
/// <https://pq-crystals.org/dilithium/data/dilithium-specification-round3-20210208.pdf>.
168
168
///
169
169
/// # Errors
170
- /// Returns an error when the random number generator fails; propagates internal errors.
170
+ /// Returns an error when the random number generator fails or the `ctx` is longer than 255 bytes ; propagates internal errors.
171
171
///
172
172
/// # Examples
173
173
/// ```rust
@@ -193,7 +193,45 @@ pub trait Signer {
193
193
& self , rng : & mut impl CryptoRngCore , message : & [ u8 ] , ctx : & [ u8 ] ,
194
194
) -> Result < Self :: Signature , & ' static str > ;
195
195
196
+
197
+ /// Attempt to sign the given message, returning a digital signature on success, or an error if
198
+ /// something went wrong. This function utilizes the **provided seed to support (less common)
199
+ /// deterministic signatures**. This function operates in constant-time relative to secret data
200
+ /// (which specifically excludes the `rho` value stored in the public key, the hash-derived
201
+ /// `rho_prime` value that is rejection-sampled/expanded into the internal `s_1` and `s_2` values,
202
+ /// and the main signing rejection loop as noted in section 5.5 of
203
+ /// <https://pq-crystals.org/dilithium/data/dilithium-specification-round3-20210208.pdf>.
204
+ ///
205
+ /// # Errors
206
+ /// Returns an error when the `ctx` is longer than 255 bytes; propagates internal errors.
207
+ ///
208
+ /// # Examples
209
+ /// ```rust
210
+ /// # use std::error::Error;
211
+ /// # fn main() -> Result<(), Box<dyn Error>> {
212
+ /// # #[cfg(feature = "ml-dsa-65")] {
213
+ /// use fips204::ml_dsa_65; // Could also be ml_dsa_44 or ml_dsa_87.
214
+ /// use fips204::traits::{KeyGen, SerDes, Signer, Verifier};
215
+ /// use rand_chacha::rand_core::SeedableRng;
216
+ ///
217
+ /// let message = [0u8, 1, 2, 3, 4, 5, 6, 7];
218
+ /// let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(123);
196
219
///
220
+ /// // Generate key pair and signature
221
+ /// let (pk, sk) = ml_dsa_65::KG::try_keygen_with_rng(&mut rng)?; // Generate both public and secret keys
222
+ /// let sig = sk.try_sign_with_seed(&[0u8;32], &message, &[0])?; // Use the secret key to generate a message signature
223
+ /// let v = pk.verify(&message, &sig, &[0]); // Use the public to verify message signature
224
+ /// assert!(v);
225
+ /// # }
226
+ /// # Ok(())}
227
+ /// ```
228
+ fn try_sign_with_seed (
229
+ & self , seed : & [ u8 ; 32 ] , message : & [ u8 ] , ctx : & [ u8 ] ,
230
+ ) -> Result < Self :: Signature , & ' static str > {
231
+ self . try_sign_with_rng ( & mut DummyRng { data : * seed} , message, ctx)
232
+ }
233
+
234
+
197
235
/// Attempt to sign the hash of the given message, returning a digital signature on success,
198
236
/// or an error if something went wrong. This function utilizes the **default OS** random number
199
237
/// generator and allows for several hash algorithms. This function operates in constant-time
@@ -204,7 +242,7 @@ pub trait Signer {
204
242
/// <https://pq-crystals.org/dilithium/data/dilithium-specification-round3-20210208.pdf>.
205
243
///
206
244
/// # Errors
207
- /// Will return an error on rng failure
245
+ /// Returns an error when the random number generator fails or the `ctx` is longer than 255 bytes; propagates internal errors.
208
246
#[ cfg( feature = "default-rng" ) ]
209
247
fn try_hash_sign (
210
248
& self , message : & [ u8 ] , ctx : & [ u8 ] , ph : & Ph ,
@@ -223,12 +261,29 @@ pub trait Signer {
223
261
/// <https://pq-crystals.org/dilithium/data/dilithium-specification-round3-20210208.pdf>.
224
262
///
225
263
/// # Errors
226
- /// Will return an error on rng failure
264
+ /// Returns an error when the random number generator fails or the `ctx` is longer than 255 bytes; propagates internal errors.
227
265
fn try_hash_sign_with_rng (
228
266
& self , rng : & mut impl CryptoRngCore , message : & [ u8 ] , ctx : & [ u8 ] , ph : & Ph ,
229
267
) -> Result < Self :: Signature , & ' static str > ;
230
268
231
269
270
+ /// Attempt to sign the hash of the given message, returning a digital signature on success,
271
+ /// something went wrong. This function utilizes the **provided seed to support (less common)
272
+ /// deterministic signatures**. This function operates in constant-time relative to secret data
273
+ /// (which specifically excludes the `rho` value stored in the public key, the hash-derived
274
+ /// `rho_prime` value that is rejection-sampled/expanded into the internal `s_1` and `s_2` values,
275
+ /// and the main signing rejection loop as noted in section 5.5 of
276
+ /// <https://pq-crystals.org/dilithium/data/dilithium-specification-round3-20210208.pdf>.
277
+ ///
278
+ /// # Errors
279
+ /// Returns an error when the `ctx` is longer than 255 bytes; propagates internal errors.
280
+ fn try_hash_sign_with_seed (
281
+ & self , seed : & [ u8 ; 32 ] , message : & [ u8 ] , ctx : & [ u8 ] , ph : & Ph ,
282
+ ) -> Result < Self :: Signature , & ' static str > {
283
+ self . try_hash_sign_with_rng ( & mut DummyRng { data : * seed} , message, ctx, ph)
284
+ }
285
+
286
+
232
287
/// Retrieves the public key associated with this private/secret key
233
288
///
234
289
/// # Examples
@@ -252,6 +307,24 @@ pub trait Signer {
252
307
fn get_public_key ( & self ) -> Self :: PublicKey ;
253
308
}
254
309
310
+ // This is for the deterministic signing functions; will be refactored more nicely
311
+ struct DummyRng { data : [ u8 ; 32 ] }
312
+
313
+ impl RngCore for DummyRng {
314
+ fn next_u32 ( & mut self ) -> u32 { unimplemented ! ( ) }
315
+
316
+ fn next_u64 ( & mut self ) -> u64 { unimplemented ! ( ) }
317
+
318
+ fn fill_bytes ( & mut self , _out : & mut [ u8 ] ) { unimplemented ! ( ) }
319
+
320
+ fn try_fill_bytes ( & mut self , out : & mut [ u8 ] ) -> Result < ( ) , rand_core:: Error > {
321
+ out. copy_from_slice ( & self . data ) ;
322
+ Ok ( ( ) )
323
+ }
324
+ }
325
+
326
+ impl CryptoRng for DummyRng { }
327
+
255
328
256
329
/// The Verifier trait is implemented for `PublicKey` on each of the security parameter sets.
257
330
pub trait Verifier {
0 commit comments