From 7e314dcd1b2b6c98fa59c7127a27d425a0e0b7a2 Mon Sep 17 00:00:00 2001 From: SymmetricChaos <42520289+SymmetricChaos@users.noreply.github.com> Date: Tue, 24 Dec 2024 16:38:07 -0500 Subject: [PATCH] reorganizing ascon --- hashers/src/argon2/argon2.rs | 2 +- hashers/src/ascon/hash.rs | 432 ++++++++++++++++-------- hashers/src/ascon/mac.rs | 2 +- hashers/src/ascon/mod.rs | 87 ++++- hashers/src/ascon/tests.rs | 126 +++++++ hashers/src/blake/blake2b.rs | 24 +- src/hasher_panel/ascon_hash_controls.rs | 65 ++-- 7 files changed, 559 insertions(+), 179 deletions(-) create mode 100644 hashers/src/ascon/tests.rs diff --git a/hashers/src/argon2/argon2.rs b/hashers/src/argon2/argon2.rs index bbdbad81..e584dbda 100644 --- a/hashers/src/argon2/argon2.rs +++ b/hashers/src/argon2/argon2.rs @@ -384,7 +384,7 @@ impl ClassicHasher for Argon2 { } // Hash the final value - Blake2bLong::init_hash(64).hash(&c.to_be_bytes()) + Blake2bLong::init_hash(self.tag_len as u64).hash(&c.to_be_bytes()) } fn hash_bytes_from_string(&self, text: &str) -> Result { diff --git a/hashers/src/ascon/hash.rs b/hashers/src/ascon/hash.rs index d380eef6..02647dd2 100644 --- a/hashers/src/ascon/hash.rs +++ b/hashers/src/ascon/hash.rs @@ -1,187 +1,349 @@ -use crate::traits::ClassicHasher; -use strum::EnumIter; -use utils::byte_formatting::ByteFormat; - -use super::AsconState; - -#[derive(Debug, PartialEq, Eq, Copy, Clone, EnumIter)] -pub enum Variant { - AsconHash, - AsconHasha, - AsconXof, - AsconXofa, -} +use utils::byte_formatting::make_u64s_be; -impl std::fmt::Display for Variant { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::AsconHash => write!(f, "Ascon-Hash"), - Self::AsconHasha => write!(f, "Ascon-Hasha"), - Self::AsconXof => write!(f, "Ascon-XOF"), - Self::AsconXofa => write!(f, "Ascon-XOFa"), - } - } +use crate::traits::StatefulHasher; + +use super::{padded_bytes_256, padded_bytes_320, padded_bytes_64, Variant, C, ROTS}; + +pub struct Ascon { + hash_len: usize, + state: [u64; 5], + buffer: Vec, + variant: Variant, } -impl Variant { - pub fn initialize(&self) -> AsconState { - match self { - Variant::AsconHash => AsconState([ +impl Ascon { + // 256-bit hash + pub fn init_hash() -> Self { + Self { + hash_len: 32, + state: [ 0xee9398aadb67f03d, 0x8bb21831c60f1002, 0xb48a92db98d5da62, 0x43189921b8f8e3e8, 0x348fa5c9d525e140, - ]), - Variant::AsconHasha => AsconState([ + ], + buffer: Vec::new(), + variant: Variant::Hash, + } + } + + // 256-bit hash + pub fn init_hasha() -> Self { + Self { + hash_len: 32, + state: [ 0x01470194fc6528a6, 0x738ec38ac0adffa7, 0x2ec8e3296c76384c, 0xd6f6a54d7f52377d, 0xa13c42a223be8d87, - ]), - Variant::AsconXof => AsconState([ + ], + buffer: Vec::new(), + variant: Variant::Hasha, + } + } + + // 128-bit MAC + pub fn init_mac(key: [u8; 16]) -> Self { + let key: [u64; 2] = make_u64s_be(&key); + let mut h = Self { + hash_len: 16, + state: [0x80808c0000000080, key[0], key[1], 0, 0], + buffer: Vec::new(), + variant: Variant::Mac, + }; + h.rounds_12(); + h + } + + // 128-bit MAC + pub fn init_maca(key: [u8; 16]) -> Self { + let key: [u64; 2] = make_u64s_be(&key); + let mut h = Self { + hash_len: 16, + state: [0x80808c0400000080, key[0], key[1], 0, 0], + buffer: Vec::new(), + variant: Variant::Maca, + }; + h.rounds_12(); + h + } + + // Arbitrary length PRF + pub fn init_prf(key: [u8; 16], hash_len: usize) -> Self { + let key: [u64; 2] = make_u64s_be(&key); + let mut h = Self { + hash_len, + state: [0x80808c0000000000, key[0], key[1], 0, 0], + buffer: Vec::new(), + variant: Variant::Prf, + }; + h.rounds_12(); + h + } + + // Arbitrary length PRF + pub fn init_prfa(key: [u8; 16], hash_len: usize) -> Self { + let key: [u64; 2] = make_u64s_be(&key); + let mut h = Self { + hash_len, + state: [0x80808c0400000000, key[0], key[1], 0, 0], + buffer: Vec::new(), + variant: Variant::Prfa, + }; + h.rounds_12(); + h + } + + // Arbitrary length XOF + pub fn init_xof(hash_len: usize) -> Self { + Self { + hash_len, + state: [ 0xb57e273b814cd416, 0x2b51042562ae2420, 0x66a3a7768ddf2218, 0x5aad0a7a8153650c, 0x4f3e0e32539493b6, - ]), - Variant::AsconXofa => AsconState([ + ], + buffer: Vec::new(), + variant: Variant::Xof, + } + } + + // Arbitrary length XOF + pub fn init_xofa(hash_len: usize) -> Self { + Self { + hash_len, + state: [ 0x44906568b77b9832, 0xcd8d6cae53455532, 0xf7b5212756422129, 0x246885e1de0d225b, 0xa8cb5ce33449973f, - ]), + ], + buffer: Vec::new(), + variant: Variant::Xofa, } } -} -pub struct AsconMac { - pub input_format: ByteFormat, - pub output_format: ByteFormat, - pub hash_len: usize, - pub variant: Variant, -} + pub fn hash(bytes: &[u8]) -> Vec { + let mut h = Self::init_hash(); + h.update(bytes); + h.finalize() + } -impl Default for AsconMac { - fn default() -> Self { - Self { - input_format: ByteFormat::Hex, - output_format: ByteFormat::Hex, - hash_len: 32, - variant: Variant::AsconHash, + pub fn hasha(bytes: &[u8]) -> Vec { + let mut h = Self::init_hasha(); + h.update(bytes); + h.finalize() + } + + pub fn mac(bytes: &[u8], key: [u8; 16]) -> Vec { + let mut h = Self::init_mac(key); + h.update(bytes); + h.finalize() + } + + pub fn maca(bytes: &[u8], key: [u8; 16]) -> Vec { + let mut h = Self::init_maca(key); + h.update(bytes); + h.finalize() + } + + pub fn xof(bytes: &[u8], hash_len: usize) -> Vec { + let mut h = Self::init_xof(hash_len); + h.update(bytes); + h.finalize() + } + + pub fn xofa(bytes: &[u8], hash_len: usize) -> Vec { + let mut h = Self::init_xofa(hash_len); + h.update(bytes); + h.finalize() + } + + pub fn prf(bytes: &[u8], key: [u8; 16], hash_len: usize) -> Vec { + let mut h = Self::init_prf(key, hash_len); + h.update(bytes); + h.finalize() + } + + pub fn prfa(bytes: &[u8], key: [u8; 16], hash_len: usize) -> Vec { + let mut h = Self::init_prfa(key, hash_len); + h.update(bytes); + h.finalize() + } + + pub fn rounds_12(&mut self) { + for i in 0..12 { + self.transform(i as usize); } } -} -impl AsconMac { - pub fn ascon_hash() -> Self { - Self { - input_format: ByteFormat::Hex, - output_format: ByteFormat::Hex, - hash_len: 32, - variant: Variant::AsconHash, + pub fn rounds_8(&mut self) { + for i in 0..8 { + self.transform((i + 4) as usize); } } - pub fn ascon_hasha() -> Self { - Self { - input_format: ByteFormat::Hex, - output_format: ByteFormat::Hex, - hash_len: 32, - variant: Variant::AsconHasha, + + pub fn rounds_6(&mut self) { + for i in 0..6 { + self.transform((i + 6) as usize); } } - pub fn ascon_xof(hash_len: usize) -> Self { - Self { - input_format: ByteFormat::Hex, - output_format: ByteFormat::Hex, - hash_len, - variant: Variant::AsconXof, + + pub fn rounds(&mut self, n: usize) { + match n { + 6 => self.rounds_6(), + 8 => self.rounds_8(), + 12 => self.rounds_12(), + _ => unreachable!("only 6, 8, and 12 should be possible"), } } - pub fn ascon_xofa(hash_len: usize) -> Self { - Self { - input_format: ByteFormat::Hex, - output_format: ByteFormat::Hex, - hash_len, - variant: Variant::AsconXofa, + + pub fn transform(&mut self, i: usize) { + // round constant + self.state[2] ^= C[i]; + // substitution + self.sbox(); + // linear diffusion + self.linear_diffusor(); + } + + // The sbox works across words + // It effectively take the nth bit of each word, interprets it as a 5-bit word, then substitutes it + pub fn sbox(&mut self) { + self.state[0] ^= self.state[4]; + self.state[4] ^= self.state[3]; + self.state[2] ^= self.state[1]; + + let mut t = self.state.clone(); + for i in 0..5 { + t[i] ^= !self.state[(i + 1) % 5] & self.state[(i + 2) % 5]; } + + t[1] ^= t[0]; + t[0] ^= t[4]; + t[3] ^= t[2]; + t[2] = !t[2]; + + self.state = t; } -} -impl ClassicHasher for AsconMac { - fn hash(&self, bytes: &[u8]) -> Vec { - let mut state = self.variant.initialize(); + // This diffuses bits within each word of state + pub fn linear_diffusor(&mut self) { + for i in 0..5 { + self.state[i] ^= + self.state[i].rotate_right(ROTS[i].0) ^ self.state[i].rotate_right(ROTS[i].1); + } + } + + pub fn absorb(&mut self) { + let rate = self.variant.rate(); + let mut mlen = self.buffer.len(); + let mut ptr = 0; match self.variant { - Variant::AsconHash | Variant::AsconXof => { - state.absorb_64_hash(&bytes, 12); - state.squeeze_64_hash(self.hash_len, 12) + Variant::Hash | Variant::Hasha | Variant::Xof | Variant::Xofa => { + while mlen >= rate { + self.state[0] ^= padded_bytes_64(&self.buffer[ptr..ptr + rate]); + self.rounds(self.variant.a()); + ptr += rate; + mlen -= rate; + } } - Variant::AsconHasha | Variant::AsconXofa => { - state.absorb_64_hash(&bytes, 8); - state.squeeze_64_hash(self.hash_len, 8) + + Variant::Mac | Variant::Prf => { + while mlen >= rate { + let [x0, x1, x2, x3] = padded_bytes_256(&self.buffer[ptr..ptr + rate]); + self.state[0] ^= x0; + self.state[1] ^= x1; + self.state[2] ^= x2; + self.state[3] ^= x3; + self.rounds(self.variant.a()); + ptr += rate; + mlen -= rate; + } + } + Variant::Maca | Variant::Prfa => { + while mlen >= rate { + let [x0, x1, x2, x3, x4] = padded_bytes_320(&self.buffer[ptr..ptr + rate]); + self.state[0] ^= x0; + self.state[1] ^= x1; + self.state[2] ^= x2; + self.state[3] ^= x3; + self.state[4] ^= x4; + self.rounds(self.variant.a()); + ptr += rate; + mlen -= rate; + } } } + self.buffer = self.buffer[ptr..].to_vec(); } - crate::hash_bytes_from_string! {} -} + pub fn absorb_final_chunk(&mut self) { + match self.variant { + Variant::Hash | Variant::Hasha | Variant::Xof | Variant::Xofa => { + self.state[0] ^= padded_bytes_64(&self.buffer); + self.rounds_12(); + } -#[cfg(test)] -mod ascon_tests { - use super::*; + Variant::Mac | Variant::Prf => { + let [x0, x1, x2, x3] = padded_bytes_256(&self.buffer); + self.state[0] ^= x0; + self.state[1] ^= x1; + self.state[2] ^= x2; + self.state[3] ^= x3; + self.state[4] ^= 1; + } - #[test] - fn test_initialization_hash() { - assert_eq!( - AsconState::initialize(0x00400c0000000100).0, - Variant::AsconHash.initialize().0 - ) + Variant::Maca | Variant::Prfa => { + let [x0, x1, x2, x3, x4] = padded_bytes_320(&self.buffer); + self.state[0] ^= x0; + self.state[1] ^= x1; + self.state[2] ^= x2; + self.state[3] ^= x3; + self.state[4] ^= x4; + self.state[5] ^= 1; + } + } } - #[test] - fn test_initialization_xof() { - assert_eq!( - AsconState::initialize(0x00400c0000000000).0, - Variant::AsconXof.initialize().0 - ) + fn squeeze(&mut self, output: &mut Vec) { + match self.variant { + Variant::Hash | Variant::Hasha | Variant::Xof | Variant::Xofa => { + output.extend(self.state[0].to_be_bytes()); + self.rounds(self.variant.b()); + } + Variant::Mac | Variant::Maca | Variant::Prf | Variant::Prfa => { + output.extend(self.state[0].to_be_bytes()); + output.extend(self.state[1].to_be_bytes()); + self.rounds(self.variant.b()); + } + } } } -pub const INPUT_1: &'static str = ""; -pub const INPUT_2: &'static str = "00"; -pub const INPUT_9: &'static str = "0001020304050607"; -pub const INPUT_1025: &'static str = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; - -crate::basic_hash_tests!( - ascon_hash_1, AsconMac::ascon_hash(), INPUT_1, - "7346bc14f036e87ae03d0997913088f5f68411434b3cf8b54fa796a80d251f91"; - ascon_hash_2, AsconMac::ascon_hash(), INPUT_2, - "8dd446ada58a7740ecf56eb638ef775f7d5c0fd5f0c2bbbdfdec29609d3c43a2"; - ascon_hash_9, AsconMac::ascon_hash(), INPUT_9, - "f4c6a44b29915d3d57cf928a18ec6226bb8dd6c1136acd24965f7e7780cd69cf"; - ascon_hash_1025, AsconMac::ascon_hash(), INPUT_1025, - "2eb89744de7f9a6f47d53db756bb2f67b127da96762a1c47a5d7bfc1f7273f5c"; - - ascon_xof_1, AsconMac::ascon_xof(32), INPUT_1, - "5d4cbde6350ea4c174bd65b5b332f8408f99740b81aa02735eaefbcf0ba0339e"; - ascon_xof_2, AsconMac::ascon_xof(32), INPUT_2, - "b2edbb27ac8397a55bc83d137c151de9ede048338fe907f0d3629e717846fedc"; - ascon_xof_1025, AsconMac::ascon_xof(32), INPUT_1025, - "675b6da0d02ddd65042b7487bdefce06a4be090662ed39a703ad802c977a4b3b"; - - - ascon_hasha_1, AsconMac::ascon_hasha(), INPUT_1, - "aecd027026d0675f9de7a8ad8ccf512db64b1edcf0b20c388a0c7cc617aaa2c4"; - ascon_hasha_2, AsconMac::ascon_hasha(), INPUT_2, - "5a55f0367763d334a3174f9c17fa476eb9196a22f10daf29505633572e7756e4"; - ascon_hasha_1025, AsconMac::ascon_hasha(), INPUT_1025, - "14f6a0c1e5751733955b820ca67bc89bb7eb7014c88caeb5f380d75eed484fe9"; - - ascon_xofa_1, AsconMac::ascon_xofa(32), INPUT_1, - "7c10dffd6bb03be262d72fbe1b0f530013c6c4eadaabde278d6f29d579e3908d"; - ascon_xofa_1025, AsconMac::ascon_xofa(32), INPUT_1025, - "8096e9bb573ea6b2c1d7acac7fb9d9f8f6c89e52a63b1b129037fd4fcc913ffb"; -); +impl StatefulHasher for Ascon { + fn update(&mut self, bytes: &[u8]) { + self.buffer.extend_from_slice(bytes); + self.absorb(); + } + + // Absorb the last block and squeeze the output + fn finalize(mut self) -> Vec { + self.absorb_final_chunk(); + let mut output = Vec::with_capacity(self.hash_len); + + while output.len() < self.hash_len { + self.squeeze(&mut output); + } + + output.truncate(self.hash_len); + output + } + + crate::stateful_hash_helpers!(); +} diff --git a/hashers/src/ascon/mac.rs b/hashers/src/ascon/mac.rs index 25beccf3..673ebff0 100644 --- a/hashers/src/ascon/mac.rs +++ b/hashers/src/ascon/mac.rs @@ -159,7 +159,7 @@ impl ClassicHasher for AsconMac { let mut state = self.variant.initialize(self.key, self.hash_len, bytes); match self.variant { Variant::AsconMac | Variant::AsconPrf => { - state.absorb_256_prf(&bytes, 12); + state.absorb_256_prf(&bytes, 8); state.squeeze_128_prf(self.hash_len as usize, 12) } Variant::AsconMaca | Variant::AsconPrfa => { diff --git a/hashers/src/ascon/mod.rs b/hashers/src/ascon/mod.rs index c56dff47..ff642ac7 100644 --- a/hashers/src/ascon/mod.rs +++ b/hashers/src/ascon/mod.rs @@ -1,8 +1,79 @@ +use strum::EnumIter; + pub mod hash; pub mod mac; +pub mod tests; const DEBUG: bool = false; +#[derive(Debug, PartialEq, Eq, Copy, Clone, EnumIter)] +pub enum Variant { + Hash, + Hasha, + Xof, + Xofa, + Mac, + Maca, + Prf, + Prfa, +} + +impl std::fmt::Display for Variant { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Hash => write!(f, "Ascon-Hash"), + Self::Hasha => write!(f, "Ascon-Hasha"), + Self::Xof => write!(f, "Ascon-XOF"), + Self::Xofa => write!(f, "Ascon-XOFa"), + Self::Mac => write!(f, "Ascon-MAC"), + Self::Maca => write!(f, "Ascon-MACa"), + Self::Prf => write!(f, "Ascon-XOF"), + Self::Prfa => write!(f, "Ascon-XOFa"), + } + } +} + +impl Variant { + pub fn a(&self) -> usize { + match self { + Variant::Hash => 12, + Variant::Hasha => 8, + Variant::Xof => 12, + Variant::Xofa => 8, + Variant::Mac => 12, + Variant::Maca => 8, + Variant::Prf => 12, + Variant::Prfa => 8, + } + } + + pub fn b(&self) -> usize { + match self { + Variant::Hash => 12, + Variant::Hasha => 8, + Variant::Xof => 12, + Variant::Xofa => 8, + Variant::Mac => 12, + Variant::Maca => 12, + Variant::Prf => 12, + Variant::Prfa => 12, + } + } + + pub fn rate(&self) -> usize { + match self { + Variant::Hash => 8, + Variant::Hasha => 8, + Variant::Xof => 8, + Variant::Xofa => 8, + Variant::Mac => 32, + Variant::Maca => 40, + Variant::Prf => 32, + Variant::Prfa => 40, + } + } +} + fn padded_bytes_64(bytes: &[u8]) -> u64 { assert!(bytes.len() <= 8); if bytes.len() == 8 { @@ -150,7 +221,7 @@ const C: [u64; 12] = [ ]; const ROTS: [(u32, u32); 5] = [(19, 28), (61, 39), (1, 6), (10, 17), (7, 41)]; - +const RATE: usize = 8; // number of bytes absorbed at a time #[derive(Debug, Clone)] pub struct AsconState([u64; 5]); @@ -170,8 +241,6 @@ impl std::ops::IndexMut for AsconState { } impl AsconState { - const RATE: usize = 8; // number of bytes absorbed at a time - // Initial state for Ascon-Hash pub fn initialize(iv: u64) -> Self { let mut out = Self([iv, 0, 0, 0, 0]); @@ -261,16 +330,14 @@ impl AsconState { } pub fn absorb_64_hash(&mut self, message: &[u8], a: usize) { - let rate = Self::RATE; - // Encrypt the plaintext treating the last block specially let mut mlen = message.len(); let mut ptr = 0; // Absorb full blocks - while mlen >= rate { - self[0] ^= padded_bytes_64(&message[ptr..ptr + rate]); - ptr += rate; - mlen -= rate; + while mlen >= RATE { + self[0] ^= padded_bytes_64(&message[ptr..ptr + RATE]); + ptr += RATE; + mlen -= RATE; self.rounds(a); if DEBUG { @@ -293,7 +360,7 @@ impl AsconState { let mut ptr = 0; // Absorb full blocks while mlen >= rate { - let [x0, x1, x2, x3] = padded_bytes_256(&message[ptr..ptr + rate]); + let [x0, x1, x2, x3] = padded_bytes_256(&message[ptr..ptr + RATE]); self[0] ^= x0; self[1] ^= x1; self[2] ^= x2; diff --git a/hashers/src/ascon/tests.rs b/hashers/src/ascon/tests.rs new file mode 100644 index 00000000..fff54407 --- /dev/null +++ b/hashers/src/ascon/tests.rs @@ -0,0 +1,126 @@ +pub const INPUT_1: &'static [u8] = &[]; +pub const INPUT_2: &'static [u8] = &[0x00]; +pub const INPUT_9: &'static [u8] = &[0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]; +pub const INPUT_1025: &'static [u8] = &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, +]; + +pub const TEST_KEY: [u8; 16] = [ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, +]; + +use crate::ascon::hash::Ascon; +use crate::traits::StatefulHasher; + +crate::stateful_hash_tests!( + ascon_hash_1, Ascon::init_hash(), INPUT_1, + "7346bc14f036e87ae03d0997913088f5f68411434b3cf8b54fa796a80d251f91"; + ascon_hash_2, Ascon::init_hash(), INPUT_2, + "8dd446ada58a7740ecf56eb638ef775f7d5c0fd5f0c2bbbdfdec29609d3c43a2"; + ascon_hash_9, Ascon::init_hash(), INPUT_9, + "f4c6a44b29915d3d57cf928a18ec6226bb8dd6c1136acd24965f7e7780cd69cf"; + ascon_hash_1025, Ascon::init_hash(), INPUT_1025, + "2eb89744de7f9a6f47d53db756bb2f67b127da96762a1c47a5d7bfc1f7273f5c"; + + ascon_xof_1, Ascon::init_xof(32), INPUT_1, + "5d4cbde6350ea4c174bd65b5b332f8408f99740b81aa02735eaefbcf0ba0339e"; + ascon_xof_2, Ascon::init_xof(32), INPUT_2, + "b2edbb27ac8397a55bc83d137c151de9ede048338fe907f0d3629e717846fedc"; + ascon_xof_1025, Ascon::init_xof(32), INPUT_1025, + "675b6da0d02ddd65042b7487bdefce06a4be090662ed39a703ad802c977a4b3b"; + + + ascon_hasha_1, Ascon::init_hasha(), INPUT_1, + "aecd027026d0675f9de7a8ad8ccf512db64b1edcf0b20c388a0c7cc617aaa2c4"; + ascon_hasha_2, Ascon::init_hasha(), INPUT_2, + "5a55f0367763d334a3174f9c17fa476eb9196a22f10daf29505633572e7756e4"; + ascon_hasha_1025, Ascon::init_hasha(), INPUT_1025, + "14f6a0c1e5751733955b820ca67bc89bb7eb7014c88caeb5f380d75eed484fe9"; + + ascon_xofa_1, Ascon::init_xofa(32), INPUT_1, + "7c10dffd6bb03be262d72fbe1b0f530013c6c4eadaabde278d6f29d579e3908d"; + ascon_xofa_1025, Ascon::init_xofa(32), INPUT_1025, + "8096e9bb573ea6b2c1d7acac7fb9d9f8f6c89e52a63b1b129037fd4fcc913ffb"; + + ascon_prf_1, Ascon::init_prf(TEST_KEY, 16), INPUT_1, + "2a766fe9a4894073bc811b19d54ac33d"; + ascon_prf_2, Ascon::init_prf(TEST_KEY, 16), INPUT_2, + "62dcf5fd8253089b765e2cf1a0d1a4fa"; + ascon_prf_9, Ascon::init_prf(TEST_KEY, 16), INPUT_9, + "25d813eea510ddef67d0152153c35bb8"; + ascon_prf_1025, Ascon::init_prf(TEST_KEY, 16), INPUT_1025, + "3003aba5ab23b18d5ae5230b0c8d6af7"; + + + ascon_prfa_1, Ascon::init_prfa(TEST_KEY, 16), INPUT_1, + "99fdc07ca98af6e6d282e84094cd79cf"; + ascon_prfa_2, Ascon::init_prfa(TEST_KEY, 16), INPUT_2, + "08ae72db8e69d636b9964428dd5feb3f"; + ascon_prfa_9, Ascon::init_prfa(TEST_KEY, 16), INPUT_9, + "55b7ed6b4eda680af96095156a8cdc87"; + ascon_prfa_1025, Ascon::init_prfa(TEST_KEY, 16), INPUT_1025, + "66edf17a4b66dec6176db0fc7c146b89"; +); diff --git a/hashers/src/blake/blake2b.rs b/hashers/src/blake/blake2b.rs index 97b882d3..12734d60 100644 --- a/hashers/src/blake/blake2b.rs +++ b/hashers/src/blake/blake2b.rs @@ -127,18 +127,18 @@ impl Blake2b { self.hash_len } - pub fn state(&self) -> &[u64; 8] { - &self.state - } - - pub fn state_bytes(&self) -> Vec { - self.state - .iter() - .map(|x| x.to_le_bytes()) - .flatten() - .take(self.hash_len as usize) - .collect_vec() - } + // pub fn state(&self) -> &[u64; 8] { + // &self.state + // } + + // pub fn state_bytes(&self) -> Vec { + // self.state + // .iter() + // .map(|x| x.to_le_bytes()) + // .flatten() + // .take(self.hash_len as usize) + // .collect_vec() + // } pub fn hash_256(bytes: &[u8]) -> Vec { let mut h = Self::init_hash_256(); diff --git a/src/hasher_panel/ascon_hash_controls.rs b/src/hasher_panel/ascon_hash_controls.rs index cf6aff4e..7e1bf38d 100644 --- a/src/hasher_panel/ascon_hash_controls.rs +++ b/src/hasher_panel/ascon_hash_controls.rs @@ -1,17 +1,27 @@ -use hashers::ascon::hash::{AsconMac, Variant}; +use hashers::{ + ascon::{hash::Ascon, Variant}, + errors::HasherError, +}; use strum::IntoEnumIterator; +use utils::byte_formatting::ByteFormat; use super::HasherFrame; use crate::ui_elements::UiElements; pub struct AsconHashFrame { - hasher: AsconMac, + input_format: ByteFormat, + output_format: ByteFormat, + variant: Variant, + hash_len: usize, } impl Default for AsconHashFrame { fn default() -> Self { Self { - hasher: AsconMac::default(), + input_format: ByteFormat::Utf8, + output_format: ByteFormat::Hex, + variant: Variant::Hash, + hash_len: 32, } } } @@ -24,39 +34,54 @@ impl HasherFrame for AsconHashFrame { ); ui.add_space(8.0); - 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(4.0); for variant in Variant::iter() { - ui.selectable_value(&mut self.hasher.variant, variant, variant.to_string()); + ui.selectable_value(&mut self.variant, variant, variant.to_string()); } ui.add_space(4.0); ui.subheading("Hash Length"); - match self.hasher.variant { - Variant::AsconHash => { + match self.variant { + Variant::Hash => { ui.label("Ascon-Hash can return a hash of any length from 16 bytes to 32 bytes (128 bits to 256 bits). There are 12 rounds for all steps."); - ui.add(egui::DragValue::new(&mut self.hasher.hash_len).range(16..=32)); + ui.add(egui::DragValue::new(&mut self.hash_len).range(16..=32)); } - Variant::AsconHasha => { + Variant::Hasha => { ui.label("Ascon-Hasha can return a hash of any length from 16 bytes to 32 bytes (128 bits to 256 bits). There are 12 initialization round and 8 rounds for all other steps."); - ui.add(egui::DragValue::new(&mut self.hasher.hash_len).range(16..=32)); + ui.add(egui::DragValue::new(&mut self.hash_len).range(16..=32)); + } + Variant::Xof => { + ui.label("Ascon-XOF can return an output of any length but here is limited to 1024 bytes (4096 bits). There are 12 rounds for all steps."); + ui.add(egui::DragValue::new(&mut self.hash_len).range(1..=1024)); } - Variant::AsconXof => { - ui.label("Ascon-XOF can return an output of any length but here is limited to 512 bytes (4096 bits). There are 12 rounds for all steps."); - ui.add(egui::DragValue::new(&mut self.hasher.hash_len).range(1..=512)); + Variant::Xofa => { + ui.label("Ascon-XOFa can return an output of any length but here is limited to 1024 bytes (4096 bits). There are 12 initialization round and 8 rounds for all other steps."); + ui.add(egui::DragValue::new(&mut self.hash_len).range(1..=1024)); } - Variant::AsconXofa => { - ui.label("Ascon-XOFa can return an output of any length but here is limited to 512 bytes (4096 bits). There are 12 initialization round and 8 rounds for all other steps."); - ui.add(egui::DragValue::new(&mut self.hasher.hash_len).range(1..=512)); + _ => { + ui.error_text("VARIANT NOT COVERED"); } } 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 { + Variant::Hash => Ascon::hash(&bytes), + Variant::Hasha => Ascon::hasha(&bytes), + Variant::Xof => Ascon::xof(self.hash_len, &bytes), + Variant::Xofa => Ascon::xofa(self.hash_len, &bytes), + _ => panic!("VARIANT NOT COVERED"), + }; + + Ok(self.output_format.byte_slice_to_text(&h)) + } }