diff --git a/hashers/src/sha/mod.rs b/hashers/src/sha/mod.rs index a60516eb..02cbda31 100644 --- a/hashers/src/sha/mod.rs +++ b/hashers/src/sha/mod.rs @@ -1,5 +1,4 @@ pub mod keccak_state; -pub mod sha3_stateful; pub use keccak_state::KeccackState; pub mod sha0; pub mod sha512; diff --git a/hashers/src/sha/sha3.rs b/hashers/src/sha/sha3.rs index ee79d31d..9aeeb02b 100644 --- a/hashers/src/sha/sha3.rs +++ b/hashers/src/sha/sha3.rs @@ -1,5 +1,4 @@ -use crate::traits::ClassicHasher; -use utils::byte_formatting::ByteFormat; +use crate::traits::StatefulHasher; use super::KeccackState; @@ -22,7 +21,7 @@ impl Domain { } } - /// Domain separation value combine with with 0x80 byte + /// Domain separation value combined with with 0x80 byte pub fn pad_one(&self) -> u8 { match self { Domain::Keccak => 0x81, @@ -35,67 +34,33 @@ impl Domain { // https://chemejon.wordpress.com/2021/12/06/sha-3-explained-in-plain-english/ pub struct Keccack { - pub input_format: ByteFormat, - pub output_format: ByteFormat, - pub rate: usize, // rate in bytes, block size - pub hash_len: usize, // output length in bytes, recommended to be half the capacity + state: KeccackState, + buffer: Vec, + rate: usize, // rate in bytes, block size + hash_len: usize, // output length in bytes, recommended to be half the capacity // pub function_name: Vec, // pub customization: Vec, - pub domain: Domain, -} - -/// Default to SHA3-256 -impl Default for Keccack { - fn default() -> Self { - Self { - input_format: ByteFormat::Utf8, - output_format: ByteFormat::Hex, - rate: 1152 / 8, - hash_len: 224 / 8, - // function_name: Vec::new(), - // customization: Vec::new(), - domain: Domain::Sha3, - } - } + domain: Domain, } impl Keccack { - /// Input mode - pub fn input(mut self, input: ByteFormat) -> Self { - self.input_format = input; - self - } - - /// Output mode - pub fn output(mut self, output: ByteFormat) -> Self { - self.output_format = output; - self - } - - /// Rate in bytes. Less than or equal to 200. - pub fn rate(mut self, rate: usize) -> Self { + // Rate in bytes. Less than or equal to 200. + fn with_rate(mut self, rate: usize) -> Self { assert!(rate <= 200); self.rate = rate; self } - /// Capacity in bytes. Less than or equal to 200. Sets rate to be 200 - capacity. - pub fn capacity(mut self, capacity: usize) -> Self { - assert!(capacity <= 200); - self.rate = 200 - capacity; - self - } - - /// Length of the output in bytes. - pub fn hash_len(mut self, hash_len: usize) -> Self { + // Length of the output in bytes. + fn with_hash_len(mut self, hash_len: usize) -> Self { self.hash_len = hash_len; self } pub fn sha3() -> Self { Self { - input_format: ByteFormat::Utf8, - output_format: ByteFormat::Hex, + state: KeccackState::new(), + buffer: Vec::new(), rate: 0, hash_len: 0, // function_name: Vec::new(), @@ -106,8 +71,8 @@ impl Keccack { pub fn shake() -> Self { Self { - input_format: ByteFormat::Utf8, - output_format: ByteFormat::Hex, + state: KeccackState::new(), + buffer: Vec::new(), rate: 0, hash_len: 0, // function_name: Vec::new(), @@ -118,8 +83,8 @@ impl Keccack { pub fn cshake() -> Self { Self { - input_format: ByteFormat::Utf8, - output_format: ByteFormat::Hex, + state: KeccackState::new(), + buffer: Vec::new(), rate: 0, hash_len: 0, // function_name: Vec::new(), @@ -130,8 +95,8 @@ impl Keccack { pub fn keccak() -> Self { Self { - input_format: ByteFormat::Utf8, - output_format: ByteFormat::Hex, + state: KeccackState::new(), + buffer: Vec::new(), rate: 0, hash_len: 0, // function_name: Vec::new(), @@ -143,91 +108,121 @@ impl Keccack { // NIST settings /// SHA3-224; rate of 1152 bits pub fn sha3_224() -> Self { - Keccack::sha3().rate(1152 / 8).hash_len(224 / 8) + Keccack::sha3().with_rate(1152 / 8).with_hash_len(224 / 8) } /// SHA3-256; rate of 1088 bits pub fn sha3_256() -> Self { - Keccack::sha3().rate(1088 / 8).hash_len(256 / 8) + Keccack::sha3().with_rate(1088 / 8).with_hash_len(256 / 8) } /// SHA3-382; rate of 832 bits pub fn sha3_384() -> Self { - Keccack::sha3().rate(832 / 8).hash_len(384 / 8) + Keccack::sha3().with_rate(832 / 8).with_hash_len(384 / 8) } /// SHA3-512; rate of 576 bits pub fn sha3_512() -> Self { - Keccack::sha3().rate(576 / 8).hash_len(512 / 8) + Keccack::sha3().with_rate(576 / 8).with_hash_len(512 / 8) } /// SHAKE128; rate of 1344 bits pub fn shake_128(hash_len: usize) -> Self { - Keccack::shake().rate(1344 / 8).hash_len(hash_len) + Keccack::shake().with_rate(1344 / 8).with_hash_len(hash_len) } /// SHAKE256; rate of 1088 bits pub fn shake_256(hash_len: usize) -> Self { - Keccack::shake().rate(1088 / 8).hash_len(hash_len) + Keccack::shake().with_rate(1088 / 8).with_hash_len(hash_len) } /// cSHAKE128; rate of 1344 bits pub fn cshake_128(hash_len: usize) -> Self { - Keccack::cshake().rate(1344 / 8).hash_len(hash_len) + Keccack::cshake() + .with_rate(1344 / 8) + .with_hash_len(hash_len) } /// cSHAKE256; rate of 1088 bits pub fn cshake_256(hash_len: usize) -> Self { - Keccack::cshake().rate(1088 / 8).hash_len(hash_len) + Keccack::cshake() + .with_rate(1088 / 8) + .with_hash_len(hash_len) } } -impl ClassicHasher for Keccack { - fn hash(&self, bytes: &[u8]) -> Vec { - let mut input = bytes.to_vec(); +impl StatefulHasher for Keccack { + fn update(&mut self, bytes: &[u8]) { + self.buffer.extend_from_slice(bytes); + let chunks = self.buffer.chunks_exact(self.rate); + let rem = chunks.remainder().to_vec(); + for chunk in chunks { + self.state.absorb(chunk, self.rate); + } + self.buffer = rem; + } - // Padding rules taken from NIST FIPS-202 - // https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf - // This will never be zero since. Notably if the input length is equal to the rate we push an entire extra block - let padding_len = self.rate - (input.len() % self.rate); + fn finalize(mut self) -> Vec { + let padding_len = self.rate - (self.buffer.len() % self.rate); if padding_len == 1 { // If only one padding bit is needed it combines the domain value and the 0x80 byte - input.push(self.domain.pad_one()); + self.buffer.push(self.domain.pad_one()); } else { // If multiple bits are needed append the domain value and then pad until ending with 0x80 - input.push(self.domain.pad()); - input.extend(vec![0x00; padding_len - 2]); - input.push(0x80) + self.buffer.push(self.domain.pad()); + self.buffer.extend(vec![0x00; padding_len - 2]); + self.buffer.push(0x80) } - let mut state = KeccackState::new(); - state.absorb(&input, self.rate); - state.squeeze(self.rate, self.hash_len) + self.state.absorb(&self.buffer, self.rate); + self.state.squeeze(self.rate, self.hash_len) } - crate::hash_bytes_from_string! {} + crate::stateful_hash_helpers!(); } -crate::basic_hash_tests!( - empty_sha3_224, Keccack::sha3_224(), "", +crate::stateful_hash_tests!( + empty_sha3_224, Keccack::sha3_224(), b"", "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7"; - empty_sha3_256, Keccack::sha3_256(), "", + abc_sha3_224, Keccack::sha3_224(), b"abc", + "e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf"; + long_sha3_224, Keccack::sha3_224(), b"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + "543e6868e1666c1a643630df77367ae5a62a85070a51c14cbf665cbc"; + very_long_sha3_224, Keccack::sha3_224(), &[0x61; 1_000_000], + "d69335b93325192e516a912e6d19a15cb51c6ed5c15243e7a7fd653c"; + + empty_sha3_256, Keccack::sha3_256(), b"", "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"; - empty_sha3_384, Keccack::sha3_384(), "", + abc_sha3_256, Keccack::sha3_256(), b"abc", + "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532"; + long_sha3_256, Keccack::sha3_256(), b"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + "916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18"; + very_long_sha3_256, Keccack::sha3_256(), &[0x61; 1_000_000], + "5c8875ae474a3634ba4fd55ec85bffd661f32aca75c6d699d0cdcb6c115891c1"; + + empty_sha3_384, Keccack::sha3_384(), b"", "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004"; - empty_sha3_512, Keccack::sha3_512(), "", + long_sha3_384, Keccack::sha3_384(), b"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + "79407d3b5916b59c3e30b09822974791c313fb9ecc849e406f23592d04f625dc8c709b98b43b3852b337216179aa7fc7"; + very_long_sha3_384, Keccack::sha3_384(), &[0x61; 1_000_000], + "eee9e24d78c1855337983451df97c8ad9eedf256c6334f8e948d252d5e0e76847aa0774ddb90a842190d2c558b4b8340"; + + empty_sha3_512, Keccack::sha3_512(), b"", "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"; - empty_shake128, Keccack::shake_128(200), "", + long_sha3_512, Keccack::sha3_512(), b"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + "afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185"; + very_long_sha3_512, Keccack::sha3_512(), &[0x61; 1_000_000], + "3c3a876da14034ab60627c077bb98f7e120a2a5370212dffb3385a18d4f38859ed311d0a9d5141ce9cc5c66ee689b266a8aa18ace8282a0e0db596c90b0a7b87"; + + empty_shake128, Keccack::shake_128(200), b"", "7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef263cb1eea988004b93103cfb0aeefd2a686e01fa4a58e8a3639ca8a1e3f9ae57e235b8cc873c23dc62b8d260169afa2f75ab916a58d974918835d25e6a435085b2badfd6dfaac359a5efbb7bcc4b59d538df9a04302e10c8bc1cbf1a0b3a5120ea17cda7cfad765f5623474d368ccca8af0007cd9f5e4c849f167a580b14aabdefaee7eef47cb0fca9767be1fda69419dfb927e9df07348b196691abaeb580b32def58538b8d23f877"; - empty_shake256, Keccack::shake_256(200), "", + empty_shake256, Keccack::shake_256(200), b"", "46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762fd75dc4ddd8c0f200cb05019d67b592f6fc821c49479ab48640292eacb3b7c4be141e96616fb13957692cc7edd0b45ae3dc07223c8e92937bef84bc0eab862853349ec75546f58fb7c2775c38462c5010d846c185c15111e595522a6bcd16cf86f3d122109e3b1fdd943b6aec468a2d621a7c06c6a957c62b54dafc3be87567d677231395f6147293b68ceab7a9e0c58d864e8efde4e1b9a46cbe854713672f5caaae314ed9083dab"; - abc_sha3_224, Keccack::sha3_224().input(ByteFormat::Hex), "616263", - "e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf"; - abc_sha3_256, Keccack::sha3_256(), "abc", - "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532"; - sha3_256_1600_bits, Keccack::sha3_256().input(ByteFormat::Hex), "a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3", + + + sha3_256_1600_bits, Keccack::sha3_256(), &utils::byte_formatting::ByteFormat::Hex.text_to_bytes("a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3").unwrap(), "79f38adec5c20307a98ef76e8324afbfd46cfd81b22e3973c65fa1bd9de31787"; - sha3_256_2008_bits, Keccack::sha3_256().input(ByteFormat::Hex),"83af34279ccb5430febec07a81950d30f4b66f484826afee7456f0071a51e1bbc55570b5cc7ec6f9309c17bf5befdd7c6ba6e968cf218a2b34bd5cf927ab846e38a40bbd81759e9e33381016a755f699df35d660007b5eadf292feefb735207ebf70b5bd17834f7bfa0e16cb219ad4af524ab1ea37334aa66435e5d397fc0a065c411ebbce32c240b90476d307ce802ec82c1c49bc1bec48c0675ec2a6c6f3ed3e5b741d13437095707c565e10d8a20b8c20468ff9514fcf31b4249cd82dcee58c0a2af538b291a87e3390d737191a07484a5d3f3fb8c8f15ce056e5e5f8febe5e1fb59d6740980aa06ca8a0c20f5712b4cde5d032e92ab89f0ae1", + sha3_256_2008_bits, Keccack::sha3_256(), &utils::byte_formatting::ByteFormat::Hex.text_to_bytes("83af34279ccb5430febec07a81950d30f4b66f484826afee7456f0071a51e1bbc55570b5cc7ec6f9309c17bf5befdd7c6ba6e968cf218a2b34bd5cf927ab846e38a40bbd81759e9e33381016a755f699df35d660007b5eadf292feefb735207ebf70b5bd17834f7bfa0e16cb219ad4af524ab1ea37334aa66435e5d397fc0a065c411ebbce32c240b90476d307ce802ec82c1c49bc1bec48c0675ec2a6c6f3ed3e5b741d13437095707c565e10d8a20b8c20468ff9514fcf31b4249cd82dcee58c0a2af538b291a87e3390d737191a07484a5d3f3fb8c8f15ce056e5e5f8febe5e1fb59d6740980aa06ca8a0c20f5712b4cde5d032e92ab89f0ae1").unwrap(), "3298a95cfe59b9d6cab99c36dc1324194c09f97f08944a02d9574bbca3186b41"; ); diff --git a/hashers/src/sha/sha3_stateful.rs b/hashers/src/sha/sha3_stateful.rs deleted file mode 100644 index 9aeeb02b..00000000 --- a/hashers/src/sha/sha3_stateful.rs +++ /dev/null @@ -1,228 +0,0 @@ -use crate::traits::StatefulHasher; - -use super::KeccackState; - -/// There are four domain separation values possible. Each starts with a different padding byte. -pub enum Domain { - Keccak, - Sha3, - Shake, - Cshake, -} - -impl Domain { - /// Domain separation value - pub fn pad(&self) -> u8 { - match self { - Domain::Keccak => 0x01, - Domain::Sha3 => 0x06, - Domain::Shake => 0x1f, - Domain::Cshake => 0x04, - } - } - - /// Domain separation value combined with with 0x80 byte - pub fn pad_one(&self) -> u8 { - match self { - Domain::Keccak => 0x81, - Domain::Sha3 => 0x86, - Domain::Shake => 0x9f, - Domain::Cshake => 0x84, - } - } -} - -// https://chemejon.wordpress.com/2021/12/06/sha-3-explained-in-plain-english/ -pub struct Keccack { - state: KeccackState, - buffer: Vec, - rate: usize, // rate in bytes, block size - hash_len: usize, // output length in bytes, recommended to be half the capacity - // pub function_name: Vec, - // pub customization: Vec, - domain: Domain, -} - -impl Keccack { - // Rate in bytes. Less than or equal to 200. - fn with_rate(mut self, rate: usize) -> Self { - assert!(rate <= 200); - self.rate = rate; - self - } - - // Length of the output in bytes. - fn with_hash_len(mut self, hash_len: usize) -> Self { - self.hash_len = hash_len; - self - } - - pub fn sha3() -> Self { - Self { - state: KeccackState::new(), - buffer: Vec::new(), - rate: 0, - hash_len: 0, - // function_name: Vec::new(), - // customization: Vec::new(), - domain: Domain::Sha3, - } - } - - pub fn shake() -> Self { - Self { - state: KeccackState::new(), - buffer: Vec::new(), - rate: 0, - hash_len: 0, - // function_name: Vec::new(), - // customization: Vec::new(), - domain: Domain::Shake, - } - } - - pub fn cshake() -> Self { - Self { - state: KeccackState::new(), - buffer: Vec::new(), - rate: 0, - hash_len: 0, - // function_name: Vec::new(), - // customization: Vec::new(), - domain: Domain::Cshake, - } - } - - pub fn keccak() -> Self { - Self { - state: KeccackState::new(), - buffer: Vec::new(), - rate: 0, - hash_len: 0, - // function_name: Vec::new(), - // customization: Vec::new(), - domain: Domain::Keccak, - } - } - - // NIST settings - /// SHA3-224; rate of 1152 bits - pub fn sha3_224() -> Self { - Keccack::sha3().with_rate(1152 / 8).with_hash_len(224 / 8) - } - - /// SHA3-256; rate of 1088 bits - pub fn sha3_256() -> Self { - Keccack::sha3().with_rate(1088 / 8).with_hash_len(256 / 8) - } - - /// SHA3-382; rate of 832 bits - pub fn sha3_384() -> Self { - Keccack::sha3().with_rate(832 / 8).with_hash_len(384 / 8) - } - - /// SHA3-512; rate of 576 bits - pub fn sha3_512() -> Self { - Keccack::sha3().with_rate(576 / 8).with_hash_len(512 / 8) - } - - /// SHAKE128; rate of 1344 bits - pub fn shake_128(hash_len: usize) -> Self { - Keccack::shake().with_rate(1344 / 8).with_hash_len(hash_len) - } - - /// SHAKE256; rate of 1088 bits - pub fn shake_256(hash_len: usize) -> Self { - Keccack::shake().with_rate(1088 / 8).with_hash_len(hash_len) - } - - /// cSHAKE128; rate of 1344 bits - pub fn cshake_128(hash_len: usize) -> Self { - Keccack::cshake() - .with_rate(1344 / 8) - .with_hash_len(hash_len) - } - - /// cSHAKE256; rate of 1088 bits - pub fn cshake_256(hash_len: usize) -> Self { - Keccack::cshake() - .with_rate(1088 / 8) - .with_hash_len(hash_len) - } -} - -impl StatefulHasher for Keccack { - fn update(&mut self, bytes: &[u8]) { - self.buffer.extend_from_slice(bytes); - let chunks = self.buffer.chunks_exact(self.rate); - let rem = chunks.remainder().to_vec(); - for chunk in chunks { - self.state.absorb(chunk, self.rate); - } - self.buffer = rem; - } - - fn finalize(mut self) -> Vec { - let padding_len = self.rate - (self.buffer.len() % self.rate); - - if padding_len == 1 { - // If only one padding bit is needed it combines the domain value and the 0x80 byte - self.buffer.push(self.domain.pad_one()); - } else { - // If multiple bits are needed append the domain value and then pad until ending with 0x80 - self.buffer.push(self.domain.pad()); - self.buffer.extend(vec![0x00; padding_len - 2]); - self.buffer.push(0x80) - } - - self.state.absorb(&self.buffer, self.rate); - self.state.squeeze(self.rate, self.hash_len) - } - - crate::stateful_hash_helpers!(); -} - -crate::stateful_hash_tests!( - empty_sha3_224, Keccack::sha3_224(), b"", - "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7"; - abc_sha3_224, Keccack::sha3_224(), b"abc", - "e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf"; - long_sha3_224, Keccack::sha3_224(), b"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", - "543e6868e1666c1a643630df77367ae5a62a85070a51c14cbf665cbc"; - very_long_sha3_224, Keccack::sha3_224(), &[0x61; 1_000_000], - "d69335b93325192e516a912e6d19a15cb51c6ed5c15243e7a7fd653c"; - - empty_sha3_256, Keccack::sha3_256(), b"", - "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"; - abc_sha3_256, Keccack::sha3_256(), b"abc", - "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532"; - long_sha3_256, Keccack::sha3_256(), b"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", - "916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18"; - very_long_sha3_256, Keccack::sha3_256(), &[0x61; 1_000_000], - "5c8875ae474a3634ba4fd55ec85bffd661f32aca75c6d699d0cdcb6c115891c1"; - - empty_sha3_384, Keccack::sha3_384(), b"", - "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004"; - long_sha3_384, Keccack::sha3_384(), b"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", - "79407d3b5916b59c3e30b09822974791c313fb9ecc849e406f23592d04f625dc8c709b98b43b3852b337216179aa7fc7"; - very_long_sha3_384, Keccack::sha3_384(), &[0x61; 1_000_000], - "eee9e24d78c1855337983451df97c8ad9eedf256c6334f8e948d252d5e0e76847aa0774ddb90a842190d2c558b4b8340"; - - empty_sha3_512, Keccack::sha3_512(), b"", - "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"; - long_sha3_512, Keccack::sha3_512(), b"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", - "afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185"; - very_long_sha3_512, Keccack::sha3_512(), &[0x61; 1_000_000], - "3c3a876da14034ab60627c077bb98f7e120a2a5370212dffb3385a18d4f38859ed311d0a9d5141ce9cc5c66ee689b266a8aa18ace8282a0e0db596c90b0a7b87"; - - empty_shake128, Keccack::shake_128(200), b"", - "7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef263cb1eea988004b93103cfb0aeefd2a686e01fa4a58e8a3639ca8a1e3f9ae57e235b8cc873c23dc62b8d260169afa2f75ab916a58d974918835d25e6a435085b2badfd6dfaac359a5efbb7bcc4b59d538df9a04302e10c8bc1cbf1a0b3a5120ea17cda7cfad765f5623474d368ccca8af0007cd9f5e4c849f167a580b14aabdefaee7eef47cb0fca9767be1fda69419dfb927e9df07348b196691abaeb580b32def58538b8d23f877"; - empty_shake256, Keccack::shake_256(200), b"", - "46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762fd75dc4ddd8c0f200cb05019d67b592f6fc821c49479ab48640292eacb3b7c4be141e96616fb13957692cc7edd0b45ae3dc07223c8e92937bef84bc0eab862853349ec75546f58fb7c2775c38462c5010d846c185c15111e595522a6bcd16cf86f3d122109e3b1fdd943b6aec468a2d621a7c06c6a957c62b54dafc3be87567d677231395f6147293b68ceab7a9e0c58d864e8efde4e1b9a46cbe854713672f5caaae314ed9083dab"; - - - sha3_256_1600_bits, Keccack::sha3_256(), &utils::byte_formatting::ByteFormat::Hex.text_to_bytes("a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3").unwrap(), - "79f38adec5c20307a98ef76e8324afbfd46cfd81b22e3973c65fa1bd9de31787"; - sha3_256_2008_bits, Keccack::sha3_256(), &utils::byte_formatting::ByteFormat::Hex.text_to_bytes("83af34279ccb5430febec07a81950d30f4b66f484826afee7456f0071a51e1bbc55570b5cc7ec6f9309c17bf5befdd7c6ba6e968cf218a2b34bd5cf927ab846e38a40bbd81759e9e33381016a755f699df35d660007b5eadf292feefb735207ebf70b5bd17834f7bfa0e16cb219ad4af524ab1ea37334aa66435e5d397fc0a065c411ebbce32c240b90476d307ce802ec82c1c49bc1bec48c0675ec2a6c6f3ed3e5b741d13437095707c565e10d8a20b8c20468ff9514fcf31b4249cd82dcee58c0a2af538b291a87e3390d737191a07484a5d3f3fb8c8f15ce056e5e5f8febe5e1fb59d6740980aa06ca8a0c20f5712b4cde5d032e92ab89f0ae1").unwrap(), - "3298a95cfe59b9d6cab99c36dc1324194c09f97f08944a02d9574bbca3186b41"; -); diff --git a/src/hasher_panel/sha3_controls.rs b/src/hasher_panel/sha3_controls.rs index 1029f146..bf0de360 100644 --- a/src/hasher_panel/sha3_controls.rs +++ b/src/hasher_panel/sha3_controls.rs @@ -1,5 +1,10 @@ use egui::DragValue; -use hashers::sha::{Keccack, KeccackState}; +use hashers::{ + errors::HasherError, + sha::{Keccack, KeccackState}, + traits::StatefulHasher, +}; +use utils::byte_formatting::ByteFormat; use crate::ui_elements::UiElements; @@ -22,7 +27,8 @@ pub enum Sha3Variant { } pub struct Sha3Frame { - hasher: Keccack, + input_format: ByteFormat, + output_format: ByteFormat, variant: Sha3Variant, shake_hash_len: usize, example_state: KeccackState, @@ -32,29 +38,16 @@ pub struct Sha3Frame { impl Default for Sha3Frame { fn default() -> Self { Self { - hasher: Default::default(), + input_format: ByteFormat::Utf8, + output_format: ByteFormat::Hex, variant: Sha3Variant::Sha3_256, shake_hash_len: 128, - example_state: KeccackState::new(), example_round: 0, } } } -impl Sha3Frame { - fn set_hasher(&mut self) { - match self.variant { - Sha3Variant::Sha3_224 => self.hasher = Keccack::sha3_224(), - Sha3Variant::Sha3_256 => self.hasher = Keccack::sha3_256(), - Sha3Variant::Sha3_384 => self.hasher = Keccack::sha3_384(), - Sha3Variant::Sha3_512 => self.hasher = Keccack::sha3_512(), - Sha3Variant::Shake128 => self.hasher = Keccack::shake_128(self.shake_hash_len), - Sha3Variant::Shake256 => self.hasher = Keccack::shake_256(self.shake_hash_len), - } - } -} - impl HasherFrame for Sha3Frame { fn ui(&mut self, ui: &mut egui::Ui, _errors: &mut String) { ui.hyperlink_to( @@ -62,55 +55,29 @@ impl HasherFrame for Sha3Frame { "https://github.com/SymmetricChaos/crypto-gui/blob/master/hashers/src/sha/sha3.rs", ); - ui.byte_io_mode_hasher( - &mut self.hasher.input_format, - &mut self.hasher.output_format, - ); + ui.byte_io_mode_hasher(&mut self.input_format, &mut self.output_format); ui.add_space(16.0); ui.subheading("SHA-3 Hash Algorithms"); ui.horizontal(|ui| { - if ui - .selectable_value(&mut self.variant, Sha3Variant::Sha3_224, "SHA3-224") - .changed() - || ui - .selectable_value(&mut self.variant, Sha3Variant::Sha3_256, "SHA3-256") - .changed() - || ui - .selectable_value(&mut self.variant, Sha3Variant::Sha3_384, "SHA3-384") - .changed() - || ui - .selectable_value(&mut self.variant, Sha3Variant::Sha3_512, "SHA3-512") - .changed() - { - self.set_hasher() - } + ui.selectable_value(&mut self.variant, Sha3Variant::Sha3_224, "SHA3-224"); + ui.selectable_value(&mut self.variant, Sha3Variant::Sha3_256, "SHA3-256"); + ui.selectable_value(&mut self.variant, Sha3Variant::Sha3_384, "SHA3-384"); + ui.selectable_value(&mut self.variant, Sha3Variant::Sha3_512, "SHA3-512"); }); ui.add_space(8.0); ui.subheading("SHA-3 Extensible Output Functions"); ui.horizontal(|ui| { - if ui - .selectable_value(&mut self.variant, Sha3Variant::Shake128, "SHAKE128") - .changed() - || ui - .selectable_value(&mut self.variant, Sha3Variant::Shake256, "SHAKE256") - .changed() - { - self.set_hasher() - } + ui.selectable_value(&mut self.variant, Sha3Variant::Shake128, "SHAKE128"); + ui.selectable_value(&mut self.variant, Sha3Variant::Shake256, "SHAKE256"); }); ui.add_space(8.0); ui.subheading("SHAKE Output Length (in bytes)"); - if ui - .add_enabled( - self.variant == Sha3Variant::Shake128 || self.variant == Sha3Variant::Shake256, - DragValue::new(&mut self.shake_hash_len).range(1..=512), - ) - .changed() - { - self.hasher.hash_len = self.shake_hash_len; - } + ui.add_enabled( + self.variant == Sha3Variant::Shake128 || self.variant == Sha3Variant::Shake256, + DragValue::new(&mut self.shake_hash_len).range(1..=512), + ); ui.add_space(16.0); ui.subheading("Discussion"); @@ -132,11 +99,6 @@ impl HasherFrame for Sha3Frame { ui.horizontal(|ui| { for x in 0..5 { ui.u64_hex_edit(&mut self.example_state[x][y]); - // control_hex_u64( - // ui, - // &mut self.example_state_strings[x][y], - // &mut self.example_state[x][y], - // ); } }); } @@ -176,5 +138,21 @@ impl HasherFrame for Sha3Frame { ui.add_space(16.0); } - crate::hash_string! {} + fn hash_string(&self, text: &str) -> Result { + let bytes = self + .input_format + .text_to_bytes(text) + .map_err(|_| hashers::errors::HasherError::general("byte format error"))?; + + let h = match self.variant { + Sha3Variant::Sha3_224 => Keccack::sha3_224().hash(&bytes), + Sha3Variant::Sha3_256 => Keccack::sha3_256().hash(&bytes), + Sha3Variant::Sha3_384 => Keccack::sha3_384().hash(&bytes), + Sha3Variant::Sha3_512 => Keccack::sha3_512().hash(&bytes), + Sha3Variant::Shake128 => Keccack::shake_128(self.shake_hash_len).hash(&bytes), + Sha3Variant::Shake256 => Keccack::shake_256(self.shake_hash_len).hash(&bytes), + }; + + Ok(self.output_format.byte_slice_to_text(&h)) + } }