pub(crate) const MAX_N: usize = 32;
pub(crate) const MAX_WOTS_LEN: usize = 67;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub(crate) enum HashFamily {
Sha2_256,
Shake128,
Shake256,
}
#[derive(Clone, Copy)]
pub(crate) struct Params {
pub n: usize,
pub padding_len: usize,
pub full_height: u32,
pub d: u32,
pub tree_height: u32,
pub wots_log_w: u32,
pub wots_w: u32,
pub wots_len1: usize,
pub wots_len2: usize,
pub wots_len: usize,
pub family: HashFamily,
pub index_bytes: usize,
}
impl Params {
pub(crate) fn wots_sig_bytes(&self) -> usize {
self.wots_len * self.n
}
pub(crate) fn sig_bytes(&self) -> usize {
self.index_bytes
+ self.n
+ self.d as usize * self.wots_sig_bytes()
+ self.full_height as usize * self.n
}
pub(crate) fn sk_bytes(&self) -> usize {
self.index_bytes + 4 * self.n
}
pub(crate) fn pk_bytes(&self) -> usize {
2 * self.n
}
pub(crate) fn exhausted_index(&self) -> Option<u64> {
if self.full_height >= 64 {
return None;
}
let total = 1u64 << self.full_height;
if self.index_bytes * 8 == self.full_height as usize {
Some(total - 1)
} else {
Some(total)
}
}
}
const fn make(n: usize, full_height: u32, d: u32, family: HashFamily) -> Params {
let padding_len = if n == 24 { 4 } else { n };
let wots_log_w = 4; let wots_len1 = (8 * n) / wots_log_w as usize;
let wots_len2 = 3;
let index_bytes = if d == 1 {
4
} else {
(full_height as usize).div_ceil(8)
};
Params {
n,
padding_len,
full_height,
d,
tree_height: full_height / d,
wots_log_w,
wots_w: 16,
wots_len1,
wots_len2,
wots_len: wots_len1 + wots_len2,
family,
index_bytes,
}
}
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[repr(u32)]
pub enum XmssParamSet {
Sha2_10_256 = 0x0000_0001,
Sha2_16_256 = 0x0000_0002,
Sha2_20_256 = 0x0000_0003,
Shake_10_256 = 0x0000_0007,
Shake_16_256 = 0x0000_0008,
Shake_20_256 = 0x0000_0009,
Sha2_10_192 = 0x0000_000d,
Sha2_16_192 = 0x0000_000e,
Sha2_20_192 = 0x0000_000f,
Shake256_10_256 = 0x0000_0010,
Shake256_16_256 = 0x0000_0011,
Shake256_20_256 = 0x0000_0012,
}
impl XmssParamSet {
pub fn oid(self) -> u32 {
self as u32
}
pub fn from_oid(oid: u32) -> Option<Self> {
use XmssParamSet::*;
Some(match oid {
0x0000_0001 => Sha2_10_256,
0x0000_0002 => Sha2_16_256,
0x0000_0003 => Sha2_20_256,
0x0000_0007 => Shake_10_256,
0x0000_0008 => Shake_16_256,
0x0000_0009 => Shake_20_256,
0x0000_000d => Sha2_10_192,
0x0000_000e => Sha2_16_192,
0x0000_000f => Sha2_20_192,
0x0000_0010 => Shake256_10_256,
0x0000_0011 => Shake256_16_256,
0x0000_0012 => Shake256_20_256,
_ => return None,
})
}
pub(crate) fn params(self) -> Params {
use HashFamily::*;
use XmssParamSet::*;
match self {
Sha2_10_256 => make(32, 10, 1, Sha2_256),
Sha2_16_256 => make(32, 16, 1, Sha2_256),
Sha2_20_256 => make(32, 20, 1, Sha2_256),
Shake_10_256 => make(32, 10, 1, Shake128),
Shake_16_256 => make(32, 16, 1, Shake128),
Shake_20_256 => make(32, 20, 1, Shake128),
Sha2_10_192 => make(24, 10, 1, Sha2_256),
Sha2_16_192 => make(24, 16, 1, Sha2_256),
Sha2_20_192 => make(24, 20, 1, Sha2_256),
Shake256_10_256 => make(32, 10, 1, Shake256),
Shake256_16_256 => make(32, 16, 1, Shake256),
Shake256_20_256 => make(32, 20, 1, Shake256),
}
}
}
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[repr(u32)]
pub enum XmssMtParamSet {
Sha2_20_2_256 = 0x0000_0001,
Sha2_20_4_256 = 0x0000_0002,
Sha2_40_2_256 = 0x0000_0003,
Sha2_40_4_256 = 0x0000_0004,
Sha2_40_8_256 = 0x0000_0005,
Sha2_60_3_256 = 0x0000_0006,
Sha2_60_6_256 = 0x0000_0007,
Sha2_60_12_256 = 0x0000_0008,
Shake_20_2_256 = 0x0000_0011,
Shake_20_4_256 = 0x0000_0012,
}
impl XmssMtParamSet {
pub fn oid(self) -> u32 {
self as u32
}
pub fn from_oid(oid: u32) -> Option<Self> {
use XmssMtParamSet::*;
Some(match oid {
0x0000_0001 => Sha2_20_2_256,
0x0000_0002 => Sha2_20_4_256,
0x0000_0003 => Sha2_40_2_256,
0x0000_0004 => Sha2_40_4_256,
0x0000_0005 => Sha2_40_8_256,
0x0000_0006 => Sha2_60_3_256,
0x0000_0007 => Sha2_60_6_256,
0x0000_0008 => Sha2_60_12_256,
0x0000_0011 => Shake_20_2_256,
0x0000_0012 => Shake_20_4_256,
_ => return None,
})
}
pub(crate) fn params(self) -> Params {
use HashFamily::*;
use XmssMtParamSet::*;
match self {
Sha2_20_2_256 => make(32, 20, 2, Sha2_256),
Sha2_20_4_256 => make(32, 20, 4, Sha2_256),
Sha2_40_2_256 => make(32, 40, 2, Sha2_256),
Sha2_40_4_256 => make(32, 40, 4, Sha2_256),
Sha2_40_8_256 => make(32, 40, 8, Sha2_256),
Sha2_60_3_256 => make(32, 60, 3, Sha2_256),
Sha2_60_6_256 => make(32, 60, 6, Sha2_256),
Sha2_60_12_256 => make(32, 60, 12, Sha2_256),
Shake_20_2_256 => make(32, 20, 2, Shake128),
Shake_20_4_256 => make(32, 20, 4, Shake128),
}
}
}