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 = WotsSig{ data: [[0u8; N]; LEN] }; // 1: csum ← 0 let mut csum = 0_u32; // 2: // 3: msg ← base_2b(M, lgw, len1) ▷ Convert message to base w - let mut msg = GenericArray::::default(); // note: 3 entries left over, used step 10 - helpers::base_2b(m, crate::LGW, 2 * N::to_u32(), &mut msg[0..(2 * N::to_usize())]); + let mut msg = [0u32; LEN]; //GenericArray::::default(); // note: 3 entries left over, used step 10 + helpers::base_2b(m, crate::LGW, 2 * n32, &mut msg[0..(2 * N)]); // 4: // 5: for i from 0 to len1 − 1 do ▷ Compute checksum - for item in msg.iter().take(2 * N::to_usize()) { + for item in msg.iter().take(2 * N) { // // 6: csum ← csum + w − 1 − msg[i] csum += crate::W - 1 - *item; @@ -151,7 +152,7 @@ pub(crate) fn wots_sign /// Output: WOTS+ public key `pksig` derived from `sig`. -pub(crate) fn wots_pk_from_sig( +pub(crate) fn wots_pk_from_sig( hashers: &Hashers, sig: &WotsSig, m: &[u8], pk_seed: &[u8], adrs: &Adrs, ) -> WotsPk { + let n32 = u32::try_from(N).unwrap(); let mut adrs = adrs.clone(); - let mut tmp: GenericArray, LEN> = GenericArray::default(); + let mut tmp = [[0u8; N]; LEN]; //GenericArray::default(); // 1: csum ← 0 let mut csum = 0_u32; // 2: // 3: msg ← base_2b (M, lgw , len1 ) ▷ Convert message to base w - let mut msg: GenericArray = GenericArray::default(); - helpers::base_2b(m, crate::LGW, 2 * N::to_u32(), &mut msg[0..(2 * N::to_usize())]); + let mut msg = [0u32; LEN]; //GenericArray::default(); + helpers::base_2b(m, crate::LGW, 2 * n32, &mut msg[0..(2 * N)]); // 4: // 5: for i from 0 to len1 − 1 do ▷ Compute checksum - for item in msg.iter().take(2 * N::to_usize()) { + for item in msg.iter().take(2 * N) { // // 6: csum ← csum + w − 1 − msg[i] csum += crate::W - 1 - item; @@ -225,12 +227,12 @@ pub(crate) fn wots_pk_from_sig( hashers, - sig.data[i].clone(), + sig.data[i], msg[i], crate::W - 1 - msg[i], pk_seed, diff --git a/src/xmss.rs b/src/xmss.rs index 3715906..1a2f9d5 100644 --- a/src/xmss.rs +++ b/src/xmss.rs @@ -1,7 +1,6 @@ use crate::hashers::Hashers; -use crate::types::{Adrs, XmssSig, TREE, WOTS_HASH}; +use crate::types::{Adrs, XmssSig, TREE, WOTS_HASH, WotsSig}; use crate::wots; -use generic_array::{ArrayLength, GenericArray}; /// Algorithm 8: `xmss_node(SK.seed, i, z, PK.seed, ADRS)` on page 22. @@ -12,19 +11,20 @@ use generic_array::{ArrayLength, GenericArray}; /// Output: n-byte root `node`. #[allow(clippy::similar_names)] // sk_seed and pk_seed pub(crate) fn xmss_node< - H: ArrayLength, - HP: ArrayLength, - K: ArrayLength, - LEN: ArrayLength, - M: ArrayLength, - N: ArrayLength, + const H: usize, + const HP: usize, + const K: usize, + const LEN: usize, + const M: usize, + const N: usize, >( hashers: &Hashers, sk_seed: &[u8], i: u32, z: u32, pk_seed: &[u8], adrs: &Adrs, -) -> Result, &'static str> { +) -> Result<[u8; N], &'static str> { + let hp32 = u32::try_from(HP).unwrap(); let mut adrs = adrs.clone(); // 1: if z > h′ or i ≥ 2^{h −z} then - if (z > HP::to_u32()) | (u64::from(i) >= 2u64.pow(HP::to_u32() - z)) { + if (z > hp32) | (u64::from(i) >= 2u64.pow(hp32 - z)) { // // 2: return NULL return Err("Alg8: fail"); @@ -44,7 +44,6 @@ pub(crate) fn xmss_node< // 7: node ← wots_PKgen(SK.seed, PK.seed, ADRS) wots::wots_pkgen::(hashers, sk_seed, pk_seed, &adrs)? .0 - .clone() // 8: else } else { @@ -84,21 +83,23 @@ pub(crate) fn xmss_node< /// Output: XMSS signature SIGXMSS = (sig ∥ AUTH). #[allow(clippy::similar_names)] // sk_seed and pk_seed pub(crate) fn xmss_sign< - H: ArrayLength, - HP: ArrayLength, - K: ArrayLength, - LEN: ArrayLength, - M: ArrayLength, - N: ArrayLength, + 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], idx: u32, pk_seed: &[u8], adrs: &Adrs, ) -> Result, &'static str> { + let hp32 = u32::try_from(HP).unwrap(); let mut adrs = adrs.clone(); - let mut sig_xmss = XmssSig::default(); + //let mut sig_xmss = XmssSig::default(); + let mut sig_xmss = XmssSig{ sig_wots: WotsSig { data: [[0u8; N]; LEN] }, auth: [[0u8; N]; HP] }; // 1: for j from 0 to h′-1 do ▷ Build authentication path - for j in 0..HP::to_u32() { + for j in 0..hp32 { // // 2: k ← idx/2 ^j xor 1 let k = (idx >> j) ^ 1; @@ -135,15 +136,16 @@ pub(crate) fn xmss_sign< /// address `ADRS`.
/// Output: n-byte root value `node[0]`. pub(crate) fn xmss_pk_from_sig< - HP: ArrayLength, - K: ArrayLength, - LEN: ArrayLength, - M: ArrayLength, - N: ArrayLength, + const HP: usize, + const K: usize, + const LEN: usize, + const M: usize, + const N: usize, >( hashers: &Hashers, idx: u32, sig_xmss: &XmssSig, m: &[u8], pk_seed: &[u8], adrs: &Adrs, -) -> GenericArray { +) -> [u8; N] { + let hp32 = u32::try_from(HP).unwrap(); let mut adrs = adrs.clone(); // 1: ADRS.setTypeAndClear(WOTS_HASH) ▷ Compute WOTS+ pk from WOTS+ sig @@ -160,8 +162,7 @@ pub(crate) fn xmss_pk_from_sig< // 5: node[0] ← wots_PKFromSig(sig, M, PK.seed, ADRS) let mut node_0 = wots::wots_pk_from_sig::(hashers, sig, m, pk_seed, &adrs) - .0 - .clone(); + .0; // 6: // 7: ADRS.setTypeAndClear(TREE) ▷ Compute root from WOTS+ pk and AUTH @@ -171,7 +172,7 @@ pub(crate) fn xmss_pk_from_sig< adrs.set_tree_index(idx); // 9: for k from 0 to h′ − 1 do - for k in 0..HP::to_u32() { + for k in 0..hp32 { // // 10: ADRS.setTreeHeight(k + 1) adrs.set_tree_height(k + 1);