Skip to content

Commit abebea1

Browse files
committed
v0.4.3 RC1
1 parent b398b68 commit abebea1

File tree

8 files changed

+37
-73
lines changed

8 files changed

+37
-73
lines changed

CHANGELOG.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ 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.3 (2024-10-XX)
8+
## 0.4.3 (2024-10-16)
99

10-
- Adapted PrivateKey into PrivateKey and PublicKey into PublicKey, removed the former(s)
11-
- Internal revision to align comments with released spec
10+
- Adapted ExpandedPrivateKey into PrivateKey and ExpandedPublicKey into PublicKey, removed the former(s)
11+
- Internal revision to align comments with released spec; added try_hash_sign (using OS rng)
1212
- Revisit/revise supporting benchmarks, embedded target, dudect, fuzz and wasm functionality
1313
- Fixed a bug in verify relating to non-empty contexts; asserts on all doctests
1414

benches/benchmark.rs

-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ pub fn criterion_benchmark(c: &mut Criterion) {
5858
c.bench_function("ml_dsa_44 pk verify", |b| b.iter(|| pk44.verify(&msg, &sig44, &[])));
5959
c.bench_function("ml_dsa_65 pk verify", |b| b.iter(|| pk65.verify(&msg, &sig65, &[])));
6060
c.bench_function("ml_dsa_87 pk verify", |b| b.iter(|| pk87.verify(&msg, &sig87, &[])));
61-
6261
}
6362

6463
criterion_group!(benches, criterion_benchmark);

src/encodings.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub(crate) fn pk_encode<const K: usize, const PK_LEN: usize>(
3232
pk[32..]
3333
.chunks_mut(32 * blqd)
3434
.enumerate()
35-
.take(K) // not strictly needed
35+
.take(K) // not strictly needed
3636
.for_each(|(i, chunk)| simple_bit_pack(&t1[i], (1 << blqd) - 1, chunk));
3737

3838
// 5: return pk

src/hashing.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,8 @@ pub(crate) fn expand_mask<const L: usize>(gamma1: i32, rho: &[u8; 64], mu: u16)
298298
xof.read(&mut v);
299299

300300
// 5: y[r] ← BitUnpack(v, γ_1 − 1, γ_1)
301-
y[r as usize] = bit_unpack(&v[0..32 * c], gamma1 - 1, gamma1).expect("Alg 34: try_from2 fail");
301+
y[r as usize] =
302+
bit_unpack(&v[0..32 * c], gamma1 - 1, gamma1).expect("Alg 34: try_from2 fail");
302303

303304
// 6: end for
304305
}
@@ -312,6 +313,7 @@ pub(crate) fn expand_mask<const L: usize>(gamma1: i32, rho: &[u8; 64], mu: u16)
312313
y
313314
}
314315

316+
315317
/// See for example, Algorithm 4 lines 10-22
316318
pub(crate) fn hash_message(message: &[u8], ph: &Ph, phm: &mut [u8; 64]) -> ([u8; 11], usize) {
317319
match ph {

src/lib.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616

1717
// TODO Roadmap
1818
// 1. Improve docs on first/last few algorithms
19-
// 2. Always more testing...
19+
// 2. Several outstanding refactors (mostly down below in this file)
20+
// 3. Always more testing...
21+
2022

2123
// Implements FIPS 204 Module-Lattice-Based Digital Signature Standard.
2224
// See <https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.204.pdf>
@@ -74,7 +76,7 @@
7476
// Algorithm 49 MontgomeryReduce(a) on page 50 --> helpers.rs
7577
// Types are in types.rs, traits are in traits.rs...
7678

77-
// Note that debug! statements enforce correct program construction and are not involved
79+
// Note that debug_assert! statements enforce correct program construction and are not involved
7880
// in any operational dataflow (so are good fuzz targets). The ensure! statements implement
7981
// conservative dataflow validation. Separately, functions are only generic over security
8082
// parameters that are directly involved in memory allocation (on the stack). Some coding

src/ml_dsa.rs

+16-16
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
// This file implements functionality from FIPS 204 sections 5/6: Key Generation, Signing, Verification
22

3-
use crate::encodings::{
4-
pk_decode, pk_encode, sig_decode, sig_encode, sk_decode, w1_encode,
5-
};
3+
use crate::encodings::{pk_decode, pk_encode, sig_decode, sig_encode, sk_decode, w1_encode};
64
use crate::hashing::{expand_a, expand_mask, expand_s, h256_xof, sample_in_ball};
75
use crate::helpers::{
8-
center_mod, full_reduce32, infinity_norm, mat_vec_mul, mont_reduce, partial_reduce32, to_mont,
9-
add_vector_ntt,
6+
add_vector_ntt, center_mod, full_reduce32, infinity_norm, mat_vec_mul, mont_reduce,
7+
partial_reduce32, to_mont,
108
};
119
use crate::high_low::{high_bits, low_bits, make_hint, power2round, use_hint};
1210
use crate::ntt::{inv_ntt, ntt};
@@ -33,7 +31,7 @@ pub(crate) fn key_gen<
3331
const SK_LEN: usize,
3432
>(
3533
rng: &mut impl CryptoRngCore, eta: i32,
36-
) -> Result<(PublicKey::<K,L>, PrivateKey::<K,L>), &'static str> {
34+
) -> Result<(PublicKey<K, L>, PrivateKey<K, L>), &'static str> {
3735
//
3836
// 1: ξ ← {0,1}^{256} ▷ Choose random seed
3937
let mut xi = [0u8; 32];
@@ -258,8 +256,6 @@ pub(crate) fn sign<
258256
}
259257

260258

261-
262-
263259
/// Continuation of `verify_start()`. The `lib.rs` wrapper around this will convert `Error()` to false.
264260
#[allow(clippy::too_many_arguments, clippy::similar_names)]
265261
pub(crate) fn verify<
@@ -270,8 +266,8 @@ pub(crate) fn verify<
270266
const SIG_LEN: usize,
271267
const W1_LEN: usize,
272268
>(
273-
beta: i32, gamma1: i32, gamma2: i32, omega: i32, tau: i32, epk: &PublicKey<K, L>,
274-
m: &[u8], sig: &[u8; SIG_LEN], ctx: &[u8], oid: &[u8], phm: &[u8], nist: bool,
269+
beta: i32, gamma1: i32, gamma2: i32, omega: i32, tau: i32, epk: &PublicKey<K, L>, m: &[u8],
270+
sig: &[u8; SIG_LEN], ctx: &[u8], oid: &[u8], phm: &[u8], nist: bool,
275271
) -> Result<bool, &'static str> {
276272
//
277273
let PublicKey { rho: _, cap_a_hat, tr, t1_d2_hat_mont } = epk;
@@ -369,7 +365,7 @@ pub(crate) fn key_gen_internal<
369365
const SK_LEN: usize,
370366
>(
371367
eta: i32, xi: &[u8; 32],
372-
) -> (PublicKey::<K,L>, PrivateKey<K,L>) {
368+
) -> (PublicKey<K, L>, PrivateKey<K, L>) {
373369
//
374370
// 1: (rho, rho′, 𝐾) ∈ 𝔹32 × 𝔹64 × 𝔹32 ← H(𝜉||IntegerToBytes(𝑘, 1)||IntegerToBytes(ℓ, 1), 128)
375371
let mut h2 = h256_xof(&[xi, &[K.to_le_bytes()[0]], &[L.to_le_bytes()[0]]]);
@@ -393,7 +389,8 @@ pub(crate) fn key_gen_internal<
393389
let s_1_hat: [T; L] = ntt(&s_1);
394390
let as1_hat: [T; K] = mat_vec_mul(&cap_a_hat, &s_1_hat);
395391
let t_not_reduced: [R; K] = add_vector_ntt(&inv_ntt(&as1_hat), &s_2);
396-
let t: [R; K] = core::array::from_fn(|k| R(core::array::from_fn(|n| full_reduce32(t_not_reduced[k].0[n]))));
392+
let t: [R; K] =
393+
core::array::from_fn(|k| R(core::array::from_fn(|n| full_reduce32(t_not_reduced[k].0[n]))));
397394

398395
// 6: (t_1, t_0) ← Power2Round(t, d) ▷ Compress t
399396
let (t_1, t_0): ([R; K], [R; K]) = power2round(&t);
@@ -421,7 +418,7 @@ pub(crate) fn key_gen_internal<
421418

422419
// 2: s_hat_1 ← NTT(s_1)
423420
let s_hat_1_mont: [T; L] = to_mont(&s_1_hat); //ntt(&s_1));
424-
// 3: s_hat_2 ← NTT(s_2)
421+
// 3: s_hat_2 ← NTT(s_2)
425422
let s_hat_2_mont: [T; K] = to_mont(&ntt(&s_2));
426423
// 4: t_hat_0 ← NTT(t_0)
427424
let t_hat_0_mont: [T; K] = to_mont(&ntt(&t_0));
@@ -440,13 +437,16 @@ pub(crate) fn key_gen_internal<
440437
}
441438

442439

443-
444-
445440
/// Expand the private/secret key by pre-calculating some constants used in the signing process.
446441
/// This is only used in the `try_from_bytes()` deserialization functionality.
447442
/// # Errors
448443
/// Returns an error on malformed private key.
449-
pub(crate) fn expand_private<const CTEST: bool, const K: usize, const L: usize, const SK_LEN: usize>(
444+
pub(crate) fn expand_private<
445+
const CTEST: bool,
446+
const K: usize,
447+
const L: usize,
448+
const SK_LEN: usize,
449+
>(
450450
eta: i32, sk: &[u8; SK_LEN],
451451
) -> Result<PrivateKey<K, L>, &'static str> {
452452
//

src/traits.rs

+2-29
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,6 @@ use rand_core::OsRng;
66

77
/// The `KeyGen` trait is defined to allow trait objects for keygen.
88
pub trait KeyGen {
9-
// /// A public key specific to the chosen security parameter set, e.g., ml-dsa-44,
10-
// /// ml-dsa-65 or ml-dsa-87
11-
// type PublicKey;
12-
// /// A private (secret) key specific to the chosen security parameter set, e.g.,
13-
// /// ml-dsa-44, ml-dsa-65 or ml-dsa-87
14-
// type PrivateKey;
159
/// An expanded public key containing precomputed elements to increase (repeated)
1610
/// verify performance. Derived from the public key.
1711
type PublicKey;
@@ -108,28 +102,6 @@ pub trait KeyGen {
108102
/// ```
109103
#[must_use]
110104
fn keygen_from_seed(xi: &[u8; 32]) -> (Self::PublicKey, Self::PrivateKey);
111-
112-
113-
// /// Generates an expanded private key from the normal/compressed private key.
114-
// /// This supports improved signing performance. This function operates in constant-time
115-
// /// relative to secret data (which specifically excludes the provided random `rho`
116-
// /// value as it is stored in the public key).
117-
// /// # Errors
118-
// /// This function operates on trusted data - either a private key directly from `keygen()`
119-
// /// or one validated during deserialization. Nonetheless, a `Result<>` is returned for
120-
// /// symmetry which can propagates internal errors.
121-
// fn gen_expanded_private(
122-
// sk: &Self::PrivateKey,
123-
// ) -> Result<Self::PrivateKey, &'static str>;
124-
//
125-
// /// Generates an expanded public key from the normal/compressed public key.
126-
// /// This supports improved verification performance. As this function operates on purely
127-
// /// public data, it need not provide constant-time assurances.
128-
// /// # Errors
129-
// /// This function operates on trusted data - either a public key directly from `keygen()`
130-
// /// or one validated during deserialization. Nonetheless, a `Result<>` is returned for
131-
// /// symmetry which can propagates internal errors.
132-
// fn gen_expanded_public(pk: &Self::PublicKey) -> Result<Self::PublicKey, &'static str>;
133105
}
134106

135107

@@ -218,7 +190,8 @@ pub trait Signer {
218190
/// Will return an error on rng failure
219191
#[cfg(feature = "default-rng")]
220192
fn try_hash_sign(
221-
&self, message: &[u8], ctx: &[u8], ph: &Ph) -> Result<Self::Signature, &'static str> {
193+
&self, message: &[u8], ctx: &[u8], ph: &Ph,
194+
) -> Result<Self::Signature, &'static str> {
222195
self.try_hash_sign_with_rng(&mut OsRng, message, ctx, ph)
223196
}
224197

src/types.rs

+8-20
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,10 @@ pub enum Ph {
1212
}
1313

1414

15-
// /// Correctly sized private key specific to the target security parameter set. <br>
16-
// /// Implements the [`crate::traits::Signer`] and [`crate::traits::SerDes`] trait.
17-
// #[derive(Clone, Zeroize, ZeroizeOnDrop)]
18-
// #[repr(align(8))]
19-
// pub struct PrivateKey<const SK_LEN: usize>(pub(crate) [u8; SK_LEN]);
20-
21-
22-
/// Expanded private key, specific to the target security parameter set, that contains <br>
23-
/// precomputed elements which increase (repeated) signature performance. Implements only
24-
/// the [`crate::traits::Signer`] trait.
15+
/// Private key specific to the target security parameter set that contains
16+
/// precomputed elements which improve signature performance.
17+
///
18+
/// Implements the [`crate::traits::Signer`] and [`crate::traits::SerDes`] traits.
2519
#[derive(Clone, Zeroize, ZeroizeOnDrop)]
2620
#[repr(align(8))]
2721
pub struct PrivateKey<const K: usize, const L: usize> {
@@ -35,16 +29,10 @@ pub struct PrivateKey<const K: usize, const L: usize> {
3529
}
3630

3731

38-
// /// Correctly sized public key specific to the target security parameter set. <br>
39-
// /// Implements the [`crate::traits::Verifier`] and [`crate::traits::SerDes`] traits.
40-
// #[derive(Clone, Zeroize, ZeroizeOnDrop)]
41-
// #[repr(align(8))]
42-
// pub struct PublicKey<const PK_LEN: usize>(pub(crate) [u8; PK_LEN]);
43-
44-
45-
/// Expanded public key, specific to the target security parameter set, that contains <br>
46-
/// precomputed elements which increase (repeated) verification performance. Implements only
47-
/// the [`crate::traits::Verifier`] traits.
32+
/// Public key specific to the target security parameter set that contains
33+
/// precomputed elements which improve verification performance.
34+
///
35+
/// Implements the [`crate::traits::Verifier`] and [`crate::traits::SerDes`] traits.
4836
#[derive(Clone, Zeroize, ZeroizeOnDrop)]
4937
#[repr(align(8))]
5038
pub struct PublicKey<const K: usize, const L: usize> {

0 commit comments

Comments
 (0)