Skip to content

Commit 27de0e0

Browse files
committed
v0.4.0 RC1
1 parent 39803c9 commit 27de0e0

File tree

6 files changed

+39
-26
lines changed

6 files changed

+39
-26
lines changed

CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## 0.4.0 (2024-09-32)
8+
## 0.4.0 (2024-09-29)
99

1010
- Now aligned with **released** FIPS 204 including hash sig/verif and keygen with seed.
1111

README.md

+14-11
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
![Apache2/MIT licensed][license-image]
77
![Rust Version][rustc-image]
88

9-
[FIPS 204] Module-Lattice-Based Digital Signature Standard written in pure Rust for server,
9+
[FIPS 204] Module-Lattice-Based Digital Signature Standard written in pure/safe Rust for server,
1010
desktop, browser and embedded applications. The source repository includes examples demonstrating benchmarking,
1111
an embedded target, constant-time statistical measurements, fuzzing, and WASM execution.
1212

13-
This crate implements the FIPS 204 **released** standard in pure Rust with minimal and mainstream dependencies, **and
14-
without any unsafe code**. All three security parameter sets are fully functional and tested. The implementation's
15-
key generation and signature functionality operates in constant-time, does not require the standard library, e.g.
13+
This crate implements the FIPS 204 **released** standard in pure Rust with minimal and mainstream dependencies, and
14+
without any unsafe code. All three security parameter sets are fully functional and tested. The implementation's
15+
key- and signature-generation functionality operates in constant-time, does not require the standard library, e.g.
1616
`#[no_std]`, has no heap allocations, e.g. no `alloc` needed, and exposes the `RNG` so it is suitable for the full
1717
range of applications down to the bare-metal. The API is stabilized and the code is heavily biased towards safety
1818
and correctness; further performance optimizations will be implemented as the standard matures. This crate will
@@ -34,16 +34,19 @@ let message = [0u8, 1, 2, 3, 4, 5, 6, 7];
3434

3535
// Generate key pair and signature
3636
let (pk1, sk) = ml_dsa_44::try_keygen()?; // Generate both public and secret keys
37-
let sig = sk.try_sign(&message, &[0])?; // Use the secret key to generate a message signature
37+
let sig = sk.try_sign(&message, &[])?; // Use the secret key to generate a message signature
3838

3939
// Serialize then send the public key, message and signature
4040
let (pk_send, msg_send, sig_send) = (pk1.into_bytes(), message, sig);
4141
let (pk_recv, msg_recv, sig_recv) = (pk_send, msg_send, sig_send);
4242

4343
// Deserialize the public key and signature, then verify the message
4444
let pk2 = ml_dsa_44::PublicKey::try_from_bytes(pk_recv)?;
45-
let v = pk2.verify(&msg_recv, &sig_recv, &[0]); // Use the public to verify message signature
45+
let v = pk2.verify(&msg_recv, &sig_recv, &[]); // Use the public to verify message signature
4646
assert!(v);
47+
48+
// Note that the last argument to sign() and verify() is the (NIST specified) context
49+
// value which is typically empty for basic signature generation and verification.
4750
# }
4851
# Ok(())
4952
# }
@@ -54,13 +57,13 @@ The Rust [Documentation][docs-link] lives under each **Module** corresponding to
5457

5558
## Notes
5659

57-
* This crate is fully functional and corresponds to FIPS 204 (August 13, 2024).
60+
* This crate is fully functional and corresponds to the final released FIPS 204 (August 13, 2024).
5861
* **BEWARE:** As of September 27, 2024 NIST has not released external/hash test vectors!
59-
* Constant-time assurances target the source-code level only on MSRV, with confirmation via
62+
* Constant-time assurances target the source-code level only, with confirmation via
6063
manual review/inspection, the embedded target, and the `dudect` dynamic tests.
6164
* Note that FIPS 204 places specific requirements on randomness per section 3.5.1, hence the exposed `RNG`.
6265
* Requires Rust **1.70** or higher. The minimum supported Rust version may be changed in the future, but
63-
it will be done with a minor version bump (when the major version is larger than 0)..
66+
it will be done with a minor version bump (when the major version is larger than 0).
6467
* All on-by-default features of this library are covered by `SemVer`.
6568
* The FIPS 204 standard and this software should be considered experimental -- USE AT YOUR OWN RISK!
6669

@@ -76,7 +79,7 @@ defined in the Apache-2.0 license, shall be dual licensed as above, without any
7679

7780
[//]: # (badges)
7881

79-
[crate-image]: https://buildstats.info/crate/fips204
82+
[crate-image]: https://img.shields.io/crates/v/fips204
8083
[crate-link]: https://crates.io/crates/fips204
8184
[docs-image]: https://docs.rs/fips204/badge.svg
8285
[docs-link]: https://docs.rs/fips204/
@@ -88,4 +91,4 @@ defined in the Apache-2.0 license, shall be dual licensed as above, without any
8891
[//]: # (general links)
8992

9093
[IntegrityChain]: https://github.com/integritychain/
91-
[FIPS 204]: https://csrc.nist.gov/pubs/fips/204/ipd
94+
[FIPS 204]: https://csrc.nist.gov/pubs/fips/204/final

src/hashing.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,12 @@ pub(crate) fn sample_in_ball<const CTEST: bool>(tau: i32, rho: &[u8]) -> R {
5757

5858
// 6: for 𝑖 from 256 − 𝜏 to 255 do
5959
for i in (256 - tau)..=255 {
60+
//
6061
// 7: (ctx, 𝑗) ← H.Squeeze(ctx, 1)
61-
let mut j = [i.to_le_bytes()[0]]; // remove timing variability
62-
if !CTEST { h_ctx.read(&mut j) }; // ..
62+
let mut j = [i.to_le_bytes()[0]]; // remove timing variability
63+
if !CTEST {
64+
h_ctx.read(&mut j);
65+
};
6366

6467
// 8: while 𝑗 > 𝑖 do
6568
while usize::from(j[0]) > i {
@@ -286,7 +289,6 @@ pub(crate) fn expand_mask<const L: usize>(gamma1: i32, rho: &[u8; 64], mu: u16)
286289
for r in 0..u16::try_from(L).expect("cannot fail") {
287290
//
288291
// 3: n ← IntegerToBits(µ + r, 16)
289-
// debug_assert!((mu + r < 1024), "Alg 28: mu + r out of range"); // arbitrary limit not needed
290292
let n = mu + r; // This will perform overflow check in debug, which removes need for above assert
291293

292294
// 4: v ← (H(ρ || n)[[32rc]], H(ρ || n)[[32rc+1]], ..., H(ρ || n)[[32rc+32c − 1]])

src/helpers.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,7 @@ pub(crate) const fn full_reduce32(a: i32) -> i32 {
7979

8080
// Note: this is only used on 'fixed' security parameters (not secret values), so as not to impact CT
8181
/// Bit length required to express `a` in bits
82-
pub(crate) const fn bit_length(x: i32) -> usize {
83-
x.ilog2() as usize + 1
84-
}
82+
pub(crate) const fn bit_length(x: i32) -> usize { x.ilog2() as usize + 1 }
8583

8684

8785
/// Mod +/- see definition on page 6.

src/lib.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
//
1414
#![doc = include_str!("../README.md")]
1515

16+
// TODO: Internal code comment alignment with release spec is underway...
17+
1618
// Implements FIPS 204 Module-Lattice-Based Digital Signature Standard.
1719
// See <https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.204.pdf>
1820

@@ -453,9 +455,9 @@ macro_rules! functionality {
453455

454456
#[deprecated = "Temporary function to allow application of internal nist vectors; will be removed"]
455457
/// As of Sep 22 2024, the NIST test vectors are applied to the **internal** functions rather than
456-
/// the external API. T
458+
/// the external API.
457459
///
458-
/// he primary difference pertains to the prepending of domain, context, OID and
460+
/// The primary difference pertains to the prepending of domain, context, OID and
459461
/// hash information to the message in the `sign_finish()` and `verify_finish()` functions (follow
460462
/// the last `nist=true` function argument). This is expected to change such that the full API can
461463
/// be robustly tested - when this happens, this function will no longer be needed.
@@ -510,7 +512,7 @@ macro_rules! functionality {
510512
/// [`ml_dsa_44::PrivateKey`] struct implements the [`traits::Signer`] trait which supplies a variety of
511513
/// functions to sign byte-array messages, such as [`traits::Signer::try_sign()`].
512514
///
513-
/// **2)** Both of the `PrivateKey` and `PublicKey` structs implement the [`traits::SerDes`] trait
515+
/// **2)** Both of the `PrivateKey` and `PublicKey` structs implement the [`traits::SerDes`] trait.
514516
/// The originator utilizes the [`traits::SerDes::into_bytes()`] functions to serialize the structs
515517
/// into byte-arrays for storage and/or transmission, similar to the message. Upon retrieval and/or receipt,
516518
/// the remote party utilizes the [`traits::SerDes::try_from_bytes()`] functions to deserialize the

src/traits.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ pub trait KeyGen {
107107
/// # Ok(())}
108108
/// ```
109109
#[must_use]
110-
fn keygen_from_seed(_xi: &[u8; 32]) -> (Self::PublicKey, Self::PrivateKey);
110+
fn keygen_from_seed(xi: &[u8; 32]) -> (Self::PublicKey, Self::PrivateKey);
111111

112112

113113
/// Generates an expanded private key from the normal/compressed private key.
@@ -202,7 +202,14 @@ pub trait Signer {
202202
&self, rng: &mut impl CryptoRngCore, message: &[u8], ctx: &[u8],
203203
) -> Result<Self::Signature, &'static str>;
204204

205-
/// TKTKT placeholder
205+
/// Attempt to sign the hash of the given message, returning a digital signature on success,
206+
/// or an error if something went wrong. This function utilizes the **provided** random number
207+
/// generator and allows for several hash algorithms. This function operates in constant-time
208+
/// relative to secret data (which specifically excludes the provided random number generator
209+
/// internals, the `rho` value (also) stored in the public key, the hash-derived `rho_prime`
210+
/// value that is rejection-sampled/expanded into the internal `s_1` and `s_2` values, and the
211+
/// main signing rejection loop as noted in section 5.5 of
212+
/// <https://pq-crystals.org/dilithium/data/dilithium-specification-round3-20210208.pdf>.
206213
/// # Errors
207214
/// Will return an error on rng failure
208215
fn try_hash_sign_with_rng(
@@ -217,8 +224,8 @@ pub trait Verifier {
217224
/// or ml-dsa-87
218225
type Signature;
219226

220-
/// Verifies a digital signature with respect to a `PublicKey`. As this function operates on
221-
/// purely public data, it need/does not provide constant-time assurances.
227+
/// Verifies a digital signature on a message with respect to a `PublicKey`. As this function
228+
/// operates on purely public data, it need/does not provide constant-time assurances.
222229
/// # Examples
223230
/// ```rust
224231
/// # use std::error::Error;
@@ -238,7 +245,8 @@ pub trait Verifier {
238245
/// ```
239246
fn verify(&self, message: &[u8], signature: &Self::Signature, ctx: &[u8]) -> bool;
240247

241-
/// TKTK placeholder
248+
/// Verifies a digital signature on the hash of a message with respect to a `PublicKey`. As this
249+
/// function operates on purely public data, it need/does not provide constant-time assurances.
242250
fn hash_verify(&self, message: &[u8], sig: &Self::Signature, ctx: &[u8], ph: &Ph) -> bool;
243251
}
244252

0 commit comments

Comments
 (0)