diff --git a/Cargo.lock b/Cargo.lock index 78e580899..874fe71da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,7 +6,7 @@ version = 3 name = "blake2" version = "0.10.4" dependencies = [ - "digest", + "digest 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal", ] @@ -56,6 +56,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "git+https://github.com/RustCrypto/traits?rev=refs/pull/1078/head#fc5c8f798dbc2671f63b3cebcb50879bf5bd7fae" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "digest" version = "0.10.3" @@ -64,15 +73,25 @@ checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" dependencies = [ "blobby", "block-buffer", - "crypto-common", + "crypto-common 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "subtle", ] +[[package]] +name = "digest" +version = "0.10.3" +source = "git+https://github.com/RustCrypto/traits?rev=refs/pull/1078/head#fc5c8f798dbc2671f63b3cebcb50879bf5bd7fae" +dependencies = [ + "blobby", + "block-buffer", + "crypto-common 0.1.6 (git+https://github.com/RustCrypto/traits?rev=refs/pull/1078/head)", +] + [[package]] name = "fsb" version = "0.1.2" dependencies = [ - "digest", + "digest 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal", "whirlpool", ] @@ -91,7 +110,7 @@ dependencies = [ name = "gost94" version = "0.10.2" dependencies = [ - "digest", + "digest 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal", ] @@ -99,7 +118,7 @@ dependencies = [ name = "groestl" version = "0.10.1" dependencies = [ - "digest", + "digest 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal", ] @@ -126,7 +145,7 @@ dependencies = [ name = "k12" version = "0.2.1" dependencies = [ - "digest", + "digest 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal", ] @@ -146,7 +165,7 @@ checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" name = "md-5" version = "0.10.1" dependencies = [ - "digest", + "digest 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal", "md5-asm", ] @@ -155,7 +174,7 @@ dependencies = [ name = "md2" version = "0.10.1" dependencies = [ - "digest", + "digest 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal", ] @@ -163,7 +182,7 @@ dependencies = [ name = "md4" version = "0.10.1" dependencies = [ - "digest", + "digest 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal", ] @@ -186,7 +205,7 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" name = "ripemd" version = "0.1.1" dependencies = [ - "digest", + "digest 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal", ] @@ -196,7 +215,7 @@ version = "0.10.1" dependencies = [ "cfg-if", "cpufeatures", - "digest", + "digest 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal", "sha1-asm", ] @@ -216,7 +235,7 @@ version = "0.10.2" dependencies = [ "cfg-if", "cpufeatures", - "digest", + "digest 0.10.3 (git+https://github.com/RustCrypto/traits?rev=refs/pull/1078/head)", "hex-literal", "sha2-asm", ] @@ -234,7 +253,7 @@ dependencies = [ name = "sha3" version = "0.10.2" dependencies = [ - "digest", + "digest 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal", "keccak", ] @@ -243,7 +262,7 @@ dependencies = [ name = "shabal" version = "0.4.1" dependencies = [ - "digest", + "digest 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal", ] @@ -251,7 +270,7 @@ dependencies = [ name = "sm3" version = "0.4.1" dependencies = [ - "digest", + "digest 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal", ] @@ -259,7 +278,7 @@ dependencies = [ name = "streebog" version = "0.10.1" dependencies = [ - "digest", + "digest 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal", ] @@ -273,7 +292,7 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" name = "tiger" version = "0.2.1" dependencies = [ - "digest", + "digest 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal", ] @@ -293,7 +312,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" name = "whirlpool" version = "0.10.1" dependencies = [ - "digest", + "digest 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal", "whirlpool-asm", ] diff --git a/sha2/Cargo.toml b/sha2/Cargo.toml index cc4c783c8..adceb06c2 100644 --- a/sha2/Cargo.toml +++ b/sha2/Cargo.toml @@ -15,7 +15,7 @@ keywords = ["crypto", "sha2", "hash", "digest"] categories = ["cryptography", "no-std"] [dependencies] -digest = "0.10.3" +digest = { git = "https://github.com/RustCrypto/traits", rev = "refs/pull/1078/head" } # TODO change back to #digest = "0.10.3" cfg-if = "1.0" sha2-asm = { version = "0.6.1", optional = true } @@ -23,7 +23,7 @@ sha2-asm = { version = "0.6.1", optional = true } cpufeatures = "0.2" [dev-dependencies] -digest = { version = "0.10.3", features = ["dev"] } +digest = { git = "https://github.com/RustCrypto/traits", rev = "refs/pull/1078/head", features = ["dev"] } # TODO change back to #digest = { version = "0.10.3", features = ["dev"] } hex-literal = "0.2.2" [features] diff --git a/sha2/src/core_api.rs b/sha2/src/core_api.rs index cfec02a64..c7c9dc604 100644 --- a/sha2/src/core_api.rs +++ b/sha2/src/core_api.rs @@ -1,15 +1,37 @@ use crate::{consts, sha256::compress256, sha512::compress512}; -use core::{fmt, slice::from_ref}; +use core::{ + convert::{TryFrom, TryInto}, + fmt, + mem::size_of, + slice::from_ref, +}; use digest::{ block_buffer::Eager, core_api::{ - AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, OutputSizeUser, TruncSide, - UpdateCore, VariableOutputCore, + AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, HashCoreSerializableState, + OutputSizeUser, TruncSide, UpdateCore, VariableOutputCore, }, - typenum::{Unsigned, U128, U32, U64}, + generic_array::GenericArray, + typenum::{Unsigned, U128, U32, U40, U64, U80}, HashMarker, InvalidOutputSize, Output, }; +#[cfg(feature = "std")] +extern crate std; + +/// The error type returned when deserialization of the hash core fails. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub struct HashCoreStateDeserializationError; + +impl fmt::Display for HashCoreStateDeserializationError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.write_str("HashCoreStateDeserializationError") + } +} + +#[cfg(feature = "std")] +impl std::error::Error for HashCoreStateDeserializationError {} + /// Core block-level SHA-256 hasher with variable output size. /// /// Supports initialization only for 28 and 32 byte output sizes, @@ -82,6 +104,57 @@ impl fmt::Debug for Sha256VarCore { } } +impl HashCoreSerializableState for Sha256VarCore { + type SerializedStateSize = U40; +} + +impl Sha256VarCore { + const STATE_SIZE: usize = size_of::(); + const STATE_ELEMENT_SIZE: usize = size_of::(); +} + +impl TryFrom> for Sha256VarCore { + type Error = HashCoreStateDeserializationError; + + fn try_from(serialized_state: GenericArray) -> Result { + let buffer = serialized_state.as_slice(); + + let mut state = [0; consts::STATE_LEN]; + for (i, bytes) in buffer[..Self::STATE_SIZE] + .as_ref() + .chunks(Self::STATE_ELEMENT_SIZE) + .enumerate() + { + state[i] = u32::from_be_bytes(bytes.try_into().unwrap()); + } + + let block_len = u64::from_be_bytes(buffer[Self::STATE_SIZE..].as_ref().try_into().unwrap()); + + Ok(Self { state, block_len }) + } +} + +impl From for GenericArray { + fn from(core: Sha256VarCore) -> Self { + let mut serialized_state = Self::default(); + let buffer = serialized_state.as_mut_slice(); + + for (i, bytes) in buffer[..Sha256VarCore::STATE_SIZE] + .as_mut() + .chunks_mut(Sha256VarCore::STATE_ELEMENT_SIZE) + .enumerate() + { + bytes.copy_from_slice(core.state[i].to_be_bytes().as_slice()); + } + + buffer[Sha256VarCore::STATE_SIZE..] + .as_mut() + .copy_from_slice(core.block_len.to_be_bytes().as_slice()); + + serialized_state + } +} + /// Core block-level SHA-512 hasher with variable output size. /// /// Supports initialization only for 28, 32, 48, and 64 byte output sizes, @@ -155,3 +228,55 @@ impl fmt::Debug for Sha512VarCore { f.write_str("Sha512VarCore { ... }") } } + +impl HashCoreSerializableState for Sha512VarCore { + type SerializedStateSize = U80; +} + +impl Sha512VarCore { + const STATE_SIZE: usize = size_of::(); + const STATE_ELEMENT_SIZE: usize = size_of::(); +} + +impl TryFrom> for Sha512VarCore { + type Error = HashCoreStateDeserializationError; + + fn try_from(serialized_state: GenericArray) -> Result { + let buffer = serialized_state.as_slice(); + + let mut state = [0; consts::STATE_LEN]; + for (i, bytes) in buffer[..Self::STATE_SIZE] + .as_ref() + .chunks(Self::STATE_ELEMENT_SIZE) + .enumerate() + { + state[i] = u64::from_be_bytes(bytes.try_into().unwrap()); + } + + let block_len = + u128::from_be_bytes(buffer[Self::STATE_SIZE..].as_ref().try_into().unwrap()); + + Ok(Self { state, block_len }) + } +} + +impl From for GenericArray { + fn from(core: Sha512VarCore) -> Self { + let mut serialized_state = Self::default(); + let buffer = serialized_state.as_mut_slice(); + + for (i, bytes) in buffer[..Sha512VarCore::STATE_SIZE] + .as_mut() + .chunks_mut(Sha512VarCore::STATE_ELEMENT_SIZE) + .enumerate() + { + bytes.copy_from_slice(core.state[i].to_be_bytes().as_slice()); + } + + buffer[Sha512VarCore::STATE_SIZE..] + .as_mut() + .copy_from_slice(core.block_len.to_be_bytes().as_slice()); + + serialized_state + } +} diff --git a/sha2/src/lib.rs b/sha2/src/lib.rs index 6eeec46e0..c1e34228e 100644 --- a/sha2/src/lib.rs +++ b/sha2/src/lib.rs @@ -56,7 +56,8 @@ pub use digest::{self, Digest}; use digest::{ consts::{U28, U32, U48, U64}, - core_api::{CoreWrapper, CtVariableCoreWrapper}, + core_api::{CoreWrapper, CtVariableCoreWrapper, HashCoreSerializableState}, + generic_array::GenericArray, }; #[rustfmt::skip] @@ -72,15 +73,50 @@ pub use sha512::compress512; pub use core_api::{Sha256VarCore, Sha512VarCore}; +/// SHA-224 core. +pub type Sha224Core = CtVariableCoreWrapper; /// SHA-224 hasher. -pub type Sha224 = CoreWrapper>; +pub type Sha224 = CoreWrapper; +/// SHA-224 core serialized state. +pub type Sha224CoreSerializedState = + GenericArray::SerializedStateSize>; + +/// SHA-256 core. +pub type Sha256Core = CtVariableCoreWrapper; /// SHA-256 hasher. -pub type Sha256 = CoreWrapper>; -/// SHA-512/224 hasher. -pub type Sha512_224 = CoreWrapper>; -/// SHA-512/256 hasher. -pub type Sha512_256 = CoreWrapper>; +pub type Sha256 = CoreWrapper; +/// SHA-256 core serialized state. +pub type Sha256CoreSerializedState = + GenericArray::SerializedStateSize>; + +/// SHA-512/224 core. +pub type Sha512_224Core = CtVariableCoreWrapper; +/// SHA-512/224 core. +pub type Sha512_224 = CoreWrapper; +/// SHA-512/224 core serialized state. +pub type Sha512_224CoreSerializedState = + GenericArray::SerializedStateSize>; + +/// SHA-512/256 core. +pub type Sha512_256Core = CtVariableCoreWrapper; +/// SHA-512/256 core. +pub type Sha512_256 = CoreWrapper; +/// SHA-512/224 core serialized state. +pub type Sha512_256CoreSerializedState = + GenericArray::SerializedStateSize>; + +/// SHA-384 core. +pub type Sha384Core = CtVariableCoreWrapper; /// SHA-384 hasher. -pub type Sha384 = CoreWrapper>; +pub type Sha384 = CoreWrapper; +/// SHA-384 core serialized state. +pub type Sha384CoreSerializedState = + GenericArray::SerializedStateSize>; + +/// SHA-512 core. +pub type Sha512Core = CtVariableCoreWrapper; /// SHA-512 hasher. -pub type Sha512 = CoreWrapper>; +pub type Sha512 = CoreWrapper; +/// SHA-512 core serialized state. +pub type Sha512CoreSerializedState = + GenericArray::SerializedStateSize>; diff --git a/sha2/tests/mod.rs b/sha2/tests/mod.rs index 91df4683b..ddc566e7c 100644 --- a/sha2/tests/mod.rs +++ b/sha2/tests/mod.rs @@ -1,14 +1,63 @@ -use digest::dev::{feed_rand_16mib, fixed_reset_test}; -use digest::new_test; +use core::convert::TryFrom; +use digest::{ + dev::{feed_rand_16mib, fixed_reset_test}, + new_test, test_internal_state, +}; use hex_literal::hex; -use sha2::{Digest, Sha224, Sha256, Sha384, Sha512, Sha512_224, Sha512_256}; +use sha2::{ + Digest, Sha224, Sha224Core, Sha224CoreSerializedState, Sha256, Sha256Core, + Sha256CoreSerializedState, Sha384, Sha384Core, Sha384CoreSerializedState, Sha512, Sha512Core, + Sha512CoreSerializedState, Sha512_224, Sha512_224Core, Sha512_224CoreSerializedState, + Sha512_256, Sha512_256Core, Sha512_256CoreSerializedState, +}; new_test!(sha224_main, "sha224", Sha224, fixed_reset_test); +test_internal_state!( + sha224_internal_state, + Sha224, + Sha224Core, + Sha224CoreSerializedState +); + new_test!(sha256_main, "sha256", Sha256, fixed_reset_test); +test_internal_state!( + sha256_internal_state, + Sha256, + Sha256Core, + Sha256CoreSerializedState +); + new_test!(sha512_224_main, "sha512_224", Sha512_224, fixed_reset_test); +test_internal_state!( + sha512_224_internal_state, + Sha512_224, + Sha512_224Core, + Sha512_224CoreSerializedState +); + new_test!(sha512_256_main, "sha512_256", Sha512_256, fixed_reset_test); +test_internal_state!( + sha512_256_internal_state, + Sha512_256, + Sha512_256Core, + Sha512_256CoreSerializedState +); + new_test!(sha384_main, "sha384", Sha384, fixed_reset_test); +test_internal_state!( + sha384_internal_state, + Sha384, + Sha384Core, + Sha384CoreSerializedState +); + new_test!(sha512_main, "sha512", Sha512, fixed_reset_test); +test_internal_state!( + sha512_internal_state, + Sha512, + Sha512Core, + Sha512CoreSerializedState +); #[test] fn sha256_rand() {