diff --git a/README.md b/README.md index 5423f5c..72c07b6 100755 --- a/README.md +++ b/README.md @@ -18,3 +18,8 @@ apt install binutils-arm-none-eabi gcc-arm-none-eabi # compiler for the target a apt install ruby # ceedling is the used build system for algorithms-c, and needs to be installed with gem, the ruby package manager gem install ceedling ``` + +## Acknowledgements + +For implementing the SHA-2-256 Algorithm, [this](https://sha256algorithm.com/) +website was very helpful. diff --git a/crates/algorithms/src/hash/sha2.rs b/crates/algorithms/src/hash/sha2.rs index ddbefaa..b1aa991 100644 --- a/crates/algorithms/src/hash/sha2.rs +++ b/crates/algorithms/src/hash/sha2.rs @@ -76,7 +76,6 @@ impl Sha2_256Context { Ok(self.intermediate_hash) } - // BUG: false values at end? fn process_block(&mut self) { show_internals!({ self.show_internal_state("start processing"); @@ -93,10 +92,12 @@ impl Sha2_256Context { | (self.block[t4 + 3] as u32); } + // NOTE: The sigma functions used for initializing W and for calculating the alphabet + // variables differ. for t in 16..SHA2_256_BLOCK_SIZE { - w[t] = Self::sha256_sigma1_1(w[t - 2]) + w[t] = Self::sha256_sigma1_w(w[t - 2]) .wrapping_add(w[t - 7]) - .wrapping_add(Self::sha256_sigma0_1(w[t - 15])) + .wrapping_add(Self::sha256_sigma0_w(w[t - 15])) .wrapping_add(w[t - 16]); } @@ -134,13 +135,12 @@ impl Sha2_256Context { println!("Iter {t}"); }); - // BUG: the alphabet values are not being changed correctly? temp1 = h - .wrapping_add(Self::sha256_sigma1_0(e)) + .wrapping_add(Self::sha256_sigma1(e)) .wrapping_add(Self::sha_ch(e, f, g)) .wrapping_add(Self::K[t]) .wrapping_add(w[t]); - temp2 = Self::sha256_sigma0_0(a).wrapping_add(Self::sha_maj(a, b, c)); + temp2 = Self::sha256_sigma0(a).wrapping_add(Self::sha_maj(a, b, c)); h = g; g = f; f = e; @@ -151,6 +151,8 @@ impl Sha2_256Context { a = temp1.wrapping_add(temp2); show_internals!({ + println!("temp1:\t{temp1:032b} {temp1:08x}"); + println!("temp2:\t{temp2:032b} {temp2:08x}"); println!("A:\t{a:032b} {a:08x}"); println!("B:\t{b:032b} {b:08x}"); println!("C:\t{c:032b} {c:08x}"); @@ -180,7 +182,6 @@ impl Sha2_256Context { self.block_idx = 0; - // BUG: something is weird with these hash values, they are almost right? show_internals!({ self.show_internal_state("processing end"); for (i, h) in self.intermediate_hash.iter().enumerate() { @@ -255,25 +256,28 @@ impl Sha2_256Context { #[inline] fn sha256_rotr(bits: u32, word: u32) -> u32 { - u32::rotate_right(word, bits) + word.rotate_right(bits) } - fn sha256_sigma0_0(word: u32) -> u32 { - Self::sha256_rotr(2, word) ^ Self::sha256_rotr(13, word) ^ Self::sha256_shr(22, word) - } - - fn sha256_sigma1_0(word: u32) -> u32 { - Self::sha256_rotr(6, word) ^ Self::sha256_rotr(11, word) ^ Self::sha256_shr(25, word) - } - - fn sha256_sigma0_1(word: u32) -> u32 { + /// This is a different function for W + fn sha256_sigma0_w(word: u32) -> u32 { Self::sha256_rotr(7, word) ^ Self::sha256_rotr(18, word) ^ Self::sha256_shr(3, word) } - fn sha256_sigma1_1(word: u32) -> u32 { + /// This is a different function for W + fn sha256_sigma1_w(word: u32) -> u32 { Self::sha256_rotr(17, word) ^ Self::sha256_rotr(19, word) ^ Self::sha256_shr(10, word) } + // NOTE: these do not use shift right for the last internal variable! + fn sha256_sigma0(word: u32) -> u32 { + Self::sha256_rotr(2, word) ^ Self::sha256_rotr(13, word) ^ Self::sha256_rotr(22, word) + } + + fn sha256_sigma1(word: u32) -> u32 { + Self::sha256_rotr(6, word) ^ Self::sha256_rotr(11, word) ^ Self::sha256_rotr(25, word) + } + #[inline] fn sha_ch(x: u32, y: u32, z: u32) -> u32 { (x & (y ^ z)) ^ z @@ -309,7 +313,7 @@ mod debug { T: core::fmt::Debug + core::fmt::LowerHex, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "[\n")?; + writeln!(f, "[")?; for (i, t) in self.0.iter().enumerate() { write!(f, "0x{t:02x}")?; if i < self.0.len() - 1 { @@ -337,6 +341,7 @@ mod debug { } } #[cfg(feature = "show_internals")] +#[allow(unused)] use debug::*; #[cfg(test)] @@ -345,6 +350,31 @@ mod test { use assert_hex::*; use pretty_assertions::{assert_eq, assert_ne}; + macro_rules! assert_eq_bin { + ($left:expr, $right:expr $(,)?) => ({ + match (&$left, &$right) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + panic!(r#"assertion `left == right` failed + left: {:b} + right: {:b}"#, &*left_val, &*right_val) + } + } + } + }); + ($left:expr, $right:expr, $($arg:tt)+) => ({ + match (&($left), &($right)) { + (left_val, right_val) => { + if !(*left_val == *right_val) { + panic!(r#"assertion `left == right` failed: {} + left: {:b} + right: {:b}"#, format_args!($($arg)+), &*left_val, &*right_val) + } + } + } + }); +} + const TEST_VALUES: &[(&str, Digest256)] = &[ ( "AAAA", @@ -363,7 +393,7 @@ mod test { ]; #[test] - fn test_check() { + fn test_sha256_check() { let mut dig; for (input, expected_output) in TEST_VALUES.iter().copied() { dig = sha2_256_oneshot(input.as_bytes()).unwrap(); @@ -376,4 +406,22 @@ mod test { assert_eq_hex!(dig, expected_output) } } + + #[test] + fn test_sha256_sigma0() { + let a = 0b01101010000010011110011001100111; + assert_eq_bin!( + Sha2_256Context::sha256_sigma0(a), + 0b11001110001000001011010001111110 + ); + } + + #[test] + fn test_sha256_sigma1() { + let a = 0b01010001000011100101001001111111; + assert_eq_bin!( + Sha2_256Context::sha256_sigma1(a), + 0b00110101100001110010011100101011 + ); + } }