diff --git a/Cargo.toml b/Cargo.toml
index 7c74bc2..824ca47 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -15,10 +15,15 @@ sha3 = { version = "0.10.8", default-features = false }
generic-array = { version = "1.0.0", features=["const-default", "zeroize"] }
hex = "0.4.3"
+
+[dev-dependencies]
+rand_chacha = "0.3.1"
+
+
[features]
-default = ["default-rng", "slh_dsa_sha2_128s", "slh_dsa_shake_128s", "slh_dsa_sha2_128f", "slh_dsa_shake_128f",
- "slh_dsa_sha2_192s", "slh_dsa_shake_192s", "slh_dsa_sha2_192f", "slh_dsa_shake_192f",
- "slh_dsa_sha2_256s", "slh_dsa_shake_256s", "slh_dsa_sha2_256f", "slh_dsa_shake_256f"]
+default = ["default-rng", "slh_dsa_sha2_128s"] #, "slh_dsa_shake_128s", "slh_dsa_sha2_128f", "slh_dsa_shake_128f",
+# "slh_dsa_sha2_192s", "slh_dsa_shake_192s", "slh_dsa_sha2_192f", "slh_dsa_shake_192f",
+# "slh_dsa_sha2_256s", "slh_dsa_shake_256s", "slh_dsa_sha2_256f", "slh_dsa_shake_256f"]
default-rng = ["rand_core/getrandom"]
slh_dsa_sha2_128s = []
slh_dsa_shake_128s = []
@@ -34,5 +39,5 @@ slh_dsa_sha2_256f = []
slh_dsa_shake_256f = []
-[dev-dependencies]
-rand = "0.8.5"
+[profile.dev]
+opt-level = 3
diff --git a/src/algs.rs b/src/algs.rs
index d6e69e6..d90e7c5 100644
--- a/src/algs.rs
+++ b/src/algs.rs
@@ -1,7 +1,3 @@
-use alloc::vec;
-use alloc::vec::Vec;
-
-//use generic_array::typenum::{Prod, Sum, U2, U3};
use generic_array::{ArrayLength, GenericArray};
use rand_core::CryptoRngCore;
use sha3::{
@@ -20,8 +16,7 @@ use crate::types::{FORS_PRF, FORS_ROOTS, FORS_TREE, TREE, WOTS_HASH, WOTS_PK, WO
/// Input: n-byte string `X`.
/// Output: Integer value of `X`.
pub(crate) fn to_int(x: &[u8], n: usize) -> u64 {
- assert_eq!(x.len(), n);
- //println!("byte count {}", x.len());
+ debug_assert_eq!(x.len(), n);
// 1: total ← 0
let mut total = 0_u64;
@@ -46,8 +41,9 @@ pub(crate) fn to_int(x: &[u8], n: usize) -> u64 {
///
/// Input: Integer `x`, string length `n`.
/// Output: Byte string of length `n` containing binary representation of `x` in big-endian byte-order.
-pub(crate) fn to_byte(x: u64, n: usize) -> Vec {
- let mut s = vec![0u8; n]; // TODO revisit generic array
+pub(crate) fn to_byte(x: u64, n: usize) -> [u8; ((crate::LEN2 * crate::LGW + 7) / 8) as usize] {
+ let mut s = [0u8; ((crate::LEN2 * crate::LGW + 7) / 8) as usize]; // Size fixed across all profiles
+ debug_assert_eq!(n, ((crate::LEN2 * crate::LGW + 7) / 8) as usize); // just in case life changes
// 1: total ← x
let mut total = x;
@@ -75,10 +71,10 @@ pub(crate) fn to_byte(x: u64, n: usize) -> Vec {
///
/// Input: Byte string `X` of length at least ceil(`out_len·b/8`), integer `b`, output length `out_len`.
/// Output: Array of `out_len` integers in the range `[0, . . . , 2^b − 1]`.
-pub(crate) fn base_2b(x: &[u8], b: u32, out_len: usize) -> Vec {
+pub(crate) fn base_2b(x: &[u8], b: u32, out_len: usize, baseb: &mut [u64]) {
assert!(x.len() >= out_len * b as usize / 8);
assert!(b < 64);
- let mut baseb = vec![0u64; out_len]; // TODO revisit GenericArray
+ assert_eq!(out_len, baseb.len());
// 1: in ← 0
let mut inn = 0;
@@ -112,13 +108,12 @@ pub(crate) fn base_2b(x: &[u8], b: u32, out_len: usize) -> Vec {
bits -= b;
// 12: baseb[out] ← (total ≫ bits) mod 2^b
- *item = (total >> bits) % 2u64.pow(b); //& (2u64.pow(b) - 1);
+ *item = (total >> bits) % 2u64.pow(b);
// 13: end for
}
- // 14: return baseb
- baseb
+ // 14: return baseb (mutable parameter)
}
@@ -136,7 +131,7 @@ pub(crate) fn shake256(input: &[&[u8]]) -> GenericArray {
pub(crate) fn f(
pk_seed: &[u8], adrs: &Adrs, tmp: &GenericArray,
) -> GenericArray {
- shake256(&[&pk_seed, &adrs.to_bytes(), tmp])
+ shake256(&[&pk_seed, &adrs.to_32_bytes(), tmp])
}
@@ -166,7 +161,6 @@ pub(crate) fn chain(
// 4:
// 5: tmp ← X
- //println!("cap x: {}", hex::encode(&cap_x));
let mut tmp = cap_x;
// 6:
@@ -174,7 +168,7 @@ pub(crate) fn chain(
for j in i..(i + s) {
//
// 8: ADRS.setHashAddress(j)
- adrs.set_hash_address(j.try_into().expect("usize->u32 fails"));
+ adrs.set_hash_address(j.try_into().expect("usize->u32 fails")); // TODO: something better than expect?
// 9: tmp ← F(PK.seed, ADRS, tmp)
tmp = f(pk_seed, &adrs, &tmp);
@@ -191,15 +185,13 @@ pub(crate) fn chain(
pub(crate) fn prf(
pk_seed: &[u8], sk_seed: &[u8], adrs: &[u8],
) -> GenericArray {
- shake256(&[&pk_seed, &adrs, &sk_seed]) // note order
-} // NOTE ORDER
+ shake256(&[&pk_seed, &adrs, &sk_seed]) // note order
+} // NOTE ORDER
#[allow(clippy::similar_names)]
-pub(crate) fn prf2(
- a0: &[u8], b1: &[u8], c2: &[u8],
-) -> GenericArray {
+pub(crate) fn prf2(a0: &[u8], b1: &[u8], c2: &[u8]) -> GenericArray {
shake256(&[&a0, &b1, &c2])
-} // NOTE ORDER
+} // NOTE ORDER
pub(crate) fn tlen(
@@ -209,7 +201,7 @@ where
{
let mut hasher = Shake256::default();
hasher.update(pk_seed);
- hasher.update(&adrs.to_bytes());
+ 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();
@@ -232,7 +224,6 @@ pub(crate) fn wots_pkgen(
) -> WotsPk {
let mut adrs = adrs.clone();
let mut tmp: GenericArray, LEN> = GenericArray::default();
- //println!("pk_seed: {}", hex::encode(&pk_seed));
// 1: skADRS ← ADRS ▷ Copy address to create key generation key address
let mut sk_adrs = adrs.clone();
@@ -244,7 +235,6 @@ pub(crate) fn wots_pkgen(
sk_adrs.set_key_pair_address(adrs.get_key_pair_address());
// 4: for i from 0 to len − 1 do
- //#[allow(clippy::cast_possible_truncation)] // steps 5 and 7
let len = 2 * N::to_u32() + 3;
for i in 0..len {
//
@@ -252,8 +242,7 @@ pub(crate) fn wots_pkgen(
sk_adrs.set_chain_address(i);
// 6: sk ← PRF(PK.seed, SK.seed, skADRS) ▷ Compute secret value for chain i
- let sk = prf(pk_seed, sk_seed, &sk_adrs.to_bytes());
- //println!("sk wots pkgen: {}/n", hex::encode(&sk));
+ let sk = prf(pk_seed, sk_seed, &sk_adrs.to_32_bytes());
// 7: ADRS.setChainAddress(i)
adrs.set_chain_address(i);
@@ -299,7 +288,8 @@ pub(crate) fn wots_sign(
// 2:
// 3: msg ← base_2b(M, lgw, len1) ▷ Convert message to base w
- let mut msg = base_2b(m, crate::LGW, 2 * N::to_usize());
+ let mut msg = GenericArray::::default(); // note: 3 bytes left over, used step 10
+ base_2b(m, crate::LGW, 2 * N::to_usize(), &mut msg[0..(2 * N::to_usize())]);
// 4:
// 5: for i from 0 to len1 − 1 do ▷ Compute checksum
@@ -317,11 +307,12 @@ pub(crate) fn wots_sign(
csum <<= (8 - ((len2 as u64 * u64::from(crate::LGW)) % 8)) % 8;
// 10: msg ← msg ∥ base_2^b(toByte(csum, ceil(len2·lgw/8)), lgw, len2) ▷ Convert csum to base w
- msg.extend(&base_2b(
+ base_2b(
&to_byte(csum, (len2 * crate::LGW as usize).div_ceil(8)),
crate::LGW,
len2,
- ));
+ &mut msg[(2 * N::to_usize())..],
+ );
// 11:
// 12: skADRS ← ADRS
@@ -334,15 +325,15 @@ pub(crate) fn wots_sign(
sk_addrs.set_key_pair_address(adrs.get_key_pair_address());
// 15: for i from 0 to len − 1 do
- #[allow(clippy::cast_possible_truncation)] // step 18/19
let len = 2 * N::to_usize() + 3;
+ #[allow(clippy::cast_possible_truncation)] // step 18/19
for (i, item) in msg.iter().enumerate().take(len) {
//
// 16: skADRS.setChainAddress(i)
sk_addrs.set_chain_address(i as u32);
// 17: sk ← PRF(PK.seed, SK.seed, skADRS) ▷ Compute secret value for chain i
- let sk = prf(pk_seed, sk_seed, &sk_addrs.to_bytes());
+ let sk = prf(pk_seed, sk_seed, &sk_addrs.to_32_bytes());
// 18: ADRS.setChainAddress(i)
adrs.set_chain_address(i as u32);
@@ -375,7 +366,9 @@ pub(crate) fn wots_pk_from_sig(
// 2:
// 3: msg ← base_2b (M, lgw , len1 ) ▷ Convert message to base w
let len1 = 2 * N::to_usize();
- let mut msg = base_2b(m, crate::LGW, len1);
+ let mut msg: GenericArray = GenericArray::default();
+ base_2b(m, crate::LGW, 2 * N::to_usize(), &mut msg[0..(2 * N::to_usize())]);
+
// 4:
// 5: for i from 0 to len1 − 1 do ▷ Compute checksum
@@ -393,11 +386,12 @@ pub(crate) fn wots_pk_from_sig(
csum <<= (8 - ((len2 * crate::LGW as usize) % 8)) % 8;
// 10: msg ← msg ∥ base_2^b(toByte(csum, ceil(len2·lgw/8)), lgw, len2) ▷ Convert csum to base w
- msg.extend(&base_2b(
+ base_2b(
&to_byte(csum, (len2 * crate::LGW as usize).div_ceil(8)),
crate::LGW,
len2,
- ));
+ &mut msg[(2 * N::to_usize())..],
+ );
// 11: for i from 0 to len − 1 do
#[allow(clippy::cast_possible_truncation)] // steps 12 and 13
@@ -415,7 +409,6 @@ pub(crate) fn wots_pk_from_sig(
&adrs,
)
.expect("chain broke2!");
- //println!("wots_pk_from_sig tmp: [{}] {}", i, hex::encode(&tmp[i])); // TODO <<<========== BROKE b4 HERE!!!
// 14: end for
}
@@ -465,7 +458,7 @@ pub(crate) fn xmss_node h′ or i ≥ 2^{h −z} then
- if (z > HP::to_u32()) | (i as u64 >= 2u64.pow(HP::to_u32() - z)) {
+ if (z > HP::to_u32()) | (u64::from(i) >= 2u64.pow(HP::to_u32() - z)) {
//
// 2: return NULL
return Err("Alg8: fail");
@@ -480,19 +473,16 @@ pub(crate) fn xmss_node(sk_seed, pk_seed, &adrs).0.clone(); // TODO revisit (remove clone?)
- //println!("wots_pkgen: {}", hex::encode(&xx));
- xx //wots_pkgen
+ wots_pkgen::(sk_seed, pk_seed, &adrs).0.clone() // TODO remove clone?
// 8: else
} else {
//
// 9: lnode ← xmss_node(SK.seed, 2 * i, z − 1, PK.seed, ADRS)
let lnode = xmss_node::(sk_seed, 2 * i, z - 1, pk_seed, &adrs)?;
- //println!("lnode: {}", hex::encode(&lnode));
// 10: rnode ← xmss_node(SK.seed, 2 * i + 1, z − 1, PK.seed, ADRS)
let rnode = xmss_node::(sk_seed, 2 * i + 1, z - 1, pk_seed, &adrs)?;
@@ -504,10 +494,10 @@ pub(crate) fn xmss_node(m, sk_seed, pk_seed, &adrs); // TODO: polish out BB!
// 9: SIG_XMSS ← sig ∥ AUTH
// struct constructed above
@@ -584,12 +574,7 @@ pub(crate) fn xmss_pk_from_sig(sig, m, pk_seed, &adrs).0.clone();
- //println!("verif node_0: {}", hex::encode(&node_0)); // TODO blah...3rd? time here
- //if node_0[0] == 0x9a {
- //println!("wogga");
- //println!("auth 0 : {}", hex::encode(&auth[0]));
- //}
// 6:
// 7: ADRS.setTypeAndClear(TREE) ▷ Compute root from WOTS+ pk and AUTH
adrs.set_type_and_clear(TREE);
@@ -606,12 +591,13 @@ pub(crate) fn xmss_pk_from_sig> k) & 1) == 0 {
+ //
// 12: ADRS.setTreeIndex(ADRS.getTreeIndex()/2)
let tmp = adrs.get_tree_index() / 2;
adrs.set_tree_index(tmp);
- println!("hit even!! {:x?}", idx); // Odd, this is 4 but py is 5
+
// 13: node[1] ← H(PK.seed, ADRS, node[0] ∥ AUTH[k])
- h(pk_seed, &adrs.to_bytes(), &node_0, &auth[k as usize])
+ h(pk_seed, &adrs.to_32_bytes(), &node_0, &auth[k as usize])
// 14: else
} else {
@@ -621,16 +607,8 @@ pub(crate) fn xmss_pk_from_sig> HP::to_u32();
+ idx_tree >>= HP::to_u32();
// 10: ADRS.setLayerAddress(j)
adrs.set_layer_address(j);
@@ -697,7 +674,7 @@ pub(crate) fn ht_sign<
adrs.set_tree_address(idx_tree);
// 12: SIG_tmp ← xmss_sign(root, SK.seed, idx_leaf, PK.seed, ADRS)
- sig_tmp = xmss_sign::(&root, sk_seed, idx_leaf as u32, pk_seed, &adrs)?;
+ sig_tmp = xmss_sign::(&root, sk_seed, idx_leaf, pk_seed, &adrs)?;
// 13: SIG_HT ← SIG_HT ∥ SIG_tmp
sig_ht.xmss_sigs[j as usize] = sig_tmp.clone();
@@ -705,22 +682,20 @@ pub(crate) fn ht_sign<
// 14: if j < d − 1 then
if j < (D::to_u32() - 1) {
//
- println!("rooooooot before --> : {}", hex::encode(&root)); // we are golden here YYYYYYYYYY
-
// 15: root ← xmss_PKFromSig(idx_leaf, SIG_tmp, root, PK.seed, ADRS)
- root = xmss_pk_from_sig::(idx_leaf as u32, &sig_tmp, &root, pk_seed, &adrs);
- println!("rooooooot after --> : {}", hex::encode(&root)); // we are golden here YYYYYYYYYY
+ root = xmss_pk_from_sig::(idx_leaf, &sig_tmp, &root, pk_seed, &adrs);
// 16: end if
}
// 17: end for
}
- println!("sig_ht (maybe several): {}", hex::encode(&sig_ht.xmss_sigs[0].sig_wots.data[0])); // we are golden here YYYYYYYYYY
+
// 18: return SIGHT
Ok(sig_ht)
}
+
/// Algorithm 12: `ht_verify(M, SIG_HT, PK.seed, idx_tree, idx_leaf, PK.root)` on page 28.
/// Verify a hypertree signature.
///
@@ -745,16 +720,17 @@ pub(crate) fn ht_verify> HP::to_u32();
+ idx_tree >>= HP::to_u32();
// 9: ADRS.setLayerAddress(j)
adrs.set_layer_address(j);
@@ -766,7 +742,7 @@ pub(crate) fn ht_verify(
sk_adrs.set_tree_index(idx);
// 5: return PRF(PK.seed, SK.seed, skADRS)
- prf(pk_seed, sk_seed, &sk_adrs.to_bytes())
+ prf(pk_seed, sk_seed, &sk_adrs.to_32_bytes())
}
@@ -847,6 +820,7 @@ pub(crate) fn fors_node(
// 9: else
} else {
+ //
// 10: lnode ← fors_node(SK.seed, 2i, z − 1, PK.seed, ADRS)
let lnode = fors_node::(sk_seed, 2 * i, z - 1, pk_seed, &adrs)?;
@@ -860,7 +834,7 @@ pub(crate) fn fors_node(
adrs.set_tree_index(i);
// 14: node ← H(PK.seed, ADRS, lnode ∥ rnode)
- h(pk_seed, &adrs.to_bytes(), &lnode, &rnode)
+ h(pk_seed, &adrs.to_32_bytes(), &lnode, &rnode)
// 15: end if
};
@@ -869,6 +843,7 @@ pub(crate) fn fors_node(
Ok(node)
}
+
/// Algorithm 15: `fors_sign(md, SK.seed, PK.seed, ADRS)`
/// Generate a FORS signature.
///
@@ -882,7 +857,9 @@ pub(crate) fn fors_sign(
let mut sig_fors = ForsSig::default();
// 2: indices ← base_2^b(md, a, k)
- let indices = base_2b(md, A::to_u32(), K::to_usize());
+ let mut indices: GenericArray = GenericArray::default();
+ base_2b(md, A::to_u32(), K::to_usize(), &mut indices);
+
// 3: for i from 0 to k − 1 do ▷ Compute signature elements
#[allow(clippy::cast_possible_truncation)]
@@ -937,7 +914,9 @@ pub(crate) fn fors_pk_from_sig(
let mut adrs = adrs.clone();
// 1: indices ← base_2^b(md, a, k)
- let indices = base_2b(md, A::to_u32(), K::to_usize());
+ let mut indices: GenericArray = GenericArray::default();
+ base_2b(md, A::to_u32(), K::to_usize(), &mut indices);
+
// 2: for i from 0 to k − 1 do
let mut root: GenericArray, K> = GenericArray::default();
@@ -974,7 +953,7 @@ pub(crate) fn fors_pk_from_sig(
adrs.set_tree_index(tmp);
// 13: node[1] ← H(PK.seed, ADRS, node[0] ∥ auth[j])
- h(pk_seed, &adrs.to_bytes(), &node_0, &auth.tree[j as usize])
+ h(pk_seed, &adrs.to_32_bytes(), &node_0, &auth.tree[j as usize])
// 14: else
} else {
@@ -984,7 +963,7 @@ pub(crate) fn fors_pk_from_sig(
adrs.set_tree_index(tmp);
// 16: node[1] ← H(PK.seed, ADRS, auth[j] ∥ node[0])
- h(pk_seed, &adrs.to_bytes(), &auth.tree[j as usize], &node_0)
+ h(pk_seed, &adrs.to_32_bytes(), &auth.tree[j as usize], &node_0)
// 17: end if
};
@@ -1037,7 +1016,6 @@ pub(crate) fn slh_keygen_with_rng<
let mut sk_seed = GenericArray::default();
rng.try_fill_bytes(&mut sk_seed)
.map_err(|_| "Alg17: rng failed1")?;
- println!("sk:seed: {}", hex::encode(&sk_seed));
// 2: SK.prf ←$ B^n ▷ strings using an approved random bit generator
let mut sk_prf = GenericArray::default();
@@ -1058,7 +1036,6 @@ pub(crate) fn slh_keygen_with_rng<
// 7: PK.root ← xmss_node(SK.seed, 0, h′, PK.seed, ADRS)
let pk_root = xmss_node::(&sk_seed, 0, HP::to_u32(), &pk_seed, &adrs)?;
- println!("pk_root: {}", hex::encode(&pk_root));
// 8:
// 9: return ( (SK.seed, SK.prf, PK.seed, PK.root), (PK.seed, PK.root) )
@@ -1101,7 +1078,6 @@ pub(crate) fn slh_sign_with_rng<
// 6: end if
}
- println!("opt_rand: {}", hex::encode(&opt_rand.clone()));
// 7: R ← PRF_msg(SK.prf, opt_rand, M) ▷ Generate randomizer
let r = prf2(&sk.sk_prf, &opt_rand, m);
@@ -1110,12 +1086,10 @@ pub(crate) fn slh_sign_with_rng<
// 8: SIG ← R
let mut sig = SlhDsaSig::default();
sig.randomness = r.clone();
- println!("r: {}", hex::encode(&r.clone()));
// 9:
// 10: digest ← H_msg(R, PK.seed, PK.root, M) ▷ Compute message digest
let digest = h::(&r, &sk.pk_seed, &sk.pk_root, m);
- println!("DIGEST: {}", hex::encode(&digest));
// 11: md ← digest[0 : ceil(k·a/8)] ▷ first ceil(k·a/8) bytes
@@ -1150,21 +1124,14 @@ pub(crate) fn slh_sign_with_rng<
// 20: ADRS.setKeyPairAddress(idxleaf)
adrs.set_key_pair_address(idx_leaf as u32);
- println!("adrs a: {}", hex::encode(&adrs.to_bytes()));
-
// 21: SIG_FORS ← fors_sign(md, SK.seed, PK.seed, ADRS)
// 22: SIG ← SIG ∥ SIG_FORS
- sig.fors_sig = fors_sign(md, &sk.sk_seed, &adrs, &sk.pk_seed)?; // TODO: adrs swapped position?
-
- println!("FORS {}", hex::encode(&sig.fors_sig.private_key_value[0]));
-
+ sig.fors_sig = fors_sign(md, &sk.sk_seed, &adrs, &sk.pk_seed)?;
// 23:
// 24: PK_FORS ← fors_pkFromSig(SIG_FORS , md, PK.seed, ADRS) ▷ Get FORS key
let pk_fors = fors_pk_from_sig::(&sig.fors_sig, md, &sk.pk_seed, &adrs);
- println!("PK_FORS {}", hex::encode(&pk_fors.key));
-
// 25:
// 26: SIG_HT ← ht_sign(PK_FORS , SK.seed, PK.seed, idx_tree, idx_leaf)
// 27: SIG ← SIG ∥ SIG_HT
@@ -1175,6 +1142,7 @@ pub(crate) fn slh_sign_with_rng<
idx_tree,
idx_leaf as u32,
)?;
+
// 28: return SIG
Ok(sig)
}
@@ -1218,7 +1186,6 @@ pub(crate) fn slh_verify<
// 8:
// 9: digest ← Hmsg(R, PK.seed, PK.root, M) ▷ Compute message digest
let digest = h::(r, &pk.pk_seed, &pk.pk_root, m);
- println!("verify digest {}", hex::encode(&digest)); // good
// 10: md ← digest[0 : ceil(k·a/8)] ▷ first ceil(k·a/8) bytes
let index1 = (K::to_usize() * A::to_usize()).div_ceil(8);
@@ -1234,16 +1201,14 @@ pub(crate) fn slh_verify<
// 13:
// 14: idx_tree ← toInt(tmp_idx_tree, ceil((h - h/d)/8)) mod 2^{h−h/d}
- let idx_tree = to_int(tmp_idx_tree, (H::to_usize() - H::to_usize() / D::to_usize()).div_ceil(8))
- % 2u64.pow(H::to_u32() - H::to_u32() / D::to_u32());
+ let idx_tree =
+ to_int(tmp_idx_tree, (H::to_usize() - H::to_usize() / D::to_usize()).div_ceil(8))
+ % 2u64.pow(H::to_u32() - H::to_u32() / D::to_u32());
// 15: idx_leaf ← toInt(tmp_idx_leaf, ceil(h/8d) mod 2^{h/d}
- // 16: idx_leaf ← toInt(tmp_idx_leaf, ceil(h/8d) mod 2^{h/d}
let idx_leaf = to_int(tmp_idx_leaf, H::to_usize().div_ceil(8 * D::to_usize()))
% 2u64.pow(H::to_u32() / D::to_u32());
- println!("mod h/d ={}", H::to_u64() as f64 / D::to_u64() as f64);
-
// 16:
// 17: ADRS.setTreeAddress(idx_tree) ▷ Compute FORS public key
adrs.set_tree_address(idx_tree);
@@ -1257,8 +1222,6 @@ pub(crate) fn slh_verify<
// 20:
// 21: PK_FORS ← fors_pkFromSig(SIG_FORS, md, PK.seed, ADRS)
let pk_fors = fors_pk_from_sig::(sig_fors, md, &pk.pk_seed, &adrs);
- println!("verify pk_forst {}", hex::encode(&pk_fors.key));
-
// 22:
diff --git a/src/lib.rs b/src/lib.rs
index fdc10ea..d8b4c6d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,18 +1,15 @@
-//#![no_std]
+#![no_std]
#![deny(clippy::pedantic)]
#![deny(warnings)]
#![deny(missing_docs)]
-#![allow(dead_code)]
// TODO
// 1. Get one instance working (or at least not erroring)
-// 2. check 12-byte adrs fields -- how big is the integer really?
// 3. revisit/clean hash functions
-// 4. adrs - store in be or le; how to account for sha2/shake?? (different size)
//! TKTK crate doc
-extern crate alloc;
-extern crate core; // TODO: remove (with vecs)
+//extern crate alloc;
+//extern crate core; // TODO: remove (with vecs)
mod algs;
mod test;
@@ -22,15 +19,18 @@ mod types;
// Per eqns 5.1-4 on page 16, LGW=4, W=16 and LEN2=3 are constant across all parameter sets.
const LGW: u32 = 4;
const W: u32 = 16;
+const LEN2: u32 = 3;
macro_rules! functionality {
() => {
+ use crate::types::{SlhDsaSig, SlhPrivateKey, SlhPublicKey};
+ use generic_array::typenum::{Prod, Sum, U2, U3};
use rand_core::CryptoRngCore;
- use crate::types::{SlhPrivateKey, SlhPublicKey, SlhDsaSig};
- use generic_array::typenum::{Prod, Sum, U2, U3};
/// blah
+ /// # Errors
+ ///
pub fn slh_keygen_with_rng(
rng: &mut impl CryptoRngCore,
) -> Result<(SlhPrivateKey, SlhPublicKey), &'static str> {
@@ -38,14 +38,18 @@ macro_rules! functionality {
}
/// blah
+ /// # Errors
+ ///
pub fn slh_sign_with_rng(
rng: &mut impl CryptoRngCore, m: &[u8], sk: &SlhPrivateKey, randomize: bool,
) -> Result, U3>, N>, &'static str> {
crate::algs::slh_sign_with_rng::, U3>, M, N>(
- rng, &m, &sk, randomize)
+ rng, &m, &sk, randomize,
+ )
}
/// blah
+ #[must_use]
pub fn slh_verify(
m: &[u8], sig: &SlhDsaSig, U3>, N>, pk: &SlhPublicKey,
) -> bool {
@@ -55,24 +59,22 @@ macro_rules! functionality {
#[cfg(test)]
mod tests {
use super::*;
- use crate::algs::{slh_keygen_with_rng, slh_sign_with_rng, slh_verify};
- use generic_array::typenum::{Prod, Sum, U2, U3};
- use rand_core::OsRng;
+ use rand_chacha::rand_core::SeedableRng;
- #[ignore]
#[test]
- fn it_works1111() {
- let m = [0u8, 1, 2, 3];
- // TODO: can we push LEN SUM calculation downwards? (and remove a generic arg)
- let (sk, pk) =
- slh_keygen_with_rng::, U3>, N>(&mut OsRng).unwrap();
- let sig = slh_sign_with_rng::, U3>, M, N>(
- &mut OsRng, &m, &sk, false,
- )
- .unwrap();
- let result =
- slh_verify::, U3>, M, N>(&m, &sig, &pk);
- assert_eq!(result, false);
+ fn simple_loop() {
+ let mut message = [0u8, 1, 2, 3];
+ let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(123);
+ for i in 0..5 {
+ message[3] = i as u8;
+ let (sk, pk) = slh_keygen_with_rng(&mut rng).unwrap();
+ let sig = slh_sign_with_rng(&mut rng, &message, &sk, false).unwrap();
+ let result = slh_verify(&message, &sig, &pk);
+ assert_eq!(result, true, "Signature failed to verify");
+ message[3] = i + 1 as u8;
+ let result = slh_verify(&message, &sig, &pk);
+ assert_eq!(result, false, "Signature should not have verifed");
+ }
}
}
};
@@ -90,9 +92,9 @@ pub mod slh_dsa_sha2_128s {
type A = U12;
type K = U14;
type M = U30;
- const PK_LEN: usize = 32;
- const SIG_LEN: usize = 7856;
- const SK_LEN: usize = 0000;
+ //const PK_LEN: usize = 32;
+ //const SIG_LEN: usize = 7856;
+ //const SK_LEN: usize = 0000;
functionality!();
}
diff --git a/src/test.rs b/src/test.rs
index 26d39b7..89ff71e 100644
--- a/src/test.rs
+++ b/src/test.rs
@@ -42,9 +42,11 @@ mod tests {
use crate::slh_dsa_sha2_128s::{slh_keygen_with_rng, slh_sign_with_rng, slh_verify};
+ #[ignore]
#[test]
fn vector_debug() {
- let m = decode("d81c4d8d734fcbfbeade3d3f8a039faa2a2c9957e835ad55b22e75bf57bb556ac8").unwrap();
+ let m =
+ decode("d81c4d8d734fcbfbeade3d3f8a039faa2a2c9957e835ad55b22e75bf57bb556ac8").unwrap();
let mut rnd = TestRng::new();
let sk_seed = "7c9935a0b07694aa0c6d10e4db6b1add";
let sk_prf = "2fd81a25ccb148032dcd739936737f2d";
@@ -55,22 +57,34 @@ mod tests {
rnd.push(&decode(sk_prf).unwrap());
rnd.push(&decode(sk_seed).unwrap());
- let (sk, pk) = slh_keygen_with_rng (&mut rnd).unwrap();
- assert_eq!(*decode("ac524902fc81f5032bc27b17d9261ebd").unwrap(), *sk.pk_root, "pk_root failed!!!!!!");
+ let (sk, pk) = slh_keygen_with_rng(&mut rnd).unwrap();
+ assert_eq!(
+ *decode("ac524902fc81f5032bc27b17d9261ebd").unwrap(),
+ *sk.pk_root,
+ "pk_root failed!!!!!!"
+ );
let sig = slh_sign_with_rng(&mut rnd, &m, &sk, true).unwrap();
- assert_eq!(*decode("43f8eb75d58b652f779c5a0f5378709e").unwrap(), *sig.fors_sig.private_key_value[0], "fors_sig failed!!!");
- assert_eq!(*decode("ad62955228fdf4c3be9c22f601397a11").unwrap(), *sig.ht_sig.xmss_sigs[0].sig_wots.data[0], "fors_sig failed!!!");
- println!("{:x?}", &sig);
+ assert_eq!(
+ *decode("43f8eb75d58b652f779c5a0f5378709e").unwrap(),
+ *sig.fors_sig.private_key_value[0],
+ "fors_sig failed!!!"
+ );
+ assert_eq!(
+ *decode("ad62955228fdf4c3be9c22f601397a11").unwrap(),
+ *sig.ht_sig.xmss_sigs[0].sig_wots.data[0],
+ "fors_sig failed!!!"
+ );
+ //println!("{:x?}", &sig);
let mut sig_array_act = [0u8; 7856];
let sig2 = sig.clone();
sig2.deser(&mut sig_array_act);
let sig_exp = decode("07eb19e7d838d71ef66b8263b5d1f8ec43f8eb75d58b652f779c5a0f5378709eff39c179556ee3871600fa606ff751dcccce5e7a6981fbb8a0e959afff26ea6aef4fef5ccb66728f9d119ca2a547f0af0d3509364c7e3c9981e930c8c77ac74b8f385979dc8582063eac5b2a2532c8eb97fe1bea498bdb8b6496fcd3c5931393ac17cf96ccb35aaa9c7491b1a9897ccfbf35b70fec94687aad4e06c1b8d3aea67554d470804eec25309bf34c6487aea92b1d49edfc7afcb31d78ad4be8c1e4403b634d2db503b8cd08270dc3579aa8d639c33d024d3bebb9d401424b009793dd87053e5e0d0538b90a7a5324e5f08a8ab13de4dc1ed0b9848b421f40e5cd1ab70f07f652f3df23853c1d44ff0da5dac93d0fdd2007a1100b3c4abc9779e0fae578653d3848b520e96300cabce717b11dc1257f6c0c54add4fef22be57a67c45b288997b8f496f6fb3cde4a4cbb646b6cd922c7cb04c0bc2dd1bddca39a6154c10a07a1110c23df6b89dfd65c4107371cb98a352f88ce579bf49cda3c7062f9744594b9e431391e85622b13a6356a8fc1900f29dfd0d2a408aa2f15958707a14948294194cc3d51d26ca81dd64fa8a119d156e83ac0b1350ee98ef246e04b85edcf6567f917f4aa1e379244465145f9965a4f7a56fb14a949a0bcd08550a2de294f74ce74bf178dcf521a27d2ef642aeb05b38f835b7cd0e4ad4f2279c46c50378c06d4829ada543cac46a56fdd681dd4f473d792250cfece0fa98fecf1735caf37ec75b00a6212cfd31f57550c89e7acf2cdb257e5c021d1d465b7663b0b64d0e47b38460fcc28b1cf9e40ec44d420fa5677043ad647eb5c80b58ba88fc55e1c5c394a0f7e592a0edcb1dcf6ccfc5f1b25b30ca191e8c31232a39b0563d5b7dc2ad42582b58efbf84cb34d4572a8146ef8da7dace23229a732a901f15c7cb1a36aaa82838d6f554e49f2f18b9b73f7ef1fcc325bb31e668167c74777e0606806d81420df2dedcd56538d5d1386f2122b71e894e348820594869b84455d9a195061dfe1fc2795acb7103f25522caa538420af67dd03859480e0d046c8f175038d78d603af58176a1ab26f560ec78a8f2e45f4fa9da71f2e99c9ce038e5d95b07e8dfad89b8c6b1fb990b081bda6e848d8ce5577f852481396175cfcab40fc296e71996ec4a5c6d52a8a237bdcdc2b57680e9379deed17f929e774bf90906de5c3941a212801dd09e58a013a08a8903a0aabaa90118250370b3318db6b17f586b961a2a98678cf54ca6c422dfe32767c99ad4e12a28a3b36e85bc299f0881a5ff4d2e0efea327656f67851fdd95fd8b9d1bd941345b7ab065f78a8c342a5184ef6150f304e7d7b806de025d5c571831ad4537db35033b0121effeccdb100ecaa9805dc90e965995b39748c645e644331fee496956b6a1fb7a6029eafbae80be5e68c5aa66b369c9e9d7c96c77d32592c6696e3368ccae005a479492d400c926df2b809dcf1c49e77877792ef9c9c1cef36e679e9bfc01a67c92f093cd8ee4ec44fbc0318988014650f4d158edc630443cfde99d674f9763f20c60ea3657a2ea53af1fc2a3e7ea723e546eecfdf3be0309f5a773c228c168fdbcc97325cab9c9137322736a606935f6aa74a10d0f5bc6a83aed3fd2cd94621fbafef01bb3e601222522a9c9f6d4ceae117a2d53d2bd774eaa5948a1fa9a83b871bf763ba4787117ec0e7d62cd587edaae53427fd56e7dd25c9525886ef401a05bb58d3647e305314ba9a2c1c10a394b6cc7ce983fd11f79f6c05a624e16699be007cc57cabfb972a1b1988c1e47b4394fe4a404d0aa641b4281aa98ee047d22466c09f3a0dbf7ec6e51bfcfbe6380a23b81e6062300710423b44e88f8967f4f88e559486f7ef84726c501224c4a9faebce33e188bf9a72edee1326438f23620eaad0ab0ce53a87e8b410f243511eb3ef87c9f7af983c4b0d6e6b2a1a1407ac10c1305cda22d6dd0bbc470fd61c2e4a38c4244dd2a7ceb9d347d8d8f58906cc5b1c5934c973b048fa97a49c39a401c452a92ae8c826781b3edb77416625213e826aa6bbb131dda303cf63cd4f6f200056d13e69be148be51eaee8d059fc47f7ffeb24796a79007c0b83b75be70eeb65f46fc51c071f4ef7bc24d71374cd7955c88bc28f4ee285b6823a45abc8b157c3275c49a925d7ad45183b4f09687a8002e54635f8294768f711a47499234b7a57c5a311534920f12c284ed21522b25ca7890610aaac91666ac54bab87c3f3a566d31f1a66689d6036e968ab30c162da446ebc7cfaa9eb9bf22a8652926e7334265897b2af934d8c2bc261b4d86aaffcce72d7514326052f8c4120868be79b05c9a8f3068a5ee4e5d82b5d3d7afd3d03490caa9a3d75084e2906dc039e72837e85768d7c034b17d26eac57a86f5a3f000dfb783089d14532048eab5bfcb65f1e21af9869254f3a0873a8cb1d94c4a4849972e0d1013d3918631830473529bf392c35948e7fd8b5f60dbc03c168d3d5e5d4f074910ae674740c37be037d84d4390708aaaff47a64ad23ffeda22b8eb0006d9ab9eaa629a07899c6d9f79615a4c6c05cd2639dc87d53f60bb78e0c246766a1de332ca6f6f9b0dcaf58d3fa82149d2e244721f5c47fa6734a01071ab23a871ebeb676a16151402223cda2901338c17d5b0c59139ba82403709bce2ee6cb5b8a419a74ca8046b9da98a10efa6fa5726e235ec329938f4f36e0b3310ed946cce3f2f05a23bf7b203ad82057d8ab2dd6e6f9614187fe90ae1397a927bad5bdea19768da4e1277fdbc2465b73fd0f224a94ed00a765268b081288d14342a0e303e106bf460c247ba3bfb806da76264b8c0b0364e81da052ea399bfa331170c130e96f268c0f3c2deaa8df5462b685ad128c6a1fab979d8187cef285a555416ba01165abfec8e0fd44030288cf475f82c60f50323b3277a965f7fe57c78ec1ff8fa798f0b3f10fb4307e8c8f516a7c8ea8ef723c14782906e6295fe14af513e20f12577d53e7108d0c82ffbd5b9671afee77a7aea7f6f90b49da727447681a4de3ac28a892086026de61794cbdc43d2539379c0d16a44631e36ab058a7bda1b02f484e5a76b47f5a684fbf0a88b74721e9f28cd4cc3121ec938a042bbe315580cb7ed924de0a542bea6f52eda7c923449b41859268389694fa5f7f2cc4784b89952ff8569d7d75e1a4ee7ae7edd1fdc45a5c50b14a6d123e055f6704a25bf90b0c509e219f03d07f3d23c70437901eaff3a8110c6d24ba729553c184236189f3adc1eb5c1b8eabe544e7acd94770e44aa2660da38321c1c8e1151c96c15204cd8a661f1d5d4bced5e7e82012d3bdb6d99e9661c96de8be6bd5f4cc95991a5a4564e33acab99b1a8174610464af89d87bce2622e03ebfc5809ed27770d17137455995e05b5fbea2704da46a6968803fa7340af422db2777e2ab00c44ac0012f5495fc6728b1188400503f3a08e833359e678dae7d23d19391d6f822dd867e629d4ad8509c1510795b4268cad99acc0f73e5aa4b0fbabff30abc2ec614c3ef558d1fc5f4123a4cabb701a48f3f5d5e086426b8de105698599e81de7e4e78c153acc24ba435f943761e2203520fac0f10011ee5860d90241e06261c7b23ec61206357af23a6d8f18e41d572da802ef827ef4857a8ffdbf1dbf980756785fd7a5b3ae6235844d6fa58e7345ae767f77fa9bef0423c7d5d5759022c8953c8de5663d856b27f8b7970bd442c27869f2d08c84b2f1c35f3081bfe9d680998786591301912850b61902439b04c9bd58f1521c7832ea9dfcf8ec461435a0972d876717fd21ad56a68652f74a4bc717825c98e4e408f6f0c233b5650ea5e21b0e27b9f7987568d70e49e9919be1ada26d4613ddf96c748fc195c59cef3c20e6839a9a5ebaed476d8c2e775735eda1a25b4bde7aff4acd9c0fe7a64a4d59c123229e25a14f05e90166b2348c935f511d3ad1ae94b4e67b4ced7e9e7235e90e1f6349128e3b0df59e0e4c656bc44f59f1ef3deada102d7aa64638d2e5f85f459c2343049300e924dbc19482f4dceb78d2721c303f045cc008ae0408ed8ad68b2d6ea105166b8eaa60f971a53eee16831d7639da898c959a21b35c7df2782358f19ad62955228fdf4c3be9c22f601397a11aa015dedd38507af0fdb66630a1be7bfa33256ffe71bf0f89ed0ff10308beeade6e9adff75cf4e48c3f7190e02822fa3ad9f6f358fc664e59275daa9b933d4428458bb0fb89d5d13e11decb47a8e50d66cf14bb54f818e27c2161e1a195ff6fd76cae99ac86ef222f0fc398f99e3791b9018d73e9b535f9b8144bade55618824fca2b069667e2bf126895f86e183f430aa8961b7ee7cb437dd5c4b932069fbcff6e5bf725d2694ab6e910d68c4c165cbd3c5b9f96c0f35de72c9ebab10ca749231d7d1ecc5c2ddf0f7935907dff1897e3c1a1cf881b6701621ee50319b90c86cd2ed219605db6322b059947c4d8dc3ce3d81d045714ba4a4224d36f0b9cd54b79957872a8da4f596699e11ff9b72be5ecb9742891b95bc414204a351ac74ed4142514938b657492d8dd9d418c45c5df7351a8a685d5861c776959a77fc33f04e090ff543c5342e5147186906b9d1b3d13ec20e210b3b83a6129728abc0fc053e7f81fce4a66a9304bf2ab51e9ca0a11637a4792bc050eb678939ad86875f9497c9d52b0a32048eb3506180fa1f251f3f7e2908033e017687aae393c767579c768a091a1559dcdf6ce18f1e8591d8276b22cf06d9297b84f61ad350b8a81e5097ca1ff7d90f91de00439c3825832a93327c987916e079f56ece29209f74cea18e81d93e78974684bf01dd6e62b991fa6e1e32db935761652afeb5178c5de579e47d4e579871454e95fc651d9dde6ebbaa08ce4c82b7c36bb02cd024404059fbf2d0790cbd93dcccea566030933e4a58b88a23ad3f596992b23f45566869777b1b12070ae7b1bdebc0360f2e76cc266765930a5edb0f0c0536a2e8590fafc0a02396c1049a0d0029b873ded63a70b3080db0bce8c5ba703994b96b170a6bb6fe440568a212442aa121b1c18578b24f97523a80e46daf9b340899b05d5af4264dba6aa2fdd363e924bf7ea2f6550edfe48d24e852ecf53f82e10e47aba2a6cb72637703aea31d6158bf5fb1cb5160123ffc6f6468ba522505167e804a68f7267fbcc78723273af95ce853187aae169d4e9fa41e5fc0fa715b53faf686a06d679d34232eb166176edce277f7f4b0847c5ab6e52c11779e9b62df0e42c19c77c44756433a4817c4a84cd8d8f5c8d32ea246a4a34995ea4e4f8e31ce532a499ff50fe2ec01d7d4e3386bf389be1ecbc914fc481a6397f6598eeec872ab4783f95a5f864b9e2ec9a53ae9432e6de2ee4b45ccdee7bc5b8451f8ce0e9f4d6dd154dc8c57284d6b9f6c27471fe354be61733b7213769244c16539446e80d7760ed6e4d3747c5505e2078ccb7fdd7c34d07e7f8f3a354427b281a982cc77225ae8df5565eeddc73b605f757c79ebc9b468380fa192989a91008971f05bd03e80fdc82baea15264fd36d343782fe8d9bbf6323ca2b63c5920d2eb1b13b5a50c5314f7ac5a8968e281d8e1460cbac0e1a7e8233fb10b4e180dfe29c9f94041df9f4cd765d5c8ae45ac05548e732fb1018db4fa5e954f35ea88c5638c1b9983708f7c8013939b9604954d8e408729a495d2995f01f6c1df28ec303f701c165596771a438b933123b4214789fd31069cc6ce8435ba524384c9352854a845e5e3c1b27e50e3300f69ee4cf14fc52735ef1cc63dda2baa6b278f7383f9eb4e22206106803f72209f55918f000f27798d3f0a9040d4666778b36c6db25421176c44383e373d520f50dbfe48a9c268638b8c22f3639c86e9c104ecc3d222b692092e46d0e2ca546417ae1def31f5b4bd7a619b255378551f227cffe31a4436f062da978c6e95e959d2bb342e5328bdf9cd460fe154d13b9995c2f92613c564c88d972012faadc6a9bbeee0734e96f5ff55fdea1eefb50a1e059c53935c1b35820d2cd39b7705d66eda7c7adfa9b5b90cb97a261e10409a2eec2d5703be7c75443bdcb78d74fbc977394da78332a2be69416788c8e33be4bcc6f5466ba8c5ce2b7d5258d3a76c926f0663f7615a9fb08f8bb2c50283c14c2ba81af8b29ae11ae0f21d52be009fa4362831afd508c42e982dc23f249b33a162fde1cc854f85047eee35af5dedee193445e7748a3d6922dc462abfbc382a482a1651b4f3a5e4b6da2fb7e6fba7752828a0d52ec15c6041365f0ed760b0c9148fb45169ef99bb68bf129269cc9fd8bdd74f58d9863ba1fc4f17cd9fa6e9158504d70d54271c124b387bce9c9d749364522a90f79e766d234a22182f7248c165798d548429175ab1e9d54d335fec9a852a2b5dcda5d69bed9313df9928f3dea3c619b258cf776fd5365081d8994f6bc2471e7bb3e90e038b06da18b8351f99f4b7a95c66d0b0b86e2ee4dfbd666fca62be05bcae0cac34d9ec3d0c95e96d878ffc8bf21811fcd6bb8acd65171fcc3add6082d4b78c94bebb503cb5ca33f0988adf089d9c5ef0c009ff69a433328feb66ae5cfb2c85c622193e894eefef9b1f4e1540dac5b539f30448046c0edb544a6b46f2312d1c6d923d87dab1fab5f404f7d040bf77d5c7d78548ca92123c86c6eafa22664c38044da5baeb01184b1e8410a5b4d46972ea687ad0680ff2bd7ef645e43bc694da818f787f378f6b5ea1a238233bfd47cb62d31f57006782ba1235fbbe9c5919dcdd123683aac9ee84fc8f5d0b7261b07ab76db21a073584be6cfc44b3b2922a9b7bd88094b2f7cd28a251c516f84cdfbb8bac0a501234e0cf11548a9e116b79b07a08f834474f5af1cac7ec99be23be3ee3b4237188ce5d6d051684ad3281173413c9418c770abf830852dc4c7c2f6892e95d108ba5388b4f1e4d7c8ee4fe1c30af7e78b3bd6f94f0c53a89b66dd337c77f2a51d50fb1ba67724a1de08a7299351e797f185b65ddb8ef0b49e89b13fdfecf8f75c8442e9b62f53f91c9cdf2c1716758a83735ca34b3363849709b820c6f6e7429bab71f1ff3e5526ed629e0663813eca12befb988022f1613105ee7f5e7e594bec90a5cf04c632cce4ca56c4e10487352f1c99e7911f3c974af2a35155fead6aeebd6008f7d2cf5ebcc56860b373a130f65cc7eac4e2cb30abfb025214eac079b33f6a41bf2ac21afc3c7e3ec72874cce7f775445e972efaee607059aac7712441e7521803a9515570942735827a0572f37f8a4e6ed8a874171e59b87fbd496032f90c223c59adec3751de260ec228b003c65213c4a24d8c9d12693dac94548a3ef524adbc538bb074b35c8610b298585ee287d5054ebc381573db3cf32ba136a31e46fc8b76f9a9308a7165c7831daab52277711a10da0187c1836acbdb688080b6fd682927e7eae62bfb9b9b6638342a16ca35c5d04224753c3c3cdc0152e45cabdde589bc8aaabe81429a1c037b0d3dd0da79d1621ebaf2ff8c8e13e0cc21725bfc58e3563a01b63cd4b3a6a3755738393140a1558edc7d9245831a8d5e4bc1421cf525ea747f5510c4e34aecd05e9c2c527c8015bc88d7e7dc8933d412f83bc138d765860bc6fd6a5aa33253654911b891221bc7b0588802c3e4952dbc07911161eb9d99604cc20f5565a0d4d673bfe673489087efe4f6013e5c519b7bb8391299e29bc0af88877658397d77843a7786cf82f7770791ec7786cc75af919af22551c3cf7bd20a41cbeb0b0536c7f752da1a6e37088976373195467005e68ff58ac6311daef4b09b5aa8e49728c7e93120e408c845272f92b70e42e351ad308bd51345715c7d39b967d743acb106d719d9c8010e89bcc0a8c3447cf14f3b387dd8615f26b04db4a7649a5a66e09e99009084bee7337eb45265e55ef9e245d5d818bb22bb9919f01669c5e775fab64514f6591fc1ab4be2cc4b0632d96a6162e6a7d391bf5f94ccc5da34cef4ee7d9abd1a5d30f2fbb5d481c40857f56e3781d9e50b26a34ff7a3bdcf230cb1d29b13d9686ec24d70832642d2c1a9bce3107d287f421a56ad9844266f8edfd64afb25d84a7547971056b0cbdfee3238783903ab824f60aa20767b488c00467c9c7d0e6f6809658c9f0ad6c5b70228146dfd5eb1e59d3c36292654f25064b7cdc4631ac08d5a8bfba26529bc45510ecb86cabac40fe81b49466c66d99b48fa7036f9036cffb90d07f9b07c04ed74926331d4b192aa8ecf5b764d2472d8289979a0f3275b09852db3f657d38f68b29ff141213e75b4954c810d94aea49f14f05ec28443bad8936da3a6d4464cda85236a4255ba3dea323e9f7a14f5fc80819a748133f41eee39e30b8fd55d66f7e6fbc580b29bd7031908d7ef808c3967127e8a1e1d9db783c0b7eb9dea9f5ae52ab3e49085b2e21b2012bf0901d707ddccdee3f72f6d3059dda130754dac9522840d9b880208c663580985a8ce30977fa21446edd897f5955f893d60d8ee7f1605e0d7ef01620db3d293e3799ca54bda6a24ca9008aad5c0ef03207293d5b57f970f227a7be653c53c0a3a8cc5f25c5cf303cc97405dc65d4d3808e3bb21dc867a4e110724e1609d1b7dde8dfbb85ef501e3e0b7a358c45513a84f1f08a618e2b678fe6b68e13df7b0775c599563533cc043e3fc2433f7eb38e4136177ca272ef424dfa2281d3818f2aaf78a2337d67ecca9b90a451e5c175398c2ad713483f52a2d9fd1a9bfd256fc1ff38270ccb06e5b9ab9a2bd5ff589cc27df4faa28f57d13b50202fa46e04424f0fb06e091581b7066c2a732f1d647086c6308ff04df31cda244e583021d89d4ff4ae341fa06ad75c743d425ec6e5324cb1646d7d2bf6a5b168e48cd3527659d79a417856a2dd4bca5b106f74525db242d8c92e33312b8d91a489f6fb1983ea6bbe51422da1e8523ccb9f38e18abbc5601d27b9382bf2e2b4b15690202405c3fa5404c701c8106528f52f9ea4840040af12b4152d13638bdee216682c97a245e7f3c7f31988f5cb907ac195912750d9e45712590d3e88b24f6cec6ea1972fc8f7c900c53967b3657798482f5865a9313214a41cab7601e958cc66c25251f414e71654077828e7f29c57c2acfbd36ef0d9d4d909675035f9005f68013a9431026f971a597b29b032ffa13c857e2dac2deaf0d094f0fd3e184148ff8adb535f062219acd1724d313a7e1f985bed6e2b5736d3bc127a98ef99259a7a7d5714696826d11175a63cad28a23f1c8a06277996ddc3fa07f33d5e89243adfc21ac31d7ab9a61fd0bf7a0074a527e3061a5e45e6dfb9953ac8c20e1120fb6b23ab02870f18ae2d976ae186fea47e5f3105fca1547e4763ccc61f7ce555b740881903ca09505515e1d41539226a6320c70427f56091fb9efdc6d4f94f4273fda0bda64ef363a30214a952140b373a5e914a34f3fdf10206774b7edb4d996d72f1f377ac84806603710b77640150723894101b7799cb272a4a4ab9704cf4a6c3071175d0812aeed7e8f9c96c823d94333a1e749cbc58e86979ce2eefeb159500dd6b90bb8a76497ce94cffb38f262e0d87e6bfb86a8417d308c1a2a1b97a749c8b175760ae790ec92d8b5cefdab7e4f56d28dc8f2be6b0fbf50e3003d2d5a28b3b14a75384b2662becec4b453ec011865647c1146138defb64fae31aef84950430fe2ebd42561b9c2d772e678d7248ad72bf36675ca4eac508bd91f8aba0578bc317c837cee9032eb06d09adc2ce45eb51a03cbe52e3ee55cf02b919d78eaac99340a8bbc43c492e74b438cb5610b048d154a40985d7c105a35a3001bfdfa732ba7952b1c41e20b9c168a7dc30c34c912576c883187cf744e5fe9e29db07538df2eec05630277a6b15f7b6d6b65e5788371efe5f316388f536ddc1446783c066d760b572c0787643e6deed01b30ebd40ff253eb3279a17660c7226d925645c5d6300bbb19f209a5bc79c274a593c606edc005669e875962ea5028ce50b46b8611868db892fc596de68751caab22a7f6c3237c60f6f16bc80f6a71dd6d75dddd626d6b8182239a61079694cf45c55cd13d19d4a38bf78903c17c5c37402ed2c5dff7c164aa90869acee38c22e09bd5b8ab1542c4aafaed32f6347bd156171717ea5f2f09db652a7e7fe48b833945a46cca438eea7d77eb1d164ff5fcbe72d445aac73bc1fd44b16405348b8905399b3268608f7d89133cdc08ea8a89fcc6839ecbcd46549de8f1447b7e273596887ba3764dea52fd1ea84605034f4ccd7a6c3b5582fc7c284b22dc984840e38d9dff2109ee4ce3354f2322368d70b13d9799ae8e0bc68bf21e39a2e5174e247d1ebe28bcc24aec45e93739054fdf7f843fd3422b75459223c319c820284199488aafb41423b37990e59a6bbec4b14617eddaeb0fe7f72faf1fdbde90976542f745df725cd9947ded598c637b66034f94fac301855b4563dde7e9996c7579b147b73b331169dc6fb5ee0dae47d49c085df89956c33abdc38d891836881a1c899a8ac11e1c105ed7dfee521cb145acab582784cdf88baf835f601cce97ef21ca8223d3e83a2b2e5618872d7d51debbabd3bbe2328ddf5832bb1888866d9cfe59f41bbb574201793cc7154813c9f638838def7ccabb3ce56793143470516a7dd54a0b06db3d422189124d680cb36cd116ef8cadfeaa3b9a083fa4545b278486c6cf5a72dcd3754bc5a60ed19abe376e21f0529071fe6521b1c3f8d938acffa9fc793aeabea0e37cb53fe9eb598d2649602f2c8043826707a66d3c785fc01f00aa96faf5000ac1504a1efd2a68ae8afa0024d6d36daaa385a10da650c28eb4be4b251eff0a780b7a2b26e700bd8ed0485dbad40ec57a6a1d133c025735c8d8d645eb5d24ac65bddf1b9b90799513f58917e92673a05f67670be70e8bb1ca2cd0bb25b8efef2ad3db516234e9ce4a79f0d5a0d0c7831a926073e482be6ca6e745407dfb5d6700733e2c89f74db5a7d92ae0b2969def84ada576a1bcea10c1398a66361cb4f96de45be2454db7ee6975e47ae95222dba6a406832254e1f05a4d3db0a7e17061b18213d6bbdc66bd61b29d1ea53").unwrap();
assert_eq!(sig_array_act, *sig_exp);
- for i in 0..sig_exp.len() {
- if sig_array_act[i] != sig_exp[i] {println!(" {} ",i)}
- }
+ // for i in 0..sig_exp.len() {
+ // if sig_array_act[i] != sig_exp[i] {println!(" {} ",i)}
+ // }
let result = slh_verify(&m, &sig, &pk);
assert_eq!(result, true, "Signature did not verify!");
diff --git a/src/types.rs b/src/types.rs
index 52d8d6f..bef9c78 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -1,4 +1,4 @@
-use alloc::vec::Vec;
+//use alloc::vec::Vec;
use generic_array::{ArrayLength, GenericArray};
use zeroize::{Zeroize, ZeroizeOnDrop};
@@ -18,15 +18,18 @@ pub struct SlhDsaSig<
}
impl<
- A: ArrayLength,
- D: ArrayLength,
- HP: ArrayLength,
- K: ArrayLength,
- LEN: ArrayLength,
- N: ArrayLength,
-> SlhDsaSig {
+ A: ArrayLength,
+ D: ArrayLength,
+ HP: ArrayLength,
+ K: ArrayLength,
+ LEN: ArrayLength,
+ N: ArrayLength,
+ > SlhDsaSig
+{
pub fn deser(self, out: &mut [u8]) {
- assert_eq!(out.len(), N::to_usize() + // randomness
+ 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())
);
@@ -37,26 +40,28 @@ impl<
// 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]);
+ 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]);
+ out[start..(start + N::to_usize())].copy_from_slice(&self.fors_sig.auth[k].tree[a]);
start += N::to_usize();
}
}
for d in 0..D::to_usize() {
- println!("and we move to xmss {} starting at {}", d, start);
-
+ //println!("and we move to xmss {} starting at {}", d, start);
for len in 0..LEN::to_usize() {
- out[start..(start+N::to_usize())].copy_from_slice(&self.ht_sig.xmss_sigs[d].sig_wots.data[len]);
+ out[start..(start + N::to_usize())]
+ .copy_from_slice(&self.ht_sig.xmss_sigs[d].sig_wots.data[len]);
start += N::to_usize();
}
for hp in 0..HP::to_usize() {
- out[start..(start+N::to_usize())].copy_from_slice(&self.ht_sig.xmss_sigs[d].auth[hp]);
+ out[start..(start + N::to_usize())]
+ .copy_from_slice(&self.ht_sig.xmss_sigs[d].auth[hp]);
start += N::to_usize();
}
}
- assert_eq!(start, out.len())
+ debug_assert_eq!(start, out.len());
}
}
@@ -157,7 +162,11 @@ impl Adrs {
self.f7 = 0u32.to_be_bytes();
}
- pub(crate) fn set_tree_address(&mut self, t: u64) { self.f2 = ((t >> 32) as u32).to_be_bytes(); self.f3 = (t as u32).to_be_bytes() }
+ #[allow(clippy::cast_possible_truncation)]
+ pub(crate) fn set_tree_address(&mut self, t: u64) {
+ self.f2 = ((t >> 32) as u32).to_be_bytes();
+ self.f3 = (t as u32).to_be_bytes();
+ }
// TODO: revisit 16 bytes
@@ -169,5 +178,15 @@ impl Adrs {
pub(crate) fn set_tree_index(&mut self, i: u32) { self.f7 = i.to_be_bytes() }
- pub(crate) fn to_bytes(&self) -> Vec { [self.f0, self.f1, self.f2, self.f3, self.f4, self.f5, self.f6, self.f7].concat() }
+ pub(crate) fn to_32_bytes(&self) -> [u8; 32] {
+ let mut ret = [0u8; 32];
+ let mut start = 0;
+ for sl in [
+ self.f0, self.f1, self.f2, self.f3, self.f4, self.f5, self.f6, self.f7,
+ ] {
+ ret[start..start + 4].copy_from_slice(&sl);
+ start += 4;
+ }
+ ret
+ }
}