1.5 hashes

This commit is contained in:
eschorn1 2024-01-25 20:55:05 -06:00
parent 402cfdd832
commit 3ff32e592a
4 changed files with 116 additions and 114 deletions

View file

@ -1,15 +1,16 @@
use generic_array::{ArrayLength, GenericArray}; use generic_array::{ArrayLength, GenericArray};
use generic_array::typenum::U33;
use rand_core::CryptoRngCore; use rand_core::CryptoRngCore;
use sha3::{ use sha3::{
digest::{ExtendableOutput, Update, XofReader}, digest::{ExtendableOutput, Update, XofReader},
Shake256, Shake256,
}; };
use crate::types::{ use crate::types::{
Adrs, ForsPk, ForsSig, HtSig, SlhDsaSig, SlhPrivateKey, SlhPublicKey, WotsPk, WotsSig, XmssSig, Adrs, ForsPk, ForsSig, HtSig, SlhDsaSig, SlhPrivateKey, SlhPublicKey, WotsPk, WotsSig, XmssSig,
}; };
use crate::types::{FORS_PRF, FORS_ROOTS, FORS_TREE, TREE, WOTS_HASH, WOTS_PK, WOTS_PRF}; use crate::types::{FORS_PRF, FORS_ROOTS, FORS_TREE, TREE, WOTS_HASH, WOTS_PK, WOTS_PRF};
/// Algorithm 1: `toInt(X, n)` on page 14. /// Algorithm 1: `toInt(X, n)` on page 14.
/// Convert a byte string to an integer. /// Convert a byte string to an integer.
/// ///
@ -116,22 +117,11 @@ pub(crate) fn base_2b(x: &[u8], b: u32, out_len: usize, baseb: &mut [u64]) {
// 14: return baseb (mutable parameter) // 14: return baseb (mutable parameter)
} }
pub(crate) fn shake256_a(input: &[&[u8]], out: &mut [u8]) {
#[must_use]
pub(crate) fn shake256<N: ArrayLength>(input: &[&[u8]]) -> GenericArray<u8, N> {
let mut hasher = Shake256::default(); let mut hasher = Shake256::default();
input.iter().for_each(|item| hasher.update(item)); input.iter().for_each(|item| hasher.update(item));
let mut reader = hasher.finalize_xof(); let mut reader = hasher.finalize_xof();
let mut result = GenericArray::default(); reader.read(out);
reader.read(&mut result);
result
}
pub(crate) fn f<N: ArrayLength>(
pk_seed: &[u8], adrs: &Adrs, tmp: &GenericArray<u8, N>,
) -> GenericArray<u8, N> {
shake256(&[&pk_seed, &adrs.to_32_bytes(), tmp])
} }
@ -171,7 +161,8 @@ pub(crate) fn chain<N: ArrayLength>(
adrs.set_hash_address(j.try_into().expect("usize->u32 fails")); // TODO: something better than expect? adrs.set_hash_address(j.try_into().expect("usize->u32 fails")); // TODO: something better than expect?
// 9: tmp ← F(PK.seed, ADRS, tmp) // 9: tmp ← F(PK.seed, ADRS, tmp)
tmp = f(pk_seed, &adrs, &tmp); //tmp = f(pk_seed, &adrs, &tmp);
shake256_a(&[pk_seed, &adrs.to_32_bytes(), &tmp.clone()], &mut tmp[..]);
// 10: end for // 10: end for
} }
@ -181,23 +172,10 @@ pub(crate) fn chain<N: ArrayLength>(
} }
#[allow(clippy::similar_names)]
pub(crate) fn prf<N: ArrayLength>(
pk_seed: &[u8], sk_seed: &[u8], adrs: &[u8],
) -> GenericArray<u8, N> {
shake256(&[&pk_seed, &adrs, &sk_seed]) // note order
} // NOTE ORDER
#[allow(clippy::similar_names)]
pub(crate) fn prf2<N: ArrayLength>(a0: &[u8], b1: &[u8], c2: &[u8]) -> GenericArray<u8, N> {
shake256(&[&a0, &b1, &c2])
} // NOTE ORDER
pub(crate) fn tlen<LEN: ArrayLength, N: ArrayLength>( pub(crate) fn tlen<LEN: ArrayLength, N: ArrayLength>(
pk_seed: &[u8], adrs: &Adrs, ml: &GenericArray<GenericArray<u8, N>, LEN>, pk_seed: &[u8], adrs: &Adrs, ml: &GenericArray<GenericArray<u8, N>, LEN>,
) -> GenericArray<u8, N> ) -> GenericArray<u8, N>
where where
{ {
let mut hasher = Shake256::default(); let mut hasher = Shake256::default();
hasher.update(pk_seed); hasher.update(pk_seed);
@ -242,7 +220,8 @@ pub(crate) fn wots_pkgen<LEN: ArrayLength, N: ArrayLength>(
sk_adrs.set_chain_address(i); sk_adrs.set_chain_address(i);
// 6: sk ← PRF(PK.seed, SK.seed, skADRS) ▷ Compute secret value for chain 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_32_bytes()); let mut sk = GenericArray::default();
shake256_a(&[pk_seed, &sk_adrs.to_32_bytes(), sk_seed], &mut sk); // Note spec swaps latter two parms
// 7: ADRS.setChainAddress(i) // 7: ADRS.setChainAddress(i)
adrs.set_chain_address(i); adrs.set_chain_address(i);
@ -333,7 +312,8 @@ pub(crate) fn wots_sign<LEN: ArrayLength, N: ArrayLength>(
sk_addrs.set_chain_address(i as u32); sk_addrs.set_chain_address(i as u32);
// 17: sk ← PRF(PK.seed, SK.seed, skADRS) ▷ Compute secret value for chain i // 17: sk ← PRF(PK.seed, SK.seed, skADRS) ▷ Compute secret value for chain i
let sk = prf(pk_seed, sk_seed, &sk_addrs.to_32_bytes()); let mut sk = GenericArray::default();
shake256_a(&[pk_seed, &sk_addrs.to_32_bytes(), sk_seed], &mut sk);
// 18: ADRS.setChainAddress(i) // 18: ADRS.setChainAddress(i)
adrs.set_chain_address(i as u32); adrs.set_chain_address(i as u32);
@ -408,7 +388,7 @@ pub(crate) fn wots_pk_from_sig<LEN: ArrayLength, N: ArrayLength>(
pk_seed, pk_seed,
&adrs, &adrs,
) )
.expect("chain broke2!"); .expect("chain broke2!");
// 14: end for // 14: end for
} }
@ -430,21 +410,6 @@ pub(crate) fn wots_pk_from_sig<LEN: ArrayLength, N: ArrayLength>(
} }
#[allow(clippy::similar_names)] // lnode and rnode
pub(crate) fn h<N: ArrayLength>(
pk_seed: &[u8], adrs: &[u8], lnode: &[u8], rnode: &[u8],
) -> GenericArray<u8, N> {
let mut hasher = Shake256::default();
[pk_seed, adrs, lnode, rnode]
.iter()
.for_each(|item| hasher.update(item));
let mut reader = hasher.finalize_xof();
let mut result = GenericArray::default();
reader.read(&mut result);
result
}
/// Algorithm 8: `xmss_node(SK.seed, i, z, PK.seed, ADRS)` on page 22. /// Algorithm 8: `xmss_node(SK.seed, i, z, PK.seed, ADRS)` on page 22.
/// Compute the root of a Merkle subtree of WOTS+ public keys. /// Compute the root of a Merkle subtree of WOTS+ public keys.
/// ///
@ -478,7 +443,7 @@ pub(crate) fn xmss_node<H: ArrayLength, HP: ArrayLength, LEN: ArrayLength, N: Ar
// 7: node ← wots_PKgen(SK.seed, PK.seed, ADRS) // 7: node ← wots_PKgen(SK.seed, PK.seed, ADRS)
wots_pkgen::<LEN, N>(sk_seed, pk_seed, &adrs).0.clone() // TODO remove clone? wots_pkgen::<LEN, N>(sk_seed, pk_seed, &adrs).0.clone() // TODO remove clone?
// 8: else // 8: else
} else { } else {
// //
// 9: lnode ← xmss_node(SK.seed, 2 * i, z 1, PK.seed, ADRS) // 9: lnode ← xmss_node(SK.seed, 2 * i, z 1, PK.seed, ADRS)
@ -497,7 +462,9 @@ pub(crate) fn xmss_node<H: ArrayLength, HP: ArrayLength, LEN: ArrayLength, N: Ar
adrs.set_tree_index(i); adrs.set_tree_index(i);
// 14: node ← H(PK.seed, ADRS, lnode ∥ rnode) // 14: node ← H(PK.seed, ADRS, lnode ∥ rnode)
h(pk_seed, &adrs.to_32_bytes(), &lnode, &rnode) let mut node = GenericArray::default();
shake256_a(&[pk_seed, &adrs.to_32_bytes(), &lnode, &rnode], &mut node);
node
// 15: end if // 15: end if
}; };
@ -590,14 +557,16 @@ pub(crate) fn xmss_pk_from_sig<HP: ArrayLength, LEN: ArrayLength, N: ArrayLength
// 11: if idx/2^k is even then // 11: if idx/2^k is even then
#[allow(clippy::if_not_else)] // Follows the algorithm as written #[allow(clippy::if_not_else)] // Follows the algorithm as written
let node_1 = if ((idx >> k) & 1) == 0 { let node_1 = if ((idx >> k) & 1) == 0 {
// //
// 12: ADRS.setTreeIndex(ADRS.getTreeIndex()/2) // 12: ADRS.setTreeIndex(ADRS.getTreeIndex()/2)
let tmp = adrs.get_tree_index() / 2; let tmp = adrs.get_tree_index() / 2;
adrs.set_tree_index(tmp); adrs.set_tree_index(tmp);
// 13: node[1] ← H(PK.seed, ADRS, node[0] ∥ AUTH[k]) // 13: node[1] ← H(PK.seed, ADRS, node[0] ∥ AUTH[k])
h(pk_seed, &adrs.to_32_bytes(), &node_0, &auth[k as usize]) let mut node_1 = GenericArray::default();
shake256_a(&[pk_seed, &adrs.to_32_bytes(), &node_0, &auth[k as usize]], &mut node_1);
node_1
// 14: else // 14: else
} else { } else {
@ -607,7 +576,9 @@ pub(crate) fn xmss_pk_from_sig<HP: ArrayLength, LEN: ArrayLength, N: ArrayLength
adrs.set_tree_index(tmp); adrs.set_tree_index(tmp);
// 16: node[1] ← H(PK.seed, ADRS, AUTH[k] ∥ node[0]) // 16: node[1] ← H(PK.seed, ADRS, AUTH[k] ∥ node[0])
h(pk_seed, &adrs.to_32_bytes(), &auth[k as usize], &node_0) let mut node_1 = GenericArray::default();
shake256_a(&[pk_seed, &adrs.to_32_bytes(), &auth[k as usize], &node_0], &mut node_1);
node_1
// 17: end if // 17: end if
}; };
@ -662,7 +633,8 @@ pub(crate) fn ht_sign<
for j in 1..D::to_u32() { for j in 1..D::to_u32() {
// //
// 8: idx_leaf ← idx_tree mod 2^{h} ▷ h least significant bits of idx_tree // 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())).map_err(|_| "Alg11: oversized idx leaf")?; let idx_leaf = u32::try_from(idx_tree % 2u64.pow(HP::to_u32()))
.map_err(|_| "Alg11: oversized idx leaf")?;
// 9: idx_tree ← idx_tree ≫ h ▷ Remove least significant h bits from idx_tree // 9: idx_tree ← idx_tree ≫ h ▷ Remove least significant h bits from idx_tree
idx_tree >>= HP::to_u32(); idx_tree >>= HP::to_u32();
@ -726,7 +698,9 @@ pub(crate) fn ht_verify<D: ArrayLength, HP: ArrayLength, LEN: ArrayLength, N: Ar
// //
// 7: idx_leaf ← idx_tree mod 2^{h} ▷ h least significant bits of idx_tree // 7: idx_leaf ← idx_tree mod 2^{h} ▷ h least significant bits of idx_tree
let idx_leaf = u32::try_from(idx_tree % 2u64.pow(HP::to_u32())); let idx_leaf = u32::try_from(idx_tree % 2u64.pow(HP::to_u32()));
if idx_leaf.is_err() {return false}; if idx_leaf.is_err() {
return false;
};
let idx_leaf = idx_leaf.unwrap(); let idx_leaf = idx_leaf.unwrap();
// 8: idx_tree ← idx_tree ≫ h ▷ Remove least significant h bits from idx_tree // 8: idx_tree ← idx_tree ≫ h ▷ Remove least significant h bits from idx_tree
@ -778,7 +752,9 @@ pub(crate) fn fors_sk_gen<N: ArrayLength>(
sk_adrs.set_tree_index(idx); sk_adrs.set_tree_index(idx);
// 5: return PRF(PK.seed, SK.seed, skADRS) // 5: return PRF(PK.seed, SK.seed, skADRS)
prf(pk_seed, sk_seed, &sk_adrs.to_32_bytes()) let mut res = GenericArray::default();
shake256_a(&[pk_seed, &sk_adrs.to_32_bytes(), sk_seed], &mut res); // Note the spec swaps latter two parms
res
} }
@ -807,7 +783,7 @@ pub(crate) fn fors_node<A: ArrayLength, K: ArrayLength, N: ArrayLength>(
let node = if z == 0 { let node = if z == 0 {
// //
// 5: sk ← fors_SKgen(SK.seed, PK.seed, ADRS, i) // 5: sk ← fors_SKgen(SK.seed, PK.seed, ADRS, i)
let sk = fors_sk_gen(sk_seed, pk_seed, &adrs, i); let sk: GenericArray<u8, N> = fors_sk_gen(sk_seed, pk_seed, &adrs, i);
// 6: ADRS.setTreeHeight(0) // 6: ADRS.setTreeHeight(0)
adrs.set_tree_height(0); adrs.set_tree_height(0);
@ -816,7 +792,9 @@ pub(crate) fn fors_node<A: ArrayLength, K: ArrayLength, N: ArrayLength>(
adrs.set_tree_index(i); adrs.set_tree_index(i);
// 8: node ← F(PK.seed, ADRS, sk) // 8: node ← F(PK.seed, ADRS, sk)
f(pk_seed, &adrs, &sk) let mut node = GenericArray::default();
shake256_a(&[pk_seed, &adrs.to_32_bytes(), &sk], &mut node);
node
// 9: else // 9: else
} else { } else {
@ -834,7 +812,9 @@ pub(crate) fn fors_node<A: ArrayLength, K: ArrayLength, N: ArrayLength>(
adrs.set_tree_index(i); adrs.set_tree_index(i);
// 14: node ← H(PK.seed, ADRS, lnode ∥ rnode) // 14: node ← H(PK.seed, ADRS, lnode ∥ rnode)
h(pk_seed, &adrs.to_32_bytes(), &lnode, &rnode) let mut node = GenericArray::default();
shake256_a(&[pk_seed, &adrs.to_32_bytes(), &lnode, &rnode], &mut node);
node
// 15: end if // 15: end if
}; };
@ -933,7 +913,8 @@ pub(crate) fn fors_pk_from_sig<A: ArrayLength, K: ArrayLength, N: ArrayLength>(
adrs.set_tree_index(i * 2u32.pow(A::to_u32()) + indices[i as usize] as u32); adrs.set_tree_index(i * 2u32.pow(A::to_u32()) + indices[i as usize] as u32);
// 6: node[0] ← F(PK.seed, ADRS, sk) // 6: node[0] ← F(PK.seed, ADRS, sk)
let mut node_0 = f(pk_seed, &adrs, &sk); let mut node_0 = GenericArray::default();
shake256_a(&[pk_seed, &adrs.to_32_bytes(), &sk], &mut node_0);
// 7: // 7:
// 8: auth ← SIGFORS.getAUTH(i) ▷ SIGFORS [(i · (a + 1) + 1) · n : (i + 1) · (a + 1) · n] // 8: auth ← SIGFORS.getAUTH(i) ▷ SIGFORS [(i · (a + 1) + 1) · n : (i + 1) · (a + 1) · n]
@ -953,7 +934,9 @@ pub(crate) fn fors_pk_from_sig<A: ArrayLength, K: ArrayLength, N: ArrayLength>(
adrs.set_tree_index(tmp); adrs.set_tree_index(tmp);
// 13: node[1] ← H(PK.seed, ADRS, node[0] ∥ auth[j]) // 13: node[1] ← H(PK.seed, ADRS, node[0] ∥ auth[j])
h(pk_seed, &adrs.to_32_bytes(), &node_0, &auth.tree[j as usize]) let mut node_1 = GenericArray::default();
shake256_a(&[pk_seed, &adrs.to_32_bytes(), &node_0, &auth.tree[j as usize]], &mut node_1);
node_1
// 14: else // 14: else
} else { } else {
@ -963,7 +946,9 @@ pub(crate) fn fors_pk_from_sig<A: ArrayLength, K: ArrayLength, N: ArrayLength>(
adrs.set_tree_index(tmp); adrs.set_tree_index(tmp);
// 16: node[1] ← H(PK.seed, ADRS, auth[j] ∥ node[0]) // 16: node[1] ← H(PK.seed, ADRS, auth[j] ∥ node[0])
h(pk_seed, &adrs.to_32_bytes(), &auth.tree[j as usize], &node_0) let mut node_1 = GenericArray::default();
shake256_a(&[pk_seed, &adrs.to_32_bytes(), &auth.tree[j as usize], &node_0], &mut node_1);
node_1
// 17: end if // 17: end if
}; };
@ -990,7 +975,13 @@ pub(crate) fn fors_pk_from_sig<A: ArrayLength, K: ArrayLength, N: ArrayLength>(
fors_pk_adrs.set_key_pair_address(adrs.get_key_pair_address()); fors_pk_adrs.set_key_pair_address(adrs.get_key_pair_address());
// 25: pk ← Tk(PK.seed, forspkADRS, root) // 25: pk ← Tk(PK.seed, forspkADRS, root)
let pk = tlen(pk_seed, &fors_pk_adrs, &root); let mut pk = GenericArray::default(); // TODO: UGLY UGLY UGLY!!
let mut root_refs: GenericArray<&[u8], U33> = GenericArray::default();
root_refs[0] = &pk_seed;
let binding = fors_pk_adrs.to_32_bytes();
root_refs[1] = &binding;
root.iter().enumerate().for_each(|(a, b)| root_refs[a + 2] = b);
shake256_a(&root_refs[0..K::to_usize() + 2], &mut pk);
// 26: return pk; // 26: return pk;
ForsPk { key: pk } ForsPk { key: pk }
@ -1080,7 +1071,8 @@ pub(crate) fn slh_sign_with_rng<
} }
// 7: R ← PRF_msg(SK.prf, opt_rand, M) ▷ Generate randomizer // 7: R ← PRF_msg(SK.prf, opt_rand, M) ▷ Generate randomizer
let r = prf2(&sk.sk_prf, &opt_rand, m); let mut r = GenericArray::default();
shake256_a(&[&sk.sk_prf, &opt_rand, m], &mut r);
// 8: SIG ← R // 8: SIG ← R
@ -1089,7 +1081,8 @@ pub(crate) fn slh_sign_with_rng<
// 9: // 9:
// 10: digest ← H_msg(R, PK.seed, PK.root, M) ▷ Compute message digest // 10: digest ← H_msg(R, PK.seed, PK.root, M) ▷ Compute message digest
let digest = h::<M>(&r, &sk.pk_seed, &sk.pk_root, m); let mut digest: generic_array::GenericArray<u8, M> = GenericArray::default();
shake256_a(&[&r, &sk.pk_seed, &sk.pk_root, m], &mut digest);
// 11: md ← digest[0 : ceil(k·a/8)] ▷ first ceil(k·a/8) bytes // 11: md ← digest[0 : ceil(k·a/8)] ▷ first ceil(k·a/8) bytes
@ -1169,7 +1162,7 @@ pub(crate) fn slh_verify<
// 1: if |SIG| != (1 + k(1 + a) + h + d · len) · n then // 1: if |SIG| != (1 + k(1 + a) + h + d · len) · n then
// 2: return false // 2: return false
// 3: end if // 3: end if
// TODO: THIS FUNCTION PROBABLY WANTS A BYTE ARRAY SIGNATURE, THEN DESERIALIZE (??) // The above size is performed in the wrapper/adapter deserialize function
// 4: ADRS ← toByte(0, 32) // 4: ADRS ← toByte(0, 32)
let mut adrs = Adrs::default(); let mut adrs = Adrs::default();
@ -1185,7 +1178,8 @@ pub(crate) fn slh_verify<
// 8: // 8:
// 9: digest ← Hmsg(R, PK.seed, PK.root, M) ▷ Compute message digest // 9: digest ← Hmsg(R, PK.seed, PK.root, M) ▷ Compute message digest
let digest = h::<M>(r, &pk.pk_seed, &pk.pk_root, m); let mut digest: generic_array::GenericArray<u8, M> = GenericArray::default();
shake256_a(&[&r, &pk.pk_seed, &pk.pk_root, m], &mut digest);
// 10: md ← digest[0 : ceil(k·a/8)] ▷ first ceil(k·a/8) bytes // 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); let index1 = (K::to_usize() * A::to_usize()).div_ceil(8);

View file

@ -3,14 +3,12 @@
#![deny(warnings)] #![deny(warnings)]
#![deny(missing_docs)] #![deny(missing_docs)]
// TODO // TODO
// 1. Get one instance working (or at least not erroring) // 1. General clean-up
// 3. revisit/clean hash functions // 2. revisit/clean hash functions
// 3. Doc, of course!
//! TKTK crate doc //! TKTK crate doc
//extern crate alloc;
//extern crate core; // TODO: remove (with vecs)
mod algs; mod algs;
mod test; mod test;
mod traits; mod traits;
@ -30,7 +28,6 @@ macro_rules! functionality {
/// blah /// blah
/// # Errors /// # Errors
///
pub fn slh_keygen_with_rng( pub fn slh_keygen_with_rng(
rng: &mut impl CryptoRngCore, rng: &mut impl CryptoRngCore,
) -> Result<(SlhPrivateKey<N>, SlhPublicKey<N>), &'static str> { ) -> Result<(SlhPrivateKey<N>, SlhPublicKey<N>), &'static str> {
@ -39,20 +36,19 @@ macro_rules! functionality {
/// blah /// blah
/// # Errors /// # Errors
///
pub fn slh_sign_with_rng( pub fn slh_sign_with_rng(
rng: &mut impl CryptoRngCore, m: &[u8], sk: &SlhPrivateKey<N>, randomize: bool, rng: &mut impl CryptoRngCore, m: &[u8], sk: &SlhPrivateKey<N>, randomize: bool,
) -> Result<SlhDsaSig<A, D, HP, K, Sum<Prod<U2, N>, U3>, N>, &'static str> { ) -> Result<[u8; SIG_LEN], &'static str> {
crate::algs::slh_sign_with_rng::<A, D, H, HP, K, Sum<Prod<U2, N>, U3>, M, N>( let sig = crate::algs::slh_sign_with_rng::<A, D, H, HP, K, Sum<Prod<U2, N>, U3>, M, N>(rng, &m, &sk, randomize);
rng, &m, &sk, randomize, sig.map(|s| s.deserialize())
)
} }
/// blah /// blah
#[must_use] #[must_use]
pub fn slh_verify( pub fn slh_verify(
m: &[u8], sig: &SlhDsaSig<A, D, HP, K, Sum<Prod<U2, N>, U3>, N>, pk: &SlhPublicKey<N>, m: &[u8], sig_bytes: &[u8; SIG_LEN], pk: &SlhPublicKey<N>
) -> bool { ) -> bool {
let sig = SlhDsaSig::<A, D, HP, K, Sum<Prod<U2, N>, U3>, N>::serialize(sig_bytes);
crate::algs::slh_verify::<A, D, H, HP, K, Sum<Prod<U2, N>, U3>, M, N>(&m, &sig, &pk) crate::algs::slh_verify::<A, D, H, HP, K, Sum<Prod<U2, N>, U3>, M, N>(&m, &sig, &pk)
} }
@ -71,9 +67,9 @@ macro_rules! functionality {
let sig = slh_sign_with_rng(&mut rng, &message, &sk, false).unwrap(); let sig = slh_sign_with_rng(&mut rng, &message, &sk, false).unwrap();
let result = slh_verify(&message, &sig, &pk); let result = slh_verify(&message, &sig, &pk);
assert_eq!(result, true, "Signature failed to verify"); assert_eq!(result, true, "Signature failed to verify");
message[3] = i + 1 as u8; message[3] = (i + 1) as u8;
let result = slh_verify(&message, &sig, &pk); let result = slh_verify(&message, &sig, &pk);
assert_eq!(result, false, "Signature should not have verifed"); assert_eq!(result, false, "Signature should not have verified");
} }
} }
} }
@ -93,7 +89,7 @@ pub mod slh_dsa_sha2_128s {
type K = U14; type K = U14;
type M = U30; type M = U30;
//const PK_LEN: usize = 32; //const PK_LEN: usize = 32;
//const SIG_LEN: usize = 7856; const SIG_LEN: usize = 7856;
//const SK_LEN: usize = 0000; //const SK_LEN: usize = 0000;
functionality!(); functionality!();

File diff suppressed because one or more lines are too long

View file

@ -26,8 +26,9 @@ impl<
N: ArrayLength, N: ArrayLength,
> SlhDsaSig<A, D, HP, K, LEN, N> > SlhDsaSig<A, D, HP, K, LEN, N>
{ {
pub fn deser(self, out: &mut [u8]) { pub fn deserialize<const SIG_LEN: usize>(self) -> [u8; SIG_LEN] {
assert_eq!( let mut out = [0u8; SIG_LEN];
debug_assert_eq!(
out.len(), out.len(),
N::to_usize() + // randomness N::to_usize() + // randomness
N::to_usize() * K::to_usize() + K::to_usize() * A::to_usize() * N::to_usize() + // ForsSig N::to_usize() * K::to_usize() + K::to_usize() * A::to_usize() * N::to_usize() + // ForsSig
@ -35,10 +36,6 @@ impl<
); );
out[0..N::to_usize()].copy_from_slice(&self.randomness); out[0..N::to_usize()].copy_from_slice(&self.randomness);
let mut start = N::to_usize(); 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 k in 0..K::to_usize() { for k in 0..K::to_usize() {
out[start..(start + N::to_usize())] out[start..(start + N::to_usize())]
.copy_from_slice(&self.fors_sig.private_key_value[k]); .copy_from_slice(&self.fors_sig.private_key_value[k]);
@ -62,9 +59,47 @@ impl<
} }
} }
debug_assert_eq!(start, out.len()); debug_assert_eq!(start, out.len());
out
}
pub 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())
);
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();
}
}
for d in 0..D::to_usize() {
for len in 0..LEN::to_usize() {
output.ht_sig.xmss_sigs[d].sig_wots.data[len]
.copy_from_slice(&bytes[start..(start + N::to_usize())]);
start += N::to_usize();
}
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();
}
}
debug_assert_eq!(start, bytes.len());
output
} }
} }
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)] #[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
pub struct SlhPublicKey<N: ArrayLength> { pub struct SlhPublicKey<N: ArrayLength> {
pub(crate) pk_seed: GenericArray<u8, N>, pub(crate) pk_seed: GenericArray<u8, N>,