From b5a6545bb0a5c8889af8182340dec71f750d6e83 Mon Sep 17 00:00:00 2001 From: eschorn1 Date: Sun, 21 Jan 2024 18:15:52 -0600 Subject: [PATCH] almost loop --- Cargo.toml | 5 +++ src/algs.rs | 89 ++++++++++++++++++++++++++++++++++++---------------- src/lib.rs | 31 +++++++++++++++++- src/test.rs | 68 +++++++++++++++++++++++++++++++++++++++ src/types.rs | 4 +-- 5 files changed, 167 insertions(+), 30 deletions(-) create mode 100644 src/test.rs diff --git a/Cargo.toml b/Cargo.toml index 71d32b7..7c74bc2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ zeroize = { version = "1.7.0", features = ["zeroize_derive"] } rand_core = { version = "0.6.4", default-features = false } sha3 = { version = "0.10.8", default-features = false } generic-array = { version = "1.0.0", features=["const-default", "zeroize"] } +hex = "0.4.3" [features] default = ["default-rng", "slh_dsa_sha2_128s", "slh_dsa_shake_128s", "slh_dsa_sha2_128f", "slh_dsa_shake_128f", @@ -31,3 +32,7 @@ slh_dsa_sha2_256s = [] slh_dsa_shake_256s = [] slh_dsa_sha2_256f = [] slh_dsa_shake_256f = [] + + +[dev-dependencies] +rand = "0.8.5" diff --git a/src/algs.rs b/src/algs.rs index af19a31..a6c83db 100644 --- a/src/algs.rs +++ b/src/algs.rs @@ -166,6 +166,7 @@ pub(crate) fn chain( // 4: // 5: tmp ← X + //println!("cap x: {}", hex::encode(&cap_x)); let mut tmp = cap_x; // 6: @@ -190,8 +191,15 @@ pub(crate) fn chain( pub(crate) fn prf( pk_seed: &[u8], sk_seed: &[u8], adrs: &[u8], ) -> GenericArray { - shake256(&[&pk_seed, &sk_seed, &adrs]) -} + 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 { + shake256(&[&a0, &b1, &c2]) +} // NOTE ORDER pub(crate) fn tlen( @@ -224,6 +232,7 @@ 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,6 +253,7 @@ pub(crate) fn wots_pkgen( // 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)); // 7: ADRS.setChainAddress(i) adrs.set_chain_address(i); @@ -278,11 +288,11 @@ pub(crate) fn wots_pkgen( /// Input: Message `M`, secret seed `SK.seed`, public seed `PK.seed`, address `ADRS`.
/// Output: WOTS+ signature sig. #[allow(clippy::similar_names)] -pub(crate) fn wots_sign( +pub(crate) fn wots_sign( m: &[u8], sk_seed: &[u8], pk_seed: &[u8], adrs: &Adrs, -) -> WotsSig { +) -> WotsSig { let mut adrs = adrs.clone(); - let mut sig: WotsSig = WotsSig::default(); + let mut sig: WotsSig = WotsSig::default(); // 1: csum ← 0 let mut csum = 0u64; @@ -397,7 +407,7 @@ pub(crate) fn wots_pk_from_sig( adrs.set_chain_address(i as u32); // 13: tmp[i] ← chain(sig[i], msg[i], w − 1 − msg[i], PK.seed, ADRS) - tmp[i] = chain( + tmp[i] = chain::( sig.data[i].clone(), usize::try_from(msg[i]).unwrap(), crate::W as usize - 1 - msg[i] as usize, @@ -405,6 +415,7 @@ 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 } @@ -469,16 +480,19 @@ pub(crate) fn xmss_node(sk_seed, pk_seed, &adrs).0.clone() // TODO revisit (remove clone?) + let xx = wots_pkgen::(sk_seed, pk_seed, &adrs).0.clone(); // TODO revisit (remove clone?) + //println!("wots_pkgen: {}", hex::encode(&xx)); + xx //wots_pkgen // 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)?; @@ -490,7 +504,7 @@ pub(crate) fn xmss_node(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"); + } // 6: // 7: ADRS.setTypeAndClear(TREE) ▷ Compute root from WOTS+ pk and AUTH adrs.set_type_and_clear(TREE); @@ -586,7 +603,7 @@ pub(crate) fn xmss_pk_from_sig> k) % 2 == 0 { + let node_1 = if ((idx >> k) % 2) == 0 { // 12: ADRS.setTreeIndex(ADRS.getTreeIndex()/2) let tmp = adrs.get_tree_index() / 2; adrs.set_tree_index(tmp); @@ -632,7 +649,7 @@ pub(crate) fn ht_sign< LEN: ArrayLength, N: ArrayLength, >( - m: &[u8], sk_seed: &[u8], pk_seed: &[u8], idx_tree: u32, idx_leaf: u32, + m: &[u8], sk_seed: &[u8], pk_seed: &[u8], idx_tree: u64, idx_leaf: u32, ) -> Result, &'static str> { // // 1: ADRS ← toByte(0, 32) @@ -656,7 +673,7 @@ pub(crate) fn ht_sign< for j in 1..D::to_u32() { // // 8: idx_leaf ← idx_tree mod 2^{h′} ▷ h′ least significant bits of idx_tree - let idx_leaf = idx_tree % 2u32.pow(HP::to_u32()); + let idx_leaf = idx_tree % 2u64.pow(HP::to_u32()); // 9: idx_tree ← idx_tree ≫ h′ ▷ Remove least significant h′ bits from idx_tree let idx_tree = idx_tree >> HP::to_u32(); @@ -668,7 +685,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, pk_seed, &adrs)?; + sig_tmp = xmss_sign::(&root, sk_seed, idx_leaf as u32, pk_seed, &adrs)?; // 13: SIG_HT ← SIG_HT ∥ SIG_tmp sig_ht.xmss_sigs[j as usize] = sig_tmp.clone(); @@ -677,7 +694,7 @@ pub(crate) fn ht_sign< if j < (D::to_u32() - 1) { // // 15: root ← xmss_PKFromSig(idx_leaf, SIG_tmp, root, PK.seed, ADRS) - root = xmss_pk_from_sig::(idx_leaf, &sig_tmp, &root, pk_seed, &adrs); + root = xmss_pk_from_sig::(idx_leaf as u32, &sig_tmp, &root, pk_seed, &adrs); // 16: end if } @@ -696,7 +713,7 @@ pub(crate) fn ht_sign< /// HT public key `PK.root`.
/// Output: Boolean. pub(crate) fn ht_verify( - m: &[u8], sig_ht: &HtSig, pk_seed: &[u8], idx_tree: u32, idx_leaf: u32, + m: &[u8], sig_ht: &HtSig, pk_seed: &[u8], idx_tree: u64, idx_leaf: u32, pk_root: &GenericArray, ) -> bool { // @@ -712,12 +729,13 @@ pub(crate) fn ht_verify> HP::to_u32(); @@ -732,7 +750,7 @@ pub(crate) fn ht_verify( adrs.set_tree_height(j + 1); // 11: if indices[i]/2^j is even then - let node_1 = if indices[i as usize] >> j % 2 == 0 { + let node_1 = if ((indices[i as usize] >> j) % 2) == 0 { // // 12: ADRS.setTreeIndex(ADRS.getTreeIndex()/2) let tmp = adrs.get_tree_index() / 2; @@ -1000,6 +1018,7 @@ 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(); @@ -1020,6 +1039,7 @@ 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) ) @@ -1062,18 +1082,22 @@ 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 = prf(&sk.sk_prf, &opt_rand, m); + let r = prf2(&sk.sk_prf, &opt_rand, m); // 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 let index1 = (K::to_usize() * A::to_usize()).div_ceil(8); @@ -1099,7 +1123,7 @@ pub(crate) fn slh_sign_with_rng< // 17: // 18: ADRS.setTreeAddress(idx_tree) - adrs.set_tree_address(idx_tree as u32); //TODO not u32 + adrs.set_tree_address(idx_tree); // 19: ADRS.setTypeAndClear(FORS_TREE) adrs.set_type_and_clear(FORS_TREE); @@ -1107,14 +1131,21 @@ 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])); + + // 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 @@ -1122,7 +1153,7 @@ pub(crate) fn slh_sign_with_rng< &pk_fors.key, &sk.sk_seed, &sk.pk_seed, - idx_tree as u32, + idx_tree, idx_leaf as u32, )?; // 28: return SIG @@ -1168,6 +1199,7 @@ 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); @@ -1183,7 +1215,7 @@ 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) + 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} @@ -1195,7 +1227,7 @@ pub(crate) fn slh_verify< // 16: // 17: ADRS.setTreeAddress(idx_tree) ▷ Compute FORS public key - adrs.set_tree_address(idx_tree as u32); + adrs.set_tree_address(idx_tree); // 18: ADRS.setTypeAndClear(FORS_TREE) adrs.set_type_and_clear(FORS_TREE); @@ -1206,6 +1238,9 @@ 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: // 23: return ht_verify(PK_FORS, SIG_HT, PK.seed, idx_tree , idx_leaf, PK.root) @@ -1213,7 +1248,7 @@ pub(crate) fn slh_verify< &pk_fors.key, sig_ht, &pk.pk_seed, - idx_tree as u32, + idx_tree, idx_leaf as u32, &pk.pk_root, ) diff --git a/src/lib.rs b/src/lib.rs index 7311b9c..fdc10ea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,9 +11,11 @@ //! TKTK crate doc -extern crate alloc; // TODO: remove (with vecs) +extern crate alloc; +extern crate core; // TODO: remove (with vecs) mod algs; +mod test; mod traits; mod types; @@ -24,6 +26,32 @@ const W: u32 = 16; macro_rules! functionality { () => { + use rand_core::CryptoRngCore; + use crate::types::{SlhPrivateKey, SlhPublicKey, SlhDsaSig}; + use generic_array::typenum::{Prod, Sum, U2, U3}; + + /// blah + pub fn slh_keygen_with_rng( + rng: &mut impl CryptoRngCore, + ) -> Result<(SlhPrivateKey, SlhPublicKey), &'static str> { + crate::algs::slh_keygen_with_rng::, U3>, N>(rng) + } + + /// blah + 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) + } + + /// blah + pub fn slh_verify( + m: &[u8], sig: &SlhDsaSig, U3>, N>, pk: &SlhPublicKey, + ) -> bool { + crate::algs::slh_verify::, U3>, M, N>(&m, &sig, &pk) + } + #[cfg(test)] mod tests { use super::*; @@ -31,6 +59,7 @@ macro_rules! functionality { use generic_array::typenum::{Prod, Sum, U2, U3}; use rand_core::OsRng; + #[ignore] #[test] fn it_works1111() { let m = [0u8, 1, 2, 3]; diff --git a/src/test.rs b/src/test.rs new file mode 100644 index 0000000..64a3f5e --- /dev/null +++ b/src/test.rs @@ -0,0 +1,68 @@ +#[cfg(test)] +mod tests { + extern crate alloc; + use hex::decode; + + use alloc::vec::Vec; + //use rand::{Rng, SeedableRng}; + use rand_core::{CryptoRng, RngCore}; + + + struct TestRng { + data: Vec>, + } + + impl RngCore for TestRng { + fn next_u32(&mut self) -> u32 { unimplemented!() } + + fn next_u64(&mut self) -> u64 { unimplemented!() } + + fn fill_bytes(&mut self, out: &mut [u8]) { + let x = self.data.pop().expect("TestRng problem"); + out.copy_from_slice(&x) + } + + fn try_fill_bytes(&mut self, out: &mut [u8]) -> Result<(), rand_core::Error> { + self.fill_bytes(out); + Ok(()) // panic on probs is OK + } + } + + impl CryptoRng for TestRng {} + + impl TestRng { + fn new() -> Self { TestRng { data: Vec::new() } } + + fn push(&mut self, new_data: &[u8]) { + let x = new_data.to_vec(); + self.data.push(x); + } + } + + + use crate::slh_dsa_sha2_128s::{slh_keygen_with_rng, slh_sign_with_rng, slh_verify}; + + #[test] + fn vector_debug() { + let m = decode("d81c4d8d734fcbfbeade3d3f8a039faa2a2c9957e835ad55b22e75bf57bb556ac8").unwrap(); + let mut rnd = TestRng::new(); + let sk_seed = "7c9935a0b07694aa0c6d10e4db6b1add"; + let sk_prf = "2fd81a25ccb148032dcd739936737f2d"; + let pk_seed = "b505d7cfad1b497499323c8686325e47"; + let opt_rand = "33b3c07507e4201748494d832b6ee2a6"; + rnd.push(&decode(opt_rand).unwrap()); + rnd.push(&decode(pk_seed).unwrap()); + 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 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!!!"); + + 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 fe95650..cfacb10 100644 --- a/src/types.rs +++ b/src/types.rs @@ -114,7 +114,7 @@ impl Adrs { self.f7 = 0u32.to_be_bytes(); } - pub(crate) fn set_tree_address(&mut self, t: u32) { self.f1 = t.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() } // TODO: revisit 16 bytes @@ -126,5 +126,5 @@ 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].concat() } + pub(crate) fn to_bytes(&self) -> Vec { [self.f0, self.f1, self.f2, self.f3, self.f4, self.f5, self.f6, self.f7].concat() } }