use crate::hashers::Hashers;
use crate::types::{Adrs, WotsSig, XmssSig, TREE, WOTS_HASH};
use crate::wots;
#[allow(clippy::similar_names, clippy::let_and_return)] pub(crate) fn xmss_node<
const H: usize,
const HP: usize,
const K: usize,
const LEN: usize,
const M: usize,
const N: usize,
>(
hashers: &Hashers<K, LEN, M, N>, sk_seed: &[u8], i: u32, z: u32, pk_seed: &[u8], adrs: &Adrs,
) -> [u8; N] {
let mut adrs = adrs.clone();
let node = if z == 0 {
adrs.set_type_and_clear(WOTS_HASH);
adrs.set_key_pair_address(i);
wots::wots_pkgen::<K, LEN, M, N>(hashers, sk_seed, pk_seed, &adrs).0
} else {
let lnode =
xmss_node::<H, HP, K, LEN, M, N>(hashers, sk_seed, 2 * i, z - 1, pk_seed, &adrs);
let rnode =
xmss_node::<H, HP, K, LEN, M, N>(hashers, sk_seed, 2 * i + 1, z - 1, pk_seed, &adrs);
adrs.set_type_and_clear(TREE);
adrs.set_tree_height(z);
adrs.set_tree_index(i);
(hashers.h)(pk_seed, &adrs, &lnode, &rnode)
};
node
}
#[allow(clippy::similar_names)] pub(crate) fn xmss_sign<
const H: usize,
const HP: usize,
const K: usize,
const LEN: usize,
const M: usize,
const N: usize,
>(
hashers: &Hashers<K, LEN, M, N>, m: &[u8], sk_seed: &[u8], idx: u32, pk_seed: &[u8],
adrs: &Adrs,
) -> XmssSig<HP, LEN, N> {
let hp32 = u32::try_from(HP).unwrap();
let mut adrs = adrs.clone();
let mut sig_xmss = XmssSig {
sig_wots: WotsSig { data: [[0u8; N]; LEN] },
auth: [[0u8; N]; HP],
};
for j in 0..hp32 {
let k = (idx >> j) ^ 1;
sig_xmss.auth[j as usize] =
xmss_node::<H, HP, K, LEN, M, N>(hashers, sk_seed, k, j, pk_seed, &adrs);
}
adrs.set_type_and_clear(WOTS_HASH);
adrs.set_key_pair_address(idx);
sig_xmss.sig_wots = wots::wots_sign::<K, LEN, M, N>(hashers, m, sk_seed, pk_seed, &adrs);
sig_xmss
}
pub(crate) fn xmss_pk_from_sig<
const HP: usize,
const K: usize,
const LEN: usize,
const M: usize,
const N: usize,
>(
hashers: &Hashers<K, LEN, M, N>, idx: u32, sig_xmss: &XmssSig<HP, LEN, N>, m: &[u8],
pk_seed: &[u8], adrs: &Adrs,
) -> [u8; N] {
let hp32 = u32::try_from(HP).unwrap();
let mut adrs = adrs.clone();
adrs.set_type_and_clear(WOTS_HASH);
adrs.set_key_pair_address(idx);
let sig = sig_xmss.get_wots_sig();
let auth = sig_xmss.get_xmss_auth();
let mut node_0 = wots::wots_pk_from_sig::<K, LEN, M, N>(hashers, sig, m, pk_seed, &adrs).0;
adrs.set_type_and_clear(TREE);
adrs.set_tree_index(idx);
for k in 0..hp32 {
adrs.set_tree_height(k + 1);
let node_1 = if ((idx >> k) & 1) == 0 {
let tmp = adrs.get_tree_index() / 2;
adrs.set_tree_index(tmp);
(hashers.h)(pk_seed, &adrs, &node_0, &auth[k as usize])
} else {
let tmp = (adrs.get_tree_index() - 1) / 2;
adrs.set_tree_index(tmp);
(hashers.h)(pk_seed, &adrs, &auth[k as usize], &node_0)
};
node_0 = node_1;
}
node_0
}