mirror of
https://github.com/saymrwulf/fips205-source.git
synced 2026-09-04 20:03:45 +00:00
cc jan15
This commit is contained in:
parent
1e584bef6c
commit
753eabe836
3 changed files with 276 additions and 116 deletions
218
src/algs.rs
218
src/algs.rs
|
|
@ -7,10 +7,11 @@ use sha3::{
|
||||||
Shake256,
|
Shake256,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::types::{Adrs, WotsPk, WotsSig};
|
use crate::types::{Adrs, HtSig, WotsPk, WotsSig, XmssSig};
|
||||||
use crate::types::{TREE, WOTS_HASH, WOTS_PK, WOTS_PRF};
|
use crate::types::{TREE, WOTS_HASH, WOTS_PK, WOTS_PRF};
|
||||||
use crate::Context;
|
use crate::Context;
|
||||||
|
|
||||||
|
|
||||||
/// 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.
|
||||||
///
|
///
|
||||||
|
|
@ -228,6 +229,7 @@ pub(crate) fn wots_pkgen<LEN: ArrayLength, N: ArrayLength>(
|
||||||
sk_adrs.set_key_pair_address(adrs.get_key_pair_address());
|
sk_adrs.set_key_pair_address(adrs.get_key_pair_address());
|
||||||
|
|
||||||
// 4: for i from 0 to len − 1 do
|
// 4: for i from 0 to len − 1 do
|
||||||
|
//#[allow(clippy::cast_possible_truncation)] // steps 5 and 7
|
||||||
for i in 0..context.len1 {
|
for i in 0..context.len1 {
|
||||||
//
|
//
|
||||||
// 5: skADRS.setChainAddress(i)
|
// 5: skADRS.setChainAddress(i)
|
||||||
|
|
@ -240,7 +242,8 @@ pub(crate) fn wots_pkgen<LEN: ArrayLength, N: ArrayLength>(
|
||||||
adrs.set_chain_address(i);
|
adrs.set_chain_address(i);
|
||||||
|
|
||||||
// 8: tmp[i] ← chain(sk, 0, w − 1, PK.seed, ADRS) ▷ Compute public value for chain i
|
// 8: tmp[i] ← chain(sk, 0, w − 1, PK.seed, ADRS) ▷ Compute public value for chain i
|
||||||
tmp[i] = chain(context, sk, 0, context.w - 1, pk_seed, &adrs).expect("chain broek!");
|
tmp[i as usize] =
|
||||||
|
chain(context, sk, 0, context.w - 1, pk_seed, &adrs).expect("chain broek!");
|
||||||
|
|
||||||
// 9: end for
|
// 9: end for
|
||||||
}
|
}
|
||||||
|
|
@ -269,9 +272,9 @@ pub(crate) fn wots_pkgen<LEN: ArrayLength, N: ArrayLength>(
|
||||||
/// Output: WOTS+ signature sig.
|
/// Output: WOTS+ signature sig.
|
||||||
#[allow(clippy::similar_names)]
|
#[allow(clippy::similar_names)]
|
||||||
pub(crate) fn wots_sign<N: ArrayLength, LEN: ArrayLength>(
|
pub(crate) fn wots_sign<N: ArrayLength, LEN: ArrayLength>(
|
||||||
context: &Context, m: &[u8], sk_seed: &[u8], pk_seed: &[u8], adrs: Adrs,
|
context: &Context, m: &[u8], sk_seed: &[u8], pk_seed: &[u8], adrs: &Adrs,
|
||||||
) -> WotsSig<N, LEN> {
|
) -> WotsSig<N, LEN> {
|
||||||
let mut adrs = adrs;
|
let mut adrs = adrs.clone();
|
||||||
let mut sig: WotsSig<N, LEN> = WotsSig::default();
|
let mut sig: WotsSig<N, LEN> = WotsSig::default();
|
||||||
|
|
||||||
// 1: csum ← 0
|
// 1: csum ← 0
|
||||||
|
|
@ -279,11 +282,11 @@ pub(crate) fn wots_sign<N: ArrayLength, LEN: ArrayLength>(
|
||||||
|
|
||||||
// 2:
|
// 2:
|
||||||
// 3: msg ← base_2b(M, lgw, len1) ▷ Convert message to base w
|
// 3: msg ← base_2b(M, lgw, len1) ▷ Convert message to base w
|
||||||
let mut msg = base_2b(m, context.lgw, context.len1);
|
let mut msg = base_2b(m, context.lgw, context.len1 as usize);
|
||||||
|
|
||||||
// 4:
|
// 4:
|
||||||
// 5: for i from 0 to len1 − 1 do ▷ Compute checksum
|
// 5: for i from 0 to len1 − 1 do ▷ Compute checksum
|
||||||
for item in msg.iter().take(context.len1) {
|
for item in msg.iter().take(context.len1 as usize) {
|
||||||
//
|
//
|
||||||
// 6: csum ← csum + w − 1 − msg[i]
|
// 6: csum ← csum + w − 1 − msg[i]
|
||||||
csum += context.w as u64 - 1 - item;
|
csum += context.w as u64 - 1 - item;
|
||||||
|
|
@ -313,17 +316,17 @@ pub(crate) fn wots_sign<N: ArrayLength, LEN: ArrayLength>(
|
||||||
sk_addrs.set_key_pair_address(adrs.get_key_pair_address());
|
sk_addrs.set_key_pair_address(adrs.get_key_pair_address());
|
||||||
|
|
||||||
// 15: for i from 0 to len − 1 do
|
// 15: for i from 0 to len − 1 do
|
||||||
#[allow(clippy::cast_possible_truncation)] // step 19
|
#[allow(clippy::cast_possible_truncation)] // step 18/19
|
||||||
for (i, item) in msg.iter().enumerate().take(context.len) {
|
for (i, item) in msg.iter().enumerate().take(context.len) {
|
||||||
//
|
//
|
||||||
// 16: skADRS.setChainAddress(i)
|
// 16: skADRS.setChainAddress(i)
|
||||||
sk_addrs.set_chain_address(i);
|
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);
|
let sk = prf(pk_seed, sk_seed, &sk_addrs);
|
||||||
|
|
||||||
// 18: ADRS.setChainAddress(i)
|
// 18: ADRS.setChainAddress(i)
|
||||||
adrs.set_chain_address(i);
|
adrs.set_chain_address(i as u32);
|
||||||
|
|
||||||
// 19: sig[i] ← chain(sk, 0, msg[i], PK.seed, ADRS) ▷ Compute signature value for chain i
|
// 19: sig[i] ← chain(sk, 0, msg[i], PK.seed, ADRS) ▷ Compute signature value for chain i
|
||||||
sig.data[i] = chain(context, sk, 0, *item as usize, pk_seed, &adrs).unwrap();
|
sig.data[i] = chain(context, sk, 0, *item as usize, pk_seed, &adrs).unwrap();
|
||||||
|
|
@ -352,11 +355,11 @@ pub(crate) fn wots_pk_from_sig<LEN: ArrayLength, N: ArrayLength>(
|
||||||
|
|
||||||
// 2:
|
// 2:
|
||||||
// 3: msg ← base_2b (M, lgw , len1 ) ▷ Convert message to base w
|
// 3: msg ← base_2b (M, lgw , len1 ) ▷ Convert message to base w
|
||||||
let mut msg = base_2b(m, context.lgw, context.len1);
|
let mut msg = base_2b(m, context.lgw, context.len1 as usize);
|
||||||
|
|
||||||
// 4:
|
// 4:
|
||||||
// 5: for i from 0 to len1 − 1 do ▷ Compute checksum
|
// 5: for i from 0 to len1 − 1 do ▷ Compute checksum
|
||||||
for item in msg.iter().take(context.len1) {
|
for item in msg.iter().take(context.len1 as usize) {
|
||||||
//
|
//
|
||||||
// 6: csum ← csum + w − 1 − msg[i]
|
// 6: csum ← csum + w − 1 − msg[i]
|
||||||
csum += context.w as u64 - 1 - item;
|
csum += context.w as u64 - 1 - item;
|
||||||
|
|
@ -376,17 +379,18 @@ pub(crate) fn wots_pk_from_sig<LEN: ArrayLength, N: ArrayLength>(
|
||||||
));
|
));
|
||||||
|
|
||||||
// 11: for i from 0 to len − 1 do
|
// 11: for i from 0 to len − 1 do
|
||||||
|
#[allow(clippy::cast_possible_truncation)] // steps 12 and 13
|
||||||
for i in 0..context.len {
|
for i in 0..context.len {
|
||||||
//
|
//
|
||||||
// 12: ADRS.setChainAddress(i)
|
// 12: ADRS.setChainAddress(i)
|
||||||
adrs.set_chain_address(i);
|
adrs.set_chain_address(i as u32);
|
||||||
|
|
||||||
// 13: tmp[i] ← chain(sig[i], msg[i], w − 1 − msg[i], PK.seed, ADRS)
|
// 13: tmp[i] ← chain(sig[i], msg[i], w − 1 − msg[i], PK.seed, ADRS)
|
||||||
tmp[i] = chain(
|
tmp[i] = chain(
|
||||||
context,
|
context,
|
||||||
sig.data[i].clone(),
|
sig.data[i].clone(),
|
||||||
usize::try_from(msg[i]).unwrap(),
|
usize::try_from(msg[i]).unwrap(),
|
||||||
context.w - 1 - usize::try_from(msg[i]).unwrap(),
|
context.w - 1 - msg[i] as usize,
|
||||||
pk_seed,
|
pk_seed,
|
||||||
&adrs,
|
&adrs,
|
||||||
)
|
)
|
||||||
|
|
@ -411,6 +415,7 @@ pub(crate) fn wots_pk_from_sig<LEN: ArrayLength, N: ArrayLength>(
|
||||||
WotsPk(pk)
|
WotsPk(pk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[allow(clippy::similar_names)] // lnode and rnode
|
#[allow(clippy::similar_names)] // lnode and rnode
|
||||||
pub(crate) fn h<N: ArrayLength>(
|
pub(crate) fn h<N: ArrayLength>(
|
||||||
pk_seed: &[u8], adrs: &Adrs, lnode: &[u8], rnode: &[u8],
|
pk_seed: &[u8], adrs: &Adrs, lnode: &[u8], rnode: &[u8],
|
||||||
|
|
@ -435,14 +440,14 @@ pub(crate) fn h<N: ArrayLength>(
|
||||||
#[allow(clippy::similar_names)] // sk_seed and pk_seed
|
#[allow(clippy::similar_names)] // sk_seed and pk_seed
|
||||||
pub(crate) fn xmss_node<LEN: ArrayLength, N: ArrayLength>(
|
pub(crate) fn xmss_node<LEN: ArrayLength, N: ArrayLength>(
|
||||||
context: &Context, sk_seed: &[u8], i: u32, z: u32, pk_seed: &[u8], adrs: &Adrs,
|
context: &Context, sk_seed: &[u8], i: u32, z: u32, pk_seed: &[u8], adrs: &Adrs,
|
||||||
) -> Option<GenericArray<u8, N>> {
|
) -> Result<GenericArray<u8, N>, &'static str> {
|
||||||
let mut adrs = adrs.clone();
|
let mut adrs = adrs.clone();
|
||||||
|
|
||||||
// 1: if z > h′ or i ≥ 2^{h −z} then
|
// 1: if z > h′ or i ≥ 2^{h −z} then
|
||||||
if (z > context.h_prime) | (i >= 2u32.pow(context.h - z)) {
|
if (z > context.h_prime) | (i >= 2u32.pow(context.h - z)) {
|
||||||
//
|
//
|
||||||
// 2: return NULL
|
// 2: return NULL
|
||||||
return None;
|
return Err("Alg8: fail");
|
||||||
|
|
||||||
// 3: end if
|
// 3: end if
|
||||||
}
|
}
|
||||||
|
|
@ -454,7 +459,7 @@ pub(crate) fn xmss_node<LEN: ArrayLength, N: ArrayLength>(
|
||||||
adrs.set_type_and_clear(WOTS_HASH);
|
adrs.set_type_and_clear(WOTS_HASH);
|
||||||
|
|
||||||
// 6: ADRS.setKeyPairAddress(i)
|
// 6: ADRS.setKeyPairAddress(i)
|
||||||
adrs.set_key_pair_address(i.to_be_bytes());
|
adrs.set_key_pair_address(i);
|
||||||
|
|
||||||
// 7: node ← wots_PKgen(SK.seed, PK.seed, ADRS)
|
// 7: node ← wots_PKgen(SK.seed, PK.seed, ADRS)
|
||||||
wots_pkgen::<LEN, N>(context, sk_seed, pk_seed, &adrs)
|
wots_pkgen::<LEN, N>(context, sk_seed, pk_seed, &adrs)
|
||||||
|
|
@ -486,7 +491,7 @@ pub(crate) fn xmss_node<LEN: ArrayLength, N: ArrayLength>(
|
||||||
};
|
};
|
||||||
|
|
||||||
// 16: return node
|
// 16: return node
|
||||||
Some(node)
|
Ok(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -495,18 +500,41 @@ pub(crate) fn xmss_node<LEN: ArrayLength, N: ArrayLength>(
|
||||||
///
|
///
|
||||||
/// Input: n-byte message `M`, secret seed `SK.seed`, index `idx`, public seed `PK.seed`, address `ADRS`. <br>
|
/// Input: n-byte message `M`, secret seed `SK.seed`, index `idx`, public seed `PK.seed`, address `ADRS`. <br>
|
||||||
/// Output: XMSS signature SIGXMSS = (sig ∥ AUTH).
|
/// Output: XMSS signature SIGXMSS = (sig ∥ AUTH).
|
||||||
const _A9: u32 = 0;
|
#[allow(clippy::similar_names)] // sk_seed and pk_seed
|
||||||
//
|
pub(crate) fn xmss_sign<HP: ArrayLength, LEN: ArrayLength, N: ArrayLength>(
|
||||||
|
context: &Context, m: &[u8], sk_seed: &[u8], idx: u32, pk_seed: &[u8], adrs: &Adrs,
|
||||||
|
) -> Result<XmssSig<HP, LEN, N>, &'static str> {
|
||||||
|
let mut adrs = adrs.clone();
|
||||||
|
let mut sig_xmss = XmssSig::default();
|
||||||
|
|
||||||
// 1: for j from 0 to h′-1 do ▷ Build authentication path
|
// 1: for j from 0 to h′-1 do ▷ Build authentication path
|
||||||
|
for j in 0..HP::to_u32() {
|
||||||
|
//
|
||||||
// 2: k ← idx/2 xor 1
|
// 2: k ← idx/2 xor 1
|
||||||
|
let k = (idx / 2) ^ 1;
|
||||||
|
|
||||||
// 3: AUTH[j] ← xmss_node(SK.seed, k, j, PK.seed, ADRS)
|
// 3: AUTH[j] ← xmss_node(SK.seed, k, j, PK.seed, ADRS)
|
||||||
|
sig_xmss.auth[j as usize] = xmss_node::<LEN, N>(context, sk_seed, k, j, pk_seed, &adrs)?;
|
||||||
|
|
||||||
// 4: end for
|
// 4: end for
|
||||||
|
}
|
||||||
|
|
||||||
// 5:
|
// 5:
|
||||||
// 6: ADRS.setTypeAndClear(WOTS_HASH)
|
// 6: ADRS.setTypeAndClear(WOTS_HASH)
|
||||||
|
adrs.set_type_and_clear(WOTS_HASH);
|
||||||
|
|
||||||
// 7: ADRS.setKeyPairAddress(idx)
|
// 7: ADRS.setKeyPairAddress(idx)
|
||||||
|
adrs.set_key_pair_address(idx);
|
||||||
|
|
||||||
// 8: sig ← wots_sign(M, SK.seed, PK.seed, ADRS)
|
// 8: sig ← wots_sign(M, SK.seed, PK.seed, ADRS)
|
||||||
|
sig_xmss.sig_wots = wots_sign(context, m, sk_seed, pk_seed, &adrs);
|
||||||
|
|
||||||
// 9: SIG_XMSS ← sig ∥ AUTH
|
// 9: SIG_XMSS ← sig ∥ AUTH
|
||||||
|
// struct constructed above
|
||||||
|
|
||||||
// 10: return SIG_XMSS
|
// 10: return SIG_XMSS
|
||||||
|
Ok(sig_xmss)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Algorithm 10: `xmss_PKFromSig(idx, SIG_XMSS, M, PK.seed, ADRS)`
|
/// Algorithm 10: `xmss_PKFromSig(idx, SIG_XMSS, M, PK.seed, ADRS)`
|
||||||
|
|
@ -515,27 +543,74 @@ const _A9: u32 = 0;
|
||||||
/// Input: Index `idx`, XMSS signature `SIG_XMSS = (sig ∥ AUTH)`, n-byte message `M`, public seed `PK.seed`,
|
/// Input: Index `idx`, XMSS signature `SIG_XMSS = (sig ∥ AUTH)`, n-byte message `M`, public seed `PK.seed`,
|
||||||
/// address `ADRS`. <br>
|
/// address `ADRS`. <br>
|
||||||
/// Output: n-byte root value `node[0]`.
|
/// Output: n-byte root value `node[0]`.
|
||||||
const _A10: u32 = 0;
|
pub(crate) fn xmss_pk_from_sig<HP: ArrayLength, LEN: ArrayLength, N: ArrayLength>(
|
||||||
|
context: &Context, idx: u32, sig_xmss: &XmssSig<HP, LEN, N>, m: &[u8], pk_seed: &[u8],
|
||||||
|
adrs: &Adrs,
|
||||||
|
) -> GenericArray<u8, N> {
|
||||||
|
let mut adrs = adrs.clone();
|
||||||
|
|
||||||
// 1: ADRS.setTypeAndClear(WOTS_HASH) ▷ Compute WOTS+ pk from WOTS+ sig
|
// 1: ADRS.setTypeAndClear(WOTS_HASH) ▷ Compute WOTS+ pk from WOTS+ sig
|
||||||
|
adrs.set_type_and_clear(WOTS_HASH);
|
||||||
|
|
||||||
// 2: ADRS.setKeyPairAddress(idx)
|
// 2: ADRS.setKeyPairAddress(idx)
|
||||||
|
adrs.set_chain_address(idx);
|
||||||
|
|
||||||
// 3: sig ← SIG_XMSS.getWOTSSig() ▷ SIG_XMSS [0 : len · n]
|
// 3: sig ← SIG_XMSS.getWOTSSig() ▷ SIG_XMSS [0 : len · n]
|
||||||
|
let sig = sig_xmss.get_wots_sig();
|
||||||
|
|
||||||
// 4: AUTH ← SIG_XMSS.getXMSSAUTH() ▷ SIG_XMSS [len · n : (len + h′) · n]
|
// 4: AUTH ← SIG_XMSS.getXMSSAUTH() ▷ SIG_XMSS [len · n : (len + h′) · n]
|
||||||
|
let auth = sig_xmss.get_xmss_auth();
|
||||||
|
|
||||||
// 5: node[0] ← wots_PKFromSig(sig, M, PK.seed, ADRS)
|
// 5: node[0] ← wots_PKFromSig(sig, M, PK.seed, ADRS)
|
||||||
|
let mut node_0 = wots_pk_from_sig::<LEN, N>(context, sig, m, pk_seed, &adrs)
|
||||||
|
.0
|
||||||
|
.clone();
|
||||||
|
|
||||||
// 6:
|
// 6:
|
||||||
// 7: ADRS.setTypeAndClear(TREE) ▷ Compute root from WOTS+ pk and AUTH
|
// 7: ADRS.setTypeAndClear(TREE) ▷ Compute root from WOTS+ pk and AUTH
|
||||||
|
adrs.set_type_and_clear(TREE);
|
||||||
|
|
||||||
// 8: ADRS.setTreeIndex(idx)
|
// 8: ADRS.setTreeIndex(idx)
|
||||||
|
adrs.set_tree_index(idx);
|
||||||
|
|
||||||
// 9: for k from 0 to h′ − 1 do
|
// 9: for k from 0 to h′ − 1 do
|
||||||
|
for k in 0..HP::to_u32() {
|
||||||
|
//
|
||||||
// 10: ADRS.setTreeHeight(k + 1)
|
// 10: ADRS.setTreeHeight(k + 1)
|
||||||
|
adrs.set_tree_height(k + 1);
|
||||||
|
|
||||||
// 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
|
||||||
|
let node_1 = if (idx & 2_u32.pow(k)) != 0 {
|
||||||
// 12: ADRS.setTreeIndex(ADRS.getTreeIndex()/2)
|
// 12: ADRS.setTreeIndex(ADRS.getTreeIndex()/2)
|
||||||
|
let tmp = adrs.get_tree_index() / 2;
|
||||||
|
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, &node_0, &auth[k as usize])
|
||||||
|
|
||||||
// 14: else
|
// 14: else
|
||||||
|
} else {
|
||||||
|
//
|
||||||
// 15: ADRS.setTreeIndex((ADRS.getTreeIndex() − 1)/2)
|
// 15: ADRS.setTreeIndex((ADRS.getTreeIndex() − 1)/2)
|
||||||
|
let tmp = (adrs.get_tree_index() - 1) / 2;
|
||||||
|
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, &auth[k as usize], &node_0)
|
||||||
|
|
||||||
// 17: end if
|
// 17: end if
|
||||||
|
};
|
||||||
|
|
||||||
// 18: node[0] ← node[1]
|
// 18: node[0] ← node[1]
|
||||||
|
node_0 = node_1;
|
||||||
|
|
||||||
// 19: end for
|
// 19: end for
|
||||||
|
}
|
||||||
|
|
||||||
// 20: return node[0]
|
// 20: return node[0]
|
||||||
|
node_0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Algorithm 11: `ht_sign(M, SK.seed, PK.seed, idx_tree, idx_leaf)` on page 27.
|
/// Algorithm 11: `ht_sign(M, SK.seed, PK.seed, idx_tree, idx_leaf)` on page 27.
|
||||||
|
|
@ -544,26 +619,65 @@ const _A10: u32 = 0;
|
||||||
/// Input: Message `M`, private seed `SK.seed`, public seed `PK.seed`, tree index `idx_tree`, leaf
|
/// Input: Message `M`, private seed `SK.seed`, public seed `PK.seed`, tree index `idx_tree`, leaf
|
||||||
/// index `idx_leaf`. <br>
|
/// index `idx_leaf`. <br>
|
||||||
/// Output: HT signature `SIG_HT`.
|
/// Output: HT signature `SIG_HT`.
|
||||||
const _A11: u32 = 0;
|
#[allow(clippy::similar_names)] // sk_seed and pk_seed
|
||||||
|
pub(crate) fn ht_sign<D: ArrayLength, HP: ArrayLength, LEN: ArrayLength, N: ArrayLength>(
|
||||||
|
context: &Context, m: &[u8], sk_seed: &[u8], pk_seed: &[u8], idx_tree: u32, idx_leaf: u32,
|
||||||
|
) -> Result<HtSig<D, HP, LEN, N>, &'static str> {
|
||||||
|
//
|
||||||
// 1: ADRS ← toByte(0, 32)
|
// 1: ADRS ← toByte(0, 32)
|
||||||
|
let mut adrs = Adrs::default();
|
||||||
|
|
||||||
// 2:
|
// 2:
|
||||||
// 3: ADRS.setTreeAddress(idxtree)
|
// 3: ADRS.setTreeAddress(idxtree)
|
||||||
// 4: SIG_tmp ← xmss_sign(M, SK.seed, idxleaf, PK.seed, ADRS)
|
adrs.set_tree_address(idx_tree);
|
||||||
// 5: SIG_HT ← SIG_tmp
|
|
||||||
// 6: root ← xmss_PKFromSig(idx_leaf, SIG_tmp, M, PK.seed, ADRS)
|
|
||||||
// 7: for j from 1 to d − 1 do
|
|
||||||
// 8: idx_leaf ← idx_tree mod 2^{h′} ▷ h′ least significant bits of idx_tree
|
|
||||||
// 9: idx_tree ← idx_tree ≫ h′ ▷ Remove least significant h′ bits from idx_tree
|
|
||||||
// 10: ADRS.setLayerAddress(j)
|
|
||||||
// 11: ADRS.setTreeAddress(idx_tree)
|
|
||||||
// 12: SIG_tmp ← xmss_sign(root, SK.seed, idx_leaf, PK.seed, ADRS)
|
|
||||||
// 13: SIG_HT ← SIG_HT ∥ SIG_tmp
|
|
||||||
// 14: if j < d − 1 then
|
|
||||||
// 15: root ← xmss_PKFromSig(idx_leaf, SIG_tmp, root, PK.seed, ADRS)
|
|
||||||
// 16: end if
|
|
||||||
// 17: end for
|
|
||||||
// 18: return SIGHT
|
|
||||||
|
|
||||||
|
// 4: SIG_tmp ← xmss_sign(M, SK.seed, idxleaf, PK.seed, ADRS)
|
||||||
|
let mut sig_tmp = xmss_sign::<HP, LEN, N>(context, m, sk_seed, idx_leaf, pk_seed, &adrs)?;
|
||||||
|
|
||||||
|
// 5: SIG_HT ← SIG_tmp
|
||||||
|
let mut sig_ht = HtSig::default();
|
||||||
|
sig_ht.xmss_sigs[0] = sig_tmp.clone();
|
||||||
|
|
||||||
|
// 6: root ← xmss_PKFromSig(idx_leaf, SIG_tmp, M, PK.seed, ADRS)
|
||||||
|
let mut root = xmss_pk_from_sig::<HP, LEN, N>(context, idx_leaf, &sig_tmp, m, pk_seed, &adrs);
|
||||||
|
|
||||||
|
// 7: for j from 1 to d − 1 do
|
||||||
|
for j in 1..context.d {
|
||||||
|
//
|
||||||
|
// 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());
|
||||||
|
|
||||||
|
// 9: idx_tree ← idx_tree ≫ h′ ▷ Remove least significant h′ bits from idx_tree
|
||||||
|
let idx_tree = idx_tree >> HP::to_u32();
|
||||||
|
|
||||||
|
// 10: ADRS.setLayerAddress(j)
|
||||||
|
adrs.set_layer_address(j);
|
||||||
|
|
||||||
|
// 11: ADRS.setTreeAddress(idx_tree)
|
||||||
|
adrs.set_tree_address(idx_tree);
|
||||||
|
|
||||||
|
// 12: SIG_tmp ← xmss_sign(root, SK.seed, idx_leaf, PK.seed, ADRS)
|
||||||
|
sig_tmp = xmss_sign::<HP, LEN, N>(context, &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();
|
||||||
|
|
||||||
|
// 14: if j < d − 1 then
|
||||||
|
if j < (context.d - 1) {
|
||||||
|
//
|
||||||
|
// 15: root ← xmss_PKFromSig(idx_leaf, SIG_tmp, root, PK.seed, ADRS)
|
||||||
|
root =
|
||||||
|
xmss_pk_from_sig::<HP, LEN, N>(context, idx_leaf, &sig_tmp, &root, pk_seed, &adrs);
|
||||||
|
|
||||||
|
// 16: end if
|
||||||
|
}
|
||||||
|
|
||||||
|
// 17: end for
|
||||||
|
}
|
||||||
|
|
||||||
|
// 18: return SIGHT
|
||||||
|
Ok(sig_ht)
|
||||||
|
}
|
||||||
|
|
||||||
/// Algorithm 12: `ht_verify(M, SIG_HT, PK.seed, idx_tree, idx_leaf, PK.root)` on page 28.
|
/// Algorithm 12: `ht_verify(M, SIG_HT, PK.seed, idx_tree, idx_leaf, PK.root)` on page 28.
|
||||||
/// Verify a hypertree signature.
|
/// Verify a hypertree signature.
|
||||||
|
|
@ -571,25 +685,55 @@ const _A11: u32 = 0;
|
||||||
/// Input: Message `M`, signature `SIG_HT`, public seed `PK.seed`, tree index `idx_tree`, leaf index `idx_leaf`,
|
/// Input: Message `M`, signature `SIG_HT`, public seed `PK.seed`, tree index `idx_tree`, leaf index `idx_leaf`,
|
||||||
/// HT public key `PK.root`. <br>
|
/// HT public key `PK.root`. <br>
|
||||||
/// Output: Boolean.
|
/// Output: Boolean.
|
||||||
const _A12: u32 = 0;
|
pub(crate) fn ht_verify<D: ArrayLength, HP: ArrayLength, LEN: ArrayLength, N: ArrayLength>(
|
||||||
|
context: &Context, m: &[u8], sig_ht: &HtSig<D, HP, LEN, N>, pk_seed: &[u8], idx_tree: u32,
|
||||||
|
idx_leaf: u32, pk_root: &GenericArray<u8, N>,
|
||||||
|
) -> bool {
|
||||||
|
//
|
||||||
// 1: ADRS ← toByte(0, 32)
|
// 1: ADRS ← toByte(0, 32)
|
||||||
|
let mut adrs = Adrs::default();
|
||||||
|
|
||||||
// 2:
|
// 2:
|
||||||
// 3: ADRS.setTreeAddress(idx_tree)
|
// 3: ADRS.setTreeAddress(idx_tree)
|
||||||
|
adrs.set_tree_address(idx_tree);
|
||||||
|
|
||||||
// 4: SIG_tmp ← SIG_HT.getXMSSSignature(0) ▷ SIG_HT [0 : (h′ + len) · n]
|
// 4: SIG_tmp ← SIG_HT.getXMSSSignature(0) ▷ SIG_HT [0 : (h′ + len) · n]
|
||||||
|
let sig_tmp = sig_ht.xmss_sigs[0].clone();
|
||||||
|
|
||||||
// 5: node ← xmss_PKFromSig(idx_leaf, SIG_tmp, M, PK.seed, ADRS)
|
// 5: node ← xmss_PKFromSig(idx_leaf, SIG_tmp, M, PK.seed, ADRS)
|
||||||
|
let mut node = xmss_pk_from_sig(context, idx_leaf, &sig_tmp, m, pk_seed, &adrs);
|
||||||
|
|
||||||
// 6: for j from 1 to d − 1 do
|
// 6: for j from 1 to d − 1 do
|
||||||
|
for j in 1..(context.d) {
|
||||||
|
//
|
||||||
// 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 = idx_tree % 2u32.pow(HP::to_u32());
|
||||||
|
|
||||||
// 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
|
||||||
|
let idx_tree = idx_tree >> HP::to_u32();
|
||||||
|
|
||||||
// 9: ADRS.setLayerAddress(j)
|
// 9: ADRS.setLayerAddress(j)
|
||||||
|
adrs.set_layer_address(j);
|
||||||
|
|
||||||
// 10: ADRS.setTreeAddress(idx_tree)
|
// 10: ADRS.setTreeAddress(idx_tree)
|
||||||
|
adrs.set_tree_address(idx_tree);
|
||||||
|
|
||||||
// 11: SIG_tmp ← SIG_HT.getXMSSSignature(j) ▷ SIGHT [ j · (h′ + len) · n : ( j + 1)(h′ + len) · n]
|
// 11: SIG_tmp ← SIG_HT.getXMSSSignature(j) ▷ SIGHT [ j · (h′ + len) · n : ( j + 1)(h′ + len) · n]
|
||||||
|
let sig_tmp = sig_ht.xmss_sigs[j as usize].clone();
|
||||||
|
|
||||||
// 12: node ← xmss_PKFromSig(idx_leaf, SIG_tmp, node, PK.seed, ADRS)
|
// 12: node ← xmss_PKFromSig(idx_leaf, SIG_tmp, node, PK.seed, ADRS)
|
||||||
|
node = xmss_pk_from_sig(context, idx_leaf, &sig_tmp, &node, pk_seed, &adrs);
|
||||||
|
|
||||||
// 13: end for
|
// 13: end for
|
||||||
|
}
|
||||||
|
|
||||||
// 14: if node = PK.root then
|
// 14: if node = PK.root then
|
||||||
// 15: return true
|
// 15: return true
|
||||||
// 16: else
|
// 16: else
|
||||||
// 17: return false
|
// 17: return false
|
||||||
// 18: end if
|
// 18: end if
|
||||||
|
node == *pk_root
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Algorithm 13: `fors_SKgen(SK.seed, PK.seed, ADRS, idx)` on page 29.
|
/// Algorithm 13: `fors_SKgen(SK.seed, PK.seed, ADRS, idx)` on page 29.
|
||||||
|
|
|
||||||
20
src/lib.rs
20
src/lib.rs
|
|
@ -8,7 +8,6 @@
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
|
|
||||||
mod algs;
|
mod algs;
|
||||||
mod traits;
|
mod traits;
|
||||||
mod types;
|
mod types;
|
||||||
|
|
@ -20,14 +19,14 @@ pub fn add(left: usize, right: usize) -> usize { left + right }
|
||||||
struct Context {
|
struct Context {
|
||||||
lgw: u32,
|
lgw: u32,
|
||||||
w: usize,
|
w: usize,
|
||||||
len1: usize,
|
len1: u32,
|
||||||
len2: usize,
|
len2: usize,
|
||||||
len: usize,
|
len: usize,
|
||||||
h: u32,
|
h: u32,
|
||||||
h_prime: u32,
|
h_prime: u32,
|
||||||
|
d: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
macro_rules! functionality {
|
macro_rules! functionality {
|
||||||
() => {
|
() => {
|
||||||
use crate::traits::PK;
|
use crate::traits::PK;
|
||||||
|
|
@ -45,15 +44,18 @@ macro_rules! functionality {
|
||||||
static CONTEXT: Context = Context {
|
static CONTEXT: Context = Context {
|
||||||
lgw: LGW,
|
lgw: LGW,
|
||||||
w: W,
|
w: W,
|
||||||
len1: LEN1,
|
len1: LEN1 as u32,
|
||||||
len2: LEN2,
|
len2: LEN2,
|
||||||
len: LEN,
|
len: LEN,
|
||||||
h: H,
|
h: H,
|
||||||
h_prime: H_PRIME,
|
h_prime: H_PRIME,
|
||||||
|
d: D,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Dummy placeholder TODO: fix
|
||||||
fn sign() -> SlhDsaSig<U5, U5, U16> { SlhDsaSig::<U5, U5, U16>::default() }
|
fn sign() -> SlhDsaSig<U5, U5, U16, U5, U16, U5> {
|
||||||
|
SlhDsaSig::<U5, U5, U16, U5, U16, U5>::default()
|
||||||
|
}
|
||||||
|
|
||||||
/// Correctly sized private key specific to the target security parameter set. <br>
|
/// Correctly sized private key specific to the target security parameter set. <br>
|
||||||
#[derive(Clone, Zeroize, ZeroizeOnDrop)]
|
#[derive(Clone, Zeroize, ZeroizeOnDrop)]
|
||||||
|
|
@ -90,7 +92,6 @@ pub mod slh_dsa_sha2_128s {
|
||||||
functionality!();
|
functionality!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// TKTK
|
/// TKTK
|
||||||
#[cfg(feature = "slh_dsa_shake_128s")]
|
#[cfg(feature = "slh_dsa_shake_128s")]
|
||||||
pub mod slh_dsa_shake_128s {
|
pub mod slh_dsa_shake_128s {
|
||||||
|
|
@ -145,7 +146,6 @@ pub mod slh_dsa_shake_128f {
|
||||||
functionality!();
|
functionality!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// TKTK
|
/// TKTK
|
||||||
#[cfg(feature = "slh_dsa_sha2_192s")]
|
#[cfg(feature = "slh_dsa_sha2_192s")]
|
||||||
pub mod slh_dsa_sha2_192s {
|
pub mod slh_dsa_sha2_192s {
|
||||||
|
|
@ -164,7 +164,6 @@ pub mod slh_dsa_sha2_192s {
|
||||||
functionality!();
|
functionality!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// TKTK
|
/// TKTK
|
||||||
#[cfg(feature = "slh_dsa_shake_192s")]
|
#[cfg(feature = "slh_dsa_shake_192s")]
|
||||||
pub mod slh_dsa_shake_192s {
|
pub mod slh_dsa_shake_192s {
|
||||||
|
|
@ -219,7 +218,6 @@ pub mod slh_dsa_shake_192f {
|
||||||
functionality!();
|
functionality!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// TKTK
|
/// TKTK
|
||||||
#[cfg(feature = "slh_dsa_sha2_256s")]
|
#[cfg(feature = "slh_dsa_sha2_256s")]
|
||||||
pub mod slh_dsa_sha2_256s {
|
pub mod slh_dsa_sha2_256s {
|
||||||
|
|
@ -238,7 +236,6 @@ pub mod slh_dsa_sha2_256s {
|
||||||
functionality!();
|
functionality!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// TKTK
|
/// TKTK
|
||||||
#[cfg(feature = "slh_dsa_shake_256s")]
|
#[cfg(feature = "slh_dsa_shake_256s")]
|
||||||
pub mod slh_dsa_shake_256s {
|
pub mod slh_dsa_shake_256s {
|
||||||
|
|
@ -293,7 +290,6 @@ pub mod slh_dsa_shake_256f {
|
||||||
functionality!();
|
functionality!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
||||||
48
src/types.rs
48
src/types.rs
|
|
@ -2,16 +2,21 @@ use alloc::vec::Vec;
|
||||||
use generic_array::{ArrayLength, GenericArray};
|
use generic_array::{ArrayLength, GenericArray};
|
||||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||||
|
|
||||||
|
|
||||||
/// Fig 16 on page 34
|
/// Fig 16 on page 34
|
||||||
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
|
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
|
||||||
pub struct SlhDsaSig<A: ArrayLength, K: ArrayLength, N: ArrayLength> {
|
pub struct SlhDsaSig<
|
||||||
|
A: ArrayLength,
|
||||||
|
D: ArrayLength,
|
||||||
|
HP: ArrayLength,
|
||||||
|
K: ArrayLength,
|
||||||
|
LEN: ArrayLength,
|
||||||
|
N: ArrayLength,
|
||||||
|
> {
|
||||||
randomness: GenericArray<u8, N>,
|
randomness: GenericArray<u8, N>,
|
||||||
fors_sig: ForsSig<A, K, N>,
|
fors_sig: ForsSig<A, K, N>,
|
||||||
ht_sig: HtSig<N>,
|
ht_sig: HtSig<D, HP, LEN, N>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Fig 13 on page 29
|
/// Fig 13 on page 29
|
||||||
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
|
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
|
||||||
pub(crate) struct ForsSig<A: ArrayLength, K: ArrayLength, N: ArrayLength> {
|
pub(crate) struct ForsSig<A: ArrayLength, K: ArrayLength, N: ArrayLength> {
|
||||||
|
|
@ -19,20 +24,17 @@ pub(crate) struct ForsSig<A: ArrayLength, K: ArrayLength, N: ArrayLength> {
|
||||||
auth: GenericArray<Auth<A, N>, K>,
|
auth: GenericArray<Auth<A, N>, K>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Fig 10?
|
/// Fig 10?
|
||||||
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
|
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
|
||||||
pub(crate) struct Auth<A: ArrayLength, N: ArrayLength> {
|
pub(crate) struct Auth<A: ArrayLength, N: ArrayLength> {
|
||||||
tree: GenericArray<GenericArray<u8, N>, A>,
|
tree: GenericArray<GenericArray<u8, N>, A>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
|
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
|
||||||
pub(crate) struct HtSig<N: ArrayLength> {
|
pub(crate) struct HtSig<D: ArrayLength, HP: ArrayLength, LEN: ArrayLength, N: ArrayLength> {
|
||||||
x: GenericArray<u8, N>,
|
pub(crate) xmss_sigs: GenericArray<XmssSig<HP, LEN, N>, D>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
|
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
|
||||||
pub struct WotsSig<LEN: ArrayLength, N: ArrayLength> {
|
pub struct WotsSig<LEN: ArrayLength, N: ArrayLength> {
|
||||||
pub(crate) data: GenericArray<GenericArray<u8, N>, LEN>,
|
pub(crate) data: GenericArray<GenericArray<u8, N>, LEN>,
|
||||||
|
|
@ -42,6 +44,18 @@ pub struct WotsSig<LEN: ArrayLength, N: ArrayLength> {
|
||||||
pub struct WotsPk<N: ArrayLength>(pub(crate) GenericArray<u8, N>);
|
pub struct WotsPk<N: ArrayLength>(pub(crate) GenericArray<u8, N>);
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
|
||||||
|
pub struct XmssSig<HP: ArrayLength, LEN: ArrayLength, N: ArrayLength> {
|
||||||
|
pub(crate) sig_wots: WotsSig<LEN, N>,
|
||||||
|
pub(crate) auth: GenericArray<GenericArray<u8, N>, HP>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<HP: ArrayLength, LEN: ArrayLength, N: ArrayLength> XmssSig<HP, LEN, N> {
|
||||||
|
pub(crate) fn get_wots_sig(&self) -> &WotsSig<LEN, N> { &self.sig_wots }
|
||||||
|
|
||||||
|
pub(crate) fn get_xmss_auth(&self) -> &GenericArray<GenericArray<u8, N>, HP> { &self.auth }
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) const WOTS_HASH: u32 = 0;
|
pub(crate) const WOTS_HASH: u32 = 0;
|
||||||
pub(crate) const WOTS_PK: u32 = 1;
|
pub(crate) const WOTS_PK: u32 = 1;
|
||||||
pub(crate) const TREE: u32 = 2;
|
pub(crate) const TREE: u32 = 2;
|
||||||
|
|
@ -50,7 +64,6 @@ const FORS_ROOTS: u32 = 4;
|
||||||
pub(crate) const WOTS_PRF: u32 = 5;
|
pub(crate) const WOTS_PRF: u32 = 5;
|
||||||
const FORS_PRF: u32 = 6;
|
const FORS_PRF: u32 = 6;
|
||||||
|
|
||||||
|
|
||||||
/// Straddling the line between struct, enum and union...
|
/// Straddling the line between struct, enum and union...
|
||||||
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
|
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
|
||||||
#[repr(align(32))]
|
#[repr(align(32))]
|
||||||
|
|
@ -65,14 +78,15 @@ pub struct Adrs {
|
||||||
f7: [u8; 4], // hash address OR padding OR tree index OR hash address = 0
|
f7: [u8; 4], // hash address OR padding OR tree index OR hash address = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Adrs {
|
impl Adrs {
|
||||||
pub(crate) fn get_key_pair_address(&self) -> [u8; 4] { self.f5 }
|
pub(crate) fn set_layer_address(&mut self, la: u32) { self.f0 = la.to_be_bytes() }
|
||||||
|
|
||||||
pub(crate) fn set_key_pair_address(&mut self, kp_addr: [u8; 4]) { self.f5 = kp_addr; }
|
pub(crate) fn get_key_pair_address(&self) -> u32 { u32::from_be_bytes(self.f5) }
|
||||||
|
|
||||||
|
pub(crate) fn set_key_pair_address(&mut self, kp_addr: u32) { self.f5 = kp_addr.to_be_bytes(); }
|
||||||
|
|
||||||
#[allow(clippy::cast_possible_truncation)]
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
pub(crate) fn set_chain_address(&mut self, i: usize) { self.f6 = (i as u32).to_be_bytes(); }
|
pub(crate) fn set_chain_address(&mut self, i: u32) { self.f6 = i.to_be_bytes(); }
|
||||||
|
|
||||||
pub(crate) fn set_type_and_clear(&mut self, type_t: u32) {
|
pub(crate) fn set_type_and_clear(&mut self, type_t: u32) {
|
||||||
self.f4 = type_t.to_be_bytes();
|
self.f4 = type_t.to_be_bytes();
|
||||||
|
|
@ -81,10 +95,16 @@ impl Adrs {
|
||||||
self.f7 = 0u32.to_be_bytes();
|
self.f7 = 0u32.to_be_bytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn set_tree_address(&mut self, t: u32) { self.f1 = t.to_be_bytes() }
|
||||||
|
|
||||||
|
// TODO: revisit 16 bytes
|
||||||
|
|
||||||
pub(crate) fn set_hash_address(&mut self, addr: u32) { self.f7 = addr.to_be_bytes() }
|
pub(crate) fn set_hash_address(&mut self, addr: u32) { self.f7 = addr.to_be_bytes() }
|
||||||
|
|
||||||
pub(crate) fn set_tree_height(&mut self, z: u32) { self.f6 = z.to_be_bytes() }
|
pub(crate) fn set_tree_height(&mut self, z: u32) { self.f6 = z.to_be_bytes() }
|
||||||
|
|
||||||
|
pub(crate) fn get_tree_index(&mut self) -> u32 { u32::from_be_bytes(self.f7) }
|
||||||
|
|
||||||
pub(crate) fn set_tree_index(&mut self, i: u32) { self.f7 = i.to_be_bytes() }
|
pub(crate) fn set_tree_index(&mut self, i: u32) { self.f7 = i.to_be_bytes() }
|
||||||
|
|
||||||
pub(crate) fn to_bytes(&self) -> Vec<u8> { [self.f0, self.f1, self.f2, self.f3].concat() }
|
pub(crate) fn to_bytes(&self) -> Vec<u8> { [self.f0, self.f1, self.f2, self.f3].concat() }
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue