diff --git a/.github/workflows/dsa.yml b/.github/workflows/dsa.yml index 646dbbc5..1da1e5fa 100644 --- a/.github/workflows/dsa.yml +++ b/.github/workflows/dsa.yml @@ -24,7 +24,7 @@ jobs: - thumbv7em-none-eabi - wasm32-unknown-unknown toolchain: - - 1.72.0 # MSRV + - 1.81.0 # MSRV - stable steps: - uses: actions/checkout@v4 @@ -42,7 +42,7 @@ jobs: - macos-latest - windows-latest toolchain: - - 1.72.0 # MSRV + - 1.81.0 # MSRV - stable runs-on: ${{ matrix.platform }} steps: diff --git a/.github/workflows/ecdsa.yml b/.github/workflows/ecdsa.yml index 99fc4272..7c94110a 100644 --- a/.github/workflows/ecdsa.yml +++ b/.github/workflows/ecdsa.yml @@ -26,7 +26,7 @@ jobs: - thumbv7em-none-eabi - wasm32-unknown-unknown rust: - - 1.73.0 # MSRV + - 1.81.0 # MSRV - stable steps: - uses: actions/checkout@v4 @@ -42,7 +42,7 @@ jobs: strategy: matrix: rust: - - 1.73.0 # MSRV + - 1.81.0 # MSRV - stable steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/lms.yml b/.github/workflows/lms.yml index 9e25581a..ed64db8b 100644 --- a/.github/workflows/lms.yml +++ b/.github/workflows/lms.yml @@ -22,7 +22,7 @@ jobs: strategy: matrix: rust: - - 1.73.0 # MSRV + - 1.81.0 # MSRV - stable steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/rfc6979.yml b/.github/workflows/rfc6979.yml index 82be5fc0..5c76cce1 100644 --- a/.github/workflows/rfc6979.yml +++ b/.github/workflows/rfc6979.yml @@ -24,7 +24,7 @@ jobs: - thumbv7em-none-eabi - wasm32-unknown-unknown rust: - - 1.72.0 # MSRV + - 1.81.0 # MSRV - stable steps: - uses: actions/checkout@v4 @@ -39,7 +39,7 @@ jobs: strategy: matrix: rust: - - 1.72.0 # MSRV + - 1.81.0 # MSRV - stable steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/slh-dsa.yml b/.github/workflows/slh-dsa.yml index e83e536e..57734cf6 100644 --- a/.github/workflows/slh-dsa.yml +++ b/.github/workflows/slh-dsa.yml @@ -22,7 +22,7 @@ jobs: strategy: matrix: rust: - - 1.75.0 # MSRV + - 1.81.0 # MSRV - stable steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index 19eaf41d..ac56e05b 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -29,6 +29,6 @@ jobs: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master with: - toolchain: 1.75.0 + toolchain: 1.81.0 components: clippy - run: cargo clippy --all-features -- -D warnings 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/dsa/Cargo.toml b/dsa/Cargo.toml index 00df2734..19f50d38 100644 --- a/dsa/Cargo.toml +++ b/dsa/Cargo.toml @@ -13,7 +13,7 @@ homepage = "https://github.com/RustCrypto/signatures/tree/master/dsa" repository = "https://github.com/RustCrypto/signatures" categories = ["cryptography", "no-std"] keywords = ["crypto", "nist", "signature"] -rust-version = "1.72" +rust-version = "1.81" [dependencies] digest = "=0.11.0-pre.9" diff --git a/ecdsa/Cargo.toml b/ecdsa/Cargo.toml index 730a9c5b..4162793f 100644 --- a/ecdsa/Cargo.toml +++ b/ecdsa/Cargo.toml @@ -14,7 +14,7 @@ readme = "README.md" categories = ["cryptography", "no-std"] keywords = ["crypto", "ecc", "nist", "secp256k1", "signature"] edition = "2021" -rust-version = "1.73" +rust-version = "1.81" [dependencies] elliptic-curve = { version = "0.14.0-rc.1", default-features = false, features = ["digest", "sec1"] } diff --git a/ed25519/src/pkcs8.rs b/ed25519/src/pkcs8.rs index cac2f9b2..53b45774 100644 --- a/ed25519/src/pkcs8.rs +++ b/ed25519/src/pkcs8.rs @@ -30,10 +30,7 @@ pub use pkcs8::der::{ use core::fmt; #[cfg(feature = "pem")] -use { - alloc::string::{String, ToString}, - core::str, -}; +use core::str; #[cfg(feature = "zeroize")] use zeroize::Zeroize; @@ -323,10 +320,13 @@ impl str::FromStr for PublicKeyBytes { } #[cfg(feature = "pem")] -impl ToString for PublicKeyBytes { - fn to_string(&self) -> String { - self.to_public_key_pem(Default::default()) - .expect("PEM serialization error") +impl fmt::Display for PublicKeyBytes { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str( + &self + .to_public_key_pem(Default::default()) + .expect("PEM serialization error"), + ) } } diff --git a/lms/Cargo.lock b/lms/Cargo.lock deleted file mode 100644 index 28436ff7..00000000 --- a/lms/Cargo.lock +++ /dev/null @@ -1,225 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "anyhow" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cpufeatures" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" -dependencies = [ - "libc", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "crypto-common" -version = "0.2.0-pre.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc17eb697364b18256ec92675ebe6b7b153d2f1041e568d74533c5d0fc1ca162" -dependencies = [ - "hybrid-array", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common 0.1.6", -] - -[[package]] -name = "digest" -version = "0.11.0-pre.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3be3c52e023de5662dc05a32f747d09a1d6024fdd1f64b0850e373269efb43" -dependencies = [ - "crypto-common 0.2.0-pre.3", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", - "zeroize", -] - -[[package]] -name = "getrandom" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hex-literal" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" - -[[package]] -name = "hybrid-array" -version = "0.2.0-pre.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27fbaf242418fe980caf09ed348d5a6aeabe71fc1bd8bebad641f4591ae0a46d" -dependencies = [ - "typenum", -] - -[[package]] -name = "libc" -version = "0.2.150" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" - -[[package]] -name = "lms" -version = "0.1.0" -dependencies = [ - "anyhow", - "digest 0.10.7", - "generic-array", - "hex", - "hex-literal", - "rand", - "rand_core", - "sha2", - "signature", - "static_assertions", - "typenum", - "zeroize", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "signature" -version = "2.3.0-pre.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9b544e1447a755027450a51bc29aa51772e071bd839aca18136a7dab1b93e" -dependencies = [ - "digest 0.11.0-pre.3", - "rand_core", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "zeroize" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/lms/Cargo.toml b/lms/Cargo.toml index d93b13b0..573bc3e5 100644 --- a/lms/Cargo.toml +++ b/lms/Cargo.toml @@ -1,21 +1,21 @@ [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" repository = "https://github.com/RustCrypto/signatures" readme = "README.md" -rust-version = "1.73" +rust-version = "1.81" 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; } diff --git a/rfc6979/Cargo.toml b/rfc6979/Cargo.toml index 7d3c7e10..77f19fed 100644 --- a/rfc6979/Cargo.toml +++ b/rfc6979/Cargo.toml @@ -13,7 +13,7 @@ readme = "README.md" categories = ["cryptography", "no-std"] keywords = ["dsa", "ecdsa", "signature"] edition = "2021" -rust-version = "1.72" +rust-version = "1.81" [dependencies] hmac = { version = "=0.13.0-pre.4", default-features = false, features = ["reset"] } diff --git a/slh-dsa/Cargo.toml b/slh-dsa/Cargo.toml index deddafb2..d044fdf3 100644 --- a/slh-dsa/Cargo.toml +++ b/slh-dsa/Cargo.toml @@ -6,7 +6,7 @@ FIPS-205 standard """ version = "0.1.0" edition = "2021" -rust-version = "1.75" +rust-version = "1.81" license = "Apache-2.0 OR MIT" homepage = "https://github.com/RustCrypto/signatures/tree/master/slh-dsa" repository = "https://github.com/RustCrypto/signatures"