diff --git a/src/fors.rs b/src/fors.rs
index 6446e13..ec76bcd 100644
--- a/src/fors.rs
+++ b/src/fors.rs
@@ -1,7 +1,6 @@
use crate::hashers::Hashers;
use crate::helpers;
-use crate::types::{Adrs, ForsPk, ForsSig, FORS_PRF, FORS_ROOTS};
-use generic_array::{ArrayLength, GenericArray};
+use crate::types::{Adrs, ForsPk, ForsSig, FORS_PRF, FORS_ROOTS, Auth};
/// Algorithm 13: `fors_SKgen(SK.seed, PK.seed, ADRS, idx)` on page 29.
@@ -10,9 +9,9 @@ use generic_array::{ArrayLength, GenericArray};
/// Input: Secret seed `SK.seed`, public seed `PK.seed`, address `ADRS`, secret key index `idx`.
/// Output: n-byte FORS private-key value.
#[allow(clippy::similar_names)] // sk_seed and pk_seed
-pub(crate) fn fors_sk_gen(
+pub(crate) fn fors_sk_gen(
hashers: &Hashers, sk_seed: &[u8], pk_seed: &[u8], adrs: &Adrs, idx: u32,
-) -> GenericArray {
+) -> [u8; N] {
// 1: skADRS ← ADRS ▷ Copy address to create key generation address
let mut sk_adrs = adrs.clone();
@@ -38,18 +37,19 @@ pub(crate) fn fors_sk_gen(
hashers: &Hashers, sk_seed: &[u8], i: u32, z: u32, pk_seed: &[u8], adrs: &Adrs,
-) -> Result, &'static str> {
+) -> Result<[u8; N], &'static str> {
let mut adrs = adrs.clone();
+ let (a32, k32) = (u32::try_from(A).unwrap(), u32::try_from(K).unwrap());
// 1: if z > a or i ≥ k · 2^(a−z) then
- if (z > A::to_u32()) | (i > K::to_u32() * 2u32.pow(A::to_u32() - z)) {
+ if (z > a32) | (i > k32 * 2u32.pow(a32 - z)) {
//
// 2: return NULL
return Err("Alg14 fails");
@@ -61,7 +61,7 @@ pub(crate) fn fors_node<
let node = if z == 0 {
//
// 5: sk ← fors_SKgen(SK.seed, PK.seed, ADRS, i)
- let sk: GenericArray = fors_sk_gen(hashers, sk_seed, pk_seed, &adrs, i);
+ let sk: [u8; N] = fors_sk_gen(hashers, sk_seed, pk_seed, &adrs, i);
// 6: ADRS.setTreeHeight(0)
adrs.set_tree_height(0);
@@ -106,23 +106,24 @@ pub(crate) fn fors_node<
/// Output: FORS signature `SIG_FORS`.
#[allow(clippy::similar_names)] // sk_seed and pk_seed
pub(crate) fn fors_sign<
- A: ArrayLength,
- K: ArrayLength,
- LEN: ArrayLength,
- M: ArrayLength,
- N: ArrayLength,
+ const A: usize,
+ const K: usize,
+ const LEN: usize,
+ const M: usize,
+ const N: usize,
>(
hashers: &Hashers, md: &[u8], sk_seed: &[u8], adrs: &Adrs, pk_seed: &[u8],
) -> Result, &'static str> {
// 1: SIG_FORS = NULL ▷ Initialize SIG_FORS as a zero-length byte string
- let mut sig_fors = ForsSig::default();
+ let mut sig_fors = ForsSig { private_key_value: [[0u8; N]; K], auth: core::array::from_fn(|_| Auth{ tree: [[0u8; N]; A] }) }; //ForsSig::default();
+ let (a32, k32) = (u32::try_from(A).unwrap(), u32::try_from(K).unwrap());
// 2: indices ← base_2^b(md, a, k)
- let mut indices: GenericArray = GenericArray::default();
- helpers::base_2b(md, A::to_u32(), K::to_u32(), &mut indices);
+ let mut indices = [0u32; K];
+ helpers::base_2b(md, a32, k32, &mut indices);
// 3: for i from 0 to k − 1 do ▷ Compute signature elements
- for i in 0..K::to_u32() {
+ for i in 0..k32 {
//
// 4: SIG_FORS ← SIG_FORS ∥ fors_SKgen(SK.seed, PK.seed, ADRS, i · 2^a + indices[i])
sig_fors.private_key_value[i as usize] = fors_sk_gen::(
@@ -130,12 +131,12 @@ pub(crate) fn fors_sign<
sk_seed,
pk_seed,
adrs,
- i * 2u32.pow(A::to_u32()) + indices[i as usize],
+ i * 2u32.pow(a32) + indices[i as usize],
);
// 5:
// 6: for j from 0 to a − 1 do ▷ Compute auth path
- for j in 0..A::to_u32() {
+ for j in 0..a32 {
//
// 7: s ← indices[i]/2^j xor 1
let s = (indices[i as usize] >> j) ^ 1;
@@ -144,7 +145,7 @@ pub(crate) fn fors_sign<
sig_fors.auth[i as usize].tree[j as usize] = fors_node::(
hashers,
sk_seed,
- i * 2u32.pow(A::to_u32() - j) + s,
+ i * 2u32.pow(a32 - j) + s,
j,
pk_seed,
adrs,
@@ -169,34 +170,37 @@ pub(crate) fn fors_sign<
///
/// Input: FORS signature `SIG_FORS`, message digest `md`, public seed `PK.seed`, address `ADRS`.
/// Output: FORS public key.
+#[allow(clippy::similar_names)]
pub(crate) fn fors_pk_from_sig<
- A: ArrayLength,
- K: ArrayLength,
- LEN: ArrayLength,
- M: ArrayLength,
- N: ArrayLength,
+ const A: usize,
+ const K: usize,
+ const LEN: usize,
+ const M: usize,
+ const N: usize,
>(
hashers: &Hashers, sig_fors: &ForsSig, md: &[u8], pk_seed: &[u8],
adrs: &Adrs,
) -> ForsPk {
let mut adrs = adrs.clone();
+ let (a32, k32) = (u32::try_from(A).unwrap(), u32::try_from(K).unwrap());
+
// 1: indices ← base_2^b(md, a, k)
- let mut indices: GenericArray = GenericArray::default();
- helpers::base_2b(md, A::to_u32(), K::to_u32(), &mut indices);
+ let mut indices = [0u32; K];
+ helpers::base_2b(md, a32, k32, &mut indices);
// 2: for i from 0 to k − 1 do
- let mut root: GenericArray, K> = GenericArray::default();
- for i in 0..K::to_u32() {
+ let mut root = [[0u8; N]; K];
+ for i in 0..k32 {
//
// 3: sk ← SIG_FORS.getSK(i) ▷ SIG_FORS [i · (a + 1) · n : (i · (a + 1) + 1) · n]
- let sk = sig_fors.private_key_value[i as usize].clone();
+ let sk = sig_fors.private_key_value[i as usize];
// 4: ADRS.setTreeHeight(0) ▷ Compute leaf
adrs.set_tree_height(0);
// 5: ADRS.setTreeIndex(i · 2^a + indices[i])
- adrs.set_tree_index(i * 2u32.pow(A::to_u32()) + indices[i as usize]);
+ adrs.set_tree_index(i * 2u32.pow(a32) + indices[i as usize]);
// 6: node[0] ← F(PK.seed, ADRS, sk)
let mut node_0 = (hashers.f)(pk_seed, &adrs, &sk);
@@ -206,7 +210,7 @@ pub(crate) fn fors_pk_from_sig<
let auth = sig_fors.auth[i as usize].clone();
// 9: for j from 0 to a − 1 do ▷ Compute root from leaf and AUTH
- for j in 0..A::to_u32() {
+ for j in 0..a32 {
//
// 10: ADRS.setTreeHeight(j + 1)
adrs.set_tree_height(j + 1);
diff --git a/src/hashers.rs b/src/hashers.rs
index 28038c5..f64c474 100644
--- a/src/hashers.rs
+++ b/src/hashers.rs
@@ -1,19 +1,16 @@
use crate::types::Adrs;
-use generic_array::{ArrayLength, GenericArray};
// Holds hasher function references; constructed by each wrapper
#[allow(clippy::type_complexity)]
-pub(crate) struct Hashers {
- pub(crate) h_msg: fn(&[u8], &[u8], &[u8], &[u8]) -> GenericArray,
- pub(crate) prf: fn(&[u8], &[u8], &Adrs) -> GenericArray,
- pub(crate) prf_msg: fn(&[u8], &[u8], &[u8]) -> GenericArray,
- pub(crate) f: fn(&[u8], &Adrs, &[u8]) -> GenericArray,
- pub(crate) h: fn(&[u8], &Adrs, &[u8], &[u8]) -> GenericArray,
- pub(crate) t_l:
- fn(&[u8], &Adrs, &GenericArray, LEN>) -> GenericArray,
- pub(crate) t_len:
- fn(&[u8], &Adrs, &GenericArray, K>) -> GenericArray,
+pub(crate) struct Hashers {
+ pub(crate) h_msg: fn(&[u8], &[u8], &[u8], &[u8]) -> [u8; M],
+ pub(crate) prf: fn(&[u8], &[u8], &Adrs) -> [u8; N],
+ pub(crate) prf_msg: fn(&[u8], &[u8], &[u8]) -> [u8; N],
+ pub(crate) f: fn(&[u8], &Adrs, &[u8]) -> [u8; N],
+ pub(crate) h: fn(&[u8], &Adrs, &[u8], &[u8]) -> [u8; N],
+ pub(crate) t_l: fn(&[u8], &Adrs, &[[u8; N]; LEN]) -> [u8; N],
+ pub(crate) t_len: fn(&[u8], &Adrs, &[[u8; N]; K]) -> [u8; N],
}
@@ -27,7 +24,6 @@ pub(crate) struct Hashers(
+ pub(crate) fn h_msg(
r: &[u8], pk_seed: &[u8], pk_root: &[u8], m: &[u8],
- ) -> GenericArray {
- let mut digest: GenericArray = GenericArray::default();
+ ) -> [u8; M] {
+ let mut digest = [0u8; M];
shake256(&[r, pk_seed, pk_root, m], &mut digest);
digest
}
#[allow(clippy::similar_names)] // pk_seed and sk_seed
- pub(crate) fn prf(
- pk_seed: &[u8], sk_seed: &[u8], adrs: &Adrs,
- ) -> GenericArray {
- let mut digest: GenericArray = GenericArray::default();
+ pub(crate) fn prf(pk_seed: &[u8], sk_seed: &[u8], adrs: &Adrs) -> [u8; N] {
+ let mut digest = [0u8; N];
shake256(&[pk_seed, &adrs.to_32_bytes(), sk_seed], &mut digest); // Note that the spec swaps order of last to params
digest
}
- pub(crate) fn prf_msg(
- sk_prf: &[u8], opt_rand: &[u8], m: &[u8],
- ) -> GenericArray {
- let mut digest: GenericArray = GenericArray::default();
+ pub(crate) fn prf_msg(sk_prf: &[u8], opt_rand: &[u8], m: &[u8]) -> [u8; N] {
+ let mut digest = [0u8; N];
shake256(&[sk_prf, opt_rand, m], &mut digest);
digest
}
- pub(crate) fn f(pk_seed: &[u8], adrs: &Adrs, m1: &[u8]) -> GenericArray {
- let mut digest: GenericArray = GenericArray::default();
+ pub(crate) fn f(pk_seed: &[u8], adrs: &Adrs, m1: &[u8]) -> [u8; N] {
+ let mut digest = [0u8; N];
shake256(&[pk_seed, &adrs.to_32_bytes(), m1], &mut digest);
digest
}
- pub(crate) fn h(
- pk_seed: &[u8], adrs: &Adrs, m1: &[u8], m2: &[u8],
- ) -> GenericArray {
- let mut digest: GenericArray = GenericArray::default();
+ pub(crate) fn h(pk_seed: &[u8], adrs: &Adrs, m1: &[u8], m2: &[u8]) -> [u8; N] {
+ let mut digest = [0u8; N];
shake256(&[pk_seed, &adrs.to_32_bytes(), m1, m2], &mut digest);
digest
}
// Perhaps there is a more elegant way to covert ml into list of bytes
- pub(crate) fn t_l(
- pk_seed: &[u8], adrs: &Adrs, ml: &GenericArray, X>,
- ) -> GenericArray {
+ pub(crate) fn t_l(
+ pk_seed: &[u8], adrs: &Adrs, ml: &[[u8; Y]; X],
+ ) -> [u8; Y] {
let mut hasher = Shake256::default();
hasher.update(pk_seed);
hasher.update(&adrs.to_32_bytes());
ml.iter().for_each(|item| hasher.update(item));
let mut reader = hasher.finalize_xof();
- let mut result = GenericArray::default();
+ let mut result = [0u8; Y];
reader.read(&mut result);
result
}
@@ -105,7 +95,6 @@ pub(crate) mod shake {
pub(crate) mod sha2_cat_1 {
use crate::types::Adrs;
use core::cmp::min;
- use generic_array::{ArrayLength, GenericArray};
use sha2::{Digest, Sha256};
@@ -118,18 +107,18 @@ pub(crate) mod sha2_cat_1 {
}
- pub(crate) fn h_msg(
+ pub(crate) fn h_msg(
r: &[u8], pk_seed: &[u8], pk_root: &[u8], m: &[u8],
- ) -> GenericArray {
+ ) -> [u8; M] {
let mut digest1 = [0u8; 32];
sha2_256(&[r, pk_seed, pk_root, m], &mut digest1);
- let mut result: GenericArray = GenericArray::default();
+ let mut result = [0u8; M];
let mut start = 0;
let mut counter = 0u32;
- while start < M::to_usize() {
+ while start < M {
let mut tmp = [0u8; 32];
sha2_256(&[r, pk_seed, &digest1, &counter.to_be_bytes()], &mut tmp);
- let len = min(M::to_usize() - start, 32);
+ let len = min(M - start, 32);
result[start..start + len].copy_from_slice(&tmp[0..len]);
start += 32;
counter += 1;
@@ -139,20 +128,10 @@ pub(crate) mod sha2_cat_1 {
#[allow(clippy::similar_names)] // pk_seed and sk_seed
- pub(crate) fn prf(
- pk_seed: &[u8], sk_seed: &[u8], adrs: &Adrs,
- ) -> GenericArray {
- let mut digest: GenericArray = GenericArray::default();
+ pub(crate) fn prf(pk_seed: &[u8], sk_seed: &[u8], adrs: &Adrs) -> [u8; N] {
+ let mut digest = [0u8; N];
let to_byte = [0u8; 64];
- sha2_256(
- &[
- pk_seed,
- &to_byte[0..(64 - N::to_usize())],
- &adrs.to_22_bytes(),
- sk_seed,
- ],
- &mut digest,
- ); // Note that the spec swaps order of last to params
+ sha2_256(&[pk_seed, &to_byte[0..(64 - N)], &adrs.to_22_bytes(), sk_seed], &mut digest); // Note that the spec swaps order of last to params
digest
}
@@ -177,65 +156,43 @@ pub(crate) mod sha2_cat_1 {
}
- pub(crate) fn prf_msg(
- sk_prf: &[u8], opt_rand: &[u8], m: &[u8],
- ) -> GenericArray {
- let mut digest: GenericArray = GenericArray::default();
- //sha2_256(&[sk_prf, opt_rand, m], &mut digest);
+ pub(crate) fn prf_msg(sk_prf: &[u8], opt_rand: &[u8], m: &[u8]) -> [u8; N] {
+ let mut digest = [0u8; N];
let xxx = hmac_sha_256(sk_prf, opt_rand, m);
- digest.copy_from_slice(&xxx[0..N::to_usize()]);
+ digest.copy_from_slice(&xxx[0..N]);
digest
}
- pub(crate) fn f(pk_seed: &[u8], adrs: &Adrs, m1: &[u8]) -> GenericArray {
- let mut digest: GenericArray = GenericArray::default();
+ pub(crate) fn f(pk_seed: &[u8], adrs: &Adrs, m1: &[u8]) -> [u8; N] {
+ let mut digest = [0u8; N];
let to_byte = [0u8; 64];
- sha2_256(
- &[
- pk_seed,
- &to_byte[0..(64 - N::to_usize())],
- &adrs.to_22_bytes(),
- m1,
- ],
- &mut digest,
- );
+ sha2_256(&[pk_seed, &to_byte[0..(64 - N)], &adrs.to_22_bytes(), m1], &mut digest);
digest
}
- pub(crate) fn h(
- pk_seed: &[u8], adrs: &Adrs, m1: &[u8], m2: &[u8],
- ) -> GenericArray {
- let mut digest: GenericArray = GenericArray::default();
+ pub(crate) fn h(pk_seed: &[u8], adrs: &Adrs, m1: &[u8], m2: &[u8]) -> [u8; N] {
+ let mut digest = [0u8; N];
let to_byte = [0u8; 64];
- sha2_256(
- &[
- pk_seed,
- &to_byte[0..(64 - N::to_usize())],
- &adrs.to_22_bytes(),
- m1,
- m2,
- ],
- &mut digest,
- );
+ sha2_256(&[pk_seed, &to_byte[0..(64 - N)], &adrs.to_22_bytes(), m1, m2], &mut digest);
digest
}
// Perhaps there is a more elegant way to covert ml into list of bytes
- pub(crate) fn t_l(
- pk_seed: &[u8], adrs: &Adrs, ml: &GenericArray, LEN>,
- ) -> GenericArray {
- let mut result = GenericArray::default();
+ pub(crate) fn t_l(
+ pk_seed: &[u8], adrs: &Adrs, ml: &[[u8; N]; LEN],
+ ) -> [u8; N] {
+ let mut result = [0u8; N];
let to_byte = [0u8; 64];
let mut hasher = Sha256::new();
hasher.update(pk_seed);
- hasher.update(&to_byte[0..(64 - N::to_usize())]);
+ hasher.update(&to_byte[0..(64 - N)]);
hasher.update(adrs.to_22_bytes());
ml.iter().for_each(|item| hasher.update(item));
let digest = hasher.finalize();
- result.copy_from_slice(&digest[0..N::to_usize()]);
+ result.copy_from_slice(&digest[0..N]);
result
}
}
@@ -250,7 +207,6 @@ pub(crate) mod sha2_cat_1 {
pub(crate) mod sha2_cat_3_5 {
use crate::types::Adrs;
use core::cmp::min;
- use generic_array::{ArrayLength, GenericArray};
use sha2::{Digest, Sha256, Sha512};
@@ -272,18 +228,18 @@ pub(crate) mod sha2_cat_3_5 {
}
- pub(crate) fn h_msg(
+ pub(crate) fn h_msg(
r: &[u8], pk_seed: &[u8], pk_root: &[u8], m: &[u8],
- ) -> GenericArray {
+ ) -> [u8; M] {
let mut digest1 = [0u8; 64];
sha2_512(&[r, pk_seed, pk_root, m], &mut digest1);
- let mut result: GenericArray = GenericArray::default();
+ let mut result = [0u8; M];
let mut start = 0;
let mut counter = 0u32;
- while start < M::to_usize() {
+ while start < M {
let mut tmp = [0u8; 64];
sha2_512(&[r, pk_seed, &digest1, &counter.to_be_bytes()], &mut tmp);
- let len = min(M::to_usize() - start, 64);
+ let len = min(M - start, 64);
result[start..start + len].copy_from_slice(&tmp[0..len]);
start += 64;
counter += 1;
@@ -293,20 +249,10 @@ pub(crate) mod sha2_cat_3_5 {
#[allow(clippy::similar_names)] // pk_seed and sk_seed
- pub(crate) fn prf(
- pk_seed: &[u8], sk_seed: &[u8], adrs: &Adrs,
- ) -> GenericArray {
- let mut digest: GenericArray = GenericArray::default();
+ pub(crate) fn prf(pk_seed: &[u8], sk_seed: &[u8], adrs: &Adrs) -> [u8; N] {
+ let mut digest = [0u8; N];
let to_byte = [0u8; 64];
- sha2_256(
- &[
- pk_seed,
- &to_byte[0..(64 - N::to_usize())],
- &adrs.to_22_bytes(),
- sk_seed,
- ],
- &mut digest,
- ); // Note that the spec swaps order of last to params
+ sha2_256(&[pk_seed, &to_byte[0..(64 - N)], &adrs.to_22_bytes(), sk_seed], &mut digest); // Note that the spec swaps order of last to params
digest
}
@@ -331,64 +277,43 @@ pub(crate) mod sha2_cat_3_5 {
}
- pub(crate) fn prf_msg(
- sk_prf: &[u8], opt_rand: &[u8], m: &[u8],
- ) -> GenericArray {
- let mut digest: GenericArray = GenericArray::default();
+ pub(crate) fn prf_msg(sk_prf: &[u8], opt_rand: &[u8], m: &[u8]) -> [u8; N] {
+ let mut digest = [0u8; N];
let xxx = hmac_sha_512(sk_prf, opt_rand, m);
- digest.copy_from_slice(&xxx[0..N::to_usize()]);
+ digest.copy_from_slice(&xxx[0..N]);
digest
}
- pub(crate) fn f(pk_seed: &[u8], adrs: &Adrs, m1: &[u8]) -> GenericArray {
- let mut digest: GenericArray = GenericArray::default();
+ pub(crate) fn f(pk_seed: &[u8], adrs: &Adrs, m1: &[u8]) -> [u8; N] {
+ let mut digest = [0u8; N];
let to_byte = [0u8; 64];
- sha2_256(
- &[
- pk_seed,
- &to_byte[0..(64 - N::to_usize())],
- &adrs.to_22_bytes(),
- m1,
- ],
- &mut digest,
- );
+ sha2_256(&[pk_seed, &to_byte[0..(64-N)], &adrs.to_22_bytes(), m1], &mut digest);
digest
}
- pub(crate) fn h(
- pk_seed: &[u8], adrs: &Adrs, m1: &[u8], m2: &[u8],
- ) -> GenericArray {
- let mut digest: GenericArray = GenericArray::default();
+ pub(crate) fn h(pk_seed: &[u8], adrs: &Adrs, m1: &[u8], m2: &[u8]) -> [u8; N] {
+ let mut digest = [0u8; N];
let to_byte = [0u8; 128];
- sha2_512(
- &[
- pk_seed,
- &to_byte[0..(128 - N::to_usize())],
- &adrs.to_22_bytes(),
- m1,
- m2,
- ],
- &mut digest,
- );
+ sha2_512(&[pk_seed, &to_byte[0..(128 - N)], &adrs.to_22_bytes(), m1, m2], &mut digest);
digest
}
// Perhaps there is a more elegant way to covert ml into list of bytes
- pub(crate) fn t_l(
- pk_seed: &[u8], adrs: &Adrs, ml: &GenericArray, LEN>,
- ) -> GenericArray {
- let mut result = GenericArray::default();
+ pub(crate) fn t_l(
+ pk_seed: &[u8], adrs: &Adrs, ml: &[[u8; N]; LEN],
+ ) -> [u8; N] {
+ let mut result = [0u8; N];
let to_byte = [0u8; 128];
let mut hasher = Sha512::new();
hasher.update(pk_seed);
- hasher.update(&to_byte[0..(128 - N::to_usize())]);
+ hasher.update(&to_byte[0..(128 - N)]);
hasher.update(adrs.to_22_bytes());
ml.iter().for_each(|item| hasher.update(item));
let digest = hasher.finalize();
- result.copy_from_slice(&digest[0..N::to_usize()]);
+ result.copy_from_slice(&digest[0..N]);
result
}
}
diff --git a/src/helpers.rs b/src/helpers.rs
index e3f0a1a..0b3ded4 100644
--- a/src/helpers.rs
+++ b/src/helpers.rs
@@ -1,5 +1,4 @@
-use crate::types::{Adrs, SlhDsaSig};
-use generic_array::ArrayLength;
+use crate::types::{Adrs, Auth, ForsSig, HtSig, SlhDsaSig, WotsSig, XmssSig};
/// Algorithm 1: `toInt(X, n)` on page 14.
@@ -112,44 +111,42 @@ pub(crate) fn base_2b(x: &[u8], b: u32, out_len: u32, baseb: &mut [u32]) {
impl<
- A: ArrayLength,
- D: ArrayLength,
- HP: ArrayLength,
- K: ArrayLength,
- LEN: ArrayLength,
- N: ArrayLength,
+ const A: usize,
+ const D: usize,
+ const HP: usize,
+ const K: usize,
+ const LEN: usize,
+ const N: usize,
> SlhDsaSig
{
pub(crate) fn deserialize(self) -> [u8; SIG_LEN] {
let mut out = [0u8; SIG_LEN];
debug_assert_eq!(
out.len(),
- N::to_usize() + // randomness
- N::to_usize() * K::to_usize() + K::to_usize() * A::to_usize() * N::to_usize() + // ForsSig
- D::to_usize() * (HP::to_usize() * N::to_usize() + LEN::to_usize() * N::to_usize())
+ N + // randomness
+ N * K + K * A * N + // ForsSig
+ D * (HP * N + LEN * N)
);
- out[0..N::to_usize()].copy_from_slice(&self.randomness);
- let mut start = N::to_usize();
- for k in 0..K::to_usize() {
- out[start..(start + N::to_usize())]
- .copy_from_slice(&self.fors_sig.private_key_value[k]);
- start += N::to_usize();
- for a in 0..A::to_usize() {
- out[start..(start + N::to_usize())].copy_from_slice(&self.fors_sig.auth[k].tree[a]);
- start += N::to_usize();
+ out[0..N].copy_from_slice(&self.randomness);
+ let mut start = N;
+ for k in 0..K {
+ out[start..(start + N)].copy_from_slice(&self.fors_sig.private_key_value[k]);
+ start += N;
+ for a in 0..A {
+ out[start..(start + N)].copy_from_slice(&self.fors_sig.auth[k].tree[a]);
+ start += N;
}
}
- for d in 0..D::to_usize() {
+ for d in 0..D {
//println!("and we move to xmss {} starting at {}", d, start);
- for len in 0..LEN::to_usize() {
- out[start..(start + N::to_usize())]
+ for len in 0..LEN {
+ out[start..(start + N)]
.copy_from_slice(&self.ht_sig.xmss_sigs[d].sig_wots.data[len]);
- start += N::to_usize();
+ start += N;
}
- for hp in 0..HP::to_usize() {
- out[start..(start + N::to_usize())]
- .copy_from_slice(&self.ht_sig.xmss_sigs[d].auth[hp]);
- start += N::to_usize();
+ for hp in 0..HP {
+ out[start..(start + N)].copy_from_slice(&self.ht_sig.xmss_sigs[d].auth[hp]);
+ start += N;
}
}
debug_assert_eq!(start, out.len());
@@ -159,33 +156,35 @@ impl<
pub(crate) fn serialize(bytes: &[u8]) -> Self {
debug_assert_eq!(
bytes.len(),
- N::to_usize() + // randomness
- N::to_usize() * K::to_usize() + K::to_usize() * A::to_usize() * N::to_usize() + // ForsSig
- D::to_usize() * (HP::to_usize() * N::to_usize() + LEN::to_usize() * N::to_usize())
+ N + // randomness
+ N * K + K * A * N + // ForsSig
+ D * (HP * N + LEN * N)
);
- let mut output = Self::default();
- output.randomness.copy_from_slice(&bytes[0..N::to_usize()]);
- let mut start = N::to_usize();
- for k in 0..K::to_usize() {
- output.fors_sig.private_key_value[k]
- .copy_from_slice(&bytes[start..(start + N::to_usize())]);
- start += N::to_usize();
- for a in 0..A::to_usize() {
- output.fors_sig.auth[k].tree[a]
- .copy_from_slice(&bytes[start..(start + N::to_usize())]);
- start += N::to_usize();
+ //let mut output = Self::default();
+ let mut output = SlhDsaSig{
+ randomness: [0u8; N], //r.clone(),
+ fors_sig: ForsSig { private_key_value: [[0u8; N]; K], auth: core::array::from_fn(|_| Auth{ tree: [[0u8; N]; A] }) },
+ ht_sig: HtSig { xmss_sigs: core::array::from_fn(|_| XmssSig { sig_wots: WotsSig { data: [[0u8; N]; LEN] }, auth: [[0u8; N]; HP] }) },
+ };
+ output.randomness.copy_from_slice(&bytes[0..N]);
+ let mut start = N;
+ for k in 0..K {
+ output.fors_sig.private_key_value[k].copy_from_slice(&bytes[start..(start + N)]);
+ start += N;
+ for a in 0..A {
+ output.fors_sig.auth[k].tree[a].copy_from_slice(&bytes[start..(start + N)]);
+ start += N;
}
}
- for d in 0..D::to_usize() {
- for len in 0..LEN::to_usize() {
+ for d in 0..D {
+ for len in 0..LEN {
output.ht_sig.xmss_sigs[d].sig_wots.data[len]
- .copy_from_slice(&bytes[start..(start + N::to_usize())]);
- start += N::to_usize();
+ .copy_from_slice(&bytes[start..(start + N)]);
+ start += N;
}
- for hp in 0..HP::to_usize() {
- output.ht_sig.xmss_sigs[d].auth[hp]
- .copy_from_slice(&bytes[start..(start + N::to_usize())]);
- start += N::to_usize();
+ for hp in 0..HP {
+ output.ht_sig.xmss_sigs[d].auth[hp].copy_from_slice(&bytes[start..(start + N)]);
+ start += N;
}
}
debug_assert_eq!(start, bytes.len());
diff --git a/src/hypertree.rs b/src/hypertree.rs
index c07443f..4527d0f 100644
--- a/src/hypertree.rs
+++ b/src/hypertree.rs
@@ -1,7 +1,6 @@
use crate::hashers::Hashers;
-use crate::types::{Adrs, HtSig};
+use crate::types::{Adrs, HtSig, WotsSig, XmssSig};
use crate::xmss;
-use generic_array::{ArrayLength, GenericArray};
/// Algorithm 11: `ht_sign(M, SK.seed, PK.seed, idx_tree, idx_leaf)` on page 27.
@@ -12,18 +11,19 @@ use generic_array::{ArrayLength, GenericArray};
/// Output: HT signature `SIG_HT`.
#[allow(clippy::similar_names)] // sk_seed and pk_seed
pub(crate) fn ht_sign<
- D: ArrayLength,
- H: ArrayLength,
- HP: ArrayLength,
- K: ArrayLength,
- LEN: ArrayLength,
- M: ArrayLength,
- N: ArrayLength,
+ const D: usize,
+ const H: usize,
+ const HP: usize,
+ const K: usize,
+ const LEN: usize,
+ const M: usize,
+ const N: usize,
>(
hashers: &Hashers, m: &[u8], sk_seed: &[u8], pk_seed: &[u8], idx_tree: u64,
idx_leaf: u32,
) -> Result, &'static str> {
let mut idx_tree = idx_tree;
+ let (d32, hp32) = (u32::try_from(D).unwrap(), u32::try_from(HP).unwrap());
//
// 1: ADRS ← toByte(0, 32)
let mut adrs = Adrs::default();
@@ -37,7 +37,7 @@ pub(crate) fn ht_sign<
xmss::xmss_sign::(hashers, m, sk_seed, idx_leaf, pk_seed, &adrs)?;
// 5: SIG_HT ← SIG_tmp
- let mut sig_ht = HtSig::default();
+ let mut sig_ht = HtSig { xmss_sigs: core::array::from_fn(|_| XmssSig { sig_wots: WotsSig { data: [[0u8; N]; LEN] }, auth: [[0u8; N]; HP] }) }; //HtSig::default();
sig_ht.xmss_sigs[0] = sig_tmp.clone();
// 6: root ← xmss_PKFromSig(idx_leaf, SIG_tmp, M, PK.seed, ADRS)
@@ -45,14 +45,14 @@ pub(crate) fn ht_sign<
xmss::xmss_pk_from_sig::(hashers, idx_leaf, &sig_tmp, m, pk_seed, &adrs);
// 7: for j from 1 to d − 1 do
- for j in 1..D::to_u32() {
+ for j in 1..d32 {
//
// 8: 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()))
+ let idx_leaf = u32::try_from(idx_tree % 2u64.pow(hp32))
.map_err(|_| "Alg11: oversized idx leaf")?;
// 9: idx_tree ← idx_tree ≫ h′ ▷ Remove least significant h′ bits from idx_tree
- idx_tree >>= HP::to_u32();
+ idx_tree >>= hp32;
// 10: ADRS.setLayerAddress(j)
adrs.set_layer_address(j);
@@ -69,7 +69,7 @@ pub(crate) fn ht_sign<
sig_ht.xmss_sigs[j as usize] = sig_tmp.clone();
// 14: if j < d − 1 then
- if j < (D::to_u32() - 1) {
+ if j < (d32 - 1) {
//
// 15: root ← xmss_PKFromSig(idx_leaf, SIG_tmp, root, PK.seed, ADRS)
root = xmss::xmss_pk_from_sig::(
@@ -94,17 +94,18 @@ pub(crate) fn ht_sign<
/// HT public key `PK.root`.
/// Output: Boolean.
pub(crate) fn ht_verify<
- D: ArrayLength,
- HP: ArrayLength,
- K: ArrayLength,
- LEN: ArrayLength,
- M: ArrayLength,
- N: ArrayLength,
+ const D: usize,
+ const HP: usize,
+ const K: usize,
+ const LEN: usize,
+ const M: usize,
+ const N: usize,
>(
hashers: &Hashers, m: &[u8], sig_ht: &HtSig, pk_seed: &[u8],
- idx_tree: u64, idx_leaf: u32, pk_root: &GenericArray,
+ idx_tree: u64, idx_leaf: u32, pk_root: &[u8; N],
) -> bool {
let mut idx_tree = idx_tree;
+ let (d32, hp32) = (u32::try_from(D).unwrap(), u32::try_from(HP).unwrap());
//
// 1: ADRS ← toByte(0, 32)
let mut adrs = Adrs::default();
@@ -120,17 +121,17 @@ pub(crate) fn ht_verify<
let mut node = xmss::xmss_pk_from_sig(hashers, idx_leaf, &sig_tmp, m, pk_seed, &adrs);
// 6: for j from 1 to d − 1 do
- for j in 1..D::to_u32() {
+ for j in 1..d32 {
//
// 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(hp32)); // TODO: clean
if idx_leaf.is_err() {
return false;
};
let idx_leaf = idx_leaf.unwrap();
// 8: idx_tree ← idx_tree ≫ h′ ▷ Remove least significant h′ bits from idx_tree
- idx_tree >>= HP::to_u32();
+ idx_tree >>= hp32;
// 9: ADRS.setLayerAddress(j)
adrs.set_layer_address(j);
diff --git a/src/lib.rs b/src/lib.rs
index 8fc2648..d45e691 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -131,7 +131,7 @@ macro_rules! functionality {
fn try_keygen_with_rng_vt(
rng: &mut impl CryptoRngCore,
) -> Result<(PublicKey, PrivateKey), &'static str> {
- let res = crate::slh::slh_keygen_with_rng::(rng, &HASHERS);
+ let res = crate::slh::slh_keygen_with_rng::(rng, &HASHERS);
res.map(|(sk, pk)| (PublicKey(pk), PrivateKey(sk)))
}
}
@@ -143,7 +143,7 @@ macro_rules! functionality {
fn try_sign_with_rng_ct(
&self, rng: &mut impl CryptoRngCore, m: &[u8], randomize: bool,
) -> Result<[u8; SIG_LEN], &'static str> {
- let sig = crate::slh::slh_sign_with_rng::(
+ let sig = crate::slh::slh_sign_with_rng::(
rng, &HASHERS, &m, &self.0, randomize,
);
sig.map(|s| s.deserialize())
@@ -157,8 +157,8 @@ macro_rules! functionality {
fn try_verify_vt(
&self, m: &[u8], sig_bytes: &[u8; SIG_LEN],
) -> Result {
- let sig = SlhDsaSig::::serialize(sig_bytes);
- let res = crate::slh::slh_verify::(
+ let sig = SlhDsaSig::::serialize(sig_bytes);
+ let res = crate::slh::slh_verify::(
&HASHERS, &m, &sig, &self.0,
);
Ok(res)
@@ -180,7 +180,8 @@ macro_rules! functionality {
fn try_from_bytes(bytes: &Self::ByteArray) -> Result {
// Result: opportunity for validation
- let mut pk = SlhPublicKey::default();
+ //let mut pk = SlhPublicKey::default();
+ let mut pk = SlhPublicKey{pk_seed: [0u8; N], pk_root: [0u8; N]};
pk.pk_seed.copy_from_slice(&bytes[..(PK_LEN / 2)]);
pk.pk_root.copy_from_slice(&bytes[(PK_LEN / 2)..]);
Ok(PublicKey(pk))
@@ -202,7 +203,8 @@ macro_rules! functionality {
fn try_from_bytes(bytes: &Self::ByteArray) -> Result {
// Result: opportunity for validation
- let mut sk = SlhPrivateKey::default();
+ //let mut sk = SlhPrivateKey::default();
+ let mut sk = SlhPrivateKey{sk_seed: [0u8; N], sk_prf: [0u8; N], pk_seed: [0u8; N], pk_root: [0u8; N]};
sk.sk_seed.copy_from_slice(&bytes[0..(SK_LEN / 4)]);
sk.sk_prf
.copy_from_slice(&bytes[(SK_LEN / 4)..(SK_LEN / 2)]);
@@ -266,16 +268,15 @@ macro_rules! functionality {
pub mod slh_dsa_sha2_128s {
use crate::hashers::sha2_cat_1::{f, h, h_msg, prf, prf_msg, t_l};
use crate::hashers::Hashers;
- use generic_array::typenum::{Prod, Sum, U12, U14, U16, U2, U3, U30, U63, U7, U9};
- type N = U16;
- type H = U63;
- type D = U7;
- type HP = U9;
- type A = U12;
- type K = U14;
- type M = U30;
- type Len = Sum, U3>;
+ const N: usize = 16;
+ const H: usize = 63;
+ const D: usize = 7;
+ const HP: usize = 9;
+ const A: usize = 12;
+ const K: usize = 14;
+ const M: usize = 30;
+ const LEN: usize = 2 * N + 3;
/// Length of public key
pub const PK_LEN: usize = 32;
@@ -286,8 +287,8 @@ pub mod slh_dsa_sha2_128s {
/// Length of private/secret key
pub const SK_LEN: usize = PK_LEN * 2;
- static HASHERS: Hashers =
- Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
+ static HASHERS: Hashers =
+ Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
functionality!();
}
@@ -315,16 +316,15 @@ pub mod slh_dsa_sha2_128s {
pub mod slh_dsa_shake_128s {
use crate::hashers::shake::{f, h, h_msg, prf, prf_msg, t_l};
use crate::hashers::Hashers;
- use generic_array::typenum::{Prod, Sum, U12, U14, U16, U2, U3, U30, U63, U7, U9};
- type N = U16;
- type H = U63;
- type D = U7;
- type HP = U9;
- type A = U12;
- type K = U14;
- type M = U30;
- type Len = Sum, U3>;
+ const N: usize = 16;
+ const H: usize = 63;
+ const D: usize = 7;
+ const HP: usize = 9;
+ const A: usize = 12;
+ const K: usize = 14;
+ const M: usize = 30;
+ const LEN: usize = 2 * N + 3;
/// Length of public key
pub const PK_LEN: usize = 32;
@@ -335,8 +335,8 @@ pub mod slh_dsa_shake_128s {
/// Length of private/secret key
pub const SK_LEN: usize = PK_LEN * 2;
- static HASHERS: Hashers =
- Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
+ static HASHERS: Hashers =
+ Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
functionality!();
}
@@ -364,16 +364,15 @@ pub mod slh_dsa_shake_128s {
pub mod slh_dsa_sha2_128f {
use crate::hashers::sha2_cat_1::{f, h, h_msg, prf, prf_msg, t_l};
use crate::hashers::Hashers;
- use generic_array::typenum::{Prod, Sum, U16, U2, U22, U3, U33, U34, U6, U66};
- type N = U16;
- type H = U66;
- type D = U22;
- type HP = U3;
- type A = U6;
- type K = U33;
- type M = U34;
- type Len = Sum, U3>;
+ const N: usize = 16;
+ const H: usize = 66;
+ const D: usize = 22;
+ const HP: usize = 3;
+ const A: usize = 6;
+ const K: usize = 33;
+ const M: usize = 34;
+ const LEN: usize = 2 * N + 3;
/// Length of public key
pub const PK_LEN: usize = 32;
@@ -384,8 +383,8 @@ pub mod slh_dsa_sha2_128f {
/// Length of private/secret key
pub const SK_LEN: usize = PK_LEN * 2;
- static HASHERS: Hashers =
- Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
+ static HASHERS: Hashers =
+ Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
functionality!();
}
@@ -413,16 +412,15 @@ pub mod slh_dsa_sha2_128f {
pub mod slh_dsa_shake_128f {
use crate::hashers::shake::{f, h, h_msg, prf, prf_msg, t_l};
use crate::hashers::Hashers;
- use generic_array::typenum::{Prod, Sum, U16, U2, U22, U3, U33, U34, U6, U66};
- type N = U16;
- type H = U66;
- type D = U22;
- type HP = U3;
- type A = U6;
- type K = U33;
- type M = U34;
- type Len = Sum, U3>;
+ const N: usize = 16;
+ const H: usize = 66;
+ const D: usize = 22;
+ const HP: usize = 3;
+ const A: usize = 6;
+ const K: usize = 33;
+ const M: usize = 34;
+ const LEN: usize = 2 * N + 3;
/// Length of public key
pub const PK_LEN: usize = 32;
@@ -433,8 +431,8 @@ pub mod slh_dsa_shake_128f {
/// Length of private/secret key
pub const SK_LEN: usize = PK_LEN * 2;
- static HASHERS: Hashers =
- Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
+ static HASHERS: Hashers =
+ Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
functionality!();
}
@@ -462,16 +460,15 @@ pub mod slh_dsa_shake_128f {
pub mod slh_dsa_sha2_192s {
use crate::hashers::sha2_cat_3_5::{f, h, h_msg, prf, prf_msg, t_l};
use crate::hashers::Hashers;
- use generic_array::typenum::{Prod, Sum, U14, U17, U2, U24, U3, U39, U63, U7, U9};
- type N = U24;
- type H = U63;
- type D = U7;
- type HP = U9;
- type A = U14;
- type K = U17;
- type M = U39;
- type Len = Sum, U3>;
+ const N: usize = 24;
+ const H: usize = 63;
+ const D: usize = 7;
+ const HP: usize = 9;
+ const A: usize = 14;
+ const K: usize = 17;
+ const M: usize = 39;
+ const LEN: usize = 2 * N + 3;
/// Length of public key
pub const PK_LEN: usize = 48;
@@ -482,8 +479,8 @@ pub mod slh_dsa_sha2_192s {
/// Length of private/secret key
pub const SK_LEN: usize = PK_LEN * 2;
- static HASHERS: Hashers =
- Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
+ static HASHERS: Hashers =
+ Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
functionality!();
}
@@ -511,16 +508,15 @@ pub mod slh_dsa_sha2_192s {
pub mod slh_dsa_shake_192s {
use crate::hashers::shake::{f, h, h_msg, prf, prf_msg, t_l};
use crate::hashers::Hashers;
- use generic_array::typenum::{Prod, Sum, U14, U17, U2, U24, U3, U39, U63, U7, U9};
- type N = U24;
- type H = U63;
- type D = U7;
- type HP = U9;
- type A = U14;
- type K = U17;
- type M = U39;
- type Len = Sum, U3>;
+ const N: usize = 24;
+ const H: usize = 63;
+ const D: usize = 7;
+ const HP: usize = 9;
+ const A: usize = 14;
+ const K: usize = 17;
+ const M: usize = 39;
+ const LEN: usize = 2 * N + 3;
/// Length of public key
pub const PK_LEN: usize = 48;
@@ -531,8 +527,8 @@ pub mod slh_dsa_shake_192s {
/// Length of private/secret key
pub const SK_LEN: usize = PK_LEN * 2;
- static HASHERS: Hashers =
- Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
+ static HASHERS: Hashers =
+ Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
functionality!();
}
@@ -560,16 +556,15 @@ pub mod slh_dsa_shake_192s {
pub mod slh_dsa_sha2_192f {
use crate::hashers::sha2_cat_3_5::{f, h, h_msg, prf, prf_msg, t_l};
use crate::hashers::Hashers;
- use generic_array::typenum::{Prod, Sum, U2, U22, U24, U3, U33, U42, U66, U8};
- type N = U24;
- type H = U66;
- type D = U22;
- type HP = U3;
- type A = U8;
- type K = U33;
- type M = U42;
- type Len = Sum, U3>;
+ const N: usize = 24;
+ const H: usize = 66;
+ const D: usize = 22;
+ const HP: usize = 3;
+ const A: usize = 8;
+ const K: usize = 33;
+ const M: usize = 42;
+ const LEN: usize = 2 * N + 3;
/// Length of public key
pub const PK_LEN: usize = 48;
@@ -580,8 +575,8 @@ pub mod slh_dsa_sha2_192f {
/// Length of private/secret key
pub const SK_LEN: usize = PK_LEN * 2;
- static HASHERS: Hashers =
- Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
+ static HASHERS: Hashers =
+ Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
functionality!();
}
@@ -609,16 +604,15 @@ pub mod slh_dsa_sha2_192f {
pub mod slh_dsa_shake_192f {
use crate::hashers::shake::{f, h, h_msg, prf, prf_msg, t_l};
use crate::hashers::Hashers;
- use generic_array::typenum::{Prod, Sum, U2, U22, U24, U3, U33, U42, U66, U8};
- type N = U24;
- type H = U66;
- type D = U22;
- type HP = U3;
- type A = U8;
- type K = U33;
- type M = U42;
- type Len = Sum, U3>;
+ const N: usize = 24;
+ const H: usize = 66;
+ const D: usize = 22;
+ const HP: usize = 3;
+ const A: usize = 8;
+ const K: usize = 33;
+ const M: usize = 42;
+ const LEN: usize = 2 * N + 3;
/// Length of public key
pub const PK_LEN: usize = 48;
@@ -629,8 +623,8 @@ pub mod slh_dsa_shake_192f {
/// Length of private/secret key
pub const SK_LEN: usize = PK_LEN * 2;
- static HASHERS: Hashers =
- Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
+ static HASHERS: Hashers =
+ Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
functionality!();
}
@@ -658,16 +652,15 @@ pub mod slh_dsa_shake_192f {
pub mod slh_dsa_sha2_256s {
use crate::hashers::sha2_cat_3_5::{f, h, h_msg, prf, prf_msg, t_l};
use crate::hashers::Hashers;
- use generic_array::typenum::{Prod, Sum, U14, U2, U22, U3, U32, U47, U64, U8};
- type N = U32;
- type H = U64;
- type D = U8;
- type HP = U8;
- type A = U14;
- type K = U22;
- type M = U47;
- type Len = Sum, U3>;
+ const N: usize = 32;
+ const H: usize = 64;
+ const D: usize = 8;
+ const HP: usize = 8;
+ const A: usize = 14;
+ const K: usize = 22;
+ const M: usize = 47;
+ const LEN: usize = 2 * N + 3;
/// Length of public key
pub const PK_LEN: usize = 64;
@@ -678,8 +671,8 @@ pub mod slh_dsa_sha2_256s {
/// Length of private/secret key
pub const SK_LEN: usize = PK_LEN * 2;
- static HASHERS: Hashers =
- Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
+ static HASHERS: Hashers =
+ Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
functionality!();
}
@@ -707,16 +700,15 @@ pub mod slh_dsa_sha2_256s {
pub mod slh_dsa_shake_256s {
use crate::hashers::shake::{f, h, h_msg, prf, prf_msg, t_l};
use crate::hashers::Hashers;
- use generic_array::typenum::{Prod, Sum, U14, U2, U22, U3, U32, U47, U64, U8};
- type N = U32;
- type H = U64;
- type D = U8;
- type HP = U8;
- type A = U14;
- type K = U22;
- type M = U47;
- type Len = Sum, U3>;
+ const N: usize = 32;
+ const H: usize = 64;
+ const D: usize = 8;
+ const HP: usize = 8;
+ const A: usize = 14;
+ const K: usize = 22;
+ const M: usize = 47;
+ const LEN: usize = 2 * N + 3;
/// Length of public key
pub const PK_LEN: usize = 64;
@@ -727,8 +719,8 @@ pub mod slh_dsa_shake_256s {
/// Length of private/secret key
pub const SK_LEN: usize = PK_LEN * 2;
- static HASHERS: Hashers =
- Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
+ static HASHERS: Hashers =
+ Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
functionality!();
}
@@ -756,16 +748,15 @@ pub mod slh_dsa_shake_256s {
pub mod slh_dsa_sha2_256f {
use crate::hashers::sha2_cat_3_5::{f, h, h_msg, prf, prf_msg, t_l};
use crate::hashers::Hashers;
- use generic_array::typenum::{Prod, Sum, U17, U2, U3, U32, U35, U4, U49, U68, U9};
- type N = U32;
- type H = U68;
- type D = U17;
- type HP = U4;
- type A = U9;
- type K = U35;
- type M = U49;
- type Len = Sum, U3>;
+ const N: usize = 32;
+ const H: usize = 68;
+ const D: usize = 17;
+ const HP: usize = 4;
+ const A: usize = 9;
+ const K: usize = 35;
+ const M: usize = 49;
+ const LEN: usize = 2 * N + 3;
/// Length of public key
pub const PK_LEN: usize = 64;
@@ -776,8 +767,8 @@ pub mod slh_dsa_sha2_256f {
/// Length of private/secret key
pub const SK_LEN: usize = PK_LEN * 2;
- static HASHERS: Hashers =
- Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
+ static HASHERS: Hashers =
+ Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
functionality!();
}
@@ -805,16 +796,15 @@ pub mod slh_dsa_sha2_256f {
pub mod slh_dsa_shake_256f {
use crate::hashers::shake::{f, h, h_msg, prf, prf_msg, t_l};
use crate::hashers::Hashers;
- use generic_array::typenum::{Prod, Sum, U17, U2, U3, U32, U35, U4, U49, U68, U9};
- type N = U32;
- type H = U68;
- type D = U17;
- type HP = U4;
- type A = U9;
- type K = U35;
- type M = U49;
- type Len = Sum, U3>;
+ const N: usize = 32;
+ const H: usize = 68;
+ const D: usize = 17;
+ const HP: usize = 4;
+ const A: usize = 9;
+ const K: usize = 35;
+ const M: usize = 49;
+ const LEN: usize = 2 * N + 3;
/// Length of public key
pub const PK_LEN: usize = 64;
@@ -825,8 +815,8 @@ pub mod slh_dsa_shake_256f {
/// Length of private/secret key
pub const SK_LEN: usize = PK_LEN * 2;
- static HASHERS: Hashers =
- Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
+ static HASHERS: Hashers =
+ Hashers:: { h_msg, prf, prf_msg, f, h, t_l, t_len: t_l };
functionality!();
}
diff --git a/src/slh.rs b/src/slh.rs
index 5f31139..8fd5d00 100644
--- a/src/slh.rs
+++ b/src/slh.rs
@@ -1,8 +1,7 @@
use crate::hashers::Hashers;
-use crate::types::FORS_TREE;
+use crate::types::{Auth, FORS_TREE, ForsSig, HtSig, WotsSig, XmssSig};
use crate::types::{Adrs, SlhDsaSig, SlhPrivateKey, SlhPublicKey};
use crate::{fors, helpers, hypertree, xmss};
-use generic_array::{ArrayLength, GenericArray};
use rand_core::CryptoRngCore;
@@ -13,29 +12,31 @@ use rand_core::CryptoRngCore;
/// Output: SLH-DSA key pair `(SK, PK)`.
#[allow(clippy::similar_names)] // sk_seed and pk_seed
pub(crate) fn slh_keygen_with_rng<
- D: ArrayLength,
- H: ArrayLength,
- HP: ArrayLength,
- K: ArrayLength,
- LEN: ArrayLength,
- M: ArrayLength,
- N: ArrayLength,
+ const D: usize,
+ const H: usize,
+ const HP: usize,
+ const K: usize,
+ const LEN: usize,
+ const M: usize,
+ const N: usize,
>(
rng: &mut impl CryptoRngCore, hashers: &Hashers,
) -> Result<(SlhPrivateKey, SlhPublicKey), &'static str> {
+ let (d32, hp32) = (u32::try_from(D).unwrap(), u32::try_from(HP).unwrap());
+
//
// 1: SK.seed ←$ B^n ▷ Set SK.seed, SK.prf, and PK.seed to random n-byte
- let mut sk_seed = GenericArray::default();
+ let mut sk_seed = [0u8; N]; // = GenericArray::default();
rng.try_fill_bytes(&mut sk_seed)
.map_err(|_| "Alg17: rng failed1")?;
// 2: SK.prf ←$ B^n ▷ strings using an approved random bit generator
- let mut sk_prf = GenericArray::default();
+ let mut sk_prf = [0u8; N]; //GenericArray::default();
rng.try_fill_bytes(&mut sk_prf)
.map_err(|_| "Alg17: rng failed2")?;
// 3: PK.seed ←$ B^n
- let mut pk_seed = GenericArray::default();
+ let mut pk_seed = [0u8; N]; //GenericArray::default();
rng.try_fill_bytes(&mut pk_seed)
.map_err(|_| "Alg17: rng failed3")?;
@@ -44,21 +45,15 @@ pub(crate) fn slh_keygen_with_rng<
let mut adrs = Adrs::default();
// 6: ADRS.setLayerAddress(d − 1)
- adrs.set_layer_address(D::to_u32() - 1);
+ adrs.set_layer_address(d32 - 1);
// 7: PK.root ← xmss_node(SK.seed, 0, h′, PK.seed, ADRS)
- let pk_root = xmss::xmss_node::(
- hashers,
- &sk_seed,
- 0,
- HP::to_u32(),
- &pk_seed,
- &adrs,
- )?;
+ let pk_root =
+ xmss::xmss_node::(hashers, &sk_seed, 0, hp32, &pk_seed, &adrs)?;
// 8:
// 9: return ( (SK.seed, SK.prf, PK.seed, PK.root), (PK.seed, PK.root) )
- let pk = SlhPublicKey { pk_seed: pk_seed.clone(), pk_root: pk_root.clone() };
+ let pk = SlhPublicKey { pk_seed, pk_root };
let sk = SlhPrivateKey { sk_seed, sk_prf, pk_seed, pk_root };
Ok((sk, pk))
}
@@ -69,27 +64,29 @@ pub(crate) fn slh_keygen_with_rng<
///
/// Input: Message `M`, private key `SK = (SK.seed, SK.prf, PK.seed, PK.root)`.
/// Output: SLH-DSA signature `SIG`.
+#[allow(clippy::similar_names)]
#[allow(clippy::cast_possible_truncation)] // temporary, investigating idx_leaf int sizes
pub(crate) fn slh_sign_with_rng<
- A: ArrayLength,
- D: ArrayLength,
- H: ArrayLength,
- HP: ArrayLength,
- K: ArrayLength,
- LEN: ArrayLength,
- M: ArrayLength,
- N: ArrayLength,
+ const A: usize,
+ const D: usize,
+ const H: usize,
+ const HP: usize,
+ const K: usize,
+ const LEN: usize,
+ const M: usize,
+ const N: usize,
>(
rng: &mut impl CryptoRngCore, hashers: &Hashers, m: &[u8], sk: &SlhPrivateKey,
randomize: bool,
) -> Result, &'static str> {
+ let (d32, h32) = (u32::try_from(D).unwrap(), u32::try_from(H).unwrap());
//
// 1: ADRS ← toByte(0, 32)
let mut adrs = Adrs::default();
// 2:
// 3: opt_rand ← PK.seed ▷ Set opt_rand to either PK.seed
- let mut opt_rand = sk.pk_seed.clone();
+ let mut opt_rand = sk.pk_seed;
// 4: if (RANDOMIZE) then ▷ or to a random n-byte string
if randomize {
@@ -104,34 +101,39 @@ pub(crate) fn slh_sign_with_rng<
let r = (hashers.prf_msg)(&sk.sk_prf, &opt_rand, m);
// 8: SIG ← R
- let mut sig = SlhDsaSig::default();
- sig.randomness = r.clone();
+ //let mut sig = SlhDsaSig::default();
+ let mut sig = SlhDsaSig{
+ randomness: r,
+ fors_sig: ForsSig { private_key_value: [[0u8; N]; K], auth: core::array::from_fn(|_| Auth{ tree: [[0u8; N]; A] }) },
+ ht_sig: HtSig { xmss_sigs: core::array::from_fn(|_| XmssSig { sig_wots: WotsSig { data: [[0u8; N]; LEN] }, auth: [[0u8; N]; HP] }) },
+ };
+
+ //sig.randomness.0 = r.clone();
// 9:
// 10: digest ← H_msg(R, PK.seed, PK.root, M) ▷ Compute message digest
let digest = (hashers.h_msg)(&r, &sk.pk_seed, &sk.pk_root, m);
// 11: md ← digest[0 : ceil(k·a/8)] ▷ first ceil(k·a/8) bytes
- let index1 = (K::to_usize() * A::to_usize() + 7) / 8;
+ let index1 = (K * A + 7) / 8;
let md = &digest[0..index1];
// 12: tmp_idx_tree ← digest[ceil(k·a/8) : ceil(k·a/8) + ceil((h-h/d)/8)] ▷ next ceil((h-h/d)/8) bytes
- let index2 = index1 + (H::to_usize() - H::to_usize() / D::to_usize() + 7) / 8;
+ let index2 = index1 + (H - H / D + 7) / 8;
let tmp_idx_tree = &digest[index1..index2];
// 13: tmp_idx_leaf ← digest[ceil(k·a/8) + ceil((h-h/d)/8) : ceil(k·a/8) + ceil((h-h/d)/8) + ceil(h/8d)] ▷ next ceil(h/8d) bytes
- let index3 = index2 + (H::to_usize() + 8 * D::to_usize() - 1) / (8 * D::to_usize());
+ let index3 = index2 + (H + 8 * D - 1) / (8 * D);
let tmp_idx_leaf = &digest[index2..index3];
// 14:
// 15: idx_tree ← toInt(tmp_idx_tree, ceil((h-h/d)/8)) mod 2^{h−h/d}
- let idx_tree = helpers::to_int(tmp_idx_tree, (H::to_u32() - H::to_u32() / D::to_u32() + 7) / 8)
- & (u64::MAX >> (64 - (H::to_u32() - H::to_u32() / D::to_u32())));
+ let idx_tree = helpers::to_int(tmp_idx_tree, (h32 - h32 / d32 + 7) / 8)
+ & (u64::MAX >> (64 - (h32 - h32 / d32)));
// 16: idx_leaf ← toInt(tmp_idx_leaf, ceil(h/8d) mod 2^{h/d}
- let idx_leaf =
- helpers::to_int(tmp_idx_leaf, (H::to_u32() + 8 * D::to_u32() - 1) / (8 * D::to_u32()))
- & (u64::MAX >> (64 - H::to_u32() / D::to_u32()));
+ let idx_leaf = helpers::to_int(tmp_idx_leaf, (h32 + 8 * d32 - 1) / (8 * d32))
+ & (u64::MAX >> (64 - h32 / d32));
// 17:
// 18: ADRS.setTreeAddress(idx_tree)
@@ -175,19 +177,22 @@ pub(crate) fn slh_sign_with_rng<
/// Input: Message `M`, signature `SIG`, public key `PK = (PK.seed, PK.root)`.
/// Output: Boolean.
#[allow(clippy::cast_possible_truncation)] // TODO: temporary
+#[allow(clippy::similar_names)]
pub(crate) fn slh_verify<
- A: ArrayLength,
- D: ArrayLength,
- H: ArrayLength,
- HP: ArrayLength,
- K: ArrayLength,
- LEN: ArrayLength,
- M: ArrayLength,
- N: ArrayLength,
+ const A: usize,
+ const D: usize,
+ const H: usize,
+ const HP: usize,
+ const K: usize,
+ const LEN: usize,
+ const M: usize,
+ const N: usize,
>(
hashers: &Hashers, m: &[u8], sig: &SlhDsaSig,
pk: &SlhPublicKey,
) -> bool {
+ let (d32, h32) = (u32::try_from(D).unwrap(), u32::try_from(H).unwrap());
+
// 1: if |SIG| != (1 + k(1 + a) + h + d · len) · n then
// 2: return false
// 3: end if
@@ -210,26 +215,25 @@ pub(crate) fn slh_verify<
let digest = (hashers.h_msg)(r, &pk.pk_seed, &pk.pk_root, m);
// 10: md ← digest[0 : ceil(k·a/8)] ▷ first ceil(k·a/8) bytes
- let index1 = (K::to_usize() * A::to_usize() + 7) / 8;
+ let index1 = (K * A + 7) / 8;
let md = &digest[0..index1];
// 11: tmp_idx_tree ← digest[ceil(k·a/8) : ceil(k·a/8) + ceil((h - h/d)/8)] ▷ next ceil((h - h/d)/8) bytes
- let index2 = index1 + (H::to_usize() - H::to_usize() / D::to_usize() + 7) / 8;
+ let index2 = index1 + (H - H / D + 7) / 8;
let tmp_idx_tree = &digest[index1..index2];
// 12: tmp_idx_leaf ← digest[ceil(k·a/8) + ceil((h - h/d)/8) : ceil(k·a/8) + ceil((h - h/d)/8) + ceil(h/8d)] ▷ next ceil(h/8d) bytes
- let index3 = index2 + (H::to_usize() + 8 * D::to_usize() - 1) / (8 * D::to_usize());
+ let index3 = index2 + (H + 8 * D - 1) / (8 * D);
let tmp_idx_leaf = &digest[index2..index3];
// 13:
// 14: idx_tree ← toInt(tmp_idx_tree, ceil((h - h/d)/8)) mod 2^{h−h/d}
- let idx_tree = helpers::to_int(tmp_idx_tree, (H::to_u32() - H::to_u32() / D::to_u32() + 7) / 8)
- & (u64::MAX >> (64 - (H::to_u32() - H::to_u32() / D::to_u32())));
+ let idx_tree = helpers::to_int(tmp_idx_tree, (h32 - h32 / d32 + 7) / 8)
+ & (u64::MAX >> (64 - (h32 - h32 / d32)));
// 15: idx_leaf ← toInt(tmp_idx_leaf, ceil(h/8d) mod 2^{h/d}
- let idx_leaf =
- helpers::to_int(tmp_idx_leaf, (H::to_u32() + 8 * D::to_u32() - 1) / (8 * D::to_u32()))
- & (u64::MAX >> (64 - H::to_u32() / D::to_u32()));
+ let idx_leaf = helpers::to_int(tmp_idx_leaf, (h32 + 8 * d32 - 1) / (8 * d32))
+ & (u64::MAX >> (64 - h32 / d32));
// 16:
// 17: ADRS.setTreeAddress(idx_tree) ▷ Compute FORS public key
diff --git a/src/types.rs b/src/types.rs
index 6d69a5b..3391782 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -1,87 +1,89 @@
-use generic_array::{ArrayLength, GenericArray};
use zeroize::{Zeroize, ZeroizeOnDrop};
/// Fig 16 on page 34
-#[derive(Clone, Debug, Default, Zeroize, ZeroizeOnDrop)]
+#[derive(Clone, Debug, Zeroize, ZeroizeOnDrop)]
pub(crate) struct SlhDsaSig<
- A: ArrayLength,
- D: ArrayLength,
- HP: ArrayLength,
- K: ArrayLength,
- LEN: ArrayLength,
- N: ArrayLength,
+ const A: usize,
+ const D: usize,
+ const HP: usize,
+ const K: usize,
+ const LEN: usize,
+ const N: usize,
> {
- pub(crate) randomness: GenericArray,
+ pub(crate) randomness: [u8; N],
pub(crate) fors_sig: ForsSig,
pub(crate) ht_sig: HtSig,
}
-#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
-pub struct SlhPublicKey {
- pub(crate) pk_seed: GenericArray,
- pub(crate) pk_root: GenericArray,
+#[derive(Clone, Zeroize, ZeroizeOnDrop)]
+pub struct SlhPublicKey {
+ pub(crate) pk_seed: [u8; N],
+ pub(crate) pk_root: [u8; N],
}
-#[derive(Clone, Debug, Default, Zeroize, ZeroizeOnDrop)]
-pub struct SlhPrivateKey {
- pub(crate) sk_seed: GenericArray,
- pub(crate) sk_prf: GenericArray,
- pub(crate) pk_seed: GenericArray,
- pub(crate) pk_root: GenericArray,
+#[derive(Clone, Debug, Zeroize, ZeroizeOnDrop)]
+pub struct SlhPrivateKey {
+ pub(crate) sk_seed: [u8; N],
+ pub(crate) sk_prf: [u8; N],
+ pub(crate) pk_seed: [u8; N],
+ pub(crate) pk_root: [u8; N],
}
/// Fig 13 on page 29
-#[derive(Clone, Debug, Default, Zeroize, ZeroizeOnDrop)]
-pub(crate) struct ForsSig {
- pub(crate) private_key_value: GenericArray, K>,
- pub(crate) auth: GenericArray, K>,
+#[derive(Clone, Debug, Zeroize, ZeroizeOnDrop)]
+pub(crate) struct ForsSig {
+ pub(crate) private_key_value: [[u8; N]; K],
+ pub(crate) auth: [Auth; K],
}
-#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
-pub(crate) struct ForsPk {
- pub(crate) key: GenericArray,
+#[derive(Clone, Zeroize, ZeroizeOnDrop)]
+pub(crate) struct ForsPk {
+ pub(crate) key: [u8; N],
}
/// Fig 10?
-#[derive(Clone, Debug, Default, Zeroize, ZeroizeOnDrop)]
-pub(crate) struct Auth {
- pub(crate) tree: GenericArray, A>,
+#[derive(Clone, Debug, Zeroize, ZeroizeOnDrop)]
+pub(crate) struct Auth {
+ pub(crate) tree: [[u8; N]; A],
+}
+
+impl Default for Auth {
+ fn default() -> Self { Auth { tree: [[0u8; N]; A] } }
+}
+
+#[derive(Clone, Debug, Zeroize, ZeroizeOnDrop)]
+pub(crate) struct HtSig {
+ pub(crate) xmss_sigs: [XmssSig; D],
}
-#[derive(Clone, Debug, Default, Zeroize, ZeroizeOnDrop)]
-pub(crate) struct HtSig {
- pub(crate) xmss_sigs: GenericArray, D>,
+#[derive(Clone, Debug, Zeroize, ZeroizeOnDrop)]
+pub struct WotsSig {
+ pub(crate) data: [[u8; N]; LEN],
}
-#[derive(Clone, Debug, Default, Zeroize, ZeroizeOnDrop)]
-pub struct WotsSig {
- pub(crate) data: GenericArray, LEN>,
-}
+#[derive(Clone, Zeroize, ZeroizeOnDrop)]
+pub struct WotsPk(pub(crate) [u8; N]);
-#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
-pub struct WotsPk(pub(crate) GenericArray);
-
-
-#[derive(Clone, Debug, Default, Zeroize, ZeroizeOnDrop)]
-pub struct XmssSig {
+#[derive(Clone, Debug, Zeroize, ZeroizeOnDrop)]
+pub struct XmssSig {
pub(crate) sig_wots: WotsSig,
- pub(crate) auth: GenericArray, HP>,
+ pub(crate) auth: [[u8; N]; HP],
}
-impl XmssSig {
+impl XmssSig {
pub(crate) fn get_wots_sig(&self) -> &WotsSig { &self.sig_wots }
- pub(crate) fn get_xmss_auth(&self) -> &GenericArray, HP> { &self.auth }
+ pub(crate) fn get_xmss_auth(&self) -> &[[u8; N]; HP] { &self.auth }
}
diff --git a/src/wots.rs b/src/wots.rs
index 0cae729..67c9ffe 100644
--- a/src/wots.rs
+++ b/src/wots.rs
@@ -1,7 +1,6 @@
use crate::hashers::Hashers;
use crate::helpers;
use crate::types::{Adrs, WotsPk, WotsSig, WOTS_PK, WOTS_PRF};
-use generic_array::{ArrayLength, GenericArray};
/// Algorithm 4: `chain(X, i, s, PK.seed, ADRS)` on page 17.
@@ -14,10 +13,9 @@ use generic_array::{ArrayLength, GenericArray};
///
/// Input: Input string `X`, start index `i`, number of steps `s`, public seed `PK.seed`, address `ADRS`.
/// Output: Value of `F` iterated `s` times on `X`.
-pub(crate) fn chain(
- hashers: &Hashers, cap_x: GenericArray, i: u32, s: u32, pk_seed: &[u8],
- adrs: &Adrs,
-) -> Option> {
+pub(crate) fn chain(
+ hashers: &Hashers, cap_x: [u8; N], i: u32, s: u32, pk_seed: &[u8], adrs: &Adrs,
+) -> Option<[u8; N]> {
debug_assert!(i + s < u32::MAX);
let mut adrs = adrs.clone();
@@ -61,11 +59,12 @@ pub(crate) fn chain
/// Output: WOTS+ public key `pk`.
#[allow(clippy::similar_names)] // pk_seed and sk_seed
-pub(crate) fn wots_pkgen(
+pub(crate) fn wots_pkgen(
hashers: &Hashers, sk_seed: &[u8], pk_seed: &[u8], adrs: &Adrs,
) -> Result, &'static str> {
let mut adrs = adrs.clone();
- let mut tmp: GenericArray, LEN> = GenericArray::default();
+ let mut tmp = [[0u8; N]; LEN];
+ let len32 = u32::try_from(LEN).unwrap();
// 1: skADRS ← ADRS ▷ Copy address to create key generation key address
let mut sk_adrs = adrs.clone();
@@ -77,7 +76,7 @@ pub(crate) fn wots_pkgen
/// Output: WOTS+ signature sig.
#[allow(clippy::similar_names)] // pk_seed and sk_seed
-pub(crate) fn wots_sign(
+pub(crate) fn wots_sign(
hashers: &Hashers, m: &[u8], sk_seed: &[u8], pk_seed: &[u8], adrs: &Adrs,
) -> WotsSig {
+ let n32 = u32::try_from(N).unwrap();
let mut adrs = adrs.clone();
- let mut sig: WotsSig = WotsSig::default();
+ //let mut sig: WotsSig = WotsSig::default();
+ let mut sig: WotsSig