Skip to main content

pqcrypto_std/mldsa/
mldsa44.rs

1//! ML-DSA-44 parameter set.
2
3use super::{
4    bitlen, coeff, privkey_size, pubkey_size, sig_size, Poly, PolyVec, SigningKeyInternal,
5    VerifyingKeyInternal, Q,
6};
7use crate::hash;
8use core::mem::{transmute, MaybeUninit};
9
10const K: usize = 4;
11const L: usize = 4;
12const ETA: usize = 2;
13const GAMMA1: usize = 1 << 17;
14const GAMMA2: usize = (Q as usize - 1) / 88;
15const LAMBDA: usize = 128;
16const TAU: usize = 39;
17const BETA: usize = TAU * ETA;
18const OMEGA: usize = 80;
19
20const CT_BYTES: usize = LAMBDA / 4;
21const Z_BYTES: usize = L * 32 * (1 + bitlen(GAMMA1 - 1));
22const H_BYTES: usize = OMEGA + K;
23const W1_BYTES: usize = K * 32 * bitlen((Q as usize - 1) / (2 * GAMMA2) - 1);
24
25/// Public key bytesize.
26pub const PUBKEY_SIZE: usize = pubkey_size(K);
27
28/// Private key bytesize.
29pub const PRIVKEY_SIZE: usize = privkey_size(K, L, ETA);
30
31/// Signature bytesize.
32pub const SIG_SIZE: usize = sig_size(K, L, LAMBDA, GAMMA1, OMEGA);
33
34/// Private key used for signing.
35pub struct PrivateKey {
36    key: super::PrivateKey<K, L, ETA>,
37}
38
39impl From<super::PrivateKey<K, L, ETA>> for PrivateKey {
40    fn from(key: super::PrivateKey<K, L, ETA>) -> Self {
41        Self { key }
42    }
43}
44
45impl SigningKeyInternal<K, L, ETA, TAU, GAMMA1, GAMMA2, BETA, OMEGA, CT_BYTES, W1_BYTES, Z_BYTES>
46    for PrivateKey
47{
48    fn privkey(&self) -> &super::PrivateKey<K, L, ETA> {
49        &self.key
50    }
51
52    fn expand_mask(pvec: &mut PolyVec<L>, rho: &[u8; 64], mu: usize, h: &mut hash::Shake256) {
53        pvec.expand_mask_2pow17(rho, mu, h);
54    }
55
56    fn bitpack_z(pvec: &PolyVec<L>, dst: &mut [u8; Z_BYTES]) {
57        pvec.bitpack_2pow17(dst);
58    }
59
60    fn pack_simple(w1: &PolyVec<K>, z: &mut [u8; W1_BYTES]) {
61        w1.pack_simple_6bit(z);
62    }
63
64    fn decompose(x: &PolyVec<K>, x0: &mut PolyVec<K>, x1: &mut PolyVec<K>) {
65        x.decompose_88(x0, x1);
66    }
67}
68
69pub struct PublicKey {
70    key: super::PublicKey<K, L>,
71}
72
73impl VerifyingKeyInternal<K, L, CT_BYTES, Z_BYTES, H_BYTES, W1_BYTES, SIG_SIZE> for PublicKey {
74    const OMEGA: usize = OMEGA;
75
76    const TAU: usize = TAU;
77
78    const GAMMA1: usize = GAMMA1;
79
80    const GAMMA2: usize = GAMMA2;
81
82    const BETA: usize = BETA;
83
84    fn bitunpack_z_hat(b: &[u8; Z_BYTES]) -> PolyVec<L> {
85        let mut pvec = PolyVec::zero();
86
87        for (poly, bytes) in pvec
88            .v
89            .iter_mut()
90            .zip(b.chunks_exact(Poly::packed_bytesize(18)))
91        {
92            poly.bitunpack_2pow17(bytes.try_into().unwrap());
93        }
94
95        pvec
96    }
97
98    fn w1encode(w1: &PolyVec<K>) -> [u8; W1_BYTES] {
99        let mut bytes = [const { MaybeUninit::uninit() }; W1_BYTES];
100        for (chunk, p) in bytes
101            .chunks_exact_mut(Poly::packed_bytesize(6))
102            .zip(w1.v.iter())
103        {
104            p.pack_simple_uninit_6bit(chunk.try_into().unwrap());
105        }
106
107        unsafe { transmute(bytes) }
108    }
109
110    fn use_hint(w1: &mut PolyVec<K>, h: &PolyVec<K>) {
111        for (i, poly) in w1.v.iter_mut().enumerate() {
112            for (j, a) in poly.f.iter_mut().enumerate() {
113                *a = coeff::use_hint_88(h.v[i].f[j] as usize, *a);
114            }
115        }
116    }
117
118    fn pk(&self) -> &super::PublicKey<K, L> {
119        &self.key
120    }
121}
122
123impl From<super::PublicKey<K, L>> for PublicKey {
124    fn from(key: super::PublicKey<K, L>) -> Self {
125        Self { key }
126    }
127}