mirror of
https://github.com/saymrwulf/fips205-source.git
synced 2026-09-04 20:03:45 +00:00
working traits
This commit is contained in:
parent
69f94c55fe
commit
6c449f3e36
6 changed files with 334 additions and 122 deletions
|
|
@ -704,7 +704,7 @@ pub(crate) fn ht_verify<
|
||||||
for j in 1..D::to_u32() {
|
for j in 1..D::to_u32() {
|
||||||
//
|
//
|
||||||
// 7: idx_leaf ← idx_tree mod 2^{h′} ▷ h′ least significant bits of idx_tree
|
// 7: idx_leaf ← idx_tree mod 2^{h′} ▷ h′ least significant bits of idx_tree
|
||||||
let idx_leaf = u32::try_from(idx_tree % 2u64.pow(HP::to_u32())); // TODO: clean
|
let idx_leaf = u32::try_from(idx_tree % 2u64.pow(HP::to_u32())); // TODO: clean
|
||||||
if idx_leaf.is_err() {
|
if idx_leaf.is_err() {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ pub(crate) mod shake {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[allow(clippy::similar_names)] // pk_seed and sk_seed
|
#[allow(clippy::similar_names)] // pk_seed and sk_seed
|
||||||
pub(crate) fn prf<N: ArrayLength>(
|
pub(crate) fn prf<N: ArrayLength>(
|
||||||
pk_seed: &[u8], sk_seed: &[u8], adrs: &Adrs,
|
pk_seed: &[u8], sk_seed: &[u8], adrs: &Adrs,
|
||||||
) -> GenericArray<u8, N> {
|
) -> GenericArray<u8, N> {
|
||||||
|
|
@ -103,10 +103,7 @@ pub(crate) mod shake {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(feature = "slh_dsa_sha2_128f", feature = "slh_dsa_sha2_128s"))]
|
||||||
feature = "slh_dsa_sha2_128f",
|
|
||||||
feature = "slh_dsa_sha2_128s"
|
|
||||||
))]
|
|
||||||
pub(crate) mod sha2_cat_1 {
|
pub(crate) mod sha2_cat_1 {
|
||||||
use crate::types::Adrs;
|
use crate::types::Adrs;
|
||||||
use core::cmp::min;
|
use core::cmp::min;
|
||||||
|
|
@ -143,7 +140,7 @@ pub(crate) mod sha2_cat_1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[allow(clippy::similar_names)] // pk_seed and sk_seed
|
#[allow(clippy::similar_names)] // pk_seed and sk_seed
|
||||||
pub(crate) fn prf<N: ArrayLength>(
|
pub(crate) fn prf<N: ArrayLength>(
|
||||||
pk_seed: &[u8], sk_seed: &[u8], adrs: &Adrs,
|
pk_seed: &[u8], sk_seed: &[u8], adrs: &Adrs,
|
||||||
) -> GenericArray<u8, N> {
|
) -> GenericArray<u8, N> {
|
||||||
|
|
@ -247,10 +244,10 @@ pub(crate) mod sha2_cat_1 {
|
||||||
|
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
feature = "slh_dsa_sha2_192f",
|
feature = "slh_dsa_sha2_192f",
|
||||||
feature = "slh_dsa_sha2_192s",
|
feature = "slh_dsa_sha2_192s",
|
||||||
feature = "slh_dsa_sha2_256f",
|
feature = "slh_dsa_sha2_256f",
|
||||||
feature = "slh_dsa_sha2_256s"
|
feature = "slh_dsa_sha2_256s"
|
||||||
))]
|
))]
|
||||||
pub(crate) mod sha2_cat_3_5 {
|
pub(crate) mod sha2_cat_3_5 {
|
||||||
use crate::types::Adrs;
|
use crate::types::Adrs;
|
||||||
|
|
@ -297,7 +294,7 @@ pub(crate) mod sha2_cat_3_5 {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[allow(clippy::similar_names)] // pk_seed and sk_seed
|
#[allow(clippy::similar_names)] // pk_seed and sk_seed
|
||||||
pub(crate) fn prf<N: ArrayLength>(
|
pub(crate) fn prf<N: ArrayLength>(
|
||||||
pk_seed: &[u8], sk_seed: &[u8], adrs: &Adrs,
|
pk_seed: &[u8], sk_seed: &[u8], adrs: &Adrs,
|
||||||
) -> GenericArray<u8, N> {
|
) -> GenericArray<u8, N> {
|
||||||
|
|
|
||||||
199
src/lib.rs
199
src/lib.rs
|
|
@ -9,7 +9,6 @@
|
||||||
// 2. SerDes on keys
|
// 2. SerDes on keys
|
||||||
// 3. Proper traits and non-rng functions
|
// 3. Proper traits and non-rng functions
|
||||||
// 4. Adrs as raw bytes
|
// 4. Adrs as raw bytes
|
||||||
// 5. clippy
|
|
||||||
// 6. Separate into proper files
|
// 6. Separate into proper files
|
||||||
// 7. Doc, of course!
|
// 7. Doc, of course!
|
||||||
mod algs;
|
mod algs;
|
||||||
|
|
@ -27,33 +26,111 @@ const LEN2: u32 = 3;
|
||||||
/// blah
|
/// blah
|
||||||
macro_rules! functionality {
|
macro_rules! functionality {
|
||||||
() => {
|
() => {
|
||||||
|
use crate::traits::{KeyGen, SerDes, Signer, Verifier};
|
||||||
use crate::types::{SlhDsaSig, SlhPrivateKey, SlhPublicKey};
|
use crate::types::{SlhDsaSig, SlhPrivateKey, SlhPublicKey};
|
||||||
use rand_core::CryptoRngCore;
|
use rand_core::CryptoRngCore;
|
||||||
|
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||||
|
|
||||||
|
#[derive(Zeroize, ZeroizeOnDrop)]
|
||||||
|
pub struct PublicKey(SlhPublicKey<N>);
|
||||||
|
|
||||||
|
#[derive(Zeroize, ZeroizeOnDrop)]
|
||||||
|
pub struct PrivateKey(SlhPrivateKey<N>);
|
||||||
|
|
||||||
|
#[derive(Zeroize, ZeroizeOnDrop)]
|
||||||
|
pub struct KG(); // Arguable how useful an empty struct+trait is...
|
||||||
|
|
||||||
/// blah
|
/// blah
|
||||||
/// # Errors
|
/// # Errors
|
||||||
pub fn slh_keygen_with_rng(
|
impl KeyGen for KG {
|
||||||
rng: &mut impl CryptoRngCore,
|
type PrivateKey = PrivateKey;
|
||||||
) -> Result<(SlhPrivateKey<N>, SlhPublicKey<N>), &'static str> {
|
type PublicKey = PublicKey;
|
||||||
crate::algs::slh_keygen_with_rng::<D, H, HP, K, Len, M, N>(rng, &HASHERS)
|
|
||||||
|
fn try_keygen_with_rng_vt(
|
||||||
|
rng: &mut impl CryptoRngCore,
|
||||||
|
) -> Result<(PublicKey, PrivateKey), &'static str> {
|
||||||
|
let res = crate::algs::slh_keygen_with_rng::<D, H, HP, K, Len, M, N>(rng, &HASHERS);
|
||||||
|
res.map(|(sk, pk)| (PublicKey(pk), PrivateKey(sk)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// blah
|
#[cfg(feature = "default-rng")]
|
||||||
/// # Errors
|
pub fn try_keygen_vt() -> Result<(PublicKey, PrivateKey), &'static str> {
|
||||||
pub fn slh_sign_with_rng(
|
KG::try_keygen_vt()
|
||||||
rng: &mut impl CryptoRngCore, m: &[u8], sk: &SlhPrivateKey<N>, randomize: bool,
|
|
||||||
) -> Result<[u8; SIG_LEN], &'static str> {
|
|
||||||
let sig = crate::algs::slh_sign_with_rng::<A, D, H, HP, K, Len, M, N>(
|
|
||||||
rng, &HASHERS, &m, &sk, randomize,
|
|
||||||
);
|
|
||||||
sig.map(|s| s.deserialize())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// blah
|
impl Signer for PrivateKey {
|
||||||
#[must_use]
|
type Signature = [u8; SIG_LEN];
|
||||||
pub fn slh_verify(m: &[u8], sig_bytes: &[u8; SIG_LEN], pk: &SlhPublicKey<N>) -> bool {
|
|
||||||
let sig = SlhDsaSig::<A, D, HP, K, Len, N>::serialize(sig_bytes);
|
/// blah
|
||||||
crate::algs::slh_verify::<A, D, H, HP, K, Len, M, N>(&HASHERS, &m, &sig, &pk)
|
/// # Errors
|
||||||
|
fn try_sign_with_rng_ct(
|
||||||
|
&self, rng: &mut impl CryptoRngCore, m: &[u8], randomize: bool,
|
||||||
|
) -> Result<[u8; SIG_LEN], &'static str> {
|
||||||
|
let sig = crate::algs::slh_sign_with_rng::<A, D, H, HP, K, Len, M, N>(
|
||||||
|
rng, &HASHERS, &m, &self.0, randomize,
|
||||||
|
);
|
||||||
|
sig.map(|s| s.deserialize())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Verifier for PublicKey {
|
||||||
|
type Signature = [u8; SIG_LEN];
|
||||||
|
|
||||||
|
/// blah
|
||||||
|
#[must_use]
|
||||||
|
fn try_verify_vt(&self,
|
||||||
|
m: &[u8], sig_bytes: &[u8; SIG_LEN],
|
||||||
|
) -> Result<bool, &'static str> {
|
||||||
|
let sig = SlhDsaSig::<A, D, HP, K, Len, N>::serialize(sig_bytes);
|
||||||
|
let res =
|
||||||
|
crate::algs::slh_verify::<A, D, H, HP, K, Len, M, N>(&HASHERS, &m, &sig, &self.0);
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SerDes for PublicKey {
|
||||||
|
type ByteArray = [u8; PK_LEN];
|
||||||
|
|
||||||
|
fn into_bytes(self) -> Self::ByteArray {
|
||||||
|
let mut out = [0u8; PK_LEN];
|
||||||
|
out[0..(PK_LEN / 2)].copy_from_slice(&self.0.pk_seed);
|
||||||
|
out[(PK_LEN / 2)..].copy_from_slice(&self.0.pk_root);
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_from_bytes(bytes: &Self::ByteArray) -> Result<Self, &'static str> {
|
||||||
|
// Result: opportunity for validation
|
||||||
|
let mut pk = SlhPublicKey::default();
|
||||||
|
pk.pk_seed.copy_from_slice(&bytes[..(PK_LEN / 2)]);
|
||||||
|
pk.pk_root.copy_from_slice(&bytes[(PK_LEN / 2)..]);
|
||||||
|
Ok(PublicKey(pk))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SerDes for PrivateKey {
|
||||||
|
type ByteArray = [u8; SK_LEN];
|
||||||
|
|
||||||
|
fn into_bytes(self) -> Self::ByteArray {
|
||||||
|
let mut bytes = [0u8; SK_LEN];
|
||||||
|
bytes[0..(SK_LEN / 4)].copy_from_slice(&self.0.sk_seed);
|
||||||
|
bytes[(SK_LEN / 4)..(SK_LEN / 2)].copy_from_slice(&self.0.sk_prf);
|
||||||
|
bytes[(SK_LEN / 2)..(3 * SK_LEN / 4)].copy_from_slice(&self.0.pk_seed);
|
||||||
|
bytes[(3 * SK_LEN / 4)..].copy_from_slice(&self.0.pk_root);
|
||||||
|
bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_from_bytes(bytes: &Self::ByteArray) -> Result<Self, &'static str> {
|
||||||
|
// Result: opportunity for validation
|
||||||
|
let mut sk = SlhPrivateKey::default();
|
||||||
|
sk.sk_seed.copy_from_slice(&bytes[0..(SK_LEN / 4)]);
|
||||||
|
sk.sk_prf
|
||||||
|
.copy_from_slice(&bytes[(SK_LEN / 4)..(SK_LEN / 2)]);
|
||||||
|
sk.pk_seed
|
||||||
|
.copy_from_slice(&bytes[(SK_LEN / 2)..(3 * SK_LEN / 4)]);
|
||||||
|
sk.pk_root.copy_from_slice(&bytes[(3 * SK_LEN / 4)..]);
|
||||||
|
Ok(PrivateKey(sk))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
@ -67,12 +144,16 @@ macro_rules! functionality {
|
||||||
let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(123);
|
let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(123);
|
||||||
for i in 0..5 {
|
for i in 0..5 {
|
||||||
message[3] = i as u8;
|
message[3] = i as u8;
|
||||||
let (sk, pk) = slh_keygen_with_rng(&mut rng).unwrap();
|
let (pk1, sk1) = KG::try_keygen_with_rng_vt(&mut rng).unwrap();
|
||||||
let sig = slh_sign_with_rng(&mut rng, &message, &sk, true).unwrap();
|
let pk1_bytes = pk1.into_bytes();
|
||||||
let result = slh_verify(&message, &sig, &pk);
|
let pk2 = PublicKey::try_from_bytes(&pk1_bytes).unwrap();
|
||||||
|
let sk1_bytes = sk1.into_bytes();
|
||||||
|
let sk2 = PrivateKey::try_from_bytes(&sk1_bytes).unwrap();
|
||||||
|
let sig = sk2.try_sign_with_rng_ct(&mut rng, &message, true).unwrap();
|
||||||
|
let result = pk2.try_verify_vt(&message, &sig).unwrap();
|
||||||
assert_eq!(result, true, "Signature failed to verify");
|
assert_eq!(result, true, "Signature failed to verify");
|
||||||
message[3] = (i + 1) as u8;
|
message[3] = (i + 1) as u8;
|
||||||
let result = slh_verify(&message, &sig, &pk);
|
let result = pk2.try_verify_vt(&message, &sig).unwrap();
|
||||||
assert_eq!(result, false, "Signature should not have verified");
|
assert_eq!(result, false, "Signature should not have verified");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -96,9 +177,9 @@ pub mod slh_dsa_sha2_128s {
|
||||||
type K = U14;
|
type K = U14;
|
||||||
type M = U30;
|
type M = U30;
|
||||||
type Len = Sum<Prod<U2, N>, U3>;
|
type Len = Sum<Prod<U2, N>, U3>;
|
||||||
//const PK_LEN: usize = 32;
|
pub const PK_LEN: usize = 32;
|
||||||
const SIG_LEN: usize = 7856;
|
pub const SIG_LEN: usize = 7856;
|
||||||
//const SK_LEN: usize = 0000;
|
pub const SK_LEN: usize = PK_LEN * 2;
|
||||||
static HASHERS: Hashers<K, Len, M, N> =
|
static HASHERS: Hashers<K, Len, M, N> =
|
||||||
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
||||||
|
|
||||||
|
|
@ -121,9 +202,9 @@ pub mod slh_dsa_shake_128s {
|
||||||
type K = U14;
|
type K = U14;
|
||||||
type M = U30;
|
type M = U30;
|
||||||
type Len = Sum<Prod<U2, N>, U3>;
|
type Len = Sum<Prod<U2, N>, U3>;
|
||||||
//const PK_LEN: usize = 32;
|
pub const PK_LEN: usize = 32;
|
||||||
const SIG_LEN: usize = 7856;
|
pub const SIG_LEN: usize = 7856;
|
||||||
//const SK_LEN: usize = 0000;
|
pub const SK_LEN: usize = PK_LEN * 2;
|
||||||
static HASHERS: Hashers<K, Len, M, N> =
|
static HASHERS: Hashers<K, Len, M, N> =
|
||||||
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
||||||
|
|
||||||
|
|
@ -146,9 +227,9 @@ pub mod slh_dsa_sha2_128f {
|
||||||
type K = U33;
|
type K = U33;
|
||||||
type M = U34;
|
type M = U34;
|
||||||
type Len = Sum<Prod<U2, N>, U3>;
|
type Len = Sum<Prod<U2, N>, U3>;
|
||||||
//const PK_LEN: usize = 32;
|
pub const PK_LEN: usize = 32;
|
||||||
const SIG_LEN: usize = 17088;
|
pub const SIG_LEN: usize = 17088;
|
||||||
//const SK_LEN: usize = 0000;
|
pub const SK_LEN: usize = PK_LEN * 2;
|
||||||
static HASHERS: Hashers<K, Len, M, N> =
|
static HASHERS: Hashers<K, Len, M, N> =
|
||||||
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
||||||
|
|
||||||
|
|
@ -171,9 +252,9 @@ pub mod slh_dsa_shake_128f {
|
||||||
type K = U33;
|
type K = U33;
|
||||||
type M = U34;
|
type M = U34;
|
||||||
type Len = Sum<Prod<U2, N>, U3>;
|
type Len = Sum<Prod<U2, N>, U3>;
|
||||||
//const PK_LEN: usize = 32;
|
pub const PK_LEN: usize = 32;
|
||||||
const SIG_LEN: usize = 17088;
|
pub const SIG_LEN: usize = 17088;
|
||||||
//const SK_LEN: usize = 0000;
|
pub const SK_LEN: usize = PK_LEN * 2;
|
||||||
static HASHERS: Hashers<K, Len, M, N> =
|
static HASHERS: Hashers<K, Len, M, N> =
|
||||||
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
||||||
|
|
||||||
|
|
@ -196,9 +277,9 @@ pub mod slh_dsa_sha2_192s {
|
||||||
type K = U17;
|
type K = U17;
|
||||||
type M = U39;
|
type M = U39;
|
||||||
type Len = Sum<Prod<U2, N>, U3>;
|
type Len = Sum<Prod<U2, N>, U3>;
|
||||||
//const PK_LEN: usize = 32;
|
pub const PK_LEN: usize = 48;
|
||||||
const SIG_LEN: usize = 16224;
|
pub const SIG_LEN: usize = 16224;
|
||||||
//const SK_LEN: usize = 0000;
|
pub const SK_LEN: usize = PK_LEN * 2;
|
||||||
static HASHERS: Hashers<K, Len, M, N> =
|
static HASHERS: Hashers<K, Len, M, N> =
|
||||||
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
||||||
|
|
||||||
|
|
@ -221,9 +302,9 @@ pub mod slh_dsa_shake_192s {
|
||||||
type K = U17;
|
type K = U17;
|
||||||
type M = U39;
|
type M = U39;
|
||||||
type Len = Sum<Prod<U2, N>, U3>;
|
type Len = Sum<Prod<U2, N>, U3>;
|
||||||
//const PK_LEN: usize = 32;
|
pub const PK_LEN: usize = 48;
|
||||||
const SIG_LEN: usize = 16224;
|
pub const SIG_LEN: usize = 16224;
|
||||||
//const SK_LEN: usize = 0000;
|
pub const SK_LEN: usize = PK_LEN * 2;
|
||||||
static HASHERS: Hashers<K, Len, M, N> =
|
static HASHERS: Hashers<K, Len, M, N> =
|
||||||
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
||||||
|
|
||||||
|
|
@ -246,9 +327,9 @@ pub mod slh_dsa_sha2_192f {
|
||||||
type K = U33;
|
type K = U33;
|
||||||
type M = U42;
|
type M = U42;
|
||||||
type Len = Sum<Prod<U2, N>, U3>;
|
type Len = Sum<Prod<U2, N>, U3>;
|
||||||
//const PK_LEN: usize = 32;
|
pub const PK_LEN: usize = 48;
|
||||||
const SIG_LEN: usize = 35664;
|
pub const SIG_LEN: usize = 35664;
|
||||||
//const SK_LEN: usize = 0000;
|
pub const SK_LEN: usize = PK_LEN * 2;
|
||||||
static HASHERS: Hashers<K, Len, M, N> =
|
static HASHERS: Hashers<K, Len, M, N> =
|
||||||
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
||||||
|
|
||||||
|
|
@ -271,9 +352,9 @@ pub mod slh_dsa_shake_192f {
|
||||||
type K = U33;
|
type K = U33;
|
||||||
type M = U42;
|
type M = U42;
|
||||||
type Len = Sum<Prod<U2, N>, U3>;
|
type Len = Sum<Prod<U2, N>, U3>;
|
||||||
//const PK_LEN: usize = 32;
|
pub const PK_LEN: usize = 48;
|
||||||
const SIG_LEN: usize = 35664;
|
pub const SIG_LEN: usize = 35664;
|
||||||
//const SK_LEN: usize = 0000;
|
pub const SK_LEN: usize = PK_LEN * 2;
|
||||||
static HASHERS: Hashers<K, Len, M, N> =
|
static HASHERS: Hashers<K, Len, M, N> =
|
||||||
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
||||||
|
|
||||||
|
|
@ -296,9 +377,9 @@ pub mod slh_dsa_sha2_256s {
|
||||||
type K = U22;
|
type K = U22;
|
||||||
type M = U47;
|
type M = U47;
|
||||||
type Len = Sum<Prod<U2, N>, U3>;
|
type Len = Sum<Prod<U2, N>, U3>;
|
||||||
//const PK_LEN: usize = 32;
|
pub const PK_LEN: usize = 64;
|
||||||
const SIG_LEN: usize = 29792;
|
pub const SIG_LEN: usize = 29792;
|
||||||
//const SK_LEN: usize = 0000;
|
pub const SK_LEN: usize = PK_LEN * 2;
|
||||||
static HASHERS: Hashers<K, Len, M, N> =
|
static HASHERS: Hashers<K, Len, M, N> =
|
||||||
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
||||||
|
|
||||||
|
|
@ -321,9 +402,9 @@ pub mod slh_dsa_shake_256s {
|
||||||
type K = U22;
|
type K = U22;
|
||||||
type M = U47;
|
type M = U47;
|
||||||
type Len = Sum<Prod<U2, N>, U3>;
|
type Len = Sum<Prod<U2, N>, U3>;
|
||||||
//const PK_LEN: usize = 32;
|
pub const PK_LEN: usize = 64;
|
||||||
const SIG_LEN: usize = 29792;
|
pub const SIG_LEN: usize = 29792;
|
||||||
//const SK_LEN: usize = 0000;
|
pub const SK_LEN: usize = PK_LEN * 2;
|
||||||
static HASHERS: Hashers<K, Len, M, N> =
|
static HASHERS: Hashers<K, Len, M, N> =
|
||||||
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
||||||
|
|
||||||
|
|
@ -346,9 +427,9 @@ pub mod slh_dsa_sha2_256f {
|
||||||
type K = U35;
|
type K = U35;
|
||||||
type M = U49;
|
type M = U49;
|
||||||
type Len = Sum<Prod<U2, N>, U3>;
|
type Len = Sum<Prod<U2, N>, U3>;
|
||||||
//const PK_LEN: usize = 32;
|
pub const PK_LEN: usize = 64;
|
||||||
const SIG_LEN: usize = 49856;
|
pub const SIG_LEN: usize = 49856;
|
||||||
//const SK_LEN: usize = 0000;
|
pub const SK_LEN: usize = PK_LEN * 2;
|
||||||
static HASHERS: Hashers<K, Len, M, N> =
|
static HASHERS: Hashers<K, Len, M, N> =
|
||||||
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
||||||
|
|
||||||
|
|
@ -371,9 +452,9 @@ pub mod slh_dsa_shake_256f {
|
||||||
type K = U35;
|
type K = U35;
|
||||||
type M = U49;
|
type M = U49;
|
||||||
type Len = Sum<Prod<U2, N>, U3>;
|
type Len = Sum<Prod<U2, N>, U3>;
|
||||||
//const PK_LEN: usize = 32;
|
pub const PK_LEN: usize = 64;
|
||||||
const SIG_LEN: usize = 49856;
|
pub const SIG_LEN: usize = 49856;
|
||||||
//const SK_LEN: usize = 0000;
|
pub const SK_LEN: usize = PK_LEN * 2;
|
||||||
static HASHERS: Hashers<K, Len, M, N> =
|
static HASHERS: Hashers<K, Len, M, N> =
|
||||||
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
Hashers::<K, Len, M, N> { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
|
||||||
|
|
||||||
|
|
|
||||||
97
src/test.rs
97
src/test.rs
File diff suppressed because one or more lines are too long
118
src/traits.rs
118
src/traits.rs
|
|
@ -1,4 +1,116 @@
|
||||||
pub trait PK {
|
use rand_core::CryptoRngCore;
|
||||||
type Seed;
|
#[cfg(feature = "default-rng")]
|
||||||
fn seed(&self) -> Self::Seed;
|
use rand_core::OsRng;
|
||||||
|
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
/// ```
|
||||||
|
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
|
||||||
|
/// ```
|
||||||
|
fn try_from_bytes(bytes: &Self::ByteArray) -> Result<Self, &'static str>
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// 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;
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
/// ```
|
||||||
|
#[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
|
||||||
|
/// ```
|
||||||
|
fn try_keygen_with_rng_vt(
|
||||||
|
rng: &mut impl CryptoRngCore,
|
||||||
|
) -> Result<(Self::PublicKey, Self::PrivateKey), &'static str>;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
/// ```
|
||||||
|
#[cfg(feature = "default-rng")]
|
||||||
|
fn try_sign_ct(
|
||||||
|
&self, message: &[u8], randomize: bool,
|
||||||
|
) -> Result<Self::Signature, &'static str> {
|
||||||
|
self.try_sign_with_rng_ct(&mut OsRng, message, randomize)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
/// ```
|
||||||
|
fn try_sign_with_rng_ct(
|
||||||
|
&self, rng: &mut impl CryptoRngCore, message: &[u8], randomize: bool,
|
||||||
|
) -> 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
|
||||||
|
/// ```
|
||||||
|
fn try_verify_vt(
|
||||||
|
&self, message: &[u8], signature: &Self::Signature,
|
||||||
|
) -> Result<bool, &'static str>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
21
src/types.rs
21
src/types.rs
|
|
@ -106,6 +106,27 @@ pub struct SlhPublicKey<N: ArrayLength> {
|
||||||
pub(crate) pk_root: GenericArray<u8, N>,
|
pub(crate) pk_root: GenericArray<u8, N>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
impl<N: ArrayLength> SlhPublicKey<N> {
|
||||||
|
pub fn serialize<const PK_LEN: usize>(self) -> [u8; PK_LEN] {
|
||||||
|
let mut out = [0u8; PK_LEN];
|
||||||
|
debug_assert_eq!(out.len(), 2 * N::to_usize());
|
||||||
|
out[0..N::to_usize()].copy_from_slice(&self.pk_seed);
|
||||||
|
out[N::to_usize()..2 * N::to_usize()].copy_from_slice(&self.pk_root);
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deserialize<const PK_LEN: usize>(bytes: [u8; PK_LEN]) -> Self {
|
||||||
|
let mut pub_key = Self::default();
|
||||||
|
pub_key.pk_seed.copy_from_slice(&bytes[0..N::to_usize()]);
|
||||||
|
pub_key
|
||||||
|
.pk_root
|
||||||
|
.copy_from_slice(&bytes[N::to_usize()..2 * N::to_usize()]);
|
||||||
|
pub_key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, Zeroize, ZeroizeOnDrop)]
|
||||||
pub struct SlhPrivateKey<N: ArrayLength> {
|
pub struct SlhPrivateKey<N: ArrayLength> {
|
||||||
pub(crate) sk_seed: GenericArray<u8, N>,
|
pub(crate) sk_seed: GenericArray<u8, N>,
|
||||||
pub(crate) sk_prf: GenericArray<u8, N>,
|
pub(crate) sk_prf: GenericArray<u8, N>,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue