mirror of
https://github.com/saymrwulf/fips205-source.git
synced 2026-09-03 19:53:49 +00:00
not
This commit is contained in:
parent
7bb838973b
commit
a6ff2130de
4 changed files with 45 additions and 42 deletions
51
src/algs.rs
51
src/algs.rs
|
|
@ -10,7 +10,7 @@ use rand_core::CryptoRngCore;
|
|||
/// Algorithm 1: `toInt(X, n)` on page 14.
|
||||
/// Convert a byte string to an integer.
|
||||
///
|
||||
/// Input: n-byte string `X`. <br>
|
||||
/// Input: n-byte string `X`, string length `n`. <br>
|
||||
/// Output: Integer value of `X`.
|
||||
pub(crate) fn to_int(x: &[u8], n: usize) -> u64 {
|
||||
debug_assert_eq!(x.len(), n);
|
||||
|
|
@ -66,12 +66,12 @@ pub(crate) fn to_byte(x: u64, n: usize) -> [u8; ((crate::LEN2 * crate::LGW + 7)
|
|||
/// Algorithm 3: `base_2^b(X, b, out_len)` on page 15.
|
||||
/// Compute the base 2^b representation of X.
|
||||
///
|
||||
/// Input: Byte string `X` of length at least ceil(`out_len·b/8`), integer `b`, output length `out_len`. <br>
|
||||
/// Input: Byte string `X` of length at least ceil(out_len·b/8), integer `b`, output length `out_len`. <br>
|
||||
/// Output: Array of `out_len` integers in the range `[0, . . . , 2^b − 1]`.
|
||||
pub(crate) fn base_2b(x: &[u8], b: u32, out_len: usize, baseb: &mut [u64]) {
|
||||
assert!(x.len() >= out_len * b as usize / 8);
|
||||
assert!(b < 64);
|
||||
assert_eq!(out_len, baseb.len());
|
||||
debug_assert!(x.len() >= out_len * b as usize / 8);
|
||||
debug_assert!(b < 16);
|
||||
debug_assert_eq!(out_len, baseb.len());
|
||||
|
||||
// 1: in ← 0
|
||||
let mut inn = 0;
|
||||
|
|
@ -105,7 +105,7 @@ pub(crate) fn base_2b(x: &[u8], b: u32, out_len: usize, baseb: &mut [u64]) {
|
|||
bits -= b;
|
||||
|
||||
// 12: baseb[out] ← (total ≫ bits) mod 2^b
|
||||
*item = (total >> bits) % 2u64.pow(b);
|
||||
*item = (total >> bits) & (u64::MAX >> (16 - b));
|
||||
|
||||
// 13: end for
|
||||
}
|
||||
|
|
@ -116,7 +116,7 @@ pub(crate) fn base_2b(x: &[u8], b: u32, out_len: usize, baseb: &mut [u64]) {
|
|||
|
||||
/// Algorithm 4: `chain(X, i, s, PK.seed, ADRS)` on page 17.
|
||||
/// Chaining function used in WOTS+. The chain function takes as input an n-byte string `X` and integers `s` and `i`
|
||||
/// and returns the result of iterating a hash function `F` on the input `s` times, starting from an index of `i`.
|
||||
/// and returns the result of iterating the hash function `F` on the input `s` times, starting from an index of `i`.
|
||||
/// The chain function also requires as input PK.seed, which is part of the SLH-DSA public key, and an address `ADRS`.
|
||||
/// The type in `ADRS` must be set to `WOTS_HASH`, and the layer address, tree address, key pair address, and chain
|
||||
/// address must be set to the address of the chain being computed. The chain function updates the hash address in
|
||||
|
|
@ -128,6 +128,7 @@ pub(crate) fn chain<K: ArrayLength, LEN: ArrayLength, M: ArrayLength, N: ArrayLe
|
|||
hashers: &Hashers<K, LEN, M, N>, cap_x: GenericArray<u8, N>, i: usize, s: usize,
|
||||
pk_seed: &[u8], adrs: &Adrs,
|
||||
) -> Option<GenericArray<u8, N>> {
|
||||
debug_assert!(i + s < u32::MAX as usize);
|
||||
let mut adrs = adrs.clone();
|
||||
|
||||
// 1: if (i + s) ≥ w then
|
||||
|
|
@ -148,7 +149,7 @@ pub(crate) fn chain<K: ArrayLength, LEN: ArrayLength, M: ArrayLength, N: ArrayLe
|
|||
for j in i..(i + s) {
|
||||
//
|
||||
// 8: ADRS.setHashAddress(j)
|
||||
adrs.set_hash_address(j.try_into().expect("usize->u32 fails")); // TODO: something better than expect?
|
||||
adrs.set_hash_address(j as u32);
|
||||
|
||||
// 9: tmp ← F(PK.seed, ADRS, tmp)
|
||||
tmp = (hashers.f)(pk_seed, &adrs, &tmp);
|
||||
|
|
@ -172,7 +173,7 @@ pub(crate) fn chain<K: ArrayLength, LEN: ArrayLength, M: ArrayLength, N: ArrayLe
|
|||
#[allow(clippy::similar_names)]
|
||||
pub(crate) fn wots_pkgen<K: ArrayLength, LEN: ArrayLength, M: ArrayLength, N: ArrayLength>(
|
||||
hashers: &Hashers<K, LEN, M, N>, sk_seed: &[u8], pk_seed: &[u8], adrs: &Adrs,
|
||||
) -> WotsPk<N> {
|
||||
) -> Result<WotsPk<N>, &'static str> {
|
||||
let mut adrs = adrs.clone();
|
||||
let mut tmp: GenericArray<GenericArray<u8, N>, LEN> = GenericArray::default();
|
||||
|
||||
|
|
@ -186,8 +187,7 @@ pub(crate) fn wots_pkgen<K: ArrayLength, LEN: ArrayLength, M: ArrayLength, N: Ar
|
|||
sk_adrs.set_key_pair_address(adrs.get_key_pair_address());
|
||||
|
||||
// 4: for i from 0 to len − 1 do
|
||||
let len = 2 * N::to_u32() + 3;
|
||||
for i in 0..len {
|
||||
for i in 0..LEN::to_u32() {
|
||||
//
|
||||
// 5: skADRS.setChainAddress(i)
|
||||
sk_adrs.set_chain_address(i);
|
||||
|
|
@ -200,7 +200,7 @@ pub(crate) fn wots_pkgen<K: ArrayLength, LEN: ArrayLength, M: ArrayLength, N: Ar
|
|||
|
||||
// 8: tmp[i] ← chain(sk, 0, w − 1, PK.seed, ADRS) ▷ Compute public value for chain i
|
||||
tmp[i as usize] =
|
||||
chain(hashers, sk, 0, crate::W as usize - 1, pk_seed, &adrs).expect("chain broke!");
|
||||
chain(hashers, sk, 0, crate::W as usize - 1, pk_seed, &adrs).ok_or("chain broke")?;
|
||||
|
||||
// 9: end for
|
||||
}
|
||||
|
|
@ -218,7 +218,7 @@ pub(crate) fn wots_pkgen<K: ArrayLength, LEN: ArrayLength, M: ArrayLength, N: Ar
|
|||
let pk = (hashers.t_l)(pk_seed, &wotspk_adrs, &tmp);
|
||||
|
||||
// 14: return pk
|
||||
WotsPk(pk)
|
||||
Ok(WotsPk(pk))
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -235,7 +235,7 @@ pub(crate) fn wots_sign<K: ArrayLength, LEN: ArrayLength, M: ArrayLength, N: Arr
|
|||
let mut sig: WotsSig<LEN, N> = WotsSig::default();
|
||||
|
||||
// 1: csum ← 0
|
||||
let mut csum = 0u64;
|
||||
let mut csum = 0;
|
||||
|
||||
// 2:
|
||||
// 3: msg ← base_2b(M, lgw, len1) ▷ Convert message to base w
|
||||
|
|
@ -255,11 +255,11 @@ pub(crate) fn wots_sign<K: ArrayLength, LEN: ArrayLength, M: ArrayLength, N: Arr
|
|||
// 8:
|
||||
// 9: csum ← csum ≪ ((8 − ((len2·lgw) mod 8)) mod 8) ▷ For lgw = 4 left shift by 4
|
||||
let len2 = 3_usize; //
|
||||
csum <<= (8 - ((len2 as u64 * u64::from(crate::LGW)) % 8)) % 8;
|
||||
csum <<= (8 - ((len2 as u64 * u64::from(crate::LGW)) & 0x07)) & 0x07;
|
||||
|
||||
// 10: msg ← msg ∥ base_2^b(toByte(csum, ceil(len2·lgw/8)), lgw, len2) ▷ Convert csum to base w
|
||||
base_2b(
|
||||
&to_byte(csum, (len2 * crate::LGW as usize).div_ceil(8)),
|
||||
&to_byte(csum as u64, (len2 * crate::LGW as usize).div_ceil(8)),
|
||||
crate::LGW,
|
||||
len2,
|
||||
&mut msg[(2 * N::to_usize())..],
|
||||
|
|
@ -277,20 +277,20 @@ pub(crate) fn wots_sign<K: ArrayLength, LEN: ArrayLength, M: ArrayLength, N: Arr
|
|||
|
||||
// 15: for i from 0 to len − 1 do
|
||||
let len = 2 * N::to_usize() + 3;
|
||||
#[allow(clippy::cast_possible_truncation)] // step 18/19
|
||||
for (i, item) in msg.iter().enumerate().take(len) {
|
||||
#[allow(clippy::cast_possible_truncation)] // step 19
|
||||
for (item, i) in msg.iter().zip(0u32..).take(len) {
|
||||
//
|
||||
// 16: skADRS.setChainAddress(i)
|
||||
sk_addrs.set_chain_address(i as u32);
|
||||
sk_addrs.set_chain_address(i);
|
||||
|
||||
// 17: sk ← PRF(PK.seed, SK.seed, skADRS) ▷ Compute secret value for chain i
|
||||
let sk = (hashers.prf)(pk_seed, sk_seed, &sk_addrs);
|
||||
|
||||
// 18: ADRS.setChainAddress(i)
|
||||
adrs.set_chain_address(i as u32);
|
||||
adrs.set_chain_address(i);
|
||||
|
||||
// 19: sig[i] ← chain(sk, 0, msg[i], PK.seed, ADRS) ▷ Compute signature value for chain i
|
||||
sig.data[i] = chain(hashers, sk, 0, *item as usize, pk_seed, &adrs).unwrap();
|
||||
sig.data[i as usize] = chain(hashers, sk, 0, *item as usize, pk_seed, &adrs).unwrap();
|
||||
|
||||
// 20: end for
|
||||
}
|
||||
|
|
@ -316,13 +316,12 @@ pub(crate) fn wots_pk_from_sig<K: ArrayLength, LEN: ArrayLength, M: ArrayLength,
|
|||
|
||||
// 2:
|
||||
// 3: msg ← base_2b (M, lgw , len1 ) ▷ Convert message to base w
|
||||
let len1 = 2 * N::to_usize();
|
||||
let mut msg: GenericArray<u64, LEN> = GenericArray::default();
|
||||
base_2b(m, crate::LGW, 2 * N::to_usize(), &mut msg[0..(2 * N::to_usize())]);
|
||||
|
||||
// 4:
|
||||
// 5: for i from 0 to len1 − 1 do ▷ Compute checksum
|
||||
for item in msg.iter().take(len1) {
|
||||
for item in msg.iter().take(2 * N::to_usize()) {
|
||||
//
|
||||
// 6: csum ← csum + w − 1 − msg[i]
|
||||
csum += u64::from(crate::W) - 1 - item;
|
||||
|
|
@ -333,11 +332,11 @@ pub(crate) fn wots_pk_from_sig<K: ArrayLength, LEN: ArrayLength, M: ArrayLength,
|
|||
// 8:
|
||||
// 9: csum ← csum ≪ ((8 − ((len2·lgw) mod 8)) mod 8) ▷ For lgw = 4 left shift by 4
|
||||
let len2 = 3;
|
||||
csum <<= (8 - ((len2 * crate::LGW as usize) % 8)) % 8;
|
||||
csum <<= (8 - ((len2 * crate::LGW as usize) & 0x07)) & 0x07;
|
||||
|
||||
// 10: msg ← msg ∥ base_2^b(toByte(csum, ceil(len2·lgw/8)), lgw, len2) ▷ Convert csum to base w
|
||||
base_2b(
|
||||
&to_byte(csum, (len2 * crate::LGW as usize).div_ceil(8)),
|
||||
&to_byte(csum as u64, (len2 * crate::LGW as usize).div_ceil(8)),
|
||||
crate::LGW,
|
||||
len2,
|
||||
&mut msg[(2 * N::to_usize())..],
|
||||
|
|
@ -419,7 +418,7 @@ pub(crate) fn xmss_node<
|
|||
adrs.set_key_pair_address(i);
|
||||
|
||||
// 7: node ← wots_PKgen(SK.seed, PK.seed, ADRS)
|
||||
wots_pkgen::<K, LEN, M, N>(hashers, sk_seed, pk_seed, &adrs)
|
||||
wots_pkgen::<K, LEN, M, N>(hashers, sk_seed, pk_seed, &adrs)?
|
||||
.0
|
||||
.clone() // TODO remove clone?
|
||||
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ pub(crate) mod sha2_cat_3_5 {
|
|||
],
|
||||
&mut digest,
|
||||
); // Note that the spec swaps order of last to params
|
||||
//println!("prf: {:?}", &digest[0..4]);
|
||||
//println!("prf: {:?}", &digest[0..4]);
|
||||
digest
|
||||
}
|
||||
|
||||
|
|
|
|||
33
src/lib.rs
33
src/lib.rs
|
|
@ -1,14 +1,13 @@
|
|||
//#![no_std]
|
||||
#![no_std]
|
||||
#![deny(clippy::pedantic)]
|
||||
#![deny(warnings)]
|
||||
//#![deny(missing_docs)]
|
||||
|
||||
/// TKTK crate doc
|
||||
/// crate doc?
|
||||
// TODO
|
||||
// 1. General clean-up
|
||||
// 2. NOTE: SHA2 HASHERS DUMMIED UP TO PASS TEST; IMPLEMENT!
|
||||
// 3. Implement SHA2 KATs
|
||||
// 2. SerDes on keys
|
||||
// 3. Proper traits and non-rng functions
|
||||
// 4. Separate into proper files
|
||||
// 5. Doc, of course!
|
||||
mod algs;
|
||||
|
|
@ -17,16 +16,16 @@ mod test;
|
|||
mod traits;
|
||||
mod types;
|
||||
|
||||
// Per eqns 5.1-4 on page 16, LGW=4, W=16 and LEN2=3 are constant across all parameter sets.
|
||||
// Per eqns 5.1-4 on page 16, LGW=4, W=16 and LEN2=3 are constant across all security parameter sets.
|
||||
const LGW: u32 = 4;
|
||||
const W: u32 = 16;
|
||||
const LEN2: u32 = 3;
|
||||
|
||||
|
||||
/// blah
|
||||
macro_rules! functionality {
|
||||
() => {
|
||||
use crate::types::{SlhDsaSig, SlhPrivateKey, SlhPublicKey};
|
||||
//use generic_array::typenum::{Prod, Sum, U2, U3};
|
||||
use rand_core::CryptoRngCore;
|
||||
|
||||
/// blah
|
||||
|
|
@ -61,13 +60,13 @@ macro_rules! functionality {
|
|||
use rand_chacha::rand_core::SeedableRng;
|
||||
|
||||
#[test]
|
||||
fn simple_loop() {
|
||||
fn simple_round_trips() {
|
||||
let mut message = [0u8, 1, 2, 3];
|
||||
let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(123);
|
||||
for i in 0..5 {
|
||||
message[3] = i as u8;
|
||||
let (sk, pk) = slh_keygen_with_rng(&mut rng).unwrap();
|
||||
let sig = slh_sign_with_rng(&mut rng, &message, &sk, false).unwrap();
|
||||
let sig = slh_sign_with_rng(&mut rng, &message, &sk, true).unwrap();
|
||||
let result = slh_verify(&message, &sig, &pk);
|
||||
assert_eq!(result, true, "Signature failed to verify");
|
||||
message[3] = (i + 1) as u8;
|
||||
|
|
@ -79,11 +78,11 @@ macro_rules! functionality {
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
/// TKTK
|
||||
#[cfg(feature = "slh_dsa_sha2_128s")]
|
||||
pub mod slh_dsa_sha2_128s {
|
||||
use crate::hashers::sha2_cat_1::{f, h, h_msg, prf, prf_msg, t_l, t_len};
|
||||
|
||||
use crate::hashers::Hashers;
|
||||
use generic_array::typenum::{Prod, Sum, U12, U14, U16, U2, U3, U30, U63, U7, U9};
|
||||
|
||||
|
|
@ -104,6 +103,7 @@ pub mod slh_dsa_sha2_128s {
|
|||
functionality!();
|
||||
}
|
||||
|
||||
|
||||
/// TKTK
|
||||
#[cfg(feature = "slh_dsa_shake_128s")]
|
||||
pub mod slh_dsa_shake_128s {
|
||||
|
|
@ -128,11 +128,11 @@ pub mod slh_dsa_shake_128s {
|
|||
functionality!();
|
||||
}
|
||||
|
||||
|
||||
/// TKTK
|
||||
#[cfg(feature = "slh_dsa_sha2_128f")]
|
||||
pub mod slh_dsa_sha2_128f {
|
||||
use crate::hashers::sha2_cat_1::{f, h, h_msg, prf, prf_msg, t_l, t_len};
|
||||
|
||||
use crate::hashers::Hashers;
|
||||
use generic_array::typenum::{Prod, Sum, U16, U2, U22, U3, U33, U34, U6, U66};
|
||||
|
||||
|
|
@ -153,6 +153,7 @@ pub mod slh_dsa_sha2_128f {
|
|||
functionality!();
|
||||
}
|
||||
|
||||
|
||||
/// TKTK
|
||||
#[cfg(feature = "slh_dsa_shake_128f")]
|
||||
pub mod slh_dsa_shake_128f {
|
||||
|
|
@ -177,11 +178,11 @@ pub mod slh_dsa_shake_128f {
|
|||
functionality!();
|
||||
}
|
||||
|
||||
|
||||
/// TKTK
|
||||
#[cfg(feature = "slh_dsa_sha2_192s")]
|
||||
pub mod slh_dsa_sha2_192s {
|
||||
use crate::hashers::sha2_cat_3_5::{f, h, h_msg, prf, prf_msg, t_l, t_len};
|
||||
|
||||
use crate::hashers::Hashers;
|
||||
use generic_array::typenum::{Prod, Sum, U14, U17, U2, U24, U3, U39, U63, U7, U9};
|
||||
|
||||
|
|
@ -202,11 +203,11 @@ pub mod slh_dsa_sha2_192s {
|
|||
functionality!();
|
||||
}
|
||||
|
||||
|
||||
/// TKTK
|
||||
#[cfg(feature = "slh_dsa_shake_192s")]
|
||||
pub mod slh_dsa_shake_192s {
|
||||
use crate::hashers::shake::{f, h, h_msg, prf, prf_msg, t_l, t_len};
|
||||
|
||||
use crate::hashers::Hashers;
|
||||
use generic_array::typenum::{Prod, Sum, U14, U17, U2, U24, U3, U39, U63, U7, U9};
|
||||
|
||||
|
|
@ -227,6 +228,7 @@ pub mod slh_dsa_shake_192s {
|
|||
functionality!();
|
||||
}
|
||||
|
||||
|
||||
/// TKTK
|
||||
#[cfg(feature = "slh_dsa_sha2_192f")]
|
||||
pub mod slh_dsa_sha2_192f {
|
||||
|
|
@ -251,6 +253,7 @@ pub mod slh_dsa_sha2_192f {
|
|||
functionality!();
|
||||
}
|
||||
|
||||
|
||||
/// TKTK
|
||||
#[cfg(feature = "slh_dsa_shake_192f")]
|
||||
pub mod slh_dsa_shake_192f {
|
||||
|
|
@ -275,11 +278,11 @@ pub mod slh_dsa_shake_192f {
|
|||
functionality!();
|
||||
}
|
||||
|
||||
|
||||
/// TKTK
|
||||
#[cfg(feature = "slh_dsa_sha2_256s")]
|
||||
pub mod slh_dsa_sha2_256s {
|
||||
use crate::hashers::sha2_cat_3_5::{f, h, h_msg, prf, prf_msg, t_l, t_len};
|
||||
|
||||
use crate::hashers::Hashers;
|
||||
use generic_array::typenum::{Prod, Sum, U14, U2, U22, U3, U32, U47, U64, U8};
|
||||
|
||||
|
|
@ -300,6 +303,7 @@ pub mod slh_dsa_sha2_256s {
|
|||
functionality!();
|
||||
}
|
||||
|
||||
|
||||
/// TKTK
|
||||
#[cfg(feature = "slh_dsa_shake_256s")]
|
||||
pub mod slh_dsa_shake_256s {
|
||||
|
|
@ -324,11 +328,11 @@ pub mod slh_dsa_shake_256s {
|
|||
functionality!();
|
||||
}
|
||||
|
||||
|
||||
/// TKTK
|
||||
#[cfg(feature = "slh_dsa_sha2_256f")]
|
||||
pub mod slh_dsa_sha2_256f {
|
||||
use crate::hashers::sha2_cat_3_5::{f, h, h_msg, prf, prf_msg, t_l, t_len};
|
||||
|
||||
use crate::hashers::Hashers;
|
||||
use generic_array::typenum::{Prod, Sum, U17, U2, U3, U32, U35, U4, U49, U68, U9};
|
||||
|
||||
|
|
@ -349,6 +353,7 @@ pub mod slh_dsa_sha2_256f {
|
|||
functionality!();
|
||||
}
|
||||
|
||||
|
||||
/// TKTK
|
||||
#[cfg(feature = "slh_dsa_shake_256f")]
|
||||
pub mod slh_dsa_shake_256f {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue