use super::address::Adrs;
use super::params::Params;
use super::xmss;
use alloc::vec::Vec;
pub fn ht_sign<P: Params>(m: &[u8], sk_seed: &[u8], pk_seed: &[u8], idx_tree: u64, idx_leaf: u32) -> Vec<u8> {
let xmss_sig_len = (P::LEN + P::H_PRIME) * P::N;
let mut sig_ht = alloc::vec![0u8; P::D * xmss_sig_len];
ht_sign_into::<P>(m, sk_seed, pk_seed, idx_tree, idx_leaf, &mut sig_ht);
sig_ht
}
pub fn ht_sign_into<P: Params>(m: &[u8], sk_seed: &[u8], pk_seed: &[u8], idx_tree: u64, idx_leaf: u32, out: &mut [u8]) {
let xmss_sig_len = (P::LEN + P::H_PRIME) * P::N;
debug_assert!(out.len() >= P::D * xmss_sig_len);
let mut adrs = Adrs::new();
adrs.set_tree_address(idx_tree);
adrs.set_layer_address(0);
{
let slot = &mut out[..xmss_sig_len];
xmss::xmss_sign_into::<P>(m, sk_seed, idx_leaf, pk_seed, &mut adrs, slot);
}
let mut root = xmss::xmss_pk_from_sig::<P>(idx_leaf, &out[..xmss_sig_len], m, pk_seed, &mut adrs);
let mut current_idx_tree = idx_tree;
for j in 1..P::D {
let current_idx_leaf = (current_idx_tree & ((1u64 << P::H_PRIME) - 1)) as u32;
current_idx_tree >>= P::H_PRIME;
adrs.set_layer_address(j as u32);
adrs.set_tree_address(current_idx_tree);
let slot_start = j * xmss_sig_len;
let slot_end = slot_start + xmss_sig_len;
{
let slot = &mut out[slot_start..slot_end];
xmss::xmss_sign_into::<P>(&root, sk_seed, current_idx_leaf, pk_seed, &mut adrs, slot);
}
if j < P::D - 1 {
root = xmss::xmss_pk_from_sig::<P>(current_idx_leaf, &out[slot_start..slot_end], &root, pk_seed, &mut adrs);
}
}
}
pub fn ht_verify<P: Params>(
m: &[u8],
sig_ht: &[u8],
pk_seed: &[u8],
idx_tree: u64,
idx_leaf: u32,
pk_root: &[u8],
) -> bool {
let mut adrs = Adrs::new();
adrs.set_tree_address(idx_tree);
let xmss_sig_len = (P::LEN + P::H_PRIME) * P::N;
adrs.set_layer_address(0);
let sig_tmp = &sig_ht[..xmss_sig_len];
let mut node = xmss::xmss_pk_from_sig::<P>(idx_leaf, sig_tmp, m, pk_seed, &mut adrs);
let mut current_idx_tree = idx_tree;
for j in 1..P::D {
let current_idx_leaf = (current_idx_tree & ((1u64 << P::H_PRIME) - 1)) as u32;
current_idx_tree >>= P::H_PRIME;
adrs.set_layer_address(j as u32);
adrs.set_tree_address(current_idx_tree);
let sig_tmp = &sig_ht[j * xmss_sig_len..(j + 1) * xmss_sig_len];
node = xmss::xmss_pk_from_sig::<P>(current_idx_leaf, sig_tmp, &node, pk_seed, &mut adrs);
}
node == pk_root
}