diff --git a/Cargo.lock b/Cargo.lock index 6253f3e7..e758c9fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -488,7 +488,6 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", - "zeroize", ] [[package]] @@ -564,9 +563,9 @@ dependencies = [ [[package]] name = "hybrid-array" -version = "0.2.0-rc.9" +version = "0.2.0-rc.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d306b679262030ad8813a82d4915fc04efff97776e4db7f8eb5137039d56400" +checksum = "a5a41e5b0754cae5aaf7915f1df1147ba8d316fc6e019cfcc00fbaba96d5e030" dependencies = [ "typenum", "zeroize", @@ -654,15 +653,15 @@ checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lms-signature" -version = "0.0.1" +version = "0.1.0-pre" dependencies = [ - "digest 0.10.7", - "generic-array", + "digest 0.11.0-pre.9", "hex", "hex-literal", + "hybrid-array", "rand", "rand_core", - "sha2 0.10.8", + "sha2 0.11.0-pre.4", "signature", "static_assertions", "typenum", diff --git a/lms/Cargo.toml b/lms/Cargo.toml index d93b13b0..2432bfe1 100644 --- a/lms/Cargo.toml +++ b/lms/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "lms-signature" description = "Pure Rust implementation of Leighton-Micali Hash-Based Signatures (RFC 8554)" -version = "0.0.1" +version = "0.1.0-pre" edition = "2021" license = "Apache-2.0 OR MIT" homepage = "https://github.com/RustCrypto/signatures/tree/master/lms" @@ -12,10 +12,10 @@ categories = ["cryptography"] keywords = ["crypto", "signature"] [dependencies] -digest = "0.10.7" -generic-array = { version = "0.14.4", features = ["zeroize"] } +digest = "=0.11.0-pre.9" +hybrid-array = { version = "0.2.0-rc.11", features = ["extra-sizes", "zeroize"] } rand = "0.8.5" -sha2 = "0.10.8" +sha2 = "=0.11.0-pre.4" static_assertions = "1.1.0" rand_core = "0.6.4" signature = { version = "2.3.0-pre.0", features = ["digest", "std", "rand_core"] } diff --git a/lms/src/lms/modes.rs b/lms/src/lms/modes.rs index d4dcc128..2e600581 100644 --- a/lms/src/lms/modes.rs +++ b/lms/src/lms/modes.rs @@ -2,8 +2,7 @@ use crate::ots::modes::LmsOtsMode; use crate::types::Typecode; use digest::Digest; -use digest::Output; -use generic_array::ArrayLength; +use hybrid_array::ArraySize; use std::ops::Add; use std::{ marker::PhantomData, @@ -18,9 +17,9 @@ pub trait LmsMode: Typecode + Clone { /// The underlying LM-OTS mode type OtsMode: LmsOtsMode; /// Length of the internal Merkle tree, computed as `2^(h+1)-1` - type TreeLen: ArrayLength>; + type TreeLen: ArraySize; /// `h` as a type - type HLen: ArrayLength>; + type HLen: ArraySize; /// The length of the hash function output as a type const M: usize; /// `h` as a [usize] @@ -35,7 +34,7 @@ pub trait LmsMode: Typecode + Clone { pub struct LmsModeInternal< OtsMode: LmsOtsMode, Hasher: Digest, - HLen: ArrayLength>, + HLen: ArraySize, const M: usize, const H: usize, const TC: u32, @@ -48,7 +47,7 @@ pub struct LmsModeInternal< impl< OtsMode: LmsOtsMode, Hasher: Digest, - TreeLen: ArrayLength>, + TreeLen: ArraySize, const M: usize, const H: usize, const TC: u32, @@ -62,7 +61,7 @@ impl< impl< OtsMode: LmsOtsMode, Hasher: Digest, - TreeLen: ArrayLength>, + TreeLen: ArraySize, const M: usize, const H: usize, const TC: u32, @@ -73,7 +72,7 @@ impl< impl< OtsMode: LmsOtsMode, Hasher: Digest, - HLen: ArrayLength>, + HLen: ArraySize, const M: usize, const H: usize, const TC: u32, @@ -82,7 +81,7 @@ where HLen: Add, U1: Shl<>::Output>, Shleft>::Output>: Sub, - Sub1>::Output>>: ArrayLength>, + Sub1>::Output>>: ArraySize, { type OtsMode = OtsMode; type Hasher = Hasher; @@ -97,7 +96,7 @@ where impl< Hasher: Digest, OtsMode: LmsOtsMode, - TreeLen: ArrayLength>, + TreeLen: ArraySize, const M: usize, const H: usize, const TC: u32, diff --git a/lms/src/lms/private.rs b/lms/src/lms/private.rs index 841130fe..3bf7292b 100644 --- a/lms/src/lms/private.rs +++ b/lms/src/lms/private.rs @@ -6,10 +6,11 @@ use crate::ots::SigningKey as OtsPrivateKey; use crate::types::{Identifier, Typecode}; use digest::{Digest, Output, OutputSizeUser}; -use generic_array::{ArrayLength, GenericArray}; +use hybrid_array::{Array, ArraySize}; use rand::{CryptoRng, Rng}; use signature::{Error, RandomizedSignerMut}; +use core::array::TryFromSliceError; use std::cmp::Ordering; use std::ops::Add; use typenum::{Sum, U28}; @@ -23,7 +24,7 @@ use typenum::{Sum, U28}; pub struct SigningKey { id: Identifier, seed: Output, // Re-generate the leaf privkeys as-needed from a seed - auth_tree: GenericArray, Mode::TreeLen>, // TODO: Decide whether/when to precompute + auth_tree: Array, Mode::TreeLen>, // TODO: Decide whether/when to precompute q: u32, } @@ -36,27 +37,26 @@ impl SigningKey { let mut seed = Output::::default(); rng.fill_bytes(seed.as_mut()); - Self::new_from_seed(id, seed) + Self::new_from_seed(id, seed).expect("size invariant violation") } // Returns a new LMS private key generated pseudorandomly from an identifier // and secret seed. The seed must be equal to the hash output length of the // LMS mode ([Mode::M]) - // - // TODO: Return error rather than panic? Or just make the input a - // GenericArray? This is the algorithm from Appendix A of - // - pub fn new_from_seed(id: Identifier, seed: impl AsRef<[u8]>) -> Self { + pub fn new_from_seed( + id: Identifier, + seed: impl AsRef<[u8]>, + ) -> Result { //let seed = seed.as_ref(); - let seed = GenericArray::clone_from_slice(seed.as_ref()); + let seed = Array::try_from(seed.as_ref())?; let mut sk = Self { id, seed, - auth_tree: GenericArray::default(), + auth_tree: Array::default(), q: 0, // we set q = 0 when generating keys; it will change }; sk.gen_pk_tree(); // TODO: Use lazy generation / MTT - sk + Ok(sk) } /// Generates a Merkle tree of OTS public key hashes, using the indexing scheme of RFC 8554 offset by 1 @@ -135,14 +135,14 @@ impl RandomizedSignerMut> for SigningKey { /// Converts a [PrivateKey] into its byte representation impl From> - for GenericArray::OutputSize, U28>> + for Array::OutputSize, U28>> where ::OutputSize: Add, - Sum<::OutputSize, U28>: ArrayLength, + Sum<::OutputSize, U28>: ArraySize, { fn from(pk: SigningKey) -> Self { // Return u32(type) || u32(otstype) || u32(q) || id || seed - GenericArray::from_exact_iter( + Array::try_from_iter( std::iter::empty() .chain(Mode::TYPECODE.to_be_bytes()) .chain(Mode::OtsMode::TYPECODE.to_be_bytes()) @@ -188,8 +188,8 @@ impl<'a, Mode: LmsMode> TryFrom<&'a [u8]> for SigningKey { let mut key = Self { q: u32::from_be_bytes(q.try_into().expect("ok")), id: id.try_into().expect("ok"), - seed: GenericArray::clone_from_slice(seed), - auth_tree: GenericArray::default(), + seed: Array::try_from(seed).expect("ok"), + auth_tree: Array::default(), }; key.gen_pk_tree(); Ok(key) @@ -215,7 +215,8 @@ mod tests { let id = hex!("d08fabd4a2091ff0a8cb4ed834e74534"); let expected_k = hex!("32a58885cd9ba0431235466bff9651c6c92124404d45fa53cf161c28f1ad5a8e"); - let lms_priv = SigningKey::>::new_from_seed(id, seed); + let lms_priv = + SigningKey::>::new_from_seed(id, seed).unwrap(); let lms_pub = lms_priv.public(); assert_eq!(lms_pub.k(), expected_k); assert_eq!(lms_pub.id(), &id); @@ -229,7 +230,8 @@ mod tests { let id = hex!("215f83b7ccb9acbcd08db97b0d04dc2b"); let expected_k = hex!("a1cd035833e0e90059603f26e07ad2aad152338e7a5e5984bcd5f7bb4eba40b7"); - let lms_priv = SigningKey::>::new_from_seed(id, seed); + let lms_priv = + SigningKey::>::new_from_seed(id, seed).unwrap(); let lms_pub = lms_priv.public(); assert_eq!(lms_pub.k(), expected_k); assert_eq!(lms_pub.id(), &id); @@ -339,7 +341,8 @@ mod tests { let id = hex!("215f83b7ccb9acbcd08db97b0d04dc2b"); let _expected_k = hex!("a1cd035833e0e90059603f26e07ad2aad152338e7a5e5984bcd5f7bb4eba40b7"); - let mut lms_priv = SigningKey::>::new_from_seed(id, seed); + let mut lms_priv = + SigningKey::>::new_from_seed(id, seed).unwrap(); lms_priv.q = 4; let _lms_pub = lms_priv.public(); diff --git a/lms/src/lms/public.rs b/lms/src/lms/public.rs index 73b01263..c93a5519 100644 --- a/lms/src/lms/public.rs +++ b/lms/src/lms/public.rs @@ -8,7 +8,7 @@ use crate::lms::Signature; use crate::types::Typecode; use crate::{constants::D_INTR, lms::LmsMode}; use digest::{Digest, OutputSizeUser}; -use generic_array::{ArrayLength, GenericArray}; +use hybrid_array::{Array, ArraySize}; use signature::{Error, Verifier}; use typenum::{Sum, U24}; @@ -99,14 +99,14 @@ impl Verifier> for VerifyingKey { /// Converts a [`VerifyingKey`] into its byte representation impl From> - for GenericArray::OutputSize, U24>> + for Array::OutputSize, U24>> where ::OutputSize: Add, - Sum<::OutputSize, U24>: ArrayLength, + Sum<::OutputSize, U24>: ArraySize, { fn from(pk: VerifyingKey) -> Self { // Return u32(type) || u32(otstype) || id || k - GenericArray::from_exact_iter( + Array::try_from_iter( std::iter::empty() .chain(Mode::TYPECODE.to_be_bytes()) .chain(Mode::OtsMode::TYPECODE.to_be_bytes()) @@ -149,7 +149,7 @@ impl<'a, Mode: LmsMode> TryFrom<&'a [u8]> for VerifyingKey { Ok(Self { id: id.try_into().unwrap(), - k: GenericArray::clone_from_slice(k), + k: Array::try_from(k).expect("size invariant violation"), }) } } @@ -165,8 +165,8 @@ mod tests { ots::{LmsOtsSha256N32W4, LmsOtsSha256N32W8}, }; use digest::OutputSizeUser; - use generic_array::{ArrayLength, GenericArray}; use hex_literal::hex; + use hybrid_array::{Array, ArraySize}; use typenum::{Sum, U24}; // RFC 8554 Appendix F. Test Case 1 @@ -222,7 +222,7 @@ mod tests { #[test] fn test_kat1_round_trip() { let pk = VerifyingKey::>::try_from(&KAT1[..]).unwrap(); - let pk_serialized: GenericArray = pk.clone().into(); + let pk_serialized: Array = pk.clone().into(); let bytes = pk_serialized.as_slice(); assert_eq!(bytes, &KAT1[..]); } @@ -244,9 +244,10 @@ mod tests { c92124404d45fa53cf161c28f1ad5a8e " ); - let lms_priv = SigningKey::>::new_from_seed(id, seed); + let lms_priv = + SigningKey::>::new_from_seed(id, seed).unwrap(); let lms_pub = lms_priv.public(); - let lms_pub_serialized: GenericArray = lms_pub.into(); + let lms_pub_serialized: Array = lms_pub.into(); let bytes = lms_pub_serialized.as_slice(); assert_eq!(bytes, &expected_pubkey[..]); } @@ -255,15 +256,13 @@ mod tests { where VerifyingKey: std::fmt::Debug, ::OutputSize: Add, - Sum<::OutputSize, U24>: ArrayLength, + Sum<::OutputSize, U24>: ArraySize, { let rng = rand::thread_rng(); let lms_priv = SigningKey::::new(rng); let lms_pub = lms_priv.public(); - let lms_pub_serialized: GenericArray< - u8, - Sum<::OutputSize, U24>, - > = lms_pub.clone().into(); + let lms_pub_serialized: Array::OutputSize, U24>> = + lms_pub.clone().into(); let bytes = lms_pub_serialized.as_slice(); let lms_pub_deserialized = VerifyingKey::::try_from(bytes).unwrap(); assert_eq!(lms_pub, lms_pub_deserialized); diff --git a/lms/src/lms/signature.rs b/lms/src/lms/signature.rs index bafe2773..9418ff06 100644 --- a/lms/src/lms/signature.rs +++ b/lms/src/lms/signature.rs @@ -4,7 +4,7 @@ use crate::error::LmsDeserializeError; use crate::lms::LmsMode; use crate::ots::modes::LmsOtsMode; use crate::ots::Signature as OtsSignature; -use generic_array::{ArrayLength, GenericArray}; +use hybrid_array::{Array, ArraySize}; use signature::SignatureEncoding; use std::{ @@ -18,7 +18,7 @@ use typenum::{Prod, Sum, U1, U4}; pub struct Signature { pub(crate) q: u32, // TODO: do these really need to be public? pub(crate) lmots_sig: OtsSignature, - pub(crate) path: GenericArray, Mode::HLen>, + pub(crate) path: Array, Mode::HLen>, } // manual implementation is required to not require bounds on Mode @@ -48,9 +48,9 @@ where Sum< Prod<::NLen, Sum<::PLen, U1>>, U4, - >: ArrayLength, + >: ArraySize, { - type Repr = Vec; // TODO: GenericArray + type Repr = Vec; // TODO: Array } impl From> for Vec @@ -62,12 +62,12 @@ where Sum< Prod<::NLen, Sum<::PLen, U1>>, U4, - >: ArrayLength, + >: ArraySize, { fn from(val: Signature) -> Self { let mut sig = Vec::new(); sig.extend_from_slice(&val.q.to_be_bytes()); - let lms_sig: GenericArray = val.lmots_sig.into(); + let lms_sig: Array = val.lmots_sig.into(); sig.extend_from_slice(&lms_sig); sig.extend_from_slice(&Mode::TYPECODE.to_be_bytes()); for node in val.path { @@ -121,7 +121,7 @@ impl TryFrom<&[u8]> for Signature { // Path length is already validated by initial length check let path = path .chunks_exact(Mode::M) - .map(GenericArray::clone_from_slice) + .map(|chunk| Array::try_from(chunk).expect("size invariant violation")) .collect(); Ok(Self { @@ -139,8 +139,8 @@ mod tests { use crate::lms::modes::*; use crate::lms::{Signature, SigningKey, VerifyingKey}; use crate::ots::modes::*; - use generic_array::ArrayLength; use hex_literal::hex; + use hybrid_array::ArraySize; use rand::thread_rng; use signature::{RandomizedSignerMut, Verifier}; use typenum::{Prod, Sum, U1, U4}; @@ -264,7 +264,7 @@ mod tests { Sum< Prod<::NLen, Sum<::PLen, U1>>, U4, - >: ArrayLength, + >: ArraySize, { let mut rng = thread_rng(); let mut sk = SigningKey::::new(&mut rng); diff --git a/lms/src/ots/mod.rs b/lms/src/ots/mod.rs index 1cd53d8d..d08da24b 100644 --- a/lms/src/ots/mod.rs +++ b/lms/src/ots/mod.rs @@ -24,8 +24,8 @@ pub mod tests { use crate::ots::private::SigningKey; use digest::Digest; use digest::OutputSizeUser; - use generic_array::{ArrayLength, GenericArray}; use hex_literal::hex; + use hybrid_array::{Array, ArraySize}; use rand::thread_rng; use rand_core::{CryptoRng, RngCore}; use signature::RandomizedSignerMut; @@ -39,7 +39,7 @@ pub mod tests { fn test_sign() where ::OutputSize: Add, - Sum<::OutputSize, U2>: ArrayLength, + Sum<::OutputSize, U2>: ArraySize, { let mut rng = thread_rng(); let mut sk = SigningKey::::new(0, [0xcc; ID_LEN], &mut rng); @@ -63,7 +63,7 @@ pub mod tests { fn test_sign_fail_verify() where ::OutputSize: Add, - Sum<::OutputSize, U2>: ArrayLength, + Sum<::OutputSize, U2>: ArraySize, { let mut rng = thread_rng(); let mut sk = SigningKey::::new(0, [0xcc; ID_LEN], &mut rng); @@ -175,8 +175,8 @@ pub mod tests { let msg = "The enumeration in the Constitution, of certain rights, shall not be construed to deny or disparage others retained by the people.\n".as_bytes(); let sig = sk.try_sign_with_rng(&mut rng, msg).unwrap(); - assert_eq!(&sig.c, GenericArray::from_slice(&c)); - assert_eq!(&sig.y[0], GenericArray::from_slice(&y0)); + assert_eq!(sig.c, Array::from(c)); + assert_eq!(sig.y[0], Array::from(y0)); } #[test] diff --git a/lms/src/ots/modes.rs b/lms/src/ots/modes.rs index 427d41c1..ac6c851f 100644 --- a/lms/src/ots/modes.rs +++ b/lms/src/ots/modes.rs @@ -1,7 +1,7 @@ use crate::ots::util::coefs; use crate::types::Typecode; use digest::{Digest, Output}; -use generic_array::{ArrayLength, GenericArray}; +use hybrid_array::{Array, ArraySize}; use sha2::Sha256; use static_assertions::const_assert_eq; use std::marker::PhantomData; @@ -13,9 +13,9 @@ pub trait LmsOtsMode: Typecode { /// The underlying hash function type Hasher: Digest; /// The length of the hash function output as a type - type NLen: ArrayLength; + type NLen: ArraySize; /// The value of P as a type - type PLen: ArrayLength> + ArrayLength; + type PLen: ArraySize; /// The length of the hash function output as a [usize] const N: usize; /// The Winternitz window, which should be a value that divides 8 @@ -32,7 +32,7 @@ pub trait LmsOtsMode: Typecode { const SIG_LEN: usize; /// Expands a message into its Winternitz coefficients and checksum - fn expand(message: &Output) -> GenericArray { + fn expand(message: &Output) -> Array { // Returns an array containing Coefs(message, w, U) || Coefs(checksum, w, V) // where Coefs(M, w, L) is an array containing coef(M, i, w) for each i in 0..L // See RFC 8554 section 3.1.3. @@ -40,7 +40,7 @@ pub trait LmsOtsMode: Typecode { // Expand the message into its coefficients // Immediately allocates full expanded length, but only the first U coefficients are used // in this step - let mut arr: GenericArray::PLen> = GenericArray::default(); + let mut arr: Array::PLen> = Array::default(); for (i, c) in coefs(message, Self::W).enumerate().take(Self::U) { arr[i] = c; } @@ -70,21 +70,12 @@ pub trait LmsOtsMode: Typecode { } #[derive(Debug)] -pub struct LmsOtsModeInternal< - Hasher: Digest, - const W: usize, - PP: ArrayLength> + ArrayLength, - const TC: u32, -> { +pub struct LmsOtsModeInternal { _phantomdata: PhantomData<(Hasher, PP)>, } -impl< - Hasher: Digest, - const W: usize, - PP: ArrayLength> + ArrayLength, - const TC: u32, - > Typecode for LmsOtsModeInternal +impl Typecode + for LmsOtsModeInternal { const TYPECODE: u32 = TC; } @@ -94,12 +85,8 @@ impl< /// /// NLen and N are calculated using the associated OutputSize of the given Digest, as specified by /// https://datatracker.ietf.org/doc/html/rfc8554#section-4.1 -impl< - Hasher: Digest, - const W: usize, - PP: ArrayLength> + ArrayLength, - const TC: u32, - > LmsOtsMode for LmsOtsModeInternal +impl LmsOtsMode + for LmsOtsModeInternal { type Hasher = Hasher; type NLen = Hasher::OutputSize; @@ -177,13 +164,13 @@ const_assert_eq!(LmsOtsSha256N32W8::SIG_LEN, 1124); #[cfg(test)] mod test { - use generic_array::GenericArray; + use hybrid_array::Array; use super::LmsOtsMode; #[test] fn test_checksum_zero_w1() { let arr = [0u8; super::LmsOtsSha256N32W1::N]; - let cksm = super::LmsOtsSha256N32W1::expand(GenericArray::from_slice(&arr)); + let cksm = super::LmsOtsSha256N32W1::expand(&Array::from(arr)); assert_eq!( &cksm[super::LmsOtsSha256N32W1::U..], &[1, 0, 0, 0, 0, 0, 0, 0, 0] @@ -193,7 +180,7 @@ mod test { #[test] fn test_checksum_ones_w1() { let arr = [255u8; super::LmsOtsSha256N32W1::N]; - let cksm = super::LmsOtsSha256N32W1::expand(GenericArray::from_slice(&arr)); + let cksm = super::LmsOtsSha256N32W1::expand(&Array::from(arr)); assert_eq!( &cksm[super::LmsOtsSha256N32W1::U..], &[0, 0, 0, 0, 0, 0, 0, 0, 0] @@ -203,14 +190,14 @@ mod test { #[test] fn test_checksum_ten_w4() { let arr = [0xaa; super::LmsOtsSha256N32W4::N]; - let cksm = super::LmsOtsSha256N32W4::expand(GenericArray::from_slice(&arr)); + let cksm = super::LmsOtsSha256N32W4::expand(&Array::from(arr)); assert_eq!(&cksm[super::LmsOtsSha256N32W4::U..], &[0x01, 0x04, 0x00]); } #[test] fn test_expand_zero_w8() { let arr = [0u8; super::LmsOtsSha256N32W8::N]; - let expanded = super::LmsOtsSha256N32W8::expand(GenericArray::from_slice(&arr)); + let expanded = super::LmsOtsSha256N32W8::expand(&Array::from(arr)); let mut expected = [0u8; super::LmsOtsSha256N32W8::P]; expected[super::LmsOtsSha256N32W8::U] = 0x1f; expected[super::LmsOtsSha256N32W8::U + 1] = 0xe0; diff --git a/lms/src/ots/private.rs b/lms/src/ots/private.rs index 3bc93fc2..67ad786c 100644 --- a/lms/src/ots/private.rs +++ b/lms/src/ots/private.rs @@ -6,8 +6,7 @@ use crate::ots::signature::Signature; use crate::types::Identifier; use digest::{Digest, Output}; -use generic_array::sequence::GenericSequence; -use generic_array::GenericArray; +use hybrid_array::Array; use rand_core::CryptoRngCore; use signature::{Error, RandomizedSignerMut}; use zeroize::Zeroize; @@ -19,19 +18,19 @@ use zeroize::Zeroize; pub struct SigningKey { q: u32, id: Identifier, - x: GenericArray, Mode::PLen>, + x: Array, Mode::PLen>, valid: bool, } impl SigningKey { /// Generate a private key, expanded pseudorandomly from a seed generated by `rng`. /// Uses the algorithm from appendix A - // a key part of this code working is the DerefMut impl for GenericArray which we abuse in a similar manner to + // a key part of this code working is the DerefMut impl for Array which we abuse in a similar manner to // generic_array::ArrayBuilder's internal implementation /// If LM-OTS is being used directly, q MUST be set to the all-zero value /// pub fn new(q: u32, id: Identifier, rng: &mut impl CryptoRngCore) -> Self { - let mut seed: GenericArray = GenericArray::default(); + let mut seed: Array = Array::default(); rng.fill_bytes(&mut seed); Self::new_from_seed(q, id, seed) } @@ -40,7 +39,7 @@ impl SigningKey { /// according to Appendix A of pub fn new_from_seed(q: u32, id: Identifier, seed: impl AsRef<[u8]>) -> Self { let seed = seed.as_ref(); - let x = GenericArray::generate(|i| { + let x = Array::from_fn(|i| { Mode::Hasher::new() .chain_update(id) .chain_update(q.to_be_bytes()) @@ -134,7 +133,7 @@ impl RandomizedSignerMut> for SigningKey } tmp }); - let y = GenericArray::from_iter(y); + let y = Array::from_iter(y); let sig = Signature { c, y }; diff --git a/lms/src/ots/public.rs b/lms/src/ots/public.rs index 6687cad7..2d44da0b 100644 --- a/lms/src/ots/public.rs +++ b/lms/src/ots/public.rs @@ -8,7 +8,7 @@ use crate::ots::signature::Signature; use crate::types::Identifier; use digest::{Output, OutputSizeUser}; -use generic_array::{ArrayLength, GenericArray}; +use hybrid_array::{Array, ArraySize}; use signature::{Error, Verifier}; use std::cmp::Ordering; use std::ops::Add; @@ -44,7 +44,7 @@ impl Verifier> for VerifyingKey where // required to concat Q and cksm(Q) ::OutputSize: Add, - Sum<::OutputSize, U2>: ArrayLength, + Sum<::OutputSize, U2>: ArraySize, { // this implements algorithm 4a of https://datatracker.ietf.org/doc/html/rfc8554#section-4.6 fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), Error> { @@ -62,14 +62,14 @@ where /// Converts a [`VerifyingKey`] into its byte representation impl From> - for GenericArray::OutputSize, U24>> + for Array::OutputSize, U24>> where ::OutputSize: Add, - Sum<::OutputSize, U24>: ArrayLength, + Sum<::OutputSize, U24>: ArraySize, { fn from(pk: VerifyingKey) -> Self { // Return u32str(type) || I || u32str(q) || K - GenericArray::from_exact_iter( + Array::try_from_iter( std::iter::empty() .chain(Mode::TYPECODE.to_be_bytes()) .chain(pk.id) @@ -108,7 +108,7 @@ impl<'a, Mode: LmsOtsMode> TryFrom<&'a [u8]> for VerifyingKey { Ok(Self { q: u32::from_be_bytes(q.try_into().expect("ok")), id: i.try_into().expect("ok"), - k: GenericArray::clone_from_slice(k), + k: Array::try_from(k).expect("ok"), }) } } @@ -122,14 +122,14 @@ mod tests { use crate::ots::modes::{LmsOtsSha256N32W4, LmsOtsSha256N32W8}; use crate::ots::private::SigningKey; use crate::ots::public::VerifyingKey; - use generic_array::GenericArray; + use hybrid_array::Array; use rand::thread_rng; #[test] fn test_serde() { let pk = SigningKey::::new(0, [0xbb; ID_LEN], &mut thread_rng()).public(); - let pk_serialized: GenericArray = pk.clone().into(); + let pk_serialized: Array = pk.clone().into(); let bytes = pk_serialized.as_slice(); let pk_deserialized = VerifyingKey::::try_from(bytes); diff --git a/lms/src/ots/signature.rs b/lms/src/ots/signature.rs index 98a21995..0e014c3c 100644 --- a/lms/src/ots/signature.rs +++ b/lms/src/ots/signature.rs @@ -5,7 +5,7 @@ use crate::error::LmsDeserializeError; use crate::ots::modes::LmsOtsMode; use crate::types::Identifier; use digest::Digest; -use generic_array::{ArrayLength, GenericArray}; +use hybrid_array::{Array, ArraySize}; use signature::SignatureEncoding; use std::cmp::Ordering; use std::ops::{Add, Mul}; @@ -17,7 +17,7 @@ use super::VerifyingKey; /// Opaque struct representing a LM-OTS signature pub struct Signature { pub(crate) c: digest::Output, - pub(crate) y: GenericArray, Mode::PLen>, + pub(crate) y: Array, Mode::PLen>, } // manual implementation is required to not require bounds on Mode @@ -37,11 +37,9 @@ impl PartialEq for Signature { } } -/// Useful type alias to get the [`GenericArray`] representation -pub type Output = GenericArray< - u8, - Sum::NLen, Sum<::PLen, U1>>, U4>, ->; +/// Useful type alias to get the [`Array`] representation +pub type Output = + Array::NLen, Sum<::PLen, U1>>, U4>>; /// Converts a [`Signature`] into its byte representation impl From> for Output @@ -50,10 +48,10 @@ where Mode::PLen: Add, Mode::NLen: Mul>, Prod>: Add, - Sum>, U4>: ArrayLength, + Sum>, U4>: ArraySize, { fn from(sig: Signature) -> Self { - GenericArray::from_exact_iter( + Array::try_from_iter( std::iter::empty() .chain(Mode::TYPECODE.to_be_bytes()) .chain(sig.c.clone()) @@ -88,12 +86,14 @@ impl<'a, Mode: LmsOtsMode> TryFrom<&'a [u8]> for Signature { // sig is now guaranteed to be of the form C || y[0] || ... || y[p - 1] let (c, y) = sig.split_at(Mode::N); - let c = GenericArray::clone_from_slice(c); + let c = Array::try_from(c).expect("size invariant violation"); - // ys is an iterator over GenericArray of length p - let ys = y.chunks_exact(Mode::N).map(GenericArray::clone_from_slice); + // ys is an iterator over Array of length p + let ys = y + .chunks_exact(Mode::N) + .map(|chunk| Array::try_from(chunk).expect("size invariant violation")); debug_assert!(ys.len() == Mode::P); - let y = GenericArray::from_iter(ys); + let y = Array::from_iter(ys); Ok(Self { c, y }) } @@ -124,7 +124,7 @@ impl Signature { .chain_update(q.to_be_bytes()) .chain_update(D_PBLC); - let mut tmp = GenericArray::default(); + let mut tmp = Array::default(); for (i, a) in Mode::expand(&msg_hash).into_iter().enumerate() { tmp.clone_from(&self.y[i]); @@ -158,7 +158,7 @@ where Mode::PLen: Add, Mode::NLen: Mul>, Prod>: Add, - Sum>, U4>: ArrayLength, + Sum>, U4>: ArraySize, { type Repr = Output; }