From 1d959af79aab9952ca104ffeef053fd5f7b21c55 Mon Sep 17 00:00:00 2001 From: truthixify Date: Wed, 25 Dec 2024 18:15:52 +0100 Subject: [PATCH 01/16] implementation of md6 in pure rust --- md6/.gitignore | 1 + md6/Cargo.toml | 6 + md6/src/lib.rs | 13 ++ md6/src/md6.rs | 498 ++++++++++++++++++++++++++++++++++++++++ md6/src/md6_compress.rs | 331 ++++++++++++++++++++++++++ md6/src/md6_consts.rs | 22 ++ 6 files changed, 871 insertions(+) create mode 100644 md6/.gitignore create mode 100644 md6/Cargo.toml create mode 100644 md6/src/lib.rs create mode 100644 md6/src/md6.rs create mode 100644 md6/src/md6_compress.rs create mode 100644 md6/src/md6_consts.rs diff --git a/md6/.gitignore b/md6/.gitignore new file mode 100644 index 000000000..ea8c4bf7f --- /dev/null +++ b/md6/.gitignore @@ -0,0 +1 @@ +/target diff --git a/md6/Cargo.toml b/md6/Cargo.toml new file mode 100644 index 000000000..1f924e6b2 --- /dev/null +++ b/md6/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "md6" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/md6/src/lib.rs b/md6/src/lib.rs new file mode 100644 index 000000000..f157d35f0 --- /dev/null +++ b/md6/src/lib.rs @@ -0,0 +1,13 @@ +// Adapted from the original C code: https://github.com/brbsh/samp-plugin-md6 + + +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] + +mod md6; +mod md6_compress; +mod md6_consts; + +pub use md6::*; +pub use md6_compress::*; diff --git a/md6/src/md6.rs b/md6/src/md6.rs new file mode 100644 index 000000000..fc8e1bb92 --- /dev/null +++ b/md6/src/md6.rs @@ -0,0 +1,498 @@ +use crate::md6_compress::*; +use crate::md6_consts::*; + +const w: usize = md6_w; // number of bits in a word (64) +const c: usize = md6_c; // size of compression output in words (16) +const k: usize = md6_k; // key words per compression block (8) +const b: usize = md6_b; // data words per compression block (64) + +pub struct MD6State { + d: usize, + hashbitlen: usize, + hashval: [u8; c * (w / 8)], + hexhashval: [char; c * (w / 8) + 1], + initialized: bool, + bits_processed: usize, + compression_calls: usize, + finalized: bool, + K: [md6_word; k], + keylen: usize, + L: usize, + r: usize, + top: usize, + B: [[md6_word; b]; md6_max_stack_height], + bits: [usize; md6_max_stack_height], + i_for_level: [md6_word; md6_max_stack_height], +} + +impl MD6State { + pub fn init(d: usize) -> Self { + // + Self::full_init(d, None, 0, md6_default_L, md6_default_r(d, 0)) + } + + pub fn full_init(d: usize, key: Option>, keylen: usize, L: usize, r: usize) -> Self { + if key.is_some() { + assert!(keylen <= k * (w / 8), "bad keylen"); + } + assert!(!(d < 1 || d > 512 || d > w * c / 2), "bad hashlen"); + + let (K, keylen) = match key { + Some(key) if keylen > 0 => { + let mut key_bytes = vec![0x00; 64]; + key_bytes[..keylen.min(64)].copy_from_slice(&key[..keylen.min(64)]); + + let k_words = bytes_to_words(&key_bytes); + + (k_words.try_into().unwrap(), keylen) + } + _ => ([0u64; k], 0), + }; + + assert!(L <= 255, "bad L"); + assert!(r <= 255, "bad r"); + + let initialized = true; + let finalized = false; + let compression_calls = 0; + let bits_processed = 0; + let hexhashval = ['\n'; c * (w / 8) + 1]; + let hashval = [0; c * (w / 8)]; + let hashbitlen = 0; + let top = 1; + + let mut bits = [0; md6_max_stack_height]; + if L == 0 { + bits[1] = c * w + }; + + let B = [[0; b]; md6_max_stack_height]; + let i_for_level = [0; md6_max_stack_height]; + + MD6State { + d, + hashbitlen, + hashval, + hexhashval, + initialized, + bits_processed, + compression_calls, + finalized, + K, + keylen, + L, + r, + top, + B, + bits, + i_for_level, + } + } + + fn compress_block(&mut self, C: &mut Vec, ell: usize, z: usize) { + // check that input values are sensible + assert!(self.initialized, "state not init"); + assert!(ell < md6_max_stack_height + 1, "stackoverflow"); + + self.compression_calls += 1; + + let p = b * w - self.bits[ell]; // number of padding bits + let Q = get_Q(w); // Q constant + + md6_standard_compress( + C, + Q, + self.K, + ell, + self.i_for_level[ell], + self.r, + self.L, + z, + p, + self.keylen, + self.d, + self.B[ell], + ); + + self.bits[ell] = 0; // clear bits used count this level + self.i_for_level[ell] += 1; // increment i for this level + + self.B[ell] = [0; w]; // clear B for this level + } + + fn process(&mut self, ell: usize, is_final: bool) { + // check that input values are sensible + assert!(self.initialized, "state not init"); + + // not final -- more input will be coming + if !is_final { + // if this is a leaf, then we're done + if self.bits[ell] < b * w { + return; + } + } else { + if ell == self.top { + if ell == self.L + 1 { + /* SEQ node */ + if self.bits[ell] == c * w && self.i_for_level[ell] > 0 { + return; + } + } else { + if ell > 1 && self.bits[ell] == c * w { + return; + } + } + } + } + + let mut C = vec![0x00; c]; // compression output + let z = if is_final && ell == self.top { 1 } else { 0 }; // is this the last block? + + self.compress_block(&mut C, ell, z); // compress block + + // if this is the last block, then we're done + if z == 1 { + self.hashval = words_to_bytes(&C).try_into().unwrap(); + return; + } + + // where should result go? To "next level" + let next_level = (ell + 1).min(self.L + 1); + + if next_level == self.L + 1 + && self.i_for_level[next_level] == 0 + && self.bits[next_level] == 0 + { + self.bits[next_level] = c * w; + } + + self.B[next_level] = C.try_into().unwrap(); // copy C onto the next level + self.bits[next_level] += c * w; + + if next_level > self.top { + self.top = next_level; + } + + self.process(next_level, is_final); + } + + pub fn update(&mut self, data: Vec, databitlen: usize) { + // check that input values are sensible + assert!(self.initialized, "state not init"); + assert!(!data.is_empty(), "null data"); + + let mut j = 0; + while j < databitlen { + let portion_size = (databitlen - j).min(b * w - self.bits[1]); + if (portion_size % 8 == 0) && (self.bits[1] % 8 == 0) && (j % 8 == 0) { + let start = j / 8; + let end = start + portion_size / 8; + let data_slice = &data[start..end]; + let mut i = 0; + + while i < data_slice.len() { + let byte = data_slice[i]; + let index_u64 = i / 8; + let shift_amount = (7 - i % 8) * 8; + + self.B[1][(self.bits[1] / 64) + index_u64] |= (byte as u64) << shift_amount; + + i += 1; + } + } else { + append_bits(&mut self.B[1].to_vec(), self.bits[1], &data[j / 8..], portion_size); + } + + j += portion_size; + self.bits[1] += portion_size; + self.bits_processed += portion_size; + + if self.bits[1] == b * w && j < databitlen { + self.process(1, false); + } + } + } + + fn compute_hex_hashval(&mut self) { + let hex_digits = vec![ + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', + ]; + + for i in 0..((self.d + 7) / 8) { + self.hexhashval[2 * i] = hex_digits[((self.hashval[i] >> 4) & 0xf) as usize]; + self.hexhashval[2 * i + 1] = hex_digits[((self.hashval[i]) & 0xf) as usize]; + } + + self.hexhashval[(self.d + 3) / 4] = '\n'; + } + + fn trim_hashval(&mut self) { + let full_or_partial_bytes = (self.d + 7) / 8; + let bits = self.d % 8; + + // move relevant bytes to the front + for i in 0..full_or_partial_bytes { + self.hashval[i] = self.hashval[c * (w / 8) - full_or_partial_bytes + i]; + } + + // zero out following byte + for i in full_or_partial_bytes..(c * (w / 8)) { + self.hashval[i] = 0; + } + + // shift result left by (8-bits) bit positions, per byte, if needed + if bits > 0 { + for i in 0..full_or_partial_bytes { + self.hashval[i] <<= 8 - bits; + if (i + 1) < c * (w / 8) { + self.hashval[i] |= self.hashval[i + 1] >> bits; + } + } + } + } + + pub fn finalize(&mut self, hashval: &mut Vec) { + // check that input values are sensible + if !self.initialized { + panic!("state not init"); + } + + // "finalize" was previously called + if self.finalized { + return; + } + + let mut ell; + // force any processing that needs doing + if self.top == 1 { + ell = 1; + } else { + ell = 1; + while ell <= self.top { + if self.bits[ell] > 0 { + break; + } + ell += 1; + } + } + + // process starting at level ell, up to root + self.process(ell, true); + + // + self.trim_hashval(); + + if hashval.is_empty() { + hashval.extend(&self.hashval); + } + + self.compute_hex_hashval(); + + self.finalized = true; + } +} + +fn get_Q(wq: usize) -> Vec { + let mut Q = Vec::new(); + if wq == 64 { + Q = vec![ + 0x7311c2812425cfa0, + 0x6432286434aac8e7, + 0xb60450e9ef68b7c1, + 0xe8fb23908d9f06f1, + 0xdd2e76cba691e5bf, + 0x0cd0d63b2c30bc41, + 0x1f8ccf6823058f8a, + 0x54e5ed5b88e3775d, + 0x4ad12aae0a6d6031, + 0x3e7f16bb88222e0d, + 0x8af8671d3fb50c2c, + 0x995ad1178bd25c31, + 0xc878c1dd04c4b633, + 0x3b72066c7a1552ac, + 0x0d6f3522631effcb, + ]; + } else if wq == 32 { + Q = vec![ + 0x7311c281, 0x2425cfa0, 0x64322864, 0x34aac8e7, 0xb60450e9, 0xef68b7c1, 0xe8fb2390, + 0x8d9f06f1, 0xdd2e76cb, 0xa691e5bf, 0x0cd0d63b, 0x2c30bc41, 0x1f8ccf68, 0x23058f8a, + 0x54e5ed5b, 0x88e3775d, 0x4ad12aae, 0x0a6d6031, 0x3e7f16bb, 0x88222e0d, 0x8af8671d, + 0x3fb50c2c, 0x995ad117, 0x8bd25c31, 0xc878c1dd, 0x04c4b633, 0x3b72066c, 0x7a1552ac, + 0x0d6f3522, 0x631effcb, + ] + } else if wq == 16 { + Q = vec![ + 0x7311, 0xc281, 0x2425, 0xcfa0, 0x6432, 0x2864, 0x34aa, 0xc8e7, 0xb604, 0x50e9, 0xef68, + 0xb7c1, 0xe8fb, 0x2390, 0x8d9f, 0x06f1, 0xdd2e, 0x76cb, 0xa691, 0xe5bf, 0x0cd0, 0xd63b, + 0x2c30, 0xbc41, 0x1f8c, 0xcf68, 0x2305, 0x8f8a, 0x54e5, 0xed5b, 0x88e3, 0x775d, 0x4ad1, + 0x2aae, 0x0a6d, 0x6031, 0x3e7f, 0x16bb, 0x8822, 0x2e0d, 0x8af8, 0x671d, 0x3fb5, 0x0c2c, + 0x995a, 0xd117, 0x8bd2, 0x5c31, 0xc878, 0xc1dd, 0x04c4, 0xb633, 0x3b72, 0x066c, 0x7a15, + 0x52ac, 0x0d6f, 0x3522, 0x631e, 0xffcb, + ] + } else if w == 8 { + Q = vec![ + 0x73, 0x11, 0xc2, 0x81, 0x24, 0x25, 0xcf, 0xa0, 0x64, 0x32, 0x28, 0x64, 0x34, 0xaa, + 0xc8, 0xe7, 0xb6, 0x04, 0x50, 0xe9, 0xef, 0x68, 0xb7, 0xc1, 0xe8, 0xfb, 0x23, 0x90, + 0x8d, 0x9f, 0x06, 0xf1, 0xdd, 0x2e, 0x76, 0xcb, 0xa6, 0x91, 0xe5, 0xbf, 0x0c, 0xd0, + 0xd6, 0x3b, 0x2c, 0x30, 0xbc, 0x41, 0x1f, 0x8c, 0xcf, 0x68, 0x23, 0x05, 0x8f, 0x8a, + 0x54, 0xe5, 0xed, 0x5b, 0x88, 0xe3, 0x77, 0x5d, 0x4a, 0xd1, 0x2a, 0xae, 0x0a, 0x6d, + 0x60, 0x31, 0x3e, 0x7f, 0x16, 0xbb, 0x88, 0x22, 0x2e, 0x0d, 0x8a, 0xf8, 0x67, 0x1d, + 0x3f, 0xb5, 0x0c, 0x2c, 0x99, 0x5a, 0xd1, 0x17, 0x8b, 0xd2, 0x5c, 0x31, 0xc8, 0x78, + 0xc1, 0xdd, 0x04, 0xc4, 0xb6, 0x33, 0x3b, 0x72, 0x06, 0x6c, 0x7a, 0x15, 0x52, 0xac, + 0x0d, 0x6f, 0x35, 0x22, 0x63, 0x1e, 0xff, 0xcb, + ] + } + + Q +} + +fn append_bits(dest: &mut Vec, destlen: usize, src: &[u8], srclen: usize) { + if srclen == 0 { + return; + } + + let mut accum: u16 = 0; // Accumulates bits waiting to be moved, right-justified + let mut accumlen = 0; // Number of bits in accumulator + + // Initialize accum, accumlen, and destination index (di) + if destlen % 8 != 0 { + accumlen = destlen % 8; + accum = dest[destlen / 8] as u16; // Grab partial byte from dest + accum >>= 8 - accumlen; // Right-justify it in accumulator + } + let mut di = destlen / 8; // Index of where next byte will go within dest + + // Ensure dest has enough space + let new_len = (destlen + srclen + 7) / 8; + if dest.len() < new_len { + dest.resize(new_len, 0); + } + + // Number of bytes (full or partial) in src + let srcbytes = (srclen + 7) / 8; + + for i in 0..srcbytes { + if i != srcbytes - 1 { + // Not the last byte + accum = (accum << 8) | src[i] as u16; + accumlen += 8; + } else { + // Last byte + let newbits = if srclen % 8 == 0 { 8 } else { srclen % 8 }; + accum = (accum << newbits) | ((src[i] as u16) >> (8 - newbits)); + accumlen += newbits; + } + + // Process as many high-order bits of accum as possible + while (i != srcbytes - 1 && accumlen >= 8) || (i == srcbytes - 1 && accumlen > 0) { + let numbits = std::cmp::min(8, accumlen); + let mut bits = (accum >> (accumlen - numbits)) as u16; // Right justified + bits <<= 8 - numbits; // Left justified + bits &= 0xff00 >> numbits; // Mask + let bits = bits as u8; + dest[di] = bits as u64; // Save + di += 1; + accumlen -= numbits; + } + } +} + + +fn md6_default_r(d: usize, keylen: usize) -> usize { + // Default number of rounds is forty plus floor(d/4) + let mut r = 40 + (d / 4); + + // unless keylen > 0, in which case it must be >= 80 as well + if keylen > 0 { + r = 80.max(r); + } + + r +} + +fn bytes_to_words(bytes: &[u8]) -> Vec { + // Convert bytes to words + bytes + .chunks(8) + .map(|chunk| { + chunk + .iter() + .rev() + .fold(0u64, |acc, &byte| (acc << 8) | u64::from(byte)) + }) + .collect() +} + +fn words_to_bytes(words: &[u64]) -> Vec { + // Convert words to bytes + words + .iter() + .flat_map(|&word| (0..8).rev().map(move |shift| (word >> (shift * 8)) as u8)) + .collect() +} + +pub fn md6_full_hash( + d: usize, + data: Vec, + databitlen: usize, + key: Option>, + keylen: usize, + L: usize, + r: usize, + hashval: &mut Vec, +) { + let mut st = MD6State::full_init(d, key, keylen, L, r); + st.update(data, databitlen); + st.finalize(hashval); +} + +pub fn md6_hash(d: usize, data: Vec, databitlen: usize, hashval: &mut Vec) { + md6_full_hash( + d, + data, + databitlen, + None, + 0, + md6_default_L, + md6_default_r(d, 0), + hashval, + ); +} + +#[test] +fn test_md6() { + // Test from https://web.archive.org/web/20170812072847/https://groups.csail.mit.edu/cis/md6/submitted-2008-10-27/Supporting_Documentation/md6_report.pdf + let test_vector: [(&str, usize, Option>, usize, usize, usize, &str); 1] = [ + ( + "abc", + 256, + None, + 0, + md6_default_L, + 5, + "8854c14dc284f840ed71ad7ba542855ce189633e48c797a55121a746be48cec8", + ), + ]; + + for (msg, hashbitlen, key, keylen, L, r, expected_hex) in test_vector { + let mut output = vec![]; + + md6_full_hash( + hashbitlen, + msg.as_bytes().to_vec(), + msg.as_bytes().len() * 8, + key, + keylen, + L, + r, + &mut output, + ); + + let digest_hex = output[..hashbitlen / 8] + .into_iter() + .map(|o| format!("{:02x}", o)) + .collect::(); + + assert_eq!(digest_hex, expected_hex); + } +} diff --git a/md6/src/md6_compress.rs b/md6/src/md6_compress.rs new file mode 100644 index 000000000..42b29be9e --- /dev/null +++ b/md6/src/md6_compress.rs @@ -0,0 +1,331 @@ +use crate::md6_consts::*; + +const w: usize = md6_w; // number of bits in a word (64) +const c: usize = md6_c; // size of compression output in words (16) +const n: usize = md6_n; // size of compression input block in words (89) +const q: usize = md6_q; // Q words in a compression block (>= 0) (15) +const k: usize = md6_k; // key words per compression block (>= 0) (8) +const u: usize = md6_u; // words for unique node ID (0 or 64/w) +const v: usize = md6_v; // words for control word (0 or 64/w) +const b: usize = md6_b; // data words per compression block (> 0) (64) + +const t0: usize = 17; // index for linear feedback +const t1: usize = 18; // index for first input to first and +const t2: usize = 21; // index for second input to first and +const t3: usize = 31; // index for first input to second and +const t4: usize = 67; // index for second input to second and +const t5: usize = 89; // last tap + +/// Macro to call loop bodies based on the value of `w`. +/// +/// This macro takes three arguments: +/// - `w`: The md6_word parameter which determines the set of loop bodies to call. +/// - `S`: A round constant passed to the `loop_body` macro. +/// - `i`: An index passed to the `loop_body` macro. +/// +/// Depending on the value of `w`, this macro will call a specific set of `loop_body` invocations +/// with predefined parameters. The possible values for `w` are 64, 32, 16, and 8. Each value +/// corresponds to a different set of `loop_body` calls with specific parameters. +/// +/// # Parameters +/// - `w`: The md6_word parameter (must be one of 64, 32, 16, or 8). +/// - `S`: A round constant to be passed to each `loop_body` call. +/// - `i`: An index to be passed to each `loop_body` call. +macro_rules! call_loop_bodies { + ($w: ident, $S: expr, $i: expr) => { + if $w == 64 { + loop_body!(10, 11, 0, $S, $i); + loop_body!(5, 24, 1, $S, $i); + loop_body!(13, 9, 2, $S, $i); + loop_body!(10, 16, 3, $S, $i); + loop_body!(11, 15, 4, $S, $i); + loop_body!(12, 9, 5, $S, $i); + loop_body!(2, 27, 6, $S, $i); + loop_body!(7, 15, 7, $S, $i); + loop_body!(14, 6, 8, $S, $i); + loop_body!(15, 2, 9, $S, $i); + loop_body!(7, 29, 10, $S, $i); + loop_body!(13, 8, 11, $S, $i); + loop_body!(11, 15, 12, $S, $i); + loop_body!(7, 5, 13, $S, $i); + loop_body!(6, 31, 14, $S, $i); + loop_body!(12, 9, 15, $S, $i); + } else if $w == 32 { + loop_body!(5, 4, 0, $S, $i); + loop_body!(3, 7, 1, $S, $i); + loop_body!(6, 7, 2, $S, $i); + loop_body!(5, 9, 3, $S, $i); + loop_body!(4, 13, 4, $S, $i); + loop_body!(6, 8, 5, $S, $i); + loop_body!(7, 4, 6, $S, $i); + loop_body!(3, 14, 7, $S, $i); + loop_body!(5, 7, 8, $S, $i); + loop_body!(6, 4, 9, $S, $i); + loop_body!(5, 8, 10, $S, $i); + loop_body!(5, 11, 11, $S, $i); + loop_body!(4, 5, 12, $S, $i); + loop_body!(6, 8, 13, $S, $i); + loop_body!(7, 2, 14, $S, $i); + loop_body!(5, 11, 15, $S, $i); + } else if $w == 16 { + loop_body!(5, 6, 0, $S, $i); + loop_body!(4, 7, 1, $S, $i); + loop_body!(3, 2, 2, $S, $i); + loop_body!(5, 4, 3, $S, $i); + loop_body!(7, 2, 4, $S, $i); + loop_body!(5, 6, 5, $S, $i); + loop_body!(5, 3, 6, $S, $i); + loop_body!(2, 7, 7, $S, $i); + loop_body!(4, 5, 8, $S, $i); + loop_body!(3, 7, 9, $S, $i); + loop_body!(4, 6, 10, $S, $i); + loop_body!(3, 5, 11, $S, $i); + loop_body!(4, 5, 12, $S, $i); + loop_body!(7, 6, 13, $S, $i); + loop_body!(7, 4, 14, $S, $i); + loop_body!(2, 3, 15, $S, $i); + } else if $w == 8 { + loop_body!(3, 2, 0, $S, $i); + loop_body!(3, 4, 1, $S, $i); + loop_body!(3, 2, 2, $S, $i); + loop_body!(4, 3, 3, $S, $i); + loop_body!(3, 2, 4, $S, $i); + loop_body!(3, 2, 5, $S, $i); + loop_body!(3, 2, 6, $S, $i); + loop_body!(3, 4, 7, $S, $i); + loop_body!(2, 3, 8, $S, $i); + loop_body!(2, 3, 9, $S, $i); + loop_body!(3, 2, 10, $S, $i); + loop_body!(2, 3, 11, $S, $i); + loop_body!(2, 3, 12, $S, $i); + loop_body!(3, 4, 13, $S, $i); + loop_body!(2, 3, 14, $S, $i); + loop_body!(3, 4, 15, $S, $i); + } + }; +} + +/// Returns the initial values for `S` and `Smask` based on the width `ws`. +/// +/// # Parameters +/// - `ws`: The width parameter (must be one of 64, 32, 16, or 8). +/// +/// # Returns +/// A tuple containing the initial values for `S` and `Smask`. +/// +/// # Panics +/// Panics if `ws` is not one of the expected values. +fn get_S_vals(ws: usize) -> (md6_word, md6_word) { + match ws { + 64 => (0x0123456789abcdef, 0x7311c2812425cfa0), + 32 => (0x01234567, 0x7311c281), + 16 => (0x01234, 0x7311), + 8 => (0x01, 0x73), + _ => panic!("bad w"), + } +} + +/// Main compression loop for MD6. +/// +/// This function performs the main compression loop for the MD6 hash function. +/// +/// # Parameters +/// - `A`: A mutable reference to a vector of `md6_word` values. +/// - `r`: The number of rounds to perform. +fn md6_main_compression_loop(A: &mut Vec, r: usize) { + macro_rules! loop_body { + ($rs: expr, $ls: expr, $step: expr, $S: expr, $i: expr) => { + let mut x = $S; // feedback constant + x ^= A[$i + $step - t5]; // end-around feedback + x ^= A[$i + $step - t0]; // linear feedback + x ^= (A[$i + $step - t1] & A[$i + $step - t2]); // first quadratic term + x ^= (A[$i + $step - t3] & A[$i + $step - t4]); // second quadratic term + x ^= x >> $rs; // right shift + A[$i + $step] = x ^ (x << $ls); // left shift + }; + } + + // Get the initial values for `S` and `Smask` based on the width `w`. + let (mut S, Smask) = get_S_vals(w); + + let mut i = n; + let mut j = 0; + + while j < r * c { + // Call the loop bodies based on the value of `w`. + // This will perform the main computation for each step in the compression loop. + call_loop_bodies!(w, S, i); + + // Advance round constant S to the next round constant. + S = (S << 1) ^ (S >> (w - 1)) ^ (S & Smask); + i += 16; + j += c; + } +} + +/// Compresses the input data using the MD6 compression function. +/// +/// # Parameters +/// - `C`: A mutable reference to a vector of `md6_word` values (output). +/// - `N`: A mutable reference to a vector of `md6_word` values (input). +/// - `r`: The number of rounds to perform. +/// - `A`: A mutable reference to a vector of `md6_word` values (working space). +/// +/// # Panics +/// Panics if any of the input vectors are empty or if `r` exceeds `md6_max_r`. +pub fn md6_compress(C: &mut Vec, N: &mut Vec, r: usize, A: &mut Vec) { + // check that the input is sensible + assert!(!N.is_empty()); + assert!(!C.is_empty()); + assert!(r <= md6_max_r); + assert!(!A.is_empty()); + + A[..N.len()].copy_from_slice(&N); // copy N to front of A + + md6_main_compression_loop(A, r); // do the main computation + + C.copy_from_slice(&A[((r - 1) * c + n)..((r - 1) * c + n + c)]); // output into C +} + +/// Creates a control word for the MD6 hash function. +/// +/// # Parameters +/// - `r`: The number of rounds. +/// - `L`: The level of the node. +/// - `z`: The final node indicator. +/// - `p`: The padding length. +/// - `keylen`: The length of the key. +/// - `d`: The digest length. +/// +/// # Returns +/// The control word as an `md6_control_word`. +fn md6_make_control_word( + r: usize, + L: usize, + z: usize, + p: usize, + keylen: usize, + d: usize, +) -> md6_control_word { + let V = (0 as md6_control_word) << 60 // reserved width 4 bits + | (r as md6_control_word) << 48 // r width 12 bits + | (L as md6_control_word) << 40 // L width 8 bits + | (z as md6_control_word) << 36 // z width 4 bits + | (p as md6_control_word) << 20 // p width 16 bits + | (keylen as md6_control_word) << 12 // keylen width 8 bits + | (d as md6_control_word); // d width 12 bits + V +} + +/// Creates a node ID for the MD6 hash function. +/// +/// # Parameters +/// - `ell`: The level of the node. +/// - `i`: The index of the node. +/// +/// # Returns +/// The node ID as an `md6_nodeID`. +pub fn md6_make_nodeID(ell: usize, i: md6_word) -> md6_nodeID { + let U: md6_nodeID = (ell as md6_nodeID) << 56 | i; // ell width 8 bits, i width 56 bits + + U +} + +/// Packs the input data into the `N` vector for the MD6 compression function. +/// +/// # Parameters +/// - `N`: A mutable reference to a vector of `md6_word` values (output). +/// - `Q`: A vector of `md6_word` values (input). +/// - `K`: An array of `md6_word` values (key). +/// - `ell`: The level of the node. +/// - `i`: The index of the node. +/// - `r`: The number of rounds. +/// - `L`: The level of the node. +/// - `z`: The final node indicator. +/// - `p`: The padding length. +/// - `keylen`: The length of the key. +/// - `d`: The digest length. +/// - `B`: An array of `md6_word` values (input block). +pub fn md6_pack( + N: &mut Vec, + Q: Vec, + K: [md6_word; k], + ell: usize, + i: md6_word, + r: usize, + L: usize, + z: usize, + p: usize, + keylen: usize, + d: usize, + B: [md6_word; 64], +) { + let mut ni = 0; + + N[ni..ni + q].copy_from_slice(&Q[..q]); // Q: Q in words 0--14 + ni += q; + + N[ni..ni + k].copy_from_slice(&K[..k]); // K: key in words 15--22 + ni += k; + + let U = md6_make_nodeID(ell, i); // U: unique node ID in 23 + N[ni] = U; + ni += u; + + let V = md6_make_control_word(r, L, z, p, keylen, d); // V: control word in 24 + N[ni] = V; + ni += v; + + N[ni..ni + b].copy_from_slice(&B[..b]); // B: data words 25--88 +} + +/// Standard compression function for the MD6 hash function. +/// +/// # Parameters +/// - `C`: A mutable reference to a vector of `md6_word` values (output). +/// - `Q`: A vector of `md6_word` values (input). +/// - `K`: An array of `md6_word` values (key). +/// - `ell`: The level of the node. +/// - `i`: The index of the node. +/// - `r`: The number of rounds. +/// - `L`: The level of the node. +/// - `z`: The final node indicator. +/// - `p`: The padding length. +/// - `keylen`: The length of the key. +/// - `d`: The digest length. +/// - `B`: An array of `md6_word` values (input block). +/// +/// # Panics +/// Panics if any of the input vectors are empty or if any of the parameters are out of range. +pub fn md6_standard_compress( + C: &mut Vec, + Q: Vec, + K: [md6_word; k], + ell: usize, + i: md6_word, + r: usize, + L: usize, + z: usize, + p: usize, + keylen: usize, + d: usize, + B: [md6_word; 64], +) { + let mut N = vec![0; md6_n]; + let mut A = vec![0; 5000]; + + // check that the input values are sensible + assert!(!C.is_empty()); + assert!(!Q.is_empty()); + assert!(!B.is_empty()); + assert!(r <= md6_max_r); + assert!(L <= 255); + assert!(ell <= 255); + assert!(p <= b * w); + assert!(d <= c * w / 2); + assert!(!K.is_empty()); + + md6_pack(&mut N, Q, K, ell, i, r, L, z, p, keylen, d, B); // pack input data into N + + md6_compress(C, &mut N, r, &mut A); // compress +} diff --git a/md6/src/md6_consts.rs b/md6/src/md6_consts.rs new file mode 100644 index 000000000..38727028c --- /dev/null +++ b/md6/src/md6_consts.rs @@ -0,0 +1,22 @@ + +/// MD6 constants related to standard mode of operation + +pub type md6_word = u64; +pub type md6_control_word = u64; +pub type md6_nodeID = u64; + +pub const md6_max_stack_height: usize = 29; // maximum stack height +pub const md6_max_r: usize = 255; // maximum number of rounds +pub const md6_default_L: usize = 64; // large so that MD6 is fully hierarchical + +pub const md6_w: usize = 64; // number of bits in a word +pub const md6_c: usize = 16; // size of compression output in words +pub const md6_n: usize = 89; // size of compression input block in words + +/// These five values give lengths of the components of compression +/// input block; they should sum to md6_n. +pub const md6_q: usize = 15; // Q words in a compression block (>= 0) +pub const md6_k: usize = 8; // key words per compression block (>= 0) +pub const md6_u: usize = 64 / md6_w; // words for unique node ID (0 or 64/w) +pub const md6_v: usize = 64 / md6_w; // words for control word (0 or 64/w) +pub const md6_b: usize = 64; // data words per compression block (> 0) From 6adbabaebd88e44bae8962703d2a5a74bb538c52 Mon Sep 17 00:00:00 2001 From: truthixify Date: Sun, 29 Dec 2024 08:36:16 +0100 Subject: [PATCH 02/16] no_std md6 implementation --- Cargo.lock | 9 + Cargo.toml | 1 + md6/.gitignore | 1 - md6/Cargo.toml | 27 ++ md6/README.md | 0 md6/src/compress.rs | 233 ++++++++++++++ md6/src/consts.rs | 21 ++ md6/src/lib.rs | 43 ++- md6/src/md6.rs | 684 ++++++++++++++++++++++++++-------------- md6/src/md6_compress.rs | 331 ------------------- md6/src/md6_consts.rs | 22 -- 11 files changed, 781 insertions(+), 591 deletions(-) delete mode 100644 md6/.gitignore create mode 100644 md6/README.md create mode 100644 md6/src/compress.rs create mode 100644 md6/src/consts.rs delete mode 100644 md6/src/md6_compress.rs delete mode 100644 md6/src/md6_consts.rs diff --git a/Cargo.lock b/Cargo.lock index f53521082..36b63ab9e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -244,6 +244,15 @@ dependencies = [ "hex-literal", ] +[[package]] +name = "md6" +version = "0.1.0" +dependencies = [ + "base16ct", + "digest", + "hex-literal", +] + [[package]] name = "ppv-lite86" version = "0.2.20" diff --git a/Cargo.toml b/Cargo.toml index e13018a46..3222cccfb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ members = [ "md2", "md4", "md5", + "md6", "ripemd", "sha1", "sha1-checked", diff --git a/md6/.gitignore b/md6/.gitignore deleted file mode 100644 index ea8c4bf7f..000000000 --- a/md6/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target diff --git a/md6/Cargo.toml b/md6/Cargo.toml index 1f924e6b2..b338a5a44 100644 --- a/md6/Cargo.toml +++ b/md6/Cargo.toml @@ -1,6 +1,33 @@ [package] name = "md6" version = "0.1.0" +description = "MD6 hash function" +authors = ["RustCrypto Developers"] +license = "MIT OR Apache-2.0" +readme = "README.md" edition = "2021" +repository = "https://github.com/RustCrypto/hashes" +keywords = ["crypto", "md5", "hash", "digest"] +categories = ["cryptography", "no-std"] +rust-version = "1.81" + +[lib] +name = "md6" [dependencies] +digest = "=0.11.0-pre.9" + +[dev-dependencies] +digest = { version = "=0.11.0-pre.9", features = ["dev"] } +hex-literal = "0.4" +base16ct = { version = "0.2", features = ["alloc"] } + +[features] +default = ["oid", "std"] +std = ["digest/std"] +oid = ["digest/oid"] +zeroize = ["digest/zeroize"] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff --git a/md6/README.md b/md6/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/md6/src/compress.rs b/md6/src/compress.rs new file mode 100644 index 000000000..10c96e536 --- /dev/null +++ b/md6/src/compress.rs @@ -0,0 +1,233 @@ +use crate::consts::*; + +const W: usize = MD6_W; // number of bits in a word (64) +const C: usize = MD6_C; // size of compression output in words (16) +const N: usize = MD6_N; // size of compression input block in words (89) +const Q: usize = MD6_Q; // Q words in a compression block (>= 0) (15) +const K: usize = MD6_K; // key words per compression block (>= 0) (8) +const U: usize = MD6_U; // words for unique node ID (0 or 64/w) +const V: usize = MD6_V; // words for control word (0 or 64/w) +const B: usize = MD6_B; // data words per compression block (> 0) (64) + +const T0: usize = 17; // index for linear feedback +const T1: usize = 18; // index for first input to first and +const T2: usize = 21; // index for second input to first and +const T3: usize = 31; // index for first input to second and +const T4: usize = 67; // index for second input to second and +const T5: usize = 89; // last tap + +macro_rules! call_loop_bodies { + ($w: ident, $s: expr, $i: expr) => { + if $w == 64 { + loop_body!(10, 11, 0, $s, $i); + loop_body!(5, 24, 1, $s, $i); + loop_body!(13, 9, 2, $s, $i); + loop_body!(10, 16, 3, $s, $i); + loop_body!(11, 15, 4, $s, $i); + loop_body!(12, 9, 5, $s, $i); + loop_body!(2, 27, 6, $s, $i); + loop_body!(7, 15, 7, $s, $i); + loop_body!(14, 6, 8, $s, $i); + loop_body!(15, 2, 9, $s, $i); + loop_body!(7, 29, 10, $s, $i); + loop_body!(13, 8, 11, $s, $i); + loop_body!(11, 15, 12, $s, $i); + loop_body!(7, 5, 13, $s, $i); + loop_body!(6, 31, 14, $s, $i); + loop_body!(12, 9, 15, $s, $i); + } else if $w == 32 { + loop_body!(5, 4, 0, $s, $i); + loop_body!(3, 7, 1, $s, $i); + loop_body!(6, 7, 2, $s, $i); + loop_body!(5, 9, 3, $s, $i); + loop_body!(4, 13, 4, $s, $i); + loop_body!(6, 8, 5, $s, $i); + loop_body!(7, 4, 6, $s, $i); + loop_body!(3, 14, 7, $s, $i); + loop_body!(5, 7, 8, $s, $i); + loop_body!(6, 4, 9, $s, $i); + loop_body!(5, 8, 10, $s, $i); + loop_body!(5, 11, 11, $s, $i); + loop_body!(4, 5, 12, $s, $i); + loop_body!(6, 8, 13, $s, $i); + loop_body!(7, 2, 14, $s, $i); + loop_body!(5, 11, 15, $s, $i); + } else if $w == 16 { + loop_body!(5, 6, 0, $s, $i); + loop_body!(4, 7, 1, $s, $i); + loop_body!(3, 2, 2, $s, $i); + loop_body!(5, 4, 3, $s, $i); + loop_body!(7, 2, 4, $s, $i); + loop_body!(5, 6, 5, $s, $i); + loop_body!(5, 3, 6, $s, $i); + loop_body!(2, 7, 7, $s, $i); + loop_body!(4, 5, 8, $s, $i); + loop_body!(3, 7, 9, $s, $i); + loop_body!(4, 6, 10, $s, $i); + loop_body!(3, 5, 11, $s, $i); + loop_body!(4, 5, 12, $s, $i); + loop_body!(7, 6, 13, $s, $i); + loop_body!(7, 4, 14, $s, $i); + loop_body!(2, 3, 15, $s, $i); + } else if $w == 8 { + loop_body!(3, 2, 0, $s, $i); + loop_body!(3, 4, 1, $s, $i); + loop_body!(3, 2, 2, $s, $i); + loop_body!(4, 3, 3, $s, $i); + loop_body!(3, 2, 4, $s, $i); + loop_body!(3, 2, 5, $s, $i); + loop_body!(3, 2, 6, $s, $i); + loop_body!(3, 4, 7, $s, $i); + loop_body!(2, 3, 8, $s, $i); + loop_body!(2, 3, 9, $s, $i); + loop_body!(3, 2, 10, $s, $i); + loop_body!(2, 3, 11, $s, $i); + loop_body!(2, 3, 12, $s, $i); + loop_body!(3, 4, 13, $s, $i); + loop_body!(2, 3, 14, $s, $i); + loop_body!(3, 4, 15, $s, $i); + } + }; +} + +fn get_s_constants(ws: usize) -> (Md6Word, Md6Word) { + match ws { + 64 => (0x0123456789abcdef, 0x7311c2812425cfa0), + 32 => (0x01234567, 0x7311c281), + 16 => (0x01234, 0x7311), + 8 => (0x01, 0x73), + _ => panic!("bad w"), + } +} + +fn main_compression_loop(a: &mut [Md6Word], r: usize) { + macro_rules! loop_body { + ($rs: expr, $ls: expr, $step: expr, $s: expr, $i: expr) => { + let mut x = $s; // feedback constant + x ^= a[$i + $step - T5]; // end-around feedback + x ^= a[$i + $step - T0]; // linear feedback + x ^= (a[$i + $step - T1] & a[$i + $step - T2]); // first quadratic term + x ^= (a[$i + $step - T3] & a[$i + $step - T4]); // second quadratic term + x ^= x >> $rs; // right shift + a[$i + $step] = x ^ (x << $ls); // left shift + }; + } + + // Get the initial values for `s` and `smask` based on the width `w`. + let (mut s, smask) = get_s_constants(W); + + let mut i = N; + let mut j = 0; + + while j < r * C { + // Call the loop bodies based on the value of `w`. + // This will perform the main computation for each step in the compression loop. + call_loop_bodies!(W, s, i); + + // Advance round constant s to the next round constant. + s = (s << 1) ^ (s >> (W - 1)) ^ (s & smask); + i += 16; + j += C; + } +} + +pub fn compress(c: &mut [Md6Word], n: &mut [Md6Word], r: usize, a: &mut [Md6Word]) { + // check that the input is sensible + assert!(!n.is_empty()); + assert!(!n.is_empty()); + assert!(r <= MD6_MAX_R); + assert!(!a.is_empty()); + + a[..n.len()].copy_from_slice(n); // copy n to front of a + + main_compression_loop(a, r); // do the main computation + + c.copy_from_slice(&a[((r - 1) * C + N)..((r - 1) * C + N + C)]); // output into c +} + +fn make_control_word( + r: usize, + l: usize, + z: usize, + p: usize, + keylen: usize, + d: usize, +) -> Md6ControlWord { + (0 as Md6ControlWord) << 60 // reserved width 4 bits + | (r as Md6ControlWord) << 48 // r width 12 bits + | (l as Md6ControlWord) << 40 // L width 8 bits + | (z as Md6ControlWord) << 36 // z width 4 bits + | (p as Md6ControlWord) << 20 // p width 16 bits + | (keylen as Md6ControlWord) << 12 // keylen width 8 bits + | (d as Md6ControlWord) // d width 12 bits +} + +pub fn make_node_id(ell: usize, i: Md6Word) -> Md6NodeID { + (ell as Md6NodeID) << 56 | i // ell width 8 bits, i width 56 bits +} + +pub fn pack( + n: &mut [Md6Word], + q: &[Md6Word], + k: [Md6Word; K], + ell: usize, + i: Md6Word, + r: usize, + l: usize, + z: usize, + p: usize, + keylen: usize, + d: usize, + b: [Md6Word; 64], +) { + let mut ni = 0; + + n[ni..ni + Q].copy_from_slice(&q[..Q]); // q: q in words 0--14 + ni += Q; + + n[ni..ni + K].copy_from_slice(&k[..K]); // k: key in words 15--22 + ni += K; + + let u = make_node_id(ell, i); // u: unique node ID in 23 + n[ni] = u; + ni += U; + + let v = make_control_word(r, l, z, p, keylen, d); // v: control word in 24 + n[ni] = v; + ni += V; + + n[ni..ni + B].copy_from_slice(&b[..B]); // b: data words 25--88 +} + +pub fn standard_compress( + c: &mut [Md6Word], + q: &[Md6Word], + k: [Md6Word; K], + ell: usize, + i: Md6Word, + r: usize, + l: usize, + z: usize, + p: usize, + keylen: usize, + d: usize, + b: [Md6Word; 64], +) { + let mut n = [0; MD6_N]; + let mut a = [0; 5000]; + + // check that the input values are sensible + assert!(!c.is_empty()); + assert!(!q.is_empty()); + assert!(!b.is_empty()); + assert!(r <= MD6_MAX_R); + assert!(l <= 255); + assert!(ell <= 255); + assert!(p <= B * W); + assert!(d <= C * W / 2); + assert!(!k.is_empty()); + + pack(&mut n, q, k, ell, i, r, l, z, p, keylen, d, b); // pack input data into N + + compress(c, &mut n, r, &mut a); // compress +} diff --git a/md6/src/consts.rs b/md6/src/consts.rs new file mode 100644 index 000000000..307b3d281 --- /dev/null +++ b/md6/src/consts.rs @@ -0,0 +1,21 @@ +/// MD6 constants related to standard mode of operation + +pub(crate) type Md6Word = u64; +pub(crate) type Md6ControlWord = u64; +pub(crate) type Md6NodeID = u64; + +pub(crate) const MD6_MAX_STACK_HEIGHT: usize = 29; // maximum stack height +pub(crate) const MD6_MAX_R: usize = 255; // maximum number of rounds +pub(crate) const MD6_DEFAULT_L: usize = 64; // large so that MD6 is fully hierarchical + +pub(crate) const MD6_W: usize = 64; // number of bits in a word +pub(crate) const MD6_C: usize = 16; // size of compression output in words +pub(crate) const MD6_N: usize = 89; // size of compression input block in words + +/// These five values give lengths of the components of compression +/// input block; they should sum to MD6_N. +pub(crate) const MD6_Q: usize = 15; // Q words in a compression block (>= 0) +pub(crate) const MD6_K: usize = 8; // key words per compression block (>= 0) +pub(crate) const MD6_U: usize = 64 / MD6_W; // words for unique node ID (0 or 64/w) +pub(crate) const MD6_V: usize = 64 / MD6_W; // words for control word (0 or 64/w) +pub(crate) const MD6_B: usize = 64; // data words per compression block (> 0) diff --git a/md6/src/lib.rs b/md6/src/lib.rs index f157d35f0..2c22534fa 100644 --- a/md6/src/lib.rs +++ b/md6/src/lib.rs @@ -1,13 +1,38 @@ -// Adapted from the original C code: https://github.com/brbsh/samp-plugin-md6 +#![no_std] +#![doc = include_str!("../README.md")] +#![doc( + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" +)] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![warn(missing_docs, rust_2018_idioms)] +mod compress; +pub(crate) mod consts; +mod md6; -#![allow(non_snake_case)] -#![allow(non_upper_case_globals)] -#![allow(non_camel_case_types)] +use digest::{ + consts::{U16, U28, U32, U48, U64, U8}, + core_api::{CoreWrapper, CtVariableCoreWrapper, RtVariableCoreWrapper}, +}; -mod md6; -mod md6_compress; -mod md6_consts; +pub use digest::{Digest, Update, VariableOutput}; + +use crate::md6::Md6VarCore; -pub use md6::*; -pub use md6_compress::*; +/// Md6 which allows variable output size at runtime +pub type Md6Var = RtVariableCoreWrapper; +/// Core hash function for Md6 generic over output size +pub type Md6Core = CtVariableCoreWrapper; +/// Md6 with 64-bit output +pub type Md6_64 = CoreWrapper>; +/// Md6 with 128-bit output +pub type Md6_128 = CoreWrapper>; +/// Md6 with 224-bit output +pub type Md6_224 = CoreWrapper>; +/// Md6 with 256-bit output +pub type Md6_256 = CoreWrapper>; +/// Md6 with 384-bit output +pub type Md6_384 = CoreWrapper>; +/// Md6 with 512-bit output +pub type Md6_512 = CoreWrapper>; diff --git a/md6/src/md6.rs b/md6/src/md6.rs index fc8e1bb92..2a5f12b7f 100644 --- a/md6/src/md6.rs +++ b/md6/src/md6.rs @@ -1,75 +1,340 @@ -use crate::md6_compress::*; -use crate::md6_consts::*; - -const w: usize = md6_w; // number of bits in a word (64) -const c: usize = md6_c; // size of compression output in words (16) -const k: usize = md6_k; // key words per compression block (8) -const b: usize = md6_b; // data words per compression block (64) - -pub struct MD6State { +use crate::compress::*; +use crate::consts::*; + +use core::fmt; +use digest::{ + block_buffer::Eager, + core_api::{ + AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, OutputSizeUser, Reset, + TruncSide, UpdateCore, VariableOutputCore, + }, + crypto_common::hazmat::{DeserializeStateError, SerializableState, SerializedState}, + typenum::{Unsigned, U128, U64}, + HashMarker, Output, +}; + +const W: usize = MD6_W; // number of bits in a word (64) +const C: usize = MD6_C; // size of compression output in words (16) +const K: usize = MD6_K; // key words per compression block (8) +const B: usize = MD6_B; // data words per compression block (64) + +pub struct Md6VarCore { d: usize, hashbitlen: usize, - hashval: [u8; c * (w / 8)], - hexhashval: [char; c * (w / 8) + 1], + hashval: [u8; C * (W / 8)], + hexhashval: [char; C * (W / 8) + 1], initialized: bool, bits_processed: usize, compression_calls: usize, finalized: bool, - K: [md6_word; k], + k: [Md6Word; K], keylen: usize, - L: usize, + l: usize, r: usize, top: usize, - B: [[md6_word; b]; md6_max_stack_height], - bits: [usize; md6_max_stack_height], - i_for_level: [md6_word; md6_max_stack_height], + b: [[Md6Word; B]; MD6_MAX_STACK_HEIGHT], + bits: [usize; MD6_MAX_STACK_HEIGHT], + i_for_level: [u64; MD6_MAX_STACK_HEIGHT], +} + +impl HashMarker for Md6VarCore {} + +impl BlockSizeUser for Md6VarCore { + type BlockSize = U128; +} + +impl BufferKindUser for Md6VarCore { + type BufferKind = Eager; +} + +impl OutputSizeUser for Md6VarCore { + type OutputSize = U64; +} + +impl UpdateCore for Md6VarCore { + #[inline] + fn update_blocks(&mut self, blocks: &[Block]) { + for block in blocks { + self.update(block, block.len() * 8); + } + } +} + +impl VariableOutputCore for Md6VarCore { + const TRUNC_SIDE: TruncSide = TruncSide::Left; + + #[inline] + fn new(output_size: usize) -> Result { + if output_size > Self::OutputSize::USIZE { + return Err(digest::InvalidOutputSize); + } + + Ok(Self::init(output_size * 8)) + } + + #[inline] + fn finalize_variable_core(&mut self, buffer: &mut Buffer, out: &mut Output) { + let databitlen = buffer.get_pos() * 8; + let block = buffer.pad_with_zeros(); + self.update(&block, databitlen); + + // Create a temporary buffer to store the hash value + let mut hashval = [0u8; 128]; + + // Finalize the hash computation + self.finalize(&mut hashval); + + // Copy the resulting hash value into the output slice + for (i, o) in out.iter_mut().enumerate() { + *o = hashval[i]; + } + } +} + +impl AlgorithmName for Md6VarCore { + fn write_alg_name(f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.write_str("Md6") + } +} + +impl Default for Md6VarCore { + #[inline] + fn default() -> Self { + Self::init(256) + } +} + +impl Reset for Md6VarCore { + #[inline] + fn reset(&mut self) { + *self = Self::init(self.d); + } +} + +impl fmt::Debug for Md6VarCore { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Md6Core { ... }") + } +} + +impl Drop for Md6VarCore { + fn drop(&mut self) { + #[cfg(feature = "zeroize")] + { + self.hashval.zeroize(); + self.hexhashval.zeroize(); + self.k.zeroize(); + self.b.zeroize(); + self.bits.zeroize(); + self.i_for_level.zeroize(); + self.d.zeroize(); + self.hashbitlen.zeroize(); + self.keylen.zeroize(); + self.l.zeroize(); + self.r.zeroize(); + self.top.zeroize(); + self.compression_calls.zeroize(); + self.bits_processed.zeroize(); + self.initialized.zeroize(); + self.finalized.zeroize(); + } + } +} + +impl SerializableState for Md6VarCore { + type SerializedStateSize = U64; + + fn serialize(&self) -> SerializedState { + let mut serialized_state = SerializedState::::default(); + + // Serialize usize fields + serialized_state.copy_from_slice(&self.d.to_le_bytes()); + serialized_state.copy_from_slice(&self.hashbitlen.to_le_bytes()); + serialized_state.copy_from_slice(&self.bits_processed.to_le_bytes()); + serialized_state.copy_from_slice(&self.compression_calls.to_le_bytes()); + serialized_state.copy_from_slice(&self.keylen.to_le_bytes()); + serialized_state.copy_from_slice(&self.l.to_le_bytes()); + serialized_state.copy_from_slice(&self.r.to_le_bytes()); + serialized_state.copy_from_slice(&self.top.to_le_bytes()); + + // Serialize boolean fields + serialized_state.copy_from_slice(&(self.initialized as u8).to_le_bytes()); + serialized_state.copy_from_slice(&(self.finalized as u8).to_le_bytes()); + + // Serialize arrays + serialized_state.copy_from_slice(&self.hashval); + for &c in &self.hexhashval { + serialized_state.copy_from_slice(&(c as u32).to_le_bytes()); + } + for &word in &self.k { + serialized_state.copy_from_slice(&word.to_le_bytes()); + } + for row in &self.b { + for &word in row { + serialized_state.copy_from_slice(&word.to_le_bytes()); + } + } + for &bit in &self.bits { + serialized_state.copy_from_slice(&bit.to_le_bytes()); + } + for &level in &self.i_for_level { + serialized_state.copy_from_slice(&level.to_le_bytes()); + } + + serialized_state + } + + fn deserialize( + serialized_state: &SerializedState, + ) -> Result { + let mut offset = 0; + + // Helper function to read a usize from the serialized state + fn read_usize(serialized_state: &[u8], offset: &mut usize) -> usize { + let size = core::mem::size_of::(); + let mut buf = [0u8; core::mem::size_of::()]; + buf.copy_from_slice(&serialized_state[*offset..*offset + size]); + *offset += size; + usize::from_le_bytes(buf) + } + + // Helper function to read a u64 from the serialized state + fn read_u64(serialized_state: &[u8], offset: &mut usize) -> u64 { + let size = 8; + let mut buf = [0u8; 8]; + buf.copy_from_slice(&serialized_state[*offset..*offset + size]); + *offset += size; + u64::from_le_bytes(buf) + } + + // Helper function to read a boolean from the serialized state + fn read_bool(serialized: &[u8], offset: &mut usize) -> bool { + let val = serialized[*offset]; + *offset += 1; + val != 0 + } + + // Deserialize usize fields + let d = read_usize(serialized_state, &mut offset); + let hashbitlen = read_usize(serialized_state, &mut offset); + let bits_processed = read_usize(serialized_state, &mut offset); + let compression_calls = read_usize(serialized_state, &mut offset); + let keylen = read_usize(serialized_state, &mut offset); + let l = read_usize(serialized_state, &mut offset); + let r = read_usize(serialized_state, &mut offset); + let top = read_usize(serialized_state, &mut offset); + + // Deserialize boolean fields + let initialized = read_bool(serialized_state, &mut offset); + let finalized = read_bool(serialized_state, &mut offset); + + // Deserialize arrays + let hashval_len = C * (W / 8); + let mut hashval = [0u8; C * (W / 8)]; + hashval.copy_from_slice(&serialized_state[offset..offset + hashval_len]); + offset += hashval_len; + + let mut hexhashval = ['\0'; C * (W / 8) + 1]; + for c in &mut hexhashval { + let size = 4; + let mut buf = [0u8; 4]; + buf.copy_from_slice(&serialized_state[offset..offset + size]); + offset += size; + *c = char::from_u32(u32::from_le_bytes(buf)).expect("invalid char in serialized state"); + } + + let mut k = [0u64; K]; + for word in &mut k { + *word = read_u64(&serialized_state, &mut offset); + } + + let mut b = [[0u64; B]; MD6_MAX_STACK_HEIGHT]; + for row in &mut b { + for word in row.iter_mut() { + *word = read_u64(serialized_state, &mut offset); + } + } + + let mut bits = [0usize; MD6_MAX_STACK_HEIGHT]; + for bit in &mut bits { + *bit = read_usize(serialized_state, &mut offset); + } + + let mut i_for_level = [0u64; MD6_MAX_STACK_HEIGHT]; + for level in &mut i_for_level { + *level = read_u64(serialized_state, &mut offset); + } + + Ok(Self { + d, + hashbitlen, + hashval, + hexhashval, + initialized, + bits_processed, + compression_calls, + finalized, + k, + keylen, + l, + r, + top, + b, + bits, + i_for_level, + }) + } } -impl MD6State { - pub fn init(d: usize) -> Self { +impl Md6VarCore { + #[inline] + fn init(d: usize) -> Self { // - Self::full_init(d, None, 0, md6_default_L, md6_default_r(d, 0)) + Self::full_init(d, None, 0, MD6_DEFAULT_L, default_r(d, 0)) } - pub fn full_init(d: usize, key: Option>, keylen: usize, L: usize, r: usize) -> Self { + #[inline] + fn full_init(d: usize, key: Option<&[u8]>, keylen: usize, l: usize, r: usize) -> Self { if key.is_some() { - assert!(keylen <= k * (w / 8), "bad keylen"); + assert!(keylen <= K * (W / 8), "bad keylen"); } - assert!(!(d < 1 || d > 512 || d > w * c / 2), "bad hashlen"); + assert!(!(d < 1 || d > 512 || d > W * C / 2), "bad hashlen"); - let (K, keylen) = match key { + let (k, keylen) = match key { Some(key) if keylen > 0 => { - let mut key_bytes = vec![0x00; 64]; + let mut key_bytes = [0x00; 64]; key_bytes[..keylen.min(64)].copy_from_slice(&key[..keylen.min(64)]); - let k_words = bytes_to_words(&key_bytes); + let mut k_words = [0; K]; + + bytes_to_words(&key_bytes, &mut k_words); - (k_words.try_into().unwrap(), keylen) + (k_words, keylen) } - _ => ([0u64; k], 0), + _ => ([0u64; K], 0), }; - assert!(L <= 255, "bad L"); + assert!(l <= 255, "bad L"); assert!(r <= 255, "bad r"); let initialized = true; let finalized = false; let compression_calls = 0; let bits_processed = 0; - let hexhashval = ['\n'; c * (w / 8) + 1]; - let hashval = [0; c * (w / 8)]; + let hexhashval = ['\n'; C * (W / 8) + 1]; + let hashval = [0; C * (W / 8)]; let hashbitlen = 0; let top = 1; - let mut bits = [0; md6_max_stack_height]; - if L == 0 { - bits[1] = c * w + let mut bits = [0; MD6_MAX_STACK_HEIGHT]; + if l == 0 { + bits[1] = C * W }; - let B = [[0; b]; md6_max_stack_height]; - let i_for_level = [0; md6_max_stack_height]; + let b = [[0; B]; MD6_MAX_STACK_HEIGHT]; + let i_for_level = [0; MD6_MAX_STACK_HEIGHT]; - MD6State { + Md6VarCore { d, hashbitlen, hashval, @@ -78,48 +343,50 @@ impl MD6State { bits_processed, compression_calls, finalized, - K, + k, keylen, - L, + l, r, top, - B, + b, bits, i_for_level, } } - fn compress_block(&mut self, C: &mut Vec, ell: usize, z: usize) { + #[inline] + fn compress_block(&mut self, c: &mut [u64], ell: usize, z: usize) { // check that input values are sensible assert!(self.initialized, "state not init"); - assert!(ell < md6_max_stack_height + 1, "stackoverflow"); + assert!(ell < MD6_MAX_STACK_HEIGHT + 1, "stackoverflow"); self.compression_calls += 1; - let p = b * w - self.bits[ell]; // number of padding bits - let Q = get_Q(w); // Q constant + let p = B * W - self.bits[ell]; // number of padding bits + let q = get_round_constants(W); // Q constant - md6_standard_compress( - C, - Q, - self.K, + standard_compress( + c, + q, + self.k, ell, self.i_for_level[ell], self.r, - self.L, + self.l, z, p, self.keylen, self.d, - self.B[ell], + self.b[ell], ); self.bits[ell] = 0; // clear bits used count this level self.i_for_level[ell] += 1; // increment i for this level - self.B[ell] = [0; w]; // clear B for this level + self.b[ell] = [0; W]; // clear B for this level } + #[inline] fn process(&mut self, ell: usize, is_final: bool) { // check that input values are sensible assert!(self.initialized, "state not init"); @@ -127,47 +394,43 @@ impl MD6State { // not final -- more input will be coming if !is_final { // if this is a leaf, then we're done - if self.bits[ell] < b * w { + if self.bits[ell] < B * W { return; } - } else { - if ell == self.top { - if ell == self.L + 1 { - /* SEQ node */ - if self.bits[ell] == c * w && self.i_for_level[ell] > 0 { - return; - } - } else { - if ell > 1 && self.bits[ell] == c * w { - return; - } + } else if ell == self.top { + if ell == self.l + 1 { + // SEQ node + if self.bits[ell] == C * W && self.i_for_level[ell] > 0 { + return; } + } else if ell > 1 && self.bits[ell] == C * W { + return; } } - let mut C = vec![0x00; c]; // compression output - let z = if is_final && ell == self.top { 1 } else { 0 }; // is this the last block? + let mut c = [0x00; C]; // compression output + let z = if is_final && ell == self.top { 1 } else { 0 }; // is this the last block - self.compress_block(&mut C, ell, z); // compress block + self.compress_block(&mut c, ell, z); // compress block // if this is the last block, then we're done if z == 1 { - self.hashval = words_to_bytes(&C).try_into().unwrap(); + words_to_bytes(&c, &mut self.hashval); return; } - // where should result go? To "next level" - let next_level = (ell + 1).min(self.L + 1); + // where should result go To "next level" + let next_level = (ell + 1).min(self.l + 1); - if next_level == self.L + 1 + if next_level == self.l + 1 && self.i_for_level[next_level] == 0 && self.bits[next_level] == 0 { - self.bits[next_level] = c * w; + self.bits[next_level] = C * W; } - self.B[next_level] = C.try_into().unwrap(); // copy C onto the next level - self.bits[next_level] += c * w; + self.b[next_level][..C].copy_from_slice(&c); // copy c onto the next level + self.bits[next_level] += C * W; if next_level > self.top { self.top = next_level; @@ -176,14 +439,68 @@ impl MD6State { self.process(next_level, is_final); } - pub fn update(&mut self, data: Vec, databitlen: usize) { + #[inline] + fn append_bits(&mut self, src: &[u8], srclen: usize) { + if srclen == 0 { + return; + } + + let mut accum: u16 = 0; // Accumulates bits waiting to be moved, right-justified + let mut accumlen = 0; // Number of bits in accumulator + let destlen = self.bits[1]; + + // Initialize accum, accumlen, and destination index (di) + if destlen % 8 != 0 { + accumlen = destlen % 8; + accum = self.b[1][destlen / 8] as u16; // Grab partial byte from dest + accum >>= 8 - accumlen; // Right-justify it in accumulator + } + let mut di = destlen / 8; // Index of where next byte will go within dest + + // Ensure dest has enough space + let new_len = (destlen + srclen + 7) / 8; + if self.b[1].len() < new_len { + panic!("destination buffer is too small"); + } + + // Number of bytes (full or partial) in src + let srcbytes = (srclen + 7) / 8; + + for i in 0..srcbytes { + if i != srcbytes - 1 { + // Not the last byte + accum = (accum << 8) ^ src[i] as u16; + accumlen += 8; + } else { + // Last byte + let newbits = if srclen % 8 == 0 { 8 } else { srclen % 8 }; + accum = (accum << newbits) ^ ((src[i] as u16) >> (8 - newbits)); + accumlen += newbits; + } + + // Process as many high-order bits of accum as possible + while (i != srcbytes - 1 && accumlen >= 8) || (i == srcbytes - 1 && accumlen > 0) { + let numbits = 8.min(accumlen); + let mut bits = accum >> (accumlen - numbits); // Right justified + bits <<= 8 - numbits; // Left justified + bits &= 0xff00 >> numbits; // Mask + let bits = bits as u8; + self.b[1][di] = bits as u64; // Save + di += 1; + accumlen -= numbits; + } + } + } + + #[inline] + fn update(&mut self, data: &[u8], databitlen: usize) { // check that input values are sensible assert!(self.initialized, "state not init"); assert!(!data.is_empty(), "null data"); let mut j = 0; while j < databitlen { - let portion_size = (databitlen - j).min(b * w - self.bits[1]); + let portion_size = (databitlen - j).min(B * W - self.bits[1]); if (portion_size % 8 == 0) && (self.bits[1] % 8 == 0) && (j % 8 == 0) { let start = j / 8; let end = start + portion_size / 8; @@ -195,26 +512,27 @@ impl MD6State { let index_u64 = i / 8; let shift_amount = (7 - i % 8) * 8; - self.B[1][(self.bits[1] / 64) + index_u64] |= (byte as u64) << shift_amount; + self.b[1][(self.bits[1] / 64) + index_u64] |= (byte as u64) << shift_amount; i += 1; } } else { - append_bits(&mut self.B[1].to_vec(), self.bits[1], &data[j / 8..], portion_size); + self.append_bits(&data[j / 8..], portion_size); } j += portion_size; self.bits[1] += portion_size; self.bits_processed += portion_size; - if self.bits[1] == b * w && j < databitlen { + if self.bits[1] == B * W && j < databitlen { self.process(1, false); } } } + #[inline] fn compute_hex_hashval(&mut self) { - let hex_digits = vec![ + let hex_digits = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', ]; @@ -226,17 +544,18 @@ impl MD6State { self.hexhashval[(self.d + 3) / 4] = '\n'; } + #[inline] fn trim_hashval(&mut self) { let full_or_partial_bytes = (self.d + 7) / 8; let bits = self.d % 8; // move relevant bytes to the front for i in 0..full_or_partial_bytes { - self.hashval[i] = self.hashval[c * (w / 8) - full_or_partial_bytes + i]; + self.hashval[i] = self.hashval[C * (W / 8) - full_or_partial_bytes + i]; } // zero out following byte - for i in full_or_partial_bytes..(c * (w / 8)) { + for i in full_or_partial_bytes..(C * (W / 8)) { self.hashval[i] = 0; } @@ -244,14 +563,15 @@ impl MD6State { if bits > 0 { for i in 0..full_or_partial_bytes { self.hashval[i] <<= 8 - bits; - if (i + 1) < c * (w / 8) { + if (i + 1) < C * (W / 8) { self.hashval[i] |= self.hashval[i + 1] >> bits; } } } } - pub fn finalize(&mut self, hashval: &mut Vec) { + #[inline] + fn finalize(&mut self, hashval: &mut [u8]) { // check that input values are sensible if !self.initialized { panic!("state not init"); @@ -282,8 +602,8 @@ impl MD6State { // self.trim_hashval(); - if hashval.is_empty() { - hashval.extend(&self.hashval); + if hashval.iter().all(|&x| x == 0) { + hashval.copy_from_slice(&self.hashval); } self.compute_hex_hashval(); @@ -292,10 +612,9 @@ impl MD6State { } } -fn get_Q(wq: usize) -> Vec { - let mut Q = Vec::new(); - if wq == 64 { - Q = vec![ +const fn get_round_constants(w: usize) -> &'static [Md6Word] { + if w == 64 { + &[ 0x7311c2812425cfa0, 0x6432286434aac8e7, 0xb60450e9ef68b7c1, @@ -311,17 +630,17 @@ fn get_Q(wq: usize) -> Vec { 0xc878c1dd04c4b633, 0x3b72066c7a1552ac, 0x0d6f3522631effcb, - ]; - } else if wq == 32 { - Q = vec![ + ] + } else if w == 32 { + &[ 0x7311c281, 0x2425cfa0, 0x64322864, 0x34aac8e7, 0xb60450e9, 0xef68b7c1, 0xe8fb2390, 0x8d9f06f1, 0xdd2e76cb, 0xa691e5bf, 0x0cd0d63b, 0x2c30bc41, 0x1f8ccf68, 0x23058f8a, 0x54e5ed5b, 0x88e3775d, 0x4ad12aae, 0x0a6d6031, 0x3e7f16bb, 0x88222e0d, 0x8af8671d, 0x3fb50c2c, 0x995ad117, 0x8bd25c31, 0xc878c1dd, 0x04c4b633, 0x3b72066c, 0x7a1552ac, 0x0d6f3522, 0x631effcb, ] - } else if wq == 16 { - Q = vec![ + } else if w == 16 { + &[ 0x7311, 0xc281, 0x2425, 0xcfa0, 0x6432, 0x2864, 0x34aa, 0xc8e7, 0xb604, 0x50e9, 0xef68, 0xb7c1, 0xe8fb, 0x2390, 0x8d9f, 0x06f1, 0xdd2e, 0x76cb, 0xa691, 0xe5bf, 0x0cd0, 0xd63b, 0x2c30, 0xbc41, 0x1f8c, 0xcf68, 0x2305, 0x8f8a, 0x54e5, 0xed5b, 0x88e3, 0x775d, 0x4ad1, @@ -329,8 +648,8 @@ fn get_Q(wq: usize) -> Vec { 0x995a, 0xd117, 0x8bd2, 0x5c31, 0xc878, 0xc1dd, 0x04c4, 0xb633, 0x3b72, 0x066c, 0x7a15, 0x52ac, 0x0d6f, 0x3522, 0x631e, 0xffcb, ] - } else if w == 8 { - Q = vec![ + } else if W == 8 { + &[ 0x73, 0x11, 0xc2, 0x81, 0x24, 0x25, 0xcf, 0xa0, 0x64, 0x32, 0x28, 0x64, 0x34, 0xaa, 0xc8, 0xe7, 0xb6, 0x04, 0x50, 0xe9, 0xef, 0x68, 0xb7, 0xc1, 0xe8, 0xfb, 0x23, 0x90, 0x8d, 0x9f, 0x06, 0xf1, 0xdd, 0x2e, 0x76, 0xcb, 0xa6, 0x91, 0xe5, 0xbf, 0x0c, 0xd0, @@ -341,64 +660,12 @@ fn get_Q(wq: usize) -> Vec { 0xc1, 0xdd, 0x04, 0xc4, 0xb6, 0x33, 0x3b, 0x72, 0x06, 0x6c, 0x7a, 0x15, 0x52, 0xac, 0x0d, 0x6f, 0x35, 0x22, 0x63, 0x1e, 0xff, 0xcb, ] - } - - Q -} - -fn append_bits(dest: &mut Vec, destlen: usize, src: &[u8], srclen: usize) { - if srclen == 0 { - return; - } - - let mut accum: u16 = 0; // Accumulates bits waiting to be moved, right-justified - let mut accumlen = 0; // Number of bits in accumulator - - // Initialize accum, accumlen, and destination index (di) - if destlen % 8 != 0 { - accumlen = destlen % 8; - accum = dest[destlen / 8] as u16; // Grab partial byte from dest - accum >>= 8 - accumlen; // Right-justify it in accumulator - } - let mut di = destlen / 8; // Index of where next byte will go within dest - - // Ensure dest has enough space - let new_len = (destlen + srclen + 7) / 8; - if dest.len() < new_len { - dest.resize(new_len, 0); - } - - // Number of bytes (full or partial) in src - let srcbytes = (srclen + 7) / 8; - - for i in 0..srcbytes { - if i != srcbytes - 1 { - // Not the last byte - accum = (accum << 8) | src[i] as u16; - accumlen += 8; - } else { - // Last byte - let newbits = if srclen % 8 == 0 { 8 } else { srclen % 8 }; - accum = (accum << newbits) | ((src[i] as u16) >> (8 - newbits)); - accumlen += newbits; - } - - // Process as many high-order bits of accum as possible - while (i != srcbytes - 1 && accumlen >= 8) || (i == srcbytes - 1 && accumlen > 0) { - let numbits = std::cmp::min(8, accumlen); - let mut bits = (accum >> (accumlen - numbits)) as u16; // Right justified - bits <<= 8 - numbits; // Left justified - bits &= 0xff00 >> numbits; // Mask - let bits = bits as u8; - dest[di] = bits as u64; // Save - di += 1; - accumlen -= numbits; - } + } else { + panic!("bad w") } } - -fn md6_default_r(d: usize, keylen: usize) -> usize { +fn default_r(d: usize, keylen: usize) -> usize { // Default number of rounds is forty plus floor(d/4) let mut r = 40 + (d / 4); @@ -410,89 +677,50 @@ fn md6_default_r(d: usize, keylen: usize) -> usize { r } -fn bytes_to_words(bytes: &[u8]) -> Vec { - // Convert bytes to words - bytes - .chunks(8) - .map(|chunk| { - chunk - .iter() - .rev() - .fold(0u64, |acc, &byte| (acc << 8) | u64::from(byte)) - }) - .collect() -} - -fn words_to_bytes(words: &[u64]) -> Vec { - // Convert words to bytes - words - .iter() - .flat_map(|&word| (0..8).rev().map(move |shift| (word >> (shift * 8)) as u8)) - .collect() -} +fn bytes_to_words(bytes: &[u8], output: &mut [u64]) -> usize { + let mut bytes_len = bytes.len(); -pub fn md6_full_hash( - d: usize, - data: Vec, - databitlen: usize, - key: Option>, - keylen: usize, - L: usize, - r: usize, - hashval: &mut Vec, -) { - let mut st = MD6State::full_init(d, key, keylen, L, r); - st.update(data, databitlen); - st.finalize(hashval); -} + assert!(bytes_len != 0, "input slice should not be null"); -pub fn md6_hash(d: usize, data: Vec, databitlen: usize, hashval: &mut Vec) { - md6_full_hash( - d, - data, - databitlen, - None, - 0, - md6_default_L, - md6_default_r(d, 0), - hashval, + assert!( + core::mem::size_of_val(output) >= bytes_len, + "output slice is too small." ); -} -#[test] -fn test_md6() { - // Test from https://web.archive.org/web/20170812072847/https://groups.csail.mit.edu/cis/md6/submitted-2008-10-27/Supporting_Documentation/md6_report.pdf - let test_vector: [(&str, usize, Option>, usize, usize, usize, &str); 1] = [ - ( - "abc", - 256, - None, - 0, - md6_default_L, - 5, - "8854c14dc284f840ed71ad7ba542855ce189633e48c797a55121a746be48cec8", - ), - ]; - - for (msg, hashbitlen, key, keylen, L, r, expected_hex) in test_vector { - let mut output = vec![]; - - md6_full_hash( - hashbitlen, - msg.as_bytes().to_vec(), - msg.as_bytes().len() * 8, - key, - keylen, - L, - r, - &mut output, - ); + let words_to_write = if bytes_len % size_of::() != 0 { + bytes_len / size_of::() + 1 + } else { + bytes_len / size_of::() + }; + + for i in 0..words_to_write { + let mut word: u64 = 0; + for j in 0..core::cmp::min(size_of::(), bytes_len) { + word |= u64::from(bytes[i * size_of::() + j]) << (8 * (size_of::() - 1 - j)); + } + output[i] = word; - let digest_hex = output[..hashbitlen / 8] - .into_iter() - .map(|o| format!("{:02x}", o)) - .collect::(); + if i != words_to_write - 1 { + bytes_len -= size_of::(); + } + } + + words_to_write +} - assert_eq!(digest_hex, expected_hex); +fn words_to_bytes(words: &[u64], output: &mut [u8]) { + assert!( + output.len() == words.len() * 8, + "output slice is too small." + ); + + for (i, &word) in words.iter().enumerate() { + for shift in (0..8).rev() { + let byte = (word >> (shift * 8)) as u8; + output[i * 8 + (7 - shift)] = byte; + } } } + +#[cfg(feature = "zeroize")] +impl ZeroizeOnDrop for Md6VarCore {} diff --git a/md6/src/md6_compress.rs b/md6/src/md6_compress.rs deleted file mode 100644 index 42b29be9e..000000000 --- a/md6/src/md6_compress.rs +++ /dev/null @@ -1,331 +0,0 @@ -use crate::md6_consts::*; - -const w: usize = md6_w; // number of bits in a word (64) -const c: usize = md6_c; // size of compression output in words (16) -const n: usize = md6_n; // size of compression input block in words (89) -const q: usize = md6_q; // Q words in a compression block (>= 0) (15) -const k: usize = md6_k; // key words per compression block (>= 0) (8) -const u: usize = md6_u; // words for unique node ID (0 or 64/w) -const v: usize = md6_v; // words for control word (0 or 64/w) -const b: usize = md6_b; // data words per compression block (> 0) (64) - -const t0: usize = 17; // index for linear feedback -const t1: usize = 18; // index for first input to first and -const t2: usize = 21; // index for second input to first and -const t3: usize = 31; // index for first input to second and -const t4: usize = 67; // index for second input to second and -const t5: usize = 89; // last tap - -/// Macro to call loop bodies based on the value of `w`. -/// -/// This macro takes three arguments: -/// - `w`: The md6_word parameter which determines the set of loop bodies to call. -/// - `S`: A round constant passed to the `loop_body` macro. -/// - `i`: An index passed to the `loop_body` macro. -/// -/// Depending on the value of `w`, this macro will call a specific set of `loop_body` invocations -/// with predefined parameters. The possible values for `w` are 64, 32, 16, and 8. Each value -/// corresponds to a different set of `loop_body` calls with specific parameters. -/// -/// # Parameters -/// - `w`: The md6_word parameter (must be one of 64, 32, 16, or 8). -/// - `S`: A round constant to be passed to each `loop_body` call. -/// - `i`: An index to be passed to each `loop_body` call. -macro_rules! call_loop_bodies { - ($w: ident, $S: expr, $i: expr) => { - if $w == 64 { - loop_body!(10, 11, 0, $S, $i); - loop_body!(5, 24, 1, $S, $i); - loop_body!(13, 9, 2, $S, $i); - loop_body!(10, 16, 3, $S, $i); - loop_body!(11, 15, 4, $S, $i); - loop_body!(12, 9, 5, $S, $i); - loop_body!(2, 27, 6, $S, $i); - loop_body!(7, 15, 7, $S, $i); - loop_body!(14, 6, 8, $S, $i); - loop_body!(15, 2, 9, $S, $i); - loop_body!(7, 29, 10, $S, $i); - loop_body!(13, 8, 11, $S, $i); - loop_body!(11, 15, 12, $S, $i); - loop_body!(7, 5, 13, $S, $i); - loop_body!(6, 31, 14, $S, $i); - loop_body!(12, 9, 15, $S, $i); - } else if $w == 32 { - loop_body!(5, 4, 0, $S, $i); - loop_body!(3, 7, 1, $S, $i); - loop_body!(6, 7, 2, $S, $i); - loop_body!(5, 9, 3, $S, $i); - loop_body!(4, 13, 4, $S, $i); - loop_body!(6, 8, 5, $S, $i); - loop_body!(7, 4, 6, $S, $i); - loop_body!(3, 14, 7, $S, $i); - loop_body!(5, 7, 8, $S, $i); - loop_body!(6, 4, 9, $S, $i); - loop_body!(5, 8, 10, $S, $i); - loop_body!(5, 11, 11, $S, $i); - loop_body!(4, 5, 12, $S, $i); - loop_body!(6, 8, 13, $S, $i); - loop_body!(7, 2, 14, $S, $i); - loop_body!(5, 11, 15, $S, $i); - } else if $w == 16 { - loop_body!(5, 6, 0, $S, $i); - loop_body!(4, 7, 1, $S, $i); - loop_body!(3, 2, 2, $S, $i); - loop_body!(5, 4, 3, $S, $i); - loop_body!(7, 2, 4, $S, $i); - loop_body!(5, 6, 5, $S, $i); - loop_body!(5, 3, 6, $S, $i); - loop_body!(2, 7, 7, $S, $i); - loop_body!(4, 5, 8, $S, $i); - loop_body!(3, 7, 9, $S, $i); - loop_body!(4, 6, 10, $S, $i); - loop_body!(3, 5, 11, $S, $i); - loop_body!(4, 5, 12, $S, $i); - loop_body!(7, 6, 13, $S, $i); - loop_body!(7, 4, 14, $S, $i); - loop_body!(2, 3, 15, $S, $i); - } else if $w == 8 { - loop_body!(3, 2, 0, $S, $i); - loop_body!(3, 4, 1, $S, $i); - loop_body!(3, 2, 2, $S, $i); - loop_body!(4, 3, 3, $S, $i); - loop_body!(3, 2, 4, $S, $i); - loop_body!(3, 2, 5, $S, $i); - loop_body!(3, 2, 6, $S, $i); - loop_body!(3, 4, 7, $S, $i); - loop_body!(2, 3, 8, $S, $i); - loop_body!(2, 3, 9, $S, $i); - loop_body!(3, 2, 10, $S, $i); - loop_body!(2, 3, 11, $S, $i); - loop_body!(2, 3, 12, $S, $i); - loop_body!(3, 4, 13, $S, $i); - loop_body!(2, 3, 14, $S, $i); - loop_body!(3, 4, 15, $S, $i); - } - }; -} - -/// Returns the initial values for `S` and `Smask` based on the width `ws`. -/// -/// # Parameters -/// - `ws`: The width parameter (must be one of 64, 32, 16, or 8). -/// -/// # Returns -/// A tuple containing the initial values for `S` and `Smask`. -/// -/// # Panics -/// Panics if `ws` is not one of the expected values. -fn get_S_vals(ws: usize) -> (md6_word, md6_word) { - match ws { - 64 => (0x0123456789abcdef, 0x7311c2812425cfa0), - 32 => (0x01234567, 0x7311c281), - 16 => (0x01234, 0x7311), - 8 => (0x01, 0x73), - _ => panic!("bad w"), - } -} - -/// Main compression loop for MD6. -/// -/// This function performs the main compression loop for the MD6 hash function. -/// -/// # Parameters -/// - `A`: A mutable reference to a vector of `md6_word` values. -/// - `r`: The number of rounds to perform. -fn md6_main_compression_loop(A: &mut Vec, r: usize) { - macro_rules! loop_body { - ($rs: expr, $ls: expr, $step: expr, $S: expr, $i: expr) => { - let mut x = $S; // feedback constant - x ^= A[$i + $step - t5]; // end-around feedback - x ^= A[$i + $step - t0]; // linear feedback - x ^= (A[$i + $step - t1] & A[$i + $step - t2]); // first quadratic term - x ^= (A[$i + $step - t3] & A[$i + $step - t4]); // second quadratic term - x ^= x >> $rs; // right shift - A[$i + $step] = x ^ (x << $ls); // left shift - }; - } - - // Get the initial values for `S` and `Smask` based on the width `w`. - let (mut S, Smask) = get_S_vals(w); - - let mut i = n; - let mut j = 0; - - while j < r * c { - // Call the loop bodies based on the value of `w`. - // This will perform the main computation for each step in the compression loop. - call_loop_bodies!(w, S, i); - - // Advance round constant S to the next round constant. - S = (S << 1) ^ (S >> (w - 1)) ^ (S & Smask); - i += 16; - j += c; - } -} - -/// Compresses the input data using the MD6 compression function. -/// -/// # Parameters -/// - `C`: A mutable reference to a vector of `md6_word` values (output). -/// - `N`: A mutable reference to a vector of `md6_word` values (input). -/// - `r`: The number of rounds to perform. -/// - `A`: A mutable reference to a vector of `md6_word` values (working space). -/// -/// # Panics -/// Panics if any of the input vectors are empty or if `r` exceeds `md6_max_r`. -pub fn md6_compress(C: &mut Vec, N: &mut Vec, r: usize, A: &mut Vec) { - // check that the input is sensible - assert!(!N.is_empty()); - assert!(!C.is_empty()); - assert!(r <= md6_max_r); - assert!(!A.is_empty()); - - A[..N.len()].copy_from_slice(&N); // copy N to front of A - - md6_main_compression_loop(A, r); // do the main computation - - C.copy_from_slice(&A[((r - 1) * c + n)..((r - 1) * c + n + c)]); // output into C -} - -/// Creates a control word for the MD6 hash function. -/// -/// # Parameters -/// - `r`: The number of rounds. -/// - `L`: The level of the node. -/// - `z`: The final node indicator. -/// - `p`: The padding length. -/// - `keylen`: The length of the key. -/// - `d`: The digest length. -/// -/// # Returns -/// The control word as an `md6_control_word`. -fn md6_make_control_word( - r: usize, - L: usize, - z: usize, - p: usize, - keylen: usize, - d: usize, -) -> md6_control_word { - let V = (0 as md6_control_word) << 60 // reserved width 4 bits - | (r as md6_control_word) << 48 // r width 12 bits - | (L as md6_control_word) << 40 // L width 8 bits - | (z as md6_control_word) << 36 // z width 4 bits - | (p as md6_control_word) << 20 // p width 16 bits - | (keylen as md6_control_word) << 12 // keylen width 8 bits - | (d as md6_control_word); // d width 12 bits - V -} - -/// Creates a node ID for the MD6 hash function. -/// -/// # Parameters -/// - `ell`: The level of the node. -/// - `i`: The index of the node. -/// -/// # Returns -/// The node ID as an `md6_nodeID`. -pub fn md6_make_nodeID(ell: usize, i: md6_word) -> md6_nodeID { - let U: md6_nodeID = (ell as md6_nodeID) << 56 | i; // ell width 8 bits, i width 56 bits - - U -} - -/// Packs the input data into the `N` vector for the MD6 compression function. -/// -/// # Parameters -/// - `N`: A mutable reference to a vector of `md6_word` values (output). -/// - `Q`: A vector of `md6_word` values (input). -/// - `K`: An array of `md6_word` values (key). -/// - `ell`: The level of the node. -/// - `i`: The index of the node. -/// - `r`: The number of rounds. -/// - `L`: The level of the node. -/// - `z`: The final node indicator. -/// - `p`: The padding length. -/// - `keylen`: The length of the key. -/// - `d`: The digest length. -/// - `B`: An array of `md6_word` values (input block). -pub fn md6_pack( - N: &mut Vec, - Q: Vec, - K: [md6_word; k], - ell: usize, - i: md6_word, - r: usize, - L: usize, - z: usize, - p: usize, - keylen: usize, - d: usize, - B: [md6_word; 64], -) { - let mut ni = 0; - - N[ni..ni + q].copy_from_slice(&Q[..q]); // Q: Q in words 0--14 - ni += q; - - N[ni..ni + k].copy_from_slice(&K[..k]); // K: key in words 15--22 - ni += k; - - let U = md6_make_nodeID(ell, i); // U: unique node ID in 23 - N[ni] = U; - ni += u; - - let V = md6_make_control_word(r, L, z, p, keylen, d); // V: control word in 24 - N[ni] = V; - ni += v; - - N[ni..ni + b].copy_from_slice(&B[..b]); // B: data words 25--88 -} - -/// Standard compression function for the MD6 hash function. -/// -/// # Parameters -/// - `C`: A mutable reference to a vector of `md6_word` values (output). -/// - `Q`: A vector of `md6_word` values (input). -/// - `K`: An array of `md6_word` values (key). -/// - `ell`: The level of the node. -/// - `i`: The index of the node. -/// - `r`: The number of rounds. -/// - `L`: The level of the node. -/// - `z`: The final node indicator. -/// - `p`: The padding length. -/// - `keylen`: The length of the key. -/// - `d`: The digest length. -/// - `B`: An array of `md6_word` values (input block). -/// -/// # Panics -/// Panics if any of the input vectors are empty or if any of the parameters are out of range. -pub fn md6_standard_compress( - C: &mut Vec, - Q: Vec, - K: [md6_word; k], - ell: usize, - i: md6_word, - r: usize, - L: usize, - z: usize, - p: usize, - keylen: usize, - d: usize, - B: [md6_word; 64], -) { - let mut N = vec![0; md6_n]; - let mut A = vec![0; 5000]; - - // check that the input values are sensible - assert!(!C.is_empty()); - assert!(!Q.is_empty()); - assert!(!B.is_empty()); - assert!(r <= md6_max_r); - assert!(L <= 255); - assert!(ell <= 255); - assert!(p <= b * w); - assert!(d <= c * w / 2); - assert!(!K.is_empty()); - - md6_pack(&mut N, Q, K, ell, i, r, L, z, p, keylen, d, B); // pack input data into N - - md6_compress(C, &mut N, r, &mut A); // compress -} diff --git a/md6/src/md6_consts.rs b/md6/src/md6_consts.rs deleted file mode 100644 index 38727028c..000000000 --- a/md6/src/md6_consts.rs +++ /dev/null @@ -1,22 +0,0 @@ - -/// MD6 constants related to standard mode of operation - -pub type md6_word = u64; -pub type md6_control_word = u64; -pub type md6_nodeID = u64; - -pub const md6_max_stack_height: usize = 29; // maximum stack height -pub const md6_max_r: usize = 255; // maximum number of rounds -pub const md6_default_L: usize = 64; // large so that MD6 is fully hierarchical - -pub const md6_w: usize = 64; // number of bits in a word -pub const md6_c: usize = 16; // size of compression output in words -pub const md6_n: usize = 89; // size of compression input block in words - -/// These five values give lengths of the components of compression -/// input block; they should sum to md6_n. -pub const md6_q: usize = 15; // Q words in a compression block (>= 0) -pub const md6_k: usize = 8; // key words per compression block (>= 0) -pub const md6_u: usize = 64 / md6_w; // words for unique node ID (0 or 64/w) -pub const md6_v: usize = 64 / md6_w; // words for control word (0 or 64/w) -pub const md6_b: usize = 64; // data words per compression block (> 0) From 9b0923ba5ea52773838da8cbe59b976699b973db Mon Sep 17 00:00:00 2001 From: truthixify Date: Sun, 29 Dec 2024 10:58:15 +0100 Subject: [PATCH 03/16] fixed cargo clippy and added README.md content --- Cargo.lock | 1 + md6/Cargo.toml | 1 + md6/README.md | 81 +++++++++++++++++++++++++++++++++++++++++++++ md6/src/compress.rs | 49 +++------------------------ md6/src/lib.rs | 2 ++ md6/src/md6.rs | 53 +++++++++++++++++++---------- 6 files changed, 125 insertions(+), 62 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 36b63ab9e..b7fdbba92 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -250,6 +250,7 @@ version = "0.1.0" dependencies = [ "base16ct", "digest", + "hex", "hex-literal", ] diff --git a/md6/Cargo.toml b/md6/Cargo.toml index b338a5a44..610376836 100644 --- a/md6/Cargo.toml +++ b/md6/Cargo.toml @@ -16,6 +16,7 @@ name = "md6" [dependencies] digest = "=0.11.0-pre.9" +hex = "0.4.3" [dev-dependencies] digest = { version = "=0.11.0-pre.9", features = ["dev"] } diff --git a/md6/README.md b/md6/README.md index e69de29bb..c1906df64 100644 --- a/md6/README.md +++ b/md6/README.md @@ -0,0 +1,81 @@ +# RustCrypto: MD6 + +Pure Rust implementation of the MD6 hash function. + +## Example + +### Fixed output size + +```rust +use md6::{Md6_256, Digest}; +use hex_literal::hex; + +// create a Blake2b512 object +let mut hasher = Md6_256::new(); + +// write input message +hasher.update(b"hello world"); + +// read hash digest and consume hasher +let hash = hasher.finalize(); +assert_eq!(hash.to_vec(), hex!( + "9ae602639631cc2c60adaa7a952aae8756141f31a7e6a9b76adc1de121db2230" +)); +``` + +Also, see the [examples section] in the RustCrypto/hashes readme. + +### Variable output size + +This implementation supports run and compile time variable sizes. + +Output size set at run time: +```rust +use md6::Md6Var; +use blake2::digest::{Update, VariableOutput}; +use hex_literal::hex; + +let mut hasher = Md6Var::new(12).unwrap(); +hasher.update(b"hello rust"); +let mut buf = [0u8; 12]; +hasher.finalize_variable(&mut buf).unwrap(); +assert_eq!(buf, hex!("9c5b8d9744898ec981bcc573")); +``` + +Output size set at compile time: +```rust +use md6::{Md6, Digest, digest::consts::U20}; +use hex_literal::hex; + +type Md6_160 = Md6; + +let mut hasher = Md6_160::new(); +hasher.update(b"my_input"); +let res = hasher.finalize(); +assert_eq!(res, hex!("576d736a93a555a1c868973cfdd2d21838a26623")); +``` + +## Minimum Supported Rust Version + +Rust **1.81** or higher. + +Minimum supported Rust version can be changed in the future, but it will be +done with a minor version bump. + +## SemVer Policy + +- All on-by-default features of this library are covered by SemVer +- MSRV is considered exempt from SemVer as noted above + +## License + +The crate is licensed under either of: + +* [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) +* [MIT license](http://opensource.org/licenses/MIT) + +## Contributing + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. diff --git a/md6/src/compress.rs b/md6/src/compress.rs index 10c96e536..87931c3c7 100644 --- a/md6/src/compress.rs +++ b/md6/src/compress.rs @@ -145,7 +145,7 @@ pub fn compress(c: &mut [Md6Word], n: &mut [Md6Word], r: usize, a: &mut [Md6Word c.copy_from_slice(&a[((r - 1) * C + N)..((r - 1) * C + N + C)]); // output into c } -fn make_control_word( +pub fn make_control_word( r: usize, l: usize, z: usize, @@ -170,15 +170,9 @@ pub fn pack( n: &mut [Md6Word], q: &[Md6Word], k: [Md6Word; K], - ell: usize, - i: Md6Word, - r: usize, - l: usize, - z: usize, - p: usize, - keylen: usize, - d: usize, b: [Md6Word; 64], + u: Md6NodeID, + v: Md6ControlWord, ) { let mut ni = 0; @@ -188,46 +182,13 @@ pub fn pack( n[ni..ni + K].copy_from_slice(&k[..K]); // k: key in words 15--22 ni += K; - let u = make_node_id(ell, i); // u: unique node ID in 23 + // u: unique node ID in 23 n[ni] = u; ni += U; - let v = make_control_word(r, l, z, p, keylen, d); // v: control word in 24 + // v: control word in 24 n[ni] = v; ni += V; n[ni..ni + B].copy_from_slice(&b[..B]); // b: data words 25--88 } - -pub fn standard_compress( - c: &mut [Md6Word], - q: &[Md6Word], - k: [Md6Word; K], - ell: usize, - i: Md6Word, - r: usize, - l: usize, - z: usize, - p: usize, - keylen: usize, - d: usize, - b: [Md6Word; 64], -) { - let mut n = [0; MD6_N]; - let mut a = [0; 5000]; - - // check that the input values are sensible - assert!(!c.is_empty()); - assert!(!q.is_empty()); - assert!(!b.is_empty()); - assert!(r <= MD6_MAX_R); - assert!(l <= 255); - assert!(ell <= 255); - assert!(p <= B * W); - assert!(d <= C * W / 2); - assert!(!k.is_empty()); - - pack(&mut n, q, k, ell, i, r, l, z, p, keylen, d, b); // pack input data into N - - compress(c, &mut n, r, &mut a); // compress -} diff --git a/md6/src/lib.rs b/md6/src/lib.rs index 2c22534fa..afaa85ebc 100644 --- a/md6/src/lib.rs +++ b/md6/src/lib.rs @@ -24,6 +24,8 @@ use crate::md6::Md6VarCore; pub type Md6Var = RtVariableCoreWrapper; /// Core hash function for Md6 generic over output size pub type Md6Core = CtVariableCoreWrapper; +/// Md6 generic over output size. +pub type Md6 = CoreWrapper>; /// Md6 with 64-bit output pub type Md6_64 = CoreWrapper>; /// Md6 with 128-bit output diff --git a/md6/src/md6.rs b/md6/src/md6.rs index 2a5f12b7f..e8c93cc93 100644 --- a/md6/src/md6.rs +++ b/md6/src/md6.rs @@ -245,7 +245,7 @@ impl SerializableState for Md6VarCore { let mut k = [0u64; K]; for word in &mut k { - *word = read_u64(&serialized_state, &mut offset); + *word = read_u64(serialized_state, &mut offset); } let mut b = [[0u64; B]; MD6_MAX_STACK_HEIGHT]; @@ -298,7 +298,7 @@ impl Md6VarCore { if key.is_some() { assert!(keylen <= K * (W / 8), "bad keylen"); } - assert!(!(d < 1 || d > 512 || d > W * C / 2), "bad hashlen"); + assert!((1..=512).contains(&d), "bad hashlen"); let (k, keylen) = match key { Some(key) if keylen > 0 => { @@ -354,6 +354,36 @@ impl Md6VarCore { } } + pub fn standard_compress( + &self, + c: &mut [Md6Word], + q: &[Md6Word], + ell: usize, + p: usize, + z: usize, + ) { + let mut n = [0; MD6_N]; + let mut a = [0; 5000]; + + // check that the input values are sensible + assert!(!c.is_empty()); + assert!(!q.is_empty()); + assert!(!self.b.is_empty()); + assert!(self.r <= MD6_MAX_R); + assert!(self.l <= 255); + assert!(ell <= 255); + assert!(p <= B * W); + assert!(self.d <= C * W / 2); + assert!(!self.k.is_empty()); + + let u = make_node_id(ell, self.i_for_level[ell]); + let v = make_control_word(self.r, self.l, z, p, self.keylen, self.d); + + pack(&mut n, q, self.k, self.b[ell], u, v); // pack input data into N + + compress(c, &mut n, self.r, &mut a); // compress + } + #[inline] fn compress_block(&mut self, c: &mut [u64], ell: usize, z: usize) { // check that input values are sensible @@ -365,20 +395,7 @@ impl Md6VarCore { let p = B * W - self.bits[ell]; // number of padding bits let q = get_round_constants(W); // Q constant - standard_compress( - c, - q, - self.k, - ell, - self.i_for_level[ell], - self.r, - self.l, - z, - p, - self.keylen, - self.d, - self.b[ell], - ); + self.standard_compress(c, q, ell, p, z); self.bits[ell] = 0; // clear bits used count this level self.i_for_level[ell] += 1; // increment i for this level @@ -466,7 +483,7 @@ impl Md6VarCore { // Number of bytes (full or partial) in src let srcbytes = (srclen + 7) / 8; - for i in 0..srcbytes { + for (i, item) in src.iter().enumerate().take(srcbytes) { if i != srcbytes - 1 { // Not the last byte accum = (accum << 8) ^ src[i] as u16; @@ -474,7 +491,7 @@ impl Md6VarCore { } else { // Last byte let newbits = if srclen % 8 == 0 { 8 } else { srclen % 8 }; - accum = (accum << newbits) ^ ((src[i] as u16) >> (8 - newbits)); + accum = (accum << newbits) ^ ((*item as u16) >> (8 - newbits)); accumlen += newbits; } From d623751b75fccecab41189d3bab1461ae5e6160f Mon Sep 17 00:00:00 2001 From: truthixify Date: Tue, 31 Dec 2024 02:30:38 +0100 Subject: [PATCH 04/16] added tests and benches to md6 --- md6/Cargo.toml | 1 - md6/README.md | 10 +- md6/benches/mod.rs | 54 +++++++++++ md6/src/lib.rs | 4 +- md6/tests/mod.rs | 231 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 293 insertions(+), 7 deletions(-) create mode 100644 md6/benches/mod.rs create mode 100644 md6/tests/mod.rs diff --git a/md6/Cargo.toml b/md6/Cargo.toml index 610376836..b338a5a44 100644 --- a/md6/Cargo.toml +++ b/md6/Cargo.toml @@ -16,7 +16,6 @@ name = "md6" [dependencies] digest = "=0.11.0-pre.9" -hex = "0.4.3" [dev-dependencies] digest = { version = "=0.11.0-pre.9", features = ["dev"] } diff --git a/md6/README.md b/md6/README.md index c1906df64..b63b08dff 100644 --- a/md6/README.md +++ b/md6/README.md @@ -7,7 +7,8 @@ Pure Rust implementation of the MD6 hash function. ### Fixed output size ```rust -use md6::{Md6_256, Digest}; +use md6::Md6_256; +use digest::Digest; use hex_literal::hex; // create a Blake2b512 object @@ -32,7 +33,7 @@ This implementation supports run and compile time variable sizes. Output size set at run time: ```rust use md6::Md6Var; -use blake2::digest::{Update, VariableOutput}; +use digest::{Update, VariableOutput}; use hex_literal::hex; let mut hasher = Md6Var::new(12).unwrap(); @@ -44,13 +45,14 @@ assert_eq!(buf, hex!("9c5b8d9744898ec981bcc573")); Output size set at compile time: ```rust -use md6::{Md6, Digest, digest::consts::U20}; +use md6::Md6; +use digest::{Digest, consts::U20}; use hex_literal::hex; type Md6_160 = Md6; let mut hasher = Md6_160::new(); -hasher.update(b"my_input"); +hasher.update(b"hello rust"); let res = hasher.finalize(); assert_eq!(res, hex!("576d736a93a555a1c868973cfdd2d21838a26623")); ``` diff --git a/md6/benches/mod.rs b/md6/benches/mod.rs new file mode 100644 index 000000000..6625631f9 --- /dev/null +++ b/md6/benches/mod.rs @@ -0,0 +1,54 @@ +#![feature(test)] +extern crate test; + +use md6::{Md6_128, Md6_224, Md6_256, Md6_384, Md6_512, Md6_64}; +use digest::bench_update; +use test::Bencher; + +bench_update!( + Md6_64::default(); + md6_64_10 10; + md6_64_100 100; + md6_64_1000 1000; + md6_64_10000 10000; +); + +bench_update!( + Md6_128::default(); + md6_128_10 10; + md6_128_100 100; + md6_128_1000 1000; + md6_128_10000 10000; +); + +bench_update!( + Md6_224::default(); + md6_224_10 10; + md6_224_100 100; + md6_224_1000 1000; + md6_224_10000 10000; +); + +bench_update!( + Md6_256::default(); + md6_256_10 10; + md6_256_100 100; + md6_256_1000 1000; + md6_256_10000 10000; +); + +bench_update!( + Md6_384::default(); + md6_384_10 10; + md6_384_100 100; + md6_384_1000 1000; + md6_384_10000 10000; +); + +bench_update!( + Md6_512::default(); + md6_512_10 10; + md6_512_100 100; + md6_512_1000 1000; + md6_512_10000 10000; +); diff --git a/md6/src/lib.rs b/md6/src/lib.rs index afaa85ebc..f9315a2fa 100644 --- a/md6/src/lib.rs +++ b/md6/src/lib.rs @@ -12,7 +12,7 @@ pub(crate) mod consts; mod md6; use digest::{ - consts::{U16, U28, U32, U48, U64, U8}, + consts::{U64, U48, U32, U28, U16, U8}, core_api::{CoreWrapper, CtVariableCoreWrapper, RtVariableCoreWrapper}, }; @@ -37,4 +37,4 @@ pub type Md6_256 = CoreWrapper>; /// Md6 with 384-bit output pub type Md6_384 = CoreWrapper>; /// Md6 with 512-bit output -pub type Md6_512 = CoreWrapper>; +pub type Md6_512 = CoreWrapper>; \ No newline at end of file diff --git a/md6/tests/mod.rs b/md6/tests/mod.rs new file mode 100644 index 000000000..9dfedb8b7 --- /dev/null +++ b/md6/tests/mod.rs @@ -0,0 +1,231 @@ +#![no_std] + +use digest::Digest; +use hex_literal::hex; + +#[test] +fn test_md6_64() { + const INPUT: &[(&[u8], &[u8; 8])] = &[ + (b"a", &hex!("32d13030a6815e95")), + (b"aa", &hex!("af7966908a5d9c13")), + (b"aaa", &hex!("3d8a4ff7a21eb0c6")), + (b"aaaa", &hex!("5aafda0f42635bbe")), + (b"aaaaa", &hex!("c370f6eceefb2c04")), + (b"aaaaaa", &hex!("453f31fe99e3365d")), + (b"aaaaaaa", &hex!("9d52c725c926756b")), + (b"aaaaaaaa", &hex!("836d56b5756bd4d3")), + (b"aaaaaaaaa", &hex!("2d27ed075595d38f")), + (b"aaaaaaaaaa", &hex!("e31280f1a2fc2528")), + (b"0", &hex!("17d073d4d38b5400")), + (b"1", &hex!("870f87ac0bd00aee")), + (b"2", &hex!("0d70630287b9031a")), + (b"3", &hex!("f60aa0d9fa94116d")), + (b"4", &hex!("1e6b0691ef4d4705")), + (b"5", &hex!("6305b39e912c144b")), + (b"6", &hex!("b47486289e236138")), + (b"7", &hex!("dd018e6e7363124a")), + (b"8", &hex!("eb456a3ae7348bf8")), + (b"9", &hex!("15bc9eac62570fe7")), + (b"md6", &hex!("b2f36109e52bd99f")), + (b"md6 FTW", &hex!("47cda109418592ca")), + ]; + + for (msg, &expected_hash) in INPUT.iter() { + let mut hasher = md6::Md6_64::new(); + hasher.update(msg); + let output = hasher.finalize(); + + assert!(output.to_vec() == expected_hash); + } +} + +#[test] +fn test_md6_128() { + const INPUT: &[(&[u8], &[u8; 16])] = &[ + (b"a", &hex!("bb691c1bfa4b4345292eb35f364919ea")), + (b"aa", &hex!("19487e566f9ae2584d62628af2795f8c")), + (b"aaa", &hex!("319f1b026f76f9caf62320b4e2e79e29")), + (b"aaaa", &hex!("eb94dae524df4b84ba4a14115c3d0448")), + (b"aaaaa", &hex!("07d01330b8af7013284b9b339378aac1")), + (b"aaaaaa", &hex!("5638b2a1b7c5b66e963ea7744d1c9876")), + (b"aaaaaaa", &hex!("2ad627c7c0e089c28824a354841e9215")), + (b"aaaaaaaa", &hex!("1f7d2461fcfe705a7afadfabc9c95eb6")), + (b"aaaaaaaaa", &hex!("aa74a4962cdc8b3ae4bacf8995e9fa68")), + (b"aaaaaaaaaa", &hex!("623522019a5e40188a3b8956d44ea57d")), + (b"0", &hex!("7464cb2427a4b04bc0ca92653711e3a5")), + (b"1", &hex!("84a229d23cf5f380527c7dd9a887a384")), + (b"2", &hex!("44bf1a90a89c4bf3d6668e7886226127")), + (b"3", &hex!("cad8b9e548056c8ffd19cf469d1ac1ee")), + (b"4", &hex!("78746de94a7ff50fa11d22119a3d6545")), + (b"5", &hex!("ccc274bde4ebb8a38b6f19a8e0c022c0")), + (b"6", &hex!("b19533319a23aa00af9d143db6655041")), + (b"7", &hex!("3c049e4e57a5661b66c5235a07393bd1")), + (b"8", &hex!("ba73bb10cf0fee5758f3f8b37cd9fdd4")), + (b"9", &hex!("cc5f60133f81e505343174fa672d9f96")), + (b"md6", &hex!("98b4a2b7363159f810a60432df277b7c")), + (b"md6 FTW", &hex!("e866b430fa07b5bea28981db1f9b24a6")), + ]; + + for (msg, &expected_hash) in INPUT.iter() { + let mut hasher = md6::Md6_128::new(); + hasher.update(msg); + let output = hasher.finalize(); + + assert!(output.to_vec() == expected_hash); + } +} + +#[test] +fn test_md6_224() { + const INPUT: &[(&[u8], &[u8; 28])] = &[ + (b"a", &hex!("05de8792a96e024c806eb815f9f30053cf9f1b50661047a4934121b7")), + (b"aa", &hex!("a03a918a4d15e30c70b64a46374d8f3d97ac46bcd70176cc47fc6864")), + (b"aaa", &hex!("bb30c438e8aad6ba79c826542087a82e8d0d233c50c945a2071abb25")), + (b"aaaa", &hex!("bd4ecd894231f31df590f9e819600e363352b683b0acf0c84f69ede4")), + (b"aaaaa", &hex!("3a01ad0af963adefdff3d4f19b18fc409dbc371f52183125ea35409a")), + (b"aaaaaa", &hex!("b25d4fef8fef6de11074578de58c79da670dbfe2384c31e75b467be8")), + (b"aaaaaaa", &hex!("972c4efe175501a60a5ae668969317006640c8a79af596b6388f80c9")), + (b"aaaaaaaa", &hex!("d51f874f6ecc64526baf3d9acf1fdaaf25e5d7b0dd7a046cc5362a2d")), + (b"aaaaaaaaa", &hex!("a9713653a744b7198ac66744488de95b67ed4f97a0eff17dc5b9f0ad")), + (b"aaaaaaaaaa", &hex!("5672369481389de3fc4e5a678b071d328f2ff400b22c2aa226e72035")), + (b"0", &hex!("61ac9c7608a733ae06b37ebd729dbd2395e08aa3e08c2e645f996e0c")), + (b"1", &hex!("cbed1f15034d1a64e8ac4e4b61b20a1af88ce6b5975a66a31854f4b5")), + (b"2", &hex!("94efb1ddb684213949647ed2b7fc7cfed3c39bb7e6e7a206ce96a12d")), + (b"3", &hex!("74b69557a1caad60a0ff05605482c7683437a8cd84644b0ab511d629")), + (b"4", &hex!("8986a064f4fc94675f32f278984a472d70898267063eae0efb46b5aa")), + (b"5", &hex!("f42f6a4e12109d78a4fb1d701ea9447be6263bbdc7270c6da10fb78e")), + (b"6", &hex!("55bfa088f6d6f63579a6e79ea9b5a17101d46821ce7624b03aeed66d")), + (b"7", &hex!("48e4bbdb81eafab004a3067591765f75e10b835b04797912ce4ac6c9")), + (b"8", &hex!("4c690ad845a62e6c6f765cb58b5707f19d01af419c122b0118c8223c")), + (b"9", &hex!("a2ac8d05145172d6450806d84065211d14c712f3995dfbfbd05924a4")), + (b"md6", &hex!("577f5287cf2d8e515d5f22fefb730ba4e8e0607fc7705c5b123036cc")), + (b"md6 FTW", &hex!("7952f429ebbe134d302939817eff92e099b16273a2c3b0741614d8ad")), + ]; + + for (msg, &expected_hash) in INPUT.iter() { + let mut hasher = md6::Md6_224::new(); + hasher.update(msg); + let output = hasher.finalize(); + + assert!(output.to_vec() == expected_hash); + } +} + +#[test] +fn test_md6_256() { + const INPUT: &[(&[u8], &[u8; 32])] = &[ + (b"a", &hex!("2b0a697a081c21269514640aab4d74ffafeb3c0212df68ce92922087c69b0a77")), + (b"aa", &hex!("dc62c2f369d0d0a8de1d3239e312e12ac8c92d77d64262eb1fc209f8a2aaa48a")), + (b"aaa", &hex!("84610026b18ef3019a73be33f9b084194ce6ef4cd7348ae5a390b2d20d3b45fe")), + (b"aaaa", &hex!("28c490c3d4b0ad1809f59160b522ccd99c5a7565499b53af94bc311b3581a9f6")), + (b"aaaaa", &hex!("40f8bab5ef49065851f602e062b7fa819497ea9e1aa9419ba70b3730f108d42f")), + (b"aaaaaa", &hex!("ff01d77b95f1aa6dafa4813c75d5ba2900cbe399505097f9c4fb1d1e9b0a1ba0")), + (b"aaaaaaa", &hex!("0107532d1a2c5028124135df7783c5177bc520d622c5bac3001e2c2e90011741")), + (b"aaaaaaaa", &hex!("44e7e33cf46bc248a0476332f6d24c59252412d8db037470142eb66f1afdae11")), + (b"aaaaaaaaa", &hex!("261ac535cae8a76b2e70c2b6f24e3fe5acf32f3d5db5662c8f933c90f84cfed1")), + (b"aaaaaaaaaa", &hex!("3c74f2b9d89cf806cf0b529773ef09b8ed0b393afe166fa759f53d2cb6dfb40b")), + (b"0", &hex!("d979642b9060ce2dc24183bf3ac6d9ae4b54f144d3af24935e9b8bc907a72b4e")), + (b"1", &hex!("7fe3b063c891feb631ed0988895cfaf8a90fcb5a7d43c25f9dd1e1c21f896711")), + (b"2", &hex!("1595783f79211f1d954c181f3573025020f9495f5763934ee25954ee7c2a83cc")), + (b"3", &hex!("edae30bbeb946b55333732d7c5ad872da6ece3ba28cece17d14c2302b4f98a51")), + (b"4", &hex!("8a1cb9446a2791e600879d214e50ab9f255c763f02043df556f3aad6e41d2b41")), + (b"5", &hex!("632a4ef13a940fec5c41cadd550dcd41d491024da37cfc686cea53026a39c2e7")), + (b"6", &hex!("bfed808c85097bd8bd45fe1b0223eb3a15c013af38c4a09a2e81f5eb2c2f6d43")), + (b"7", &hex!("662e1312173e2bf826439e234367ceaab3b0d98af400907742ea2c01fec70d2a")), + (b"8", &hex!("3edd4058e60c3e85c56341aaf8d037e3f3e5ff9233d17a66880616f3151de9ad")), + (b"9", &hex!("6c9f735d57a9b12493b5c5c0ec9733b459f13e7e996edd090dda164ebfe43d54")), + (b"md6", &hex!("cbe8da56ff91be9bc299ed4c1da6159f9a41ab380f565db0a5ef08895aed4f7d")), + (b"md6 FTW", &hex!("7bfaa624f661a683be2a3b2007493006a30a7845ee1670e499927861a8e74cce")), + ]; + + for (msg, &expected_hash) in INPUT.iter() { + let mut hasher = md6::Md6_256::new(); + hasher.update(msg); + let output = hasher.finalize(); + + assert!(output.to_vec() == expected_hash); + } +} + +#[test] +fn test_md6_384() { + const INPUT: &[(&[u8], &[u8; 48])] = &[ + (b"a", &hex!("a40c8d059495a278fadd30b96e3b2227758090c759b934197265bf632cabf8547a7429e5316d496c2a1ddae8d27e87ee")), + (b"aa", &hex!("330547441b6518e7693ea01bfc55158bcfc084853fa1960a9e8999f98b57cea7d8b0564bf192b6ab1eb7638939dc9bbf")), + (b"aaa", &hex!("f43bb4e108ec31e0cf8ded506f79373e69cddcd8c7c46298f1bd475401132e4c255c08e378c9db988f0de97131cbe36c")), + (b"aaaa", &hex!("b848065d437013c8fda2493bbf240587ef5fd82a178416613e5c0077541c1ca33f205e58d49387d4d9e3cd62d2d104f6")), + (b"aaaaa", &hex!("20ba7998f75c67dd1371cec629e0606739514cdfb32a17b94fa8ad4c4ec7a06a09821c93a16c863ff7ff72631b5ad02b")), + (b"aaaaaa", &hex!("4930a7f1d619e219a12ca118f1a2f6dd9b23b32b366014b5d14976a927d4252e89d927b7c1d1e796aec3d2f3fd294287")), + (b"aaaaaaa", &hex!("cf15b1b738f91476f2a139dda60e59f5e7422d7e99cb35d9bbb96f85c52a8e6542d4b08070c0855474946d86cc99fba3")), + (b"aaaaaaaa", &hex!("7f9dba3ca2c4442eefd377877b168a2283576abd157c87cda401aa86c484669aa17326fe1e4a50dcca8cbe5bb5a0e947")), + (b"aaaaaaaaa", &hex!("067d6be27eef07c654254a62275daa41630b9fd5d074badb2d16f0cf5e9621026ef0506649efebcf3a18bdf2b6a17a3a")), + (b"aaaaaaaaaa", &hex!("f1fc124cbfa55170d508a26bdad017978bac8be6899f1a99f420c94bd1ef8d5547bf36488e8824215cf5da878041cf76")), + (b"0", &hex!("9a97b926552bb7bc61015e43e9430e3c49a76724c6d6e0b31c14f9c5bb4c7dbf78d5c583401976da7139819dc16c5934")), + (b"1", &hex!("103644563cda42ea432d325fed2b0977f0d767f475b4794322916b7d82b24308c11389a6fe2acf6cade70ddf990da337")), + (b"2", &hex!("dcfdb3807231f3c5d0da945e0cc83f1d2368479f059c46841b112796bca717b4acce887877062e60f3af0276a43eb13d")), + (b"3", &hex!("37e21bffcc21b6de5d3bbae971d9e889670e9c77ad8f42558caea4e59fea1efb7b3392ca53a294b862b04893cdf0a4f6")), + (b"4", &hex!("aaf0b2fd043fc3f2e247f02ab1618b1450db799174bf6fae883822b7cf145d7080c5b70899c10ebb7a4221c9ab36070b")), + (b"5", &hex!("4d59a67f4c321eb971d7bd26a0c8e3ff7a023bb7c15097aa9b13a94fce91b24cf82ce09acac63f63f1da708ecfe49427")), + (b"6", &hex!("36886709330eae549c25558ac0d4ae2b7082261e76d33d589379d3ada613eb31943bf8dda1e92fbc7001fa6f407b025e")), + (b"7", &hex!("9124c888a99743a90daa8a3032014c6542f0e4ed949e950e3a2ff4945ae9f7c648dc6bf712a5556edaed50e7dc299007")), + (b"8", &hex!("41b469911cebb00f5ab173e5238fe4e6aa1737f21159f550913b7b30c99d8c2c1ecd2c431f0baa992eccc5a9cfddf782")), + (b"9", &hex!("9211ce0b1ae366def2d9337c34e4b1ea75ac93efab88c273ce691ed7d20da8d0bd8cbd8d2341e7a619705fcb4eeda311")), + (b"md6", &hex!("1aa5bb36a472fdb3d19ae8b3aa84773ab9a8e7e13d0fde914488bba066d64d5309155ea5b7a3b33b4d9d6855fa9050b1")), + (b"md6 FTW", &hex!("7a4e8ecd1035ccdf00567595c15aa5a382fef2b6a4ec4bc609e0c655887b1c05e10eee223dd6c0ba5fa4a46159c70757")), + ]; + + for (msg, &expected_hash) in INPUT.iter() { + let mut hasher = md6::Md6_384::new(); + hasher.update(msg); + let output = hasher.finalize(); + + assert!(output.to_vec() == expected_hash); + } +} + +#[test] +fn test_md6_512() { + const INPUT: &[(&[u8], &[u8; 64])] = &[ + (b"a", &hex!("c0e4e18acb69cd1a7e5a20981fe6cc6f7b5b70e814d3a13b05ac292aba74c0d8c9d34c211414e7ab755a9559c27211cd749fc3eb09ae670e138881743b8d5051")), + (b"aa", &hex!("2afa253b05702770343e5c46e9d47231812a741d7bba479539a3c5484a412ea419f0d0ca96e124ba92e4ca506ca12684579323051d9d52fe5a669d079a226683")), + (b"aaa", &hex!("56b0131875d458f6d30ed1c594991df1efa8d6cae0c8abb36a9b811df23ac476c58e36d9adbe845e840d3de9175a8ceda11235144c3222587af108b902ce0fc5")), + (b"aaaa", &hex!("26a0bbf7df198fef1aa1945ebb91e7a9436e0892f4cdd5ee18e8dfe533f45da50c36debe4d98d0eae21925403e0d37603ea67f136b3076a1e053421052971480")), + (b"aaaaa", &hex!("86da00c33edf5d1daff144312af7e1a37f6441fc9905feb8caf4023fb6b34951464dc276a29925e3ad796cbdb7a09febd7d985c21702cc1b1c849e604de6580b")), + (b"aaaaaa", &hex!("7e67f0540f2afd27a17ff7a8be74039b79ff060a69b6f8fb98e3afc8e0a828fffb35aff2f3e20569933ef7c418fb3a8d7cfc7c17f3360a6ecca2a800c6657592")), + (b"aaaaaaa", &hex!("08d8eb85e5fe6b8e0f81841e9373de9ed18f14e911506a81cbd4e388535632edc425c88c1acbaefd61e98ea59fcda024acf662f79791acb3d15e935aa482dfef")), + (b"aaaaaaaa", &hex!("2db495253418869d64c3be65f304f0f73f87da659d1aa3ad457fa437e9370bf24f88b5c28c3c0dd4e67b351499ea380b60cb0010ffd28ac2449d5361925c8ce7")), + (b"aaaaaaaaa", &hex!("6d12438e615b0c1171678d262ba429a6ee58a87e24eb7b2fa0d5bec70bba1ea2e43acef122b1ca5de1a414153b0a12d795abed88cf3e88f26bf59a3222b04b99")), + (b"aaaaaaaaaa", &hex!("c4451dcd12d3847e1f2408ed3c9cc2f79a179ddf5a0a9246b68adcf918bbcea67f6c8721cc226599d587313895b8a8d53881061014b6444f3d3464b03602ecc2")), + (b"0", &hex!("057e1c40468ab5661defdbcd3bf671d398116373db2e7ab0adc6b0871d603eda39cf7255361ca456543157fbe09847b501586d701d53564fab651bd2f49dcda4")), + (b"1", &hex!("0f19bc75955c2e405620d5a69d3ce7078c11c3805523cbd5ff834704af67d40c65e9f011fdd3723fea365eb6fa744b981fc9cd53928edae43eaa942158a649d5")), + (b"2", &hex!("5f68d3c677d9cde81417f92889287e94141ff212080b1bb8d4485b01061dc0bccd8eed96fe728ea5ff3596201225337ebbf06ae6cf6162290843dfd226f7d647")), + (b"3", &hex!("f4243d7945b667900c78b894d83a343b2e8865ff62cef11e51a20472600df8a17a026d3ce09cb85925540a1515b34210bdd8eed76b8fe37f35cdc5350bb7bd19")), + (b"4", &hex!("8a1b250daf9fc0b2b5878504991b8950ed7c621e0b9163fbcb5f34b363f22fd6be96ed4a9c5aacbc9d6e30de4e97090a5758f89b6ae61b45658b2f79ec26fc51")), + (b"5", &hex!("ad6fa2a0f8e35189d5d070559124bd6cbb1170969356165dfda720b4ded83fd14ee8d81a2ef30d918ebcfc01d668950ba681bedcc3e1180b76c06a55e9a11497")), + (b"6", &hex!("2e2bb4d681f61821c6c470064b83b924cf691de74ed05bd8610cef5397d7e2c4aeda1930446f306dece4bbefe4fc87168d7a15ab80c890672b676a532739bc67")), + (b"7", &hex!("adb9009ae9abf8444d45a62b7adafcaef48c6ee7c48fa65d206d7a58ac3a5993e2eb81120d45338b9f9aa1b100365e2a98cd59fd7062783e5d23088b562176c3")), + (b"8", &hex!("516315942af5bbd028a533420a6496b77ca707a0b5dd0b473359d9bb74bdd00a59987a881c774a59dd2c62f1759f570713b881a622a70894ff319881e07cfd34")), + (b"9", &hex!("b98f4b7c5cecda77117180a38be5bda00bf72b7e4106c0d00137d269a0d48eb571004a8069f25fab4c2b4b16ab118af881eb904f9f32331dc726c1a404489604")), + (b"md6", &hex!("e94595891b2b3e2b2e3ae6943c17a34703c4230296f12f1689264e46518e0e1b0106996387ad6d8ec9b9c86e54301a71e6f4dab6e7369db4e503daae64f2e0a1")), + (b"md6 FTW", &hex!("75df3b6031e8241ef59d01628b093b05906f1a2d80c43908cb2883f7db6fbdd1cadffd7d643505c20b9529b6a5d19f8b6ff1623cabbc14a606caa7bcb239611a")), + ]; + + for (msg, &expected_hash) in INPUT.iter() { + let mut hasher = md6::Md6_512::new(); + hasher.update(msg); + let output = hasher.finalize(); + + assert!(output.to_vec() == expected_hash); + } +} + +#[test] +fn test_md6_var() { + use md6::{Update, VariableOutput}; + + let mut hasher = md6::Md6Var::new(12).unwrap(); + hasher.update(b"hello rust"); + let mut buf = [0u8; 12]; + hasher.finalize_variable(&mut buf).unwrap(); + assert_eq!(buf, hex!("9c5b8d9744898ec981bcc573")); +} \ No newline at end of file From c88621c327d12b873e5d70a2ed7dafc243648a39 Mon Sep 17 00:00:00 2001 From: truthixify Date: Tue, 31 Dec 2024 02:32:35 +0100 Subject: [PATCH 05/16] cargo fmt --- md6/benches/mod.rs | 2 +- md6/src/lib.rs | 4 +- md6/tests/mod.rs | 248 ++++++++++++++++++++++++++++++++++----------- 3 files changed, 193 insertions(+), 61 deletions(-) diff --git a/md6/benches/mod.rs b/md6/benches/mod.rs index 6625631f9..46869523e 100644 --- a/md6/benches/mod.rs +++ b/md6/benches/mod.rs @@ -1,8 +1,8 @@ #![feature(test)] extern crate test; -use md6::{Md6_128, Md6_224, Md6_256, Md6_384, Md6_512, Md6_64}; use digest::bench_update; +use md6::{Md6_128, Md6_224, Md6_256, Md6_384, Md6_512, Md6_64}; use test::Bencher; bench_update!( diff --git a/md6/src/lib.rs b/md6/src/lib.rs index f9315a2fa..afaa85ebc 100644 --- a/md6/src/lib.rs +++ b/md6/src/lib.rs @@ -12,7 +12,7 @@ pub(crate) mod consts; mod md6; use digest::{ - consts::{U64, U48, U32, U28, U16, U8}, + consts::{U16, U28, U32, U48, U64, U8}, core_api::{CoreWrapper, CtVariableCoreWrapper, RtVariableCoreWrapper}, }; @@ -37,4 +37,4 @@ pub type Md6_256 = CoreWrapper>; /// Md6 with 384-bit output pub type Md6_384 = CoreWrapper>; /// Md6 with 512-bit output -pub type Md6_512 = CoreWrapper>; \ No newline at end of file +pub type Md6_512 = CoreWrapper>; diff --git a/md6/tests/mod.rs b/md6/tests/mod.rs index 9dfedb8b7..25411b127 100644 --- a/md6/tests/mod.rs +++ b/md6/tests/mod.rs @@ -34,7 +34,7 @@ fn test_md6_64() { let mut hasher = md6::Md6_64::new(); hasher.update(msg); let output = hasher.finalize(); - + assert!(output.to_vec() == expected_hash); } } @@ -70,7 +70,7 @@ fn test_md6_128() { let mut hasher = md6::Md6_128::new(); hasher.update(msg); let output = hasher.finalize(); - + assert!(output.to_vec() == expected_hash); } } @@ -78,35 +78,101 @@ fn test_md6_128() { #[test] fn test_md6_224() { const INPUT: &[(&[u8], &[u8; 28])] = &[ - (b"a", &hex!("05de8792a96e024c806eb815f9f30053cf9f1b50661047a4934121b7")), - (b"aa", &hex!("a03a918a4d15e30c70b64a46374d8f3d97ac46bcd70176cc47fc6864")), - (b"aaa", &hex!("bb30c438e8aad6ba79c826542087a82e8d0d233c50c945a2071abb25")), - (b"aaaa", &hex!("bd4ecd894231f31df590f9e819600e363352b683b0acf0c84f69ede4")), - (b"aaaaa", &hex!("3a01ad0af963adefdff3d4f19b18fc409dbc371f52183125ea35409a")), - (b"aaaaaa", &hex!("b25d4fef8fef6de11074578de58c79da670dbfe2384c31e75b467be8")), - (b"aaaaaaa", &hex!("972c4efe175501a60a5ae668969317006640c8a79af596b6388f80c9")), - (b"aaaaaaaa", &hex!("d51f874f6ecc64526baf3d9acf1fdaaf25e5d7b0dd7a046cc5362a2d")), - (b"aaaaaaaaa", &hex!("a9713653a744b7198ac66744488de95b67ed4f97a0eff17dc5b9f0ad")), - (b"aaaaaaaaaa", &hex!("5672369481389de3fc4e5a678b071d328f2ff400b22c2aa226e72035")), - (b"0", &hex!("61ac9c7608a733ae06b37ebd729dbd2395e08aa3e08c2e645f996e0c")), - (b"1", &hex!("cbed1f15034d1a64e8ac4e4b61b20a1af88ce6b5975a66a31854f4b5")), - (b"2", &hex!("94efb1ddb684213949647ed2b7fc7cfed3c39bb7e6e7a206ce96a12d")), - (b"3", &hex!("74b69557a1caad60a0ff05605482c7683437a8cd84644b0ab511d629")), - (b"4", &hex!("8986a064f4fc94675f32f278984a472d70898267063eae0efb46b5aa")), - (b"5", &hex!("f42f6a4e12109d78a4fb1d701ea9447be6263bbdc7270c6da10fb78e")), - (b"6", &hex!("55bfa088f6d6f63579a6e79ea9b5a17101d46821ce7624b03aeed66d")), - (b"7", &hex!("48e4bbdb81eafab004a3067591765f75e10b835b04797912ce4ac6c9")), - (b"8", &hex!("4c690ad845a62e6c6f765cb58b5707f19d01af419c122b0118c8223c")), - (b"9", &hex!("a2ac8d05145172d6450806d84065211d14c712f3995dfbfbd05924a4")), - (b"md6", &hex!("577f5287cf2d8e515d5f22fefb730ba4e8e0607fc7705c5b123036cc")), - (b"md6 FTW", &hex!("7952f429ebbe134d302939817eff92e099b16273a2c3b0741614d8ad")), + ( + b"a", + &hex!("05de8792a96e024c806eb815f9f30053cf9f1b50661047a4934121b7"), + ), + ( + b"aa", + &hex!("a03a918a4d15e30c70b64a46374d8f3d97ac46bcd70176cc47fc6864"), + ), + ( + b"aaa", + &hex!("bb30c438e8aad6ba79c826542087a82e8d0d233c50c945a2071abb25"), + ), + ( + b"aaaa", + &hex!("bd4ecd894231f31df590f9e819600e363352b683b0acf0c84f69ede4"), + ), + ( + b"aaaaa", + &hex!("3a01ad0af963adefdff3d4f19b18fc409dbc371f52183125ea35409a"), + ), + ( + b"aaaaaa", + &hex!("b25d4fef8fef6de11074578de58c79da670dbfe2384c31e75b467be8"), + ), + ( + b"aaaaaaa", + &hex!("972c4efe175501a60a5ae668969317006640c8a79af596b6388f80c9"), + ), + ( + b"aaaaaaaa", + &hex!("d51f874f6ecc64526baf3d9acf1fdaaf25e5d7b0dd7a046cc5362a2d"), + ), + ( + b"aaaaaaaaa", + &hex!("a9713653a744b7198ac66744488de95b67ed4f97a0eff17dc5b9f0ad"), + ), + ( + b"aaaaaaaaaa", + &hex!("5672369481389de3fc4e5a678b071d328f2ff400b22c2aa226e72035"), + ), + ( + b"0", + &hex!("61ac9c7608a733ae06b37ebd729dbd2395e08aa3e08c2e645f996e0c"), + ), + ( + b"1", + &hex!("cbed1f15034d1a64e8ac4e4b61b20a1af88ce6b5975a66a31854f4b5"), + ), + ( + b"2", + &hex!("94efb1ddb684213949647ed2b7fc7cfed3c39bb7e6e7a206ce96a12d"), + ), + ( + b"3", + &hex!("74b69557a1caad60a0ff05605482c7683437a8cd84644b0ab511d629"), + ), + ( + b"4", + &hex!("8986a064f4fc94675f32f278984a472d70898267063eae0efb46b5aa"), + ), + ( + b"5", + &hex!("f42f6a4e12109d78a4fb1d701ea9447be6263bbdc7270c6da10fb78e"), + ), + ( + b"6", + &hex!("55bfa088f6d6f63579a6e79ea9b5a17101d46821ce7624b03aeed66d"), + ), + ( + b"7", + &hex!("48e4bbdb81eafab004a3067591765f75e10b835b04797912ce4ac6c9"), + ), + ( + b"8", + &hex!("4c690ad845a62e6c6f765cb58b5707f19d01af419c122b0118c8223c"), + ), + ( + b"9", + &hex!("a2ac8d05145172d6450806d84065211d14c712f3995dfbfbd05924a4"), + ), + ( + b"md6", + &hex!("577f5287cf2d8e515d5f22fefb730ba4e8e0607fc7705c5b123036cc"), + ), + ( + b"md6 FTW", + &hex!("7952f429ebbe134d302939817eff92e099b16273a2c3b0741614d8ad"), + ), ]; for (msg, &expected_hash) in INPUT.iter() { let mut hasher = md6::Md6_224::new(); hasher.update(msg); let output = hasher.finalize(); - + assert!(output.to_vec() == expected_hash); } } @@ -114,35 +180,101 @@ fn test_md6_224() { #[test] fn test_md6_256() { const INPUT: &[(&[u8], &[u8; 32])] = &[ - (b"a", &hex!("2b0a697a081c21269514640aab4d74ffafeb3c0212df68ce92922087c69b0a77")), - (b"aa", &hex!("dc62c2f369d0d0a8de1d3239e312e12ac8c92d77d64262eb1fc209f8a2aaa48a")), - (b"aaa", &hex!("84610026b18ef3019a73be33f9b084194ce6ef4cd7348ae5a390b2d20d3b45fe")), - (b"aaaa", &hex!("28c490c3d4b0ad1809f59160b522ccd99c5a7565499b53af94bc311b3581a9f6")), - (b"aaaaa", &hex!("40f8bab5ef49065851f602e062b7fa819497ea9e1aa9419ba70b3730f108d42f")), - (b"aaaaaa", &hex!("ff01d77b95f1aa6dafa4813c75d5ba2900cbe399505097f9c4fb1d1e9b0a1ba0")), - (b"aaaaaaa", &hex!("0107532d1a2c5028124135df7783c5177bc520d622c5bac3001e2c2e90011741")), - (b"aaaaaaaa", &hex!("44e7e33cf46bc248a0476332f6d24c59252412d8db037470142eb66f1afdae11")), - (b"aaaaaaaaa", &hex!("261ac535cae8a76b2e70c2b6f24e3fe5acf32f3d5db5662c8f933c90f84cfed1")), - (b"aaaaaaaaaa", &hex!("3c74f2b9d89cf806cf0b529773ef09b8ed0b393afe166fa759f53d2cb6dfb40b")), - (b"0", &hex!("d979642b9060ce2dc24183bf3ac6d9ae4b54f144d3af24935e9b8bc907a72b4e")), - (b"1", &hex!("7fe3b063c891feb631ed0988895cfaf8a90fcb5a7d43c25f9dd1e1c21f896711")), - (b"2", &hex!("1595783f79211f1d954c181f3573025020f9495f5763934ee25954ee7c2a83cc")), - (b"3", &hex!("edae30bbeb946b55333732d7c5ad872da6ece3ba28cece17d14c2302b4f98a51")), - (b"4", &hex!("8a1cb9446a2791e600879d214e50ab9f255c763f02043df556f3aad6e41d2b41")), - (b"5", &hex!("632a4ef13a940fec5c41cadd550dcd41d491024da37cfc686cea53026a39c2e7")), - (b"6", &hex!("bfed808c85097bd8bd45fe1b0223eb3a15c013af38c4a09a2e81f5eb2c2f6d43")), - (b"7", &hex!("662e1312173e2bf826439e234367ceaab3b0d98af400907742ea2c01fec70d2a")), - (b"8", &hex!("3edd4058e60c3e85c56341aaf8d037e3f3e5ff9233d17a66880616f3151de9ad")), - (b"9", &hex!("6c9f735d57a9b12493b5c5c0ec9733b459f13e7e996edd090dda164ebfe43d54")), - (b"md6", &hex!("cbe8da56ff91be9bc299ed4c1da6159f9a41ab380f565db0a5ef08895aed4f7d")), - (b"md6 FTW", &hex!("7bfaa624f661a683be2a3b2007493006a30a7845ee1670e499927861a8e74cce")), + ( + b"a", + &hex!("2b0a697a081c21269514640aab4d74ffafeb3c0212df68ce92922087c69b0a77"), + ), + ( + b"aa", + &hex!("dc62c2f369d0d0a8de1d3239e312e12ac8c92d77d64262eb1fc209f8a2aaa48a"), + ), + ( + b"aaa", + &hex!("84610026b18ef3019a73be33f9b084194ce6ef4cd7348ae5a390b2d20d3b45fe"), + ), + ( + b"aaaa", + &hex!("28c490c3d4b0ad1809f59160b522ccd99c5a7565499b53af94bc311b3581a9f6"), + ), + ( + b"aaaaa", + &hex!("40f8bab5ef49065851f602e062b7fa819497ea9e1aa9419ba70b3730f108d42f"), + ), + ( + b"aaaaaa", + &hex!("ff01d77b95f1aa6dafa4813c75d5ba2900cbe399505097f9c4fb1d1e9b0a1ba0"), + ), + ( + b"aaaaaaa", + &hex!("0107532d1a2c5028124135df7783c5177bc520d622c5bac3001e2c2e90011741"), + ), + ( + b"aaaaaaaa", + &hex!("44e7e33cf46bc248a0476332f6d24c59252412d8db037470142eb66f1afdae11"), + ), + ( + b"aaaaaaaaa", + &hex!("261ac535cae8a76b2e70c2b6f24e3fe5acf32f3d5db5662c8f933c90f84cfed1"), + ), + ( + b"aaaaaaaaaa", + &hex!("3c74f2b9d89cf806cf0b529773ef09b8ed0b393afe166fa759f53d2cb6dfb40b"), + ), + ( + b"0", + &hex!("d979642b9060ce2dc24183bf3ac6d9ae4b54f144d3af24935e9b8bc907a72b4e"), + ), + ( + b"1", + &hex!("7fe3b063c891feb631ed0988895cfaf8a90fcb5a7d43c25f9dd1e1c21f896711"), + ), + ( + b"2", + &hex!("1595783f79211f1d954c181f3573025020f9495f5763934ee25954ee7c2a83cc"), + ), + ( + b"3", + &hex!("edae30bbeb946b55333732d7c5ad872da6ece3ba28cece17d14c2302b4f98a51"), + ), + ( + b"4", + &hex!("8a1cb9446a2791e600879d214e50ab9f255c763f02043df556f3aad6e41d2b41"), + ), + ( + b"5", + &hex!("632a4ef13a940fec5c41cadd550dcd41d491024da37cfc686cea53026a39c2e7"), + ), + ( + b"6", + &hex!("bfed808c85097bd8bd45fe1b0223eb3a15c013af38c4a09a2e81f5eb2c2f6d43"), + ), + ( + b"7", + &hex!("662e1312173e2bf826439e234367ceaab3b0d98af400907742ea2c01fec70d2a"), + ), + ( + b"8", + &hex!("3edd4058e60c3e85c56341aaf8d037e3f3e5ff9233d17a66880616f3151de9ad"), + ), + ( + b"9", + &hex!("6c9f735d57a9b12493b5c5c0ec9733b459f13e7e996edd090dda164ebfe43d54"), + ), + ( + b"md6", + &hex!("cbe8da56ff91be9bc299ed4c1da6159f9a41ab380f565db0a5ef08895aed4f7d"), + ), + ( + b"md6 FTW", + &hex!("7bfaa624f661a683be2a3b2007493006a30a7845ee1670e499927861a8e74cce"), + ), ]; for (msg, &expected_hash) in INPUT.iter() { let mut hasher = md6::Md6_256::new(); hasher.update(msg); let output = hasher.finalize(); - + assert!(output.to_vec() == expected_hash); } } @@ -178,7 +310,7 @@ fn test_md6_384() { let mut hasher = md6::Md6_384::new(); hasher.update(msg); let output = hasher.finalize(); - + assert!(output.to_vec() == expected_hash); } } @@ -214,18 +346,18 @@ fn test_md6_512() { let mut hasher = md6::Md6_512::new(); hasher.update(msg); let output = hasher.finalize(); - + assert!(output.to_vec() == expected_hash); } } #[test] fn test_md6_var() { - use md6::{Update, VariableOutput}; - - let mut hasher = md6::Md6Var::new(12).unwrap(); - hasher.update(b"hello rust"); - let mut buf = [0u8; 12]; - hasher.finalize_variable(&mut buf).unwrap(); - assert_eq!(buf, hex!("9c5b8d9744898ec981bcc573")); -} \ No newline at end of file + use md6::{Update, VariableOutput}; + + let mut hasher = md6::Md6Var::new(12).unwrap(); + hasher.update(b"hello rust"); + let mut buf = [0u8; 12]; + hasher.finalize_variable(&mut buf).unwrap(); + assert_eq!(buf, hex!("9c5b8d9744898ec981bcc573")); +} From 42edfa8a841ee8ced85fe1a252715d01b1442079 Mon Sep 17 00:00:00 2001 From: truthixify Date: Fri, 3 Jan 2025 05:28:26 +0100 Subject: [PATCH 06/16] fixed README.md and Cargo.toml --- md6/Cargo.toml | 2 +- md6/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/md6/Cargo.toml b/md6/Cargo.toml index b338a5a44..17f2a92d3 100644 --- a/md6/Cargo.toml +++ b/md6/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" readme = "README.md" edition = "2021" repository = "https://github.com/RustCrypto/hashes" -keywords = ["crypto", "md5", "hash", "digest"] +keywords = ["crypto", "md6", "hash", "digest"] categories = ["cryptography", "no-std"] rust-version = "1.81" diff --git a/md6/README.md b/md6/README.md index b63b08dff..6080ec825 100644 --- a/md6/README.md +++ b/md6/README.md @@ -11,7 +11,7 @@ use md6::Md6_256; use digest::Digest; use hex_literal::hex; -// create a Blake2b512 object +// create a Md6_256 object let mut hasher = Md6_256::new(); // write input message From 332fb959d59711c04edc2b9c4eeb8a9b0885723d Mon Sep 17 00:00:00 2001 From: truthixify Date: Fri, 3 Jan 2025 05:30:10 +0100 Subject: [PATCH 07/16] changes to Cargo.lock --- Cargo.lock | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index b7fdbba92..36b63ab9e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -250,7 +250,6 @@ version = "0.1.0" dependencies = [ "base16ct", "digest", - "hex", "hex-literal", ] From d7939a7cfc3f2567f3bc8f4c2302fc38662fbeb7 Mon Sep 17 00:00:00 2001 From: truthixify Date: Fri, 3 Jan 2025 07:09:38 +0100 Subject: [PATCH 08/16] fixed consts docs and moved all consts defintion into consts.rs added source for test vectors --- md6/Cargo.toml | 7 ----- md6/src/compress.rs | 16 ---------- md6/src/consts.rs | 74 +++++++++++++++++++++++++++++++++++---------- md6/src/md6.rs | 6 ---- md6/tests/mod.rs | 28 ++++++++--------- 5 files changed, 72 insertions(+), 59 deletions(-) diff --git a/md6/Cargo.toml b/md6/Cargo.toml index 17f2a92d3..a82a8256b 100644 --- a/md6/Cargo.toml +++ b/md6/Cargo.toml @@ -11,9 +11,6 @@ keywords = ["crypto", "md6", "hash", "digest"] categories = ["cryptography", "no-std"] rust-version = "1.81" -[lib] -name = "md6" - [dependencies] digest = "=0.11.0-pre.9" @@ -27,7 +24,3 @@ default = ["oid", "std"] std = ["digest/std"] oid = ["digest/oid"] zeroize = ["digest/zeroize"] - -[package.metadata.docs.rs] -all-features = true -rustdoc-args = ["--cfg", "docsrs"] diff --git a/md6/src/compress.rs b/md6/src/compress.rs index 87931c3c7..959088738 100644 --- a/md6/src/compress.rs +++ b/md6/src/compress.rs @@ -1,21 +1,5 @@ use crate::consts::*; -const W: usize = MD6_W; // number of bits in a word (64) -const C: usize = MD6_C; // size of compression output in words (16) -const N: usize = MD6_N; // size of compression input block in words (89) -const Q: usize = MD6_Q; // Q words in a compression block (>= 0) (15) -const K: usize = MD6_K; // key words per compression block (>= 0) (8) -const U: usize = MD6_U; // words for unique node ID (0 or 64/w) -const V: usize = MD6_V; // words for control word (0 or 64/w) -const B: usize = MD6_B; // data words per compression block (> 0) (64) - -const T0: usize = 17; // index for linear feedback -const T1: usize = 18; // index for first input to first and -const T2: usize = 21; // index for second input to first and -const T3: usize = 31; // index for first input to second and -const T4: usize = 67; // index for second input to second and -const T5: usize = 89; // last tap - macro_rules! call_loop_bodies { ($w: ident, $s: expr, $i: expr) => { if $w == 64 { diff --git a/md6/src/consts.rs b/md6/src/consts.rs index 307b3d281..7dd259cdf 100644 --- a/md6/src/consts.rs +++ b/md6/src/consts.rs @@ -1,21 +1,63 @@ /// MD6 constants related to standard mode of operation -pub(crate) type Md6Word = u64; -pub(crate) type Md6ControlWord = u64; -pub(crate) type Md6NodeID = u64; +pub type Md6Word = u64; +pub type Md6ControlWord = u64; +pub type Md6NodeID = u64; -pub(crate) const MD6_MAX_STACK_HEIGHT: usize = 29; // maximum stack height -pub(crate) const MD6_MAX_R: usize = 255; // maximum number of rounds -pub(crate) const MD6_DEFAULT_L: usize = 64; // large so that MD6 is fully hierarchical +/// Maximum stack height +pub const MD6_MAX_STACK_HEIGHT: usize = 29; +/// Maximum number of rounds +pub const MD6_MAX_R: usize = 255; +/// Large so that MD6 is fully hierarchical +pub const MD6_DEFAULT_L: usize = 64; -pub(crate) const MD6_W: usize = 64; // number of bits in a word -pub(crate) const MD6_C: usize = 16; // size of compression output in words -pub(crate) const MD6_N: usize = 89; // size of compression input block in words +/// Number of bits in a word +pub const MD6_W: usize = 64; +/// Size of compression output in words +pub const MD6_C: usize = 16; +/// Size of compression input block in words +pub const MD6_N: usize = 89; -/// These five values give lengths of the components of compression -/// input block; they should sum to MD6_N. -pub(crate) const MD6_Q: usize = 15; // Q words in a compression block (>= 0) -pub(crate) const MD6_K: usize = 8; // key words per compression block (>= 0) -pub(crate) const MD6_U: usize = 64 / MD6_W; // words for unique node ID (0 or 64/w) -pub(crate) const MD6_V: usize = 64 / MD6_W; // words for control word (0 or 64/w) -pub(crate) const MD6_B: usize = 64; // data words per compression block (> 0) +// These five values give lengths of the components of compression +// input block; they should sum to MD6_N. + +// Q words in a compression block (>= 0) +pub const MD6_Q: usize = 15; +/// Key words per compression block (>= 0) +pub const MD6_K: usize = 8; +/// Words for unique node ID (0 or 64/w) +pub const MD6_U: usize = 64 / MD6_W; +/// Words for control word (0 or 64/w) +pub const MD6_V: usize = 64 / MD6_W; +/// Data words per compression block (> 0) +pub const MD6_B: usize = 64; + +/// Number of bits in a word (64) +pub const W: usize = MD6_W; +/// Size of compression output in words (16) +pub const C: usize = MD6_C; +/// Size of compression input block in words (89) +pub const N: usize = MD6_N; +/// Q words in a compression block (>= 0) (15) +pub const Q: usize = MD6_Q; +/// Key words per compression block (>= 0) (8) +pub const K: usize = MD6_K; +/// Words for unique node ID (0 or 64/w) +pub const U: usize = MD6_U; +/// Words for control word (0 or 64/w) +pub const V: usize = MD6_V; +/// Data words per compression block (> 0) (64) +pub const B: usize = MD6_B; + +/// Index for linear feedback +pub const T0: usize = 17; +/// Index for first input to first and +pub const T1: usize = 18; +/// Index for second input to first and +pub const T2: usize = 21; +/// Index for first input to second and +pub const T3: usize = 31; +/// Index for second input to second and +pub const T4: usize = 67; +/// Last tap +pub const T5: usize = 89; \ No newline at end of file diff --git a/md6/src/md6.rs b/md6/src/md6.rs index e8c93cc93..b43414d85 100644 --- a/md6/src/md6.rs +++ b/md6/src/md6.rs @@ -13,11 +13,6 @@ use digest::{ HashMarker, Output, }; -const W: usize = MD6_W; // number of bits in a word (64) -const C: usize = MD6_C; // size of compression output in words (16) -const K: usize = MD6_K; // key words per compression block (8) -const B: usize = MD6_B; // data words per compression block (64) - pub struct Md6VarCore { d: usize, hashbitlen: usize, @@ -289,7 +284,6 @@ impl SerializableState for Md6VarCore { impl Md6VarCore { #[inline] fn init(d: usize) -> Self { - // Self::full_init(d, None, 0, MD6_DEFAULT_L, default_r(d, 0)) } diff --git a/md6/tests/mod.rs b/md6/tests/mod.rs index 25411b127..50a13896b 100644 --- a/md6/tests/mod.rs +++ b/md6/tests/mod.rs @@ -1,11 +1,11 @@ -#![no_std] - use digest::Digest; use hex_literal::hex; +// Test vectors from https://github.com/Snack-X/md6/blob/master/test/result.csv + #[test] fn test_md6_64() { - const INPUT: &[(&[u8], &[u8; 8])] = &[ + const TEST_VECTOR: &[(&[u8], &[u8; 8])] = &[ (b"a", &hex!("32d13030a6815e95")), (b"aa", &hex!("af7966908a5d9c13")), (b"aaa", &hex!("3d8a4ff7a21eb0c6")), @@ -30,7 +30,7 @@ fn test_md6_64() { (b"md6 FTW", &hex!("47cda109418592ca")), ]; - for (msg, &expected_hash) in INPUT.iter() { + for (msg, &expected_hash) in TEST_VECTOR.iter() { let mut hasher = md6::Md6_64::new(); hasher.update(msg); let output = hasher.finalize(); @@ -41,7 +41,7 @@ fn test_md6_64() { #[test] fn test_md6_128() { - const INPUT: &[(&[u8], &[u8; 16])] = &[ + const TEST_VECTOR: &[(&[u8], &[u8; 16])] = &[ (b"a", &hex!("bb691c1bfa4b4345292eb35f364919ea")), (b"aa", &hex!("19487e566f9ae2584d62628af2795f8c")), (b"aaa", &hex!("319f1b026f76f9caf62320b4e2e79e29")), @@ -66,7 +66,7 @@ fn test_md6_128() { (b"md6 FTW", &hex!("e866b430fa07b5bea28981db1f9b24a6")), ]; - for (msg, &expected_hash) in INPUT.iter() { + for (msg, &expected_hash) in TEST_VECTOR.iter() { let mut hasher = md6::Md6_128::new(); hasher.update(msg); let output = hasher.finalize(); @@ -77,7 +77,7 @@ fn test_md6_128() { #[test] fn test_md6_224() { - const INPUT: &[(&[u8], &[u8; 28])] = &[ + const TEST_VECTOR: &[(&[u8], &[u8; 28])] = &[ ( b"a", &hex!("05de8792a96e024c806eb815f9f30053cf9f1b50661047a4934121b7"), @@ -168,7 +168,7 @@ fn test_md6_224() { ), ]; - for (msg, &expected_hash) in INPUT.iter() { + for (msg, &expected_hash) in TEST_VECTOR.iter() { let mut hasher = md6::Md6_224::new(); hasher.update(msg); let output = hasher.finalize(); @@ -179,7 +179,7 @@ fn test_md6_224() { #[test] fn test_md6_256() { - const INPUT: &[(&[u8], &[u8; 32])] = &[ + const TEST_VECTOR: &[(&[u8], &[u8; 32])] = &[ ( b"a", &hex!("2b0a697a081c21269514640aab4d74ffafeb3c0212df68ce92922087c69b0a77"), @@ -270,7 +270,7 @@ fn test_md6_256() { ), ]; - for (msg, &expected_hash) in INPUT.iter() { + for (msg, &expected_hash) in TEST_VECTOR.iter() { let mut hasher = md6::Md6_256::new(); hasher.update(msg); let output = hasher.finalize(); @@ -281,7 +281,7 @@ fn test_md6_256() { #[test] fn test_md6_384() { - const INPUT: &[(&[u8], &[u8; 48])] = &[ + const TEST_VECTOR: &[(&[u8], &[u8; 48])] = &[ (b"a", &hex!("a40c8d059495a278fadd30b96e3b2227758090c759b934197265bf632cabf8547a7429e5316d496c2a1ddae8d27e87ee")), (b"aa", &hex!("330547441b6518e7693ea01bfc55158bcfc084853fa1960a9e8999f98b57cea7d8b0564bf192b6ab1eb7638939dc9bbf")), (b"aaa", &hex!("f43bb4e108ec31e0cf8ded506f79373e69cddcd8c7c46298f1bd475401132e4c255c08e378c9db988f0de97131cbe36c")), @@ -306,7 +306,7 @@ fn test_md6_384() { (b"md6 FTW", &hex!("7a4e8ecd1035ccdf00567595c15aa5a382fef2b6a4ec4bc609e0c655887b1c05e10eee223dd6c0ba5fa4a46159c70757")), ]; - for (msg, &expected_hash) in INPUT.iter() { + for (msg, &expected_hash) in TEST_VECTOR.iter() { let mut hasher = md6::Md6_384::new(); hasher.update(msg); let output = hasher.finalize(); @@ -317,7 +317,7 @@ fn test_md6_384() { #[test] fn test_md6_512() { - const INPUT: &[(&[u8], &[u8; 64])] = &[ + const TEST_VECTOR: &[(&[u8], &[u8; 64])] = &[ (b"a", &hex!("c0e4e18acb69cd1a7e5a20981fe6cc6f7b5b70e814d3a13b05ac292aba74c0d8c9d34c211414e7ab755a9559c27211cd749fc3eb09ae670e138881743b8d5051")), (b"aa", &hex!("2afa253b05702770343e5c46e9d47231812a741d7bba479539a3c5484a412ea419f0d0ca96e124ba92e4ca506ca12684579323051d9d52fe5a669d079a226683")), (b"aaa", &hex!("56b0131875d458f6d30ed1c594991df1efa8d6cae0c8abb36a9b811df23ac476c58e36d9adbe845e840d3de9175a8ceda11235144c3222587af108b902ce0fc5")), @@ -342,7 +342,7 @@ fn test_md6_512() { (b"md6 FTW", &hex!("75df3b6031e8241ef59d01628b093b05906f1a2d80c43908cb2883f7db6fbdd1cadffd7d643505c20b9529b6a5d19f8b6ff1623cabbc14a606caa7bcb239611a")), ]; - for (msg, &expected_hash) in INPUT.iter() { + for (msg, &expected_hash) in TEST_VECTOR.iter() { let mut hasher = md6::Md6_512::new(); hasher.update(msg); let output = hasher.finalize(); From 50963983fe23df1962791d30c2e9650a3f4731ac Mon Sep 17 00:00:00 2001 From: truthixify Date: Fri, 3 Jan 2025 07:33:15 +0100 Subject: [PATCH 09/16] cargo fmt... oh my --- md6/src/consts.rs | 50 +++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/md6/src/consts.rs b/md6/src/consts.rs index 7dd259cdf..e24f0b0ef 100644 --- a/md6/src/consts.rs +++ b/md6/src/consts.rs @@ -5,59 +5,59 @@ pub type Md6ControlWord = u64; pub type Md6NodeID = u64; /// Maximum stack height -pub const MD6_MAX_STACK_HEIGHT: usize = 29; +pub const MD6_MAX_STACK_HEIGHT: usize = 29; /// Maximum number of rounds -pub const MD6_MAX_R: usize = 255; +pub const MD6_MAX_R: usize = 255; /// Large so that MD6 is fully hierarchical -pub const MD6_DEFAULT_L: usize = 64; +pub const MD6_DEFAULT_L: usize = 64; /// Number of bits in a word -pub const MD6_W: usize = 64; +pub const MD6_W: usize = 64; /// Size of compression output in words -pub const MD6_C: usize = 16; +pub const MD6_C: usize = 16; /// Size of compression input block in words -pub const MD6_N: usize = 89; +pub const MD6_N: usize = 89; // These five values give lengths of the components of compression // input block; they should sum to MD6_N. // Q words in a compression block (>= 0) -pub const MD6_Q: usize = 15; +pub const MD6_Q: usize = 15; /// Key words per compression block (>= 0) -pub const MD6_K: usize = 8; +pub const MD6_K: usize = 8; /// Words for unique node ID (0 or 64/w) -pub const MD6_U: usize = 64 / MD6_W; +pub const MD6_U: usize = 64 / MD6_W; /// Words for control word (0 or 64/w) -pub const MD6_V: usize = 64 / MD6_W; +pub const MD6_V: usize = 64 / MD6_W; /// Data words per compression block (> 0) -pub const MD6_B: usize = 64; +pub const MD6_B: usize = 64; /// Number of bits in a word (64) -pub const W: usize = MD6_W; +pub const W: usize = MD6_W; /// Size of compression output in words (16) -pub const C: usize = MD6_C; +pub const C: usize = MD6_C; /// Size of compression input block in words (89) -pub const N: usize = MD6_N; +pub const N: usize = MD6_N; /// Q words in a compression block (>= 0) (15) -pub const Q: usize = MD6_Q; +pub const Q: usize = MD6_Q; /// Key words per compression block (>= 0) (8) -pub const K: usize = MD6_K; +pub const K: usize = MD6_K; /// Words for unique node ID (0 or 64/w) -pub const U: usize = MD6_U; +pub const U: usize = MD6_U; /// Words for control word (0 or 64/w) -pub const V: usize = MD6_V; +pub const V: usize = MD6_V; /// Data words per compression block (> 0) (64) -pub const B: usize = MD6_B; +pub const B: usize = MD6_B; /// Index for linear feedback -pub const T0: usize = 17; +pub const T0: usize = 17; /// Index for first input to first and -pub const T1: usize = 18; +pub const T1: usize = 18; /// Index for second input to first and -pub const T2: usize = 21; +pub const T2: usize = 21; /// Index for first input to second and -pub const T3: usize = 31; +pub const T3: usize = 31; /// Index for second input to second and -pub const T4: usize = 67; +pub const T4: usize = 67; /// Last tap -pub const T5: usize = 89; \ No newline at end of file +pub const T5: usize = 89; From f6e7afb2c38d87d2cf25369304319de13b81ca4d Mon Sep 17 00:00:00 2001 From: truthixify Date: Mon, 24 Mar 2025 02:06:29 +0100 Subject: [PATCH 10/16] removed minimum supported rust version and semver policy from README.md --- md6/README.md | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/md6/README.md b/md6/README.md index 6080ec825..6955f0d4b 100644 --- a/md6/README.md +++ b/md6/README.md @@ -57,18 +57,6 @@ let res = hasher.finalize(); assert_eq!(res, hex!("576d736a93a555a1c868973cfdd2d21838a26623")); ``` -## Minimum Supported Rust Version - -Rust **1.81** or higher. - -Minimum supported Rust version can be changed in the future, but it will be -done with a minor version bump. - -## SemVer Policy - -- All on-by-default features of this library are covered by SemVer -- MSRV is considered exempt from SemVer as noted above - ## License The crate is licensed under either of: From e0b3c1a3075259d2d795d0a2256ac9b2767b8d8b Mon Sep 17 00:00:00 2001 From: truthixify Date: Mon, 24 Mar 2025 12:36:26 +0100 Subject: [PATCH 11/16] Update main README, md6 README, and added md6 CI workflow --- .github/workflows/md6.yml | 71 +++++++++++++++++++++++++++++++++++++++ Cargo.lock | 56 ++++++++++++++++-------------- README.md | 3 ++ md6/Cargo.toml | 14 +++++--- md6/src/consts.rs | 8 ++--- md6/tests/mod.rs | 24 ++++++------- 6 files changed, 129 insertions(+), 47 deletions(-) create mode 100644 .github/workflows/md6.yml diff --git a/.github/workflows/md6.yml b/.github/workflows/md6.yml new file mode 100644 index 000000000..949ebf8b2 --- /dev/null +++ b/.github/workflows/md6.yml @@ -0,0 +1,71 @@ +name: md6 + +on: + pull_request: + paths: + - ".github/workflows/md6.yml" + - "md6/**" + - "Cargo.*" + push: + branches: master + paths: + - "md6/**" + - "Cargo.*" + +defaults: + run: + working-directory: md6 + +env: + CARGO_INCREMENTAL: 0 + RUSTFLAGS: "-Dwarnings" + +jobs: + set-msrv: + uses: RustCrypto/actions/.github/workflows/set-msrv.yml@master + with: + msrv: 1.85.0 + + build: + needs: set-msrv + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - ${{needs.set-msrv.outputs.msrv}} + - stable + target: + - thumbv7em-none-eabi + - wasm32-unknown-unknown + - loongarch64-unknown-linux-gnu + steps: + - uses: actions/checkout@v4 + - uses: RustCrypto/actions/cargo-cache@master + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + targets: ${{ matrix.target }} + - uses: RustCrypto/actions/cargo-hack-install@master + - run: cargo hack build --target ${{ matrix.target }} --each-feature --exclude-features default,std + + test: + needs: set-msrv + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - ${{needs.set-msrv.outputs.msrv}} + - stable + steps: + - uses: actions/checkout@v4 + - uses: RustCrypto/actions/cargo-cache@master + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + - uses: RustCrypto/actions/cargo-hack-install@master + - run: cargo hack test --feature-powerset + + minimal-versions: + uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master + with: + working-directory: ${{ github.workflow }} diff --git a/Cargo.lock b/Cargo.lock index f285482a8..53dfd4415 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,7 +19,7 @@ dependencies = [ "base16ct", "digest", "hex", - "hex-literal", + "hex-literal 1.0.0", "spectral", ] @@ -42,7 +42,7 @@ dependencies = [ "base16ct", "belt-block", "digest", - "hex-literal", + "hex-literal 1.0.0", ] [[package]] @@ -51,7 +51,7 @@ version = "0.11.0-pre.5" dependencies = [ "base16ct", "digest", - "hex-literal", + "hex-literal 1.0.0", ] [[package]] @@ -118,7 +118,7 @@ version = "0.2.0-pre" dependencies = [ "base16ct", "digest", - "hex-literal", + "hex-literal 1.0.0", "whirlpool", ] @@ -128,7 +128,7 @@ version = "0.11.0-pre" dependencies = [ "base16ct", "digest", - "hex-literal", + "hex-literal 1.0.0", ] [[package]] @@ -137,7 +137,7 @@ version = "0.11.0-pre" dependencies = [ "base16ct", "digest", - "hex-literal", + "hex-literal 1.0.0", ] [[package]] @@ -146,6 +146,12 @@ 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 = "hex-literal" version = "1.0.0" @@ -167,7 +173,7 @@ version = "0.2.0-pre" dependencies = [ "base16ct", "digest", - "hex-literal", + "hex-literal 1.0.0", "ppv-lite86", ] @@ -176,7 +182,7 @@ name = "k12" version = "0.4.0-pre" dependencies = [ "digest", - "hex-literal", + "hex-literal 1.0.0", "sha3", ] @@ -195,7 +201,7 @@ version = "0.1.0" dependencies = [ "base16ct", "digest", - "hex-literal", + "hex-literal 1.0.0", ] [[package]] @@ -211,7 +217,7 @@ dependencies = [ "base16ct", "cfg-if", "digest", - "hex-literal", + "hex-literal 1.0.0", ] [[package]] @@ -220,7 +226,7 @@ version = "0.11.0-pre" dependencies = [ "base16ct", "digest", - "hex-literal", + "hex-literal 1.0.0", ] [[package]] @@ -229,16 +235,16 @@ version = "0.11.0-pre" dependencies = [ "base16ct", "digest", - "hex-literal", + "hex-literal 1.0.0", ] [[package]] name = "md6" -version = "0.1.0" +version = "0.11.0-pre.5" dependencies = [ "base16ct", "digest", - "hex-literal", + "hex-literal 0.4.1", ] [[package]] @@ -274,7 +280,7 @@ version = "0.2.0-pre.5" dependencies = [ "base16ct", "digest", - "hex-literal", + "hex-literal 1.0.0", ] [[package]] @@ -285,7 +291,7 @@ dependencies = [ "cfg-if", "cpufeatures", "digest", - "hex-literal", + "hex-literal 1.0.0", ] [[package]] @@ -294,7 +300,7 @@ version = "0.11.0-pre" dependencies = [ "base16ct", "digest", - "hex-literal", + "hex-literal 1.0.0", "sha1", "zeroize", ] @@ -307,7 +313,7 @@ dependencies = [ "cfg-if", "cpufeatures", "digest", - "hex-literal", + "hex-literal 1.0.0", ] [[package]] @@ -316,7 +322,7 @@ version = "0.11.0-pre.5" dependencies = [ "base16ct", "digest", - "hex-literal", + "hex-literal 1.0.0", "keccak", ] @@ -326,7 +332,7 @@ version = "0.5.0-pre" dependencies = [ "base16ct", "digest", - "hex-literal", + "hex-literal 1.0.0", ] [[package]] @@ -335,7 +341,7 @@ version = "0.2.0-pre" dependencies = [ "base16ct", "digest", - "hex-literal", + "hex-literal 1.0.0", "threefish", ] @@ -345,7 +351,7 @@ version = "0.5.0-pre.5" dependencies = [ "base16ct", "digest", - "hex-literal", + "hex-literal 1.0.0", ] [[package]] @@ -360,7 +366,7 @@ version = "0.11.0-pre.5" dependencies = [ "base16ct", "digest", - "hex-literal", + "hex-literal 1.0.0", ] [[package]] @@ -395,7 +401,7 @@ version = "0.3.0-pre" dependencies = [ "base16ct", "digest", - "hex-literal", + "hex-literal 1.0.0", ] [[package]] @@ -416,7 +422,7 @@ version = "0.11.0-pre.5" dependencies = [ "base16ct", "digest", - "hex-literal", + "hex-literal 1.0.0", ] [[package]] diff --git a/README.md b/README.md index 3c727aad7..2cf10f2ad 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ Additionally all crates do not require the standard library (i.e. `no_std` capab | [MD2] | [`md2`] | [![crates.io](https://img.shields.io/crates/v/md2.svg)](https://crates.io/crates/md2) | [![Documentation](https://docs.rs/md2/badge.svg)](https://docs.rs/md2) | 1.85 | :broken_heart: | | [MD4] | [`md4`] | [![crates.io](https://img.shields.io/crates/v/md4.svg)](https://crates.io/crates/md4) | [![Documentation](https://docs.rs/md4/badge.svg)](https://docs.rs/md4) | 1.85 | :broken_heart: | | [MD5] | [`md5`] [:exclamation:] | [![crates.io](https://img.shields.io/crates/v/md-5.svg)](https://crates.io/crates/md-5) | [![Documentation](https://docs.rs/md-5/badge.svg)](https://docs.rs/md-5) | 1.85 | :broken_heart: | +| [MD6] | [`md6`] | [![crates.io](https://img.shields.io/crates/v/md-6.svg)](https://crates.io/crates/md-6) | [![Documentation](https://docs.rs/md-6/badge.svg)](https://docs.rs/md-6) | 1.85 | :green_heart: | | [RIPEMD] | [`ripemd`] | [![crates.io](https://img.shields.io/crates/v/ripemd.svg)](https://crates.io/crates/ripemd) | [![Documentation](https://docs.rs/ripemd/badge.svg)](https://docs.rs/ripemd) | 1.85 | :green_heart: | | [SHA-1] | [`sha1`] | [![crates.io](https://img.shields.io/crates/v/sha1.svg)](https://crates.io/crates/sha1) | [![Documentation](https://docs.rs/sha1/badge.svg)](https://docs.rs/sha1) | 1.85 | :broken_heart: | | [SHA-1 Checked] | [`sha1-checked`] | [![crates.io](https://img.shields.io/crates/v/sha1-checked.svg)](https://crates.io/crates/sha1-checked) | [![Documentation](https://docs.rs/sha1-checked/badge.svg)](https://docs.rs/sha1-checked) | 1.85 | :yellow_heart: | @@ -246,6 +247,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [`md2`]: ./md2 [`md4`]: ./md4 [`md5`]: ./md5 +[`md6`]: ./md6 [`ripemd`]: ./ripemd [`sha1`]: ./sha1 [`sha1-checked`]: ./sha1-checked @@ -289,6 +291,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [MD2]: https://en.wikipedia.org/wiki/MD2_(cryptography) [MD4]: https://en.wikipedia.org/wiki/MD4 [MD5]: https://en.wikipedia.org/wiki/MD5 +[MD6]: https://en.wikipedia.org/wiki/MD6 [RIPEMD]: https://en.wikipedia.org/wiki/RIPEMD [SHA-1]: https://en.wikipedia.org/wiki/SHA-1 [SHA-1 Checked]: https://github.com/cr-marcstevens/sha1collisiondetection diff --git a/md6/Cargo.toml b/md6/Cargo.toml index a82a8256b..0a24f5771 100644 --- a/md6/Cargo.toml +++ b/md6/Cargo.toml @@ -1,21 +1,21 @@ [package] name = "md6" -version = "0.1.0" +version = "0.11.0-pre.5" description = "MD6 hash function" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" readme = "README.md" -edition = "2021" +edition = "2024" +rust-version = "1.85" repository = "https://github.com/RustCrypto/hashes" keywords = ["crypto", "md6", "hash", "digest"] categories = ["cryptography", "no-std"] -rust-version = "1.81" [dependencies] -digest = "=0.11.0-pre.9" +digest = "=0.11.0-pre.10" [dev-dependencies] -digest = { version = "=0.11.0-pre.9", features = ["dev"] } +digest = { version = "=0.11.0-pre.10", features = ["dev"] } hex-literal = "0.4" base16ct = { version = "0.2", features = ["alloc"] } @@ -24,3 +24,7 @@ default = ["oid", "std"] std = ["digest/std"] oid = ["digest/oid"] zeroize = ["digest/zeroize"] + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] \ No newline at end of file diff --git a/md6/src/consts.rs b/md6/src/consts.rs index e24f0b0ef..f237b0b57 100644 --- a/md6/src/consts.rs +++ b/md6/src/consts.rs @@ -1,5 +1,4 @@ /// MD6 constants related to standard mode of operation - pub type Md6Word = u64; pub type Md6ControlWord = u64; pub type Md6NodeID = u64; @@ -18,10 +17,9 @@ pub const MD6_C: usize = 16; /// Size of compression input block in words pub const MD6_N: usize = 89; -// These five values give lengths of the components of compression -// input block; they should sum to MD6_N. - -// Q words in a compression block (>= 0) +/// These five values give lengths of the components of compression +/// input block; they should sum to MD6_N. +/// Q words in a compression block (>= 0) pub const MD6_Q: usize = 15; /// Key words per compression block (>= 0) pub const MD6_K: usize = 8; diff --git a/md6/tests/mod.rs b/md6/tests/mod.rs index 50a13896b..63a6787f1 100644 --- a/md6/tests/mod.rs +++ b/md6/tests/mod.rs @@ -30,12 +30,12 @@ fn test_md6_64() { (b"md6 FTW", &hex!("47cda109418592ca")), ]; - for (msg, &expected_hash) in TEST_VECTOR.iter() { + for (msg, expected_hash) in TEST_VECTOR.iter() { let mut hasher = md6::Md6_64::new(); hasher.update(msg); let output = hasher.finalize(); - assert!(output.to_vec() == expected_hash); + assert!(output.to_vec() == *expected_hash); } } @@ -66,12 +66,12 @@ fn test_md6_128() { (b"md6 FTW", &hex!("e866b430fa07b5bea28981db1f9b24a6")), ]; - for (msg, &expected_hash) in TEST_VECTOR.iter() { + for (msg, expected_hash) in TEST_VECTOR.iter() { let mut hasher = md6::Md6_128::new(); hasher.update(msg); let output = hasher.finalize(); - assert!(output.to_vec() == expected_hash); + assert!(output.to_vec() == *expected_hash); } } @@ -168,12 +168,12 @@ fn test_md6_224() { ), ]; - for (msg, &expected_hash) in TEST_VECTOR.iter() { + for (msg, expected_hash) in TEST_VECTOR.iter() { let mut hasher = md6::Md6_224::new(); hasher.update(msg); let output = hasher.finalize(); - assert!(output.to_vec() == expected_hash); + assert!(output.to_vec() == *expected_hash); } } @@ -270,12 +270,12 @@ fn test_md6_256() { ), ]; - for (msg, &expected_hash) in TEST_VECTOR.iter() { + for (msg, expected_hash) in TEST_VECTOR.iter() { let mut hasher = md6::Md6_256::new(); hasher.update(msg); let output = hasher.finalize(); - assert!(output.to_vec() == expected_hash); + assert!(output.to_vec() == *expected_hash); } } @@ -306,12 +306,12 @@ fn test_md6_384() { (b"md6 FTW", &hex!("7a4e8ecd1035ccdf00567595c15aa5a382fef2b6a4ec4bc609e0c655887b1c05e10eee223dd6c0ba5fa4a46159c70757")), ]; - for (msg, &expected_hash) in TEST_VECTOR.iter() { + for (msg, expected_hash) in TEST_VECTOR.iter() { let mut hasher = md6::Md6_384::new(); hasher.update(msg); let output = hasher.finalize(); - assert!(output.to_vec() == expected_hash); + assert!(output.to_vec() == *expected_hash); } } @@ -342,12 +342,12 @@ fn test_md6_512() { (b"md6 FTW", &hex!("75df3b6031e8241ef59d01628b093b05906f1a2d80c43908cb2883f7db6fbdd1cadffd7d643505c20b9529b6a5d19f8b6ff1623cabbc14a606caa7bcb239611a")), ]; - for (msg, &expected_hash) in TEST_VECTOR.iter() { + for (msg, expected_hash) in TEST_VECTOR.iter() { let mut hasher = md6::Md6_512::new(); hasher.update(msg); let output = hasher.finalize(); - assert!(output.to_vec() == expected_hash); + assert!(output.to_vec() == *expected_hash); } } From a5eb5f5fb36f0b0cde0f0cfc0e60573d848e80ec Mon Sep 17 00:00:00 2001 From: truthixify Date: Mon, 24 Mar 2025 13:17:19 +0100 Subject: [PATCH 12/16] fixed workflow error for clippy, rustfmt and build --- .github/workflows/md6.yml | 1 - md6/Cargo.toml | 1 - md6/benches/mod.rs | 2 +- md6/src/compress.rs | 14 +- md6/src/lib.rs | 2 +- md6/src/md6.rs | 14 +- md6/tests/mod.rs | 320 ++++++++++++++++++++++++++++++++------ 7 files changed, 286 insertions(+), 68 deletions(-) diff --git a/.github/workflows/md6.yml b/.github/workflows/md6.yml index 949ebf8b2..581ee49ed 100644 --- a/.github/workflows/md6.yml +++ b/.github/workflows/md6.yml @@ -37,7 +37,6 @@ jobs: target: - thumbv7em-none-eabi - wasm32-unknown-unknown - - loongarch64-unknown-linux-gnu steps: - uses: actions/checkout@v4 - uses: RustCrypto/actions/cargo-cache@master diff --git a/md6/Cargo.toml b/md6/Cargo.toml index 0a24f5771..eb9500620 100644 --- a/md6/Cargo.toml +++ b/md6/Cargo.toml @@ -27,4 +27,3 @@ zeroize = ["digest/zeroize"] [package.metadata.docs.rs] all-features = true -rustdoc-args = ["--cfg", "docsrs"] \ No newline at end of file diff --git a/md6/benches/mod.rs b/md6/benches/mod.rs index 46869523e..66dd6936e 100644 --- a/md6/benches/mod.rs +++ b/md6/benches/mod.rs @@ -2,7 +2,7 @@ extern crate test; use digest::bench_update; -use md6::{Md6_128, Md6_224, Md6_256, Md6_384, Md6_512, Md6_64}; +use md6::{Md6_64, Md6_128, Md6_224, Md6_256, Md6_384, Md6_512}; use test::Bencher; bench_update!( diff --git a/md6/src/compress.rs b/md6/src/compress.rs index 959088738..42bcea16f 100644 --- a/md6/src/compress.rs +++ b/md6/src/compress.rs @@ -137,17 +137,17 @@ pub fn make_control_word( keylen: usize, d: usize, ) -> Md6ControlWord { - (0 as Md6ControlWord) << 60 // reserved width 4 bits - | (r as Md6ControlWord) << 48 // r width 12 bits - | (l as Md6ControlWord) << 40 // L width 8 bits - | (z as Md6ControlWord) << 36 // z width 4 bits - | (p as Md6ControlWord) << 20 // p width 16 bits - | (keylen as Md6ControlWord) << 12 // keylen width 8 bits + ((0 as Md6ControlWord) << 60) // reserved width 4 bits + | ((r as Md6ControlWord) << 48) // r width 12 bits + | ((l as Md6ControlWord) << 40) // L width 8 bits + | ((z as Md6ControlWord) << 36) // z width 4 bits + | ((p as Md6ControlWord) << 20) // p width 16 bits + | ((keylen as Md6ControlWord) << 12) // keylen width 8 bits | (d as Md6ControlWord) // d width 12 bits } pub fn make_node_id(ell: usize, i: Md6Word) -> Md6NodeID { - (ell as Md6NodeID) << 56 | i // ell width 8 bits, i width 56 bits + ((ell as Md6NodeID) << 56) | i // ell width 8 bits, i width 56 bits } pub fn pack( diff --git a/md6/src/lib.rs b/md6/src/lib.rs index afaa85ebc..c6d956376 100644 --- a/md6/src/lib.rs +++ b/md6/src/lib.rs @@ -12,7 +12,7 @@ pub(crate) mod consts; mod md6; use digest::{ - consts::{U16, U28, U32, U48, U64, U8}, + consts::{U8, U16, U28, U32, U48, U64}, core_api::{CoreWrapper, CtVariableCoreWrapper, RtVariableCoreWrapper}, }; diff --git a/md6/src/md6.rs b/md6/src/md6.rs index b43414d85..0fecfdea8 100644 --- a/md6/src/md6.rs +++ b/md6/src/md6.rs @@ -3,14 +3,14 @@ use crate::consts::*; use core::fmt; use digest::{ + HashMarker, Output, block_buffer::Eager, core_api::{ AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, OutputSizeUser, Reset, TruncSide, UpdateCore, VariableOutputCore, }, crypto_common::hazmat::{DeserializeStateError, SerializableState, SerializedState}, - typenum::{Unsigned, U128, U64}, - HashMarker, Output, + typenum::{U64, U128, Unsigned}, }; pub struct Md6VarCore { @@ -469,13 +469,13 @@ impl Md6VarCore { let mut di = destlen / 8; // Index of where next byte will go within dest // Ensure dest has enough space - let new_len = (destlen + srclen + 7) / 8; + let new_len = (destlen + srclen).div_ceil(8); if self.b[1].len() < new_len { panic!("destination buffer is too small"); } // Number of bytes (full or partial) in src - let srcbytes = (srclen + 7) / 8; + let srcbytes = srclen.div_ceil(8); for (i, item) in src.iter().enumerate().take(srcbytes) { if i != srcbytes - 1 { @@ -547,17 +547,17 @@ impl Md6VarCore { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', ]; - for i in 0..((self.d + 7) / 8) { + for i in 0..(self.d.div_ceil(8)) { self.hexhashval[2 * i] = hex_digits[((self.hashval[i] >> 4) & 0xf) as usize]; self.hexhashval[2 * i + 1] = hex_digits[((self.hashval[i]) & 0xf) as usize]; } - self.hexhashval[(self.d + 3) / 4] = '\n'; + self.hexhashval[self.d.div_ceil(4)] = '\n'; } #[inline] fn trim_hashval(&mut self) { - let full_or_partial_bytes = (self.d + 7) / 8; + let full_or_partial_bytes = self.d.div_ceil(8); let bits = self.d % 8; // move relevant bytes to the front diff --git a/md6/tests/mod.rs b/md6/tests/mod.rs index 63a6787f1..956e6d18c 100644 --- a/md6/tests/mod.rs +++ b/md6/tests/mod.rs @@ -35,7 +35,7 @@ fn test_md6_64() { hasher.update(msg); let output = hasher.finalize(); - assert!(output.to_vec() == *expected_hash); + assert!(output[..] == **expected_hash); } } @@ -71,7 +71,7 @@ fn test_md6_128() { hasher.update(msg); let output = hasher.finalize(); - assert!(output.to_vec() == *expected_hash); + assert!(output[..] == **expected_hash); } } @@ -173,7 +173,7 @@ fn test_md6_224() { hasher.update(msg); let output = hasher.finalize(); - assert!(output.to_vec() == *expected_hash); + assert!(output[..] == **expected_hash); } } @@ -275,35 +275,145 @@ fn test_md6_256() { hasher.update(msg); let output = hasher.finalize(); - assert!(output.to_vec() == *expected_hash); + assert!(output[..] == **expected_hash); } } #[test] fn test_md6_384() { const TEST_VECTOR: &[(&[u8], &[u8; 48])] = &[ - (b"a", &hex!("a40c8d059495a278fadd30b96e3b2227758090c759b934197265bf632cabf8547a7429e5316d496c2a1ddae8d27e87ee")), - (b"aa", &hex!("330547441b6518e7693ea01bfc55158bcfc084853fa1960a9e8999f98b57cea7d8b0564bf192b6ab1eb7638939dc9bbf")), - (b"aaa", &hex!("f43bb4e108ec31e0cf8ded506f79373e69cddcd8c7c46298f1bd475401132e4c255c08e378c9db988f0de97131cbe36c")), - (b"aaaa", &hex!("b848065d437013c8fda2493bbf240587ef5fd82a178416613e5c0077541c1ca33f205e58d49387d4d9e3cd62d2d104f6")), - (b"aaaaa", &hex!("20ba7998f75c67dd1371cec629e0606739514cdfb32a17b94fa8ad4c4ec7a06a09821c93a16c863ff7ff72631b5ad02b")), - (b"aaaaaa", &hex!("4930a7f1d619e219a12ca118f1a2f6dd9b23b32b366014b5d14976a927d4252e89d927b7c1d1e796aec3d2f3fd294287")), - (b"aaaaaaa", &hex!("cf15b1b738f91476f2a139dda60e59f5e7422d7e99cb35d9bbb96f85c52a8e6542d4b08070c0855474946d86cc99fba3")), - (b"aaaaaaaa", &hex!("7f9dba3ca2c4442eefd377877b168a2283576abd157c87cda401aa86c484669aa17326fe1e4a50dcca8cbe5bb5a0e947")), - (b"aaaaaaaaa", &hex!("067d6be27eef07c654254a62275daa41630b9fd5d074badb2d16f0cf5e9621026ef0506649efebcf3a18bdf2b6a17a3a")), - (b"aaaaaaaaaa", &hex!("f1fc124cbfa55170d508a26bdad017978bac8be6899f1a99f420c94bd1ef8d5547bf36488e8824215cf5da878041cf76")), - (b"0", &hex!("9a97b926552bb7bc61015e43e9430e3c49a76724c6d6e0b31c14f9c5bb4c7dbf78d5c583401976da7139819dc16c5934")), - (b"1", &hex!("103644563cda42ea432d325fed2b0977f0d767f475b4794322916b7d82b24308c11389a6fe2acf6cade70ddf990da337")), - (b"2", &hex!("dcfdb3807231f3c5d0da945e0cc83f1d2368479f059c46841b112796bca717b4acce887877062e60f3af0276a43eb13d")), - (b"3", &hex!("37e21bffcc21b6de5d3bbae971d9e889670e9c77ad8f42558caea4e59fea1efb7b3392ca53a294b862b04893cdf0a4f6")), - (b"4", &hex!("aaf0b2fd043fc3f2e247f02ab1618b1450db799174bf6fae883822b7cf145d7080c5b70899c10ebb7a4221c9ab36070b")), - (b"5", &hex!("4d59a67f4c321eb971d7bd26a0c8e3ff7a023bb7c15097aa9b13a94fce91b24cf82ce09acac63f63f1da708ecfe49427")), - (b"6", &hex!("36886709330eae549c25558ac0d4ae2b7082261e76d33d589379d3ada613eb31943bf8dda1e92fbc7001fa6f407b025e")), - (b"7", &hex!("9124c888a99743a90daa8a3032014c6542f0e4ed949e950e3a2ff4945ae9f7c648dc6bf712a5556edaed50e7dc299007")), - (b"8", &hex!("41b469911cebb00f5ab173e5238fe4e6aa1737f21159f550913b7b30c99d8c2c1ecd2c431f0baa992eccc5a9cfddf782")), - (b"9", &hex!("9211ce0b1ae366def2d9337c34e4b1ea75ac93efab88c273ce691ed7d20da8d0bd8cbd8d2341e7a619705fcb4eeda311")), - (b"md6", &hex!("1aa5bb36a472fdb3d19ae8b3aa84773ab9a8e7e13d0fde914488bba066d64d5309155ea5b7a3b33b4d9d6855fa9050b1")), - (b"md6 FTW", &hex!("7a4e8ecd1035ccdf00567595c15aa5a382fef2b6a4ec4bc609e0c655887b1c05e10eee223dd6c0ba5fa4a46159c70757")), + ( + b"a", + &hex!( + "a40c8d059495a278fadd30b96e3b2227758090c759b934197265bf632cabf8547a7429e5316d496c2a1ddae8d27e87ee" + ), + ), + ( + b"aa", + &hex!( + "330547441b6518e7693ea01bfc55158bcfc084853fa1960a9e8999f98b57cea7d8b0564bf192b6ab1eb7638939dc9bbf" + ), + ), + ( + b"aaa", + &hex!( + "f43bb4e108ec31e0cf8ded506f79373e69cddcd8c7c46298f1bd475401132e4c255c08e378c9db988f0de97131cbe36c" + ), + ), + ( + b"aaaa", + &hex!( + "b848065d437013c8fda2493bbf240587ef5fd82a178416613e5c0077541c1ca33f205e58d49387d4d9e3cd62d2d104f6" + ), + ), + ( + b"aaaaa", + &hex!( + "20ba7998f75c67dd1371cec629e0606739514cdfb32a17b94fa8ad4c4ec7a06a09821c93a16c863ff7ff72631b5ad02b" + ), + ), + ( + b"aaaaaa", + &hex!( + "4930a7f1d619e219a12ca118f1a2f6dd9b23b32b366014b5d14976a927d4252e89d927b7c1d1e796aec3d2f3fd294287" + ), + ), + ( + b"aaaaaaa", + &hex!( + "cf15b1b738f91476f2a139dda60e59f5e7422d7e99cb35d9bbb96f85c52a8e6542d4b08070c0855474946d86cc99fba3" + ), + ), + ( + b"aaaaaaaa", + &hex!( + "7f9dba3ca2c4442eefd377877b168a2283576abd157c87cda401aa86c484669aa17326fe1e4a50dcca8cbe5bb5a0e947" + ), + ), + ( + b"aaaaaaaaa", + &hex!( + "067d6be27eef07c654254a62275daa41630b9fd5d074badb2d16f0cf5e9621026ef0506649efebcf3a18bdf2b6a17a3a" + ), + ), + ( + b"aaaaaaaaaa", + &hex!( + "f1fc124cbfa55170d508a26bdad017978bac8be6899f1a99f420c94bd1ef8d5547bf36488e8824215cf5da878041cf76" + ), + ), + ( + b"0", + &hex!( + "9a97b926552bb7bc61015e43e9430e3c49a76724c6d6e0b31c14f9c5bb4c7dbf78d5c583401976da7139819dc16c5934" + ), + ), + ( + b"1", + &hex!( + "103644563cda42ea432d325fed2b0977f0d767f475b4794322916b7d82b24308c11389a6fe2acf6cade70ddf990da337" + ), + ), + ( + b"2", + &hex!( + "dcfdb3807231f3c5d0da945e0cc83f1d2368479f059c46841b112796bca717b4acce887877062e60f3af0276a43eb13d" + ), + ), + ( + b"3", + &hex!( + "37e21bffcc21b6de5d3bbae971d9e889670e9c77ad8f42558caea4e59fea1efb7b3392ca53a294b862b04893cdf0a4f6" + ), + ), + ( + b"4", + &hex!( + "aaf0b2fd043fc3f2e247f02ab1618b1450db799174bf6fae883822b7cf145d7080c5b70899c10ebb7a4221c9ab36070b" + ), + ), + ( + b"5", + &hex!( + "4d59a67f4c321eb971d7bd26a0c8e3ff7a023bb7c15097aa9b13a94fce91b24cf82ce09acac63f63f1da708ecfe49427" + ), + ), + ( + b"6", + &hex!( + "36886709330eae549c25558ac0d4ae2b7082261e76d33d589379d3ada613eb31943bf8dda1e92fbc7001fa6f407b025e" + ), + ), + ( + b"7", + &hex!( + "9124c888a99743a90daa8a3032014c6542f0e4ed949e950e3a2ff4945ae9f7c648dc6bf712a5556edaed50e7dc299007" + ), + ), + ( + b"8", + &hex!( + "41b469911cebb00f5ab173e5238fe4e6aa1737f21159f550913b7b30c99d8c2c1ecd2c431f0baa992eccc5a9cfddf782" + ), + ), + ( + b"9", + &hex!( + "9211ce0b1ae366def2d9337c34e4b1ea75ac93efab88c273ce691ed7d20da8d0bd8cbd8d2341e7a619705fcb4eeda311" + ), + ), + ( + b"md6", + &hex!( + "1aa5bb36a472fdb3d19ae8b3aa84773ab9a8e7e13d0fde914488bba066d64d5309155ea5b7a3b33b4d9d6855fa9050b1" + ), + ), + ( + b"md6 FTW", + &hex!( + "7a4e8ecd1035ccdf00567595c15aa5a382fef2b6a4ec4bc609e0c655887b1c05e10eee223dd6c0ba5fa4a46159c70757" + ), + ), ]; for (msg, expected_hash) in TEST_VECTOR.iter() { @@ -311,35 +421,145 @@ fn test_md6_384() { hasher.update(msg); let output = hasher.finalize(); - assert!(output.to_vec() == *expected_hash); + assert!(output[..] == **expected_hash); } } #[test] fn test_md6_512() { const TEST_VECTOR: &[(&[u8], &[u8; 64])] = &[ - (b"a", &hex!("c0e4e18acb69cd1a7e5a20981fe6cc6f7b5b70e814d3a13b05ac292aba74c0d8c9d34c211414e7ab755a9559c27211cd749fc3eb09ae670e138881743b8d5051")), - (b"aa", &hex!("2afa253b05702770343e5c46e9d47231812a741d7bba479539a3c5484a412ea419f0d0ca96e124ba92e4ca506ca12684579323051d9d52fe5a669d079a226683")), - (b"aaa", &hex!("56b0131875d458f6d30ed1c594991df1efa8d6cae0c8abb36a9b811df23ac476c58e36d9adbe845e840d3de9175a8ceda11235144c3222587af108b902ce0fc5")), - (b"aaaa", &hex!("26a0bbf7df198fef1aa1945ebb91e7a9436e0892f4cdd5ee18e8dfe533f45da50c36debe4d98d0eae21925403e0d37603ea67f136b3076a1e053421052971480")), - (b"aaaaa", &hex!("86da00c33edf5d1daff144312af7e1a37f6441fc9905feb8caf4023fb6b34951464dc276a29925e3ad796cbdb7a09febd7d985c21702cc1b1c849e604de6580b")), - (b"aaaaaa", &hex!("7e67f0540f2afd27a17ff7a8be74039b79ff060a69b6f8fb98e3afc8e0a828fffb35aff2f3e20569933ef7c418fb3a8d7cfc7c17f3360a6ecca2a800c6657592")), - (b"aaaaaaa", &hex!("08d8eb85e5fe6b8e0f81841e9373de9ed18f14e911506a81cbd4e388535632edc425c88c1acbaefd61e98ea59fcda024acf662f79791acb3d15e935aa482dfef")), - (b"aaaaaaaa", &hex!("2db495253418869d64c3be65f304f0f73f87da659d1aa3ad457fa437e9370bf24f88b5c28c3c0dd4e67b351499ea380b60cb0010ffd28ac2449d5361925c8ce7")), - (b"aaaaaaaaa", &hex!("6d12438e615b0c1171678d262ba429a6ee58a87e24eb7b2fa0d5bec70bba1ea2e43acef122b1ca5de1a414153b0a12d795abed88cf3e88f26bf59a3222b04b99")), - (b"aaaaaaaaaa", &hex!("c4451dcd12d3847e1f2408ed3c9cc2f79a179ddf5a0a9246b68adcf918bbcea67f6c8721cc226599d587313895b8a8d53881061014b6444f3d3464b03602ecc2")), - (b"0", &hex!("057e1c40468ab5661defdbcd3bf671d398116373db2e7ab0adc6b0871d603eda39cf7255361ca456543157fbe09847b501586d701d53564fab651bd2f49dcda4")), - (b"1", &hex!("0f19bc75955c2e405620d5a69d3ce7078c11c3805523cbd5ff834704af67d40c65e9f011fdd3723fea365eb6fa744b981fc9cd53928edae43eaa942158a649d5")), - (b"2", &hex!("5f68d3c677d9cde81417f92889287e94141ff212080b1bb8d4485b01061dc0bccd8eed96fe728ea5ff3596201225337ebbf06ae6cf6162290843dfd226f7d647")), - (b"3", &hex!("f4243d7945b667900c78b894d83a343b2e8865ff62cef11e51a20472600df8a17a026d3ce09cb85925540a1515b34210bdd8eed76b8fe37f35cdc5350bb7bd19")), - (b"4", &hex!("8a1b250daf9fc0b2b5878504991b8950ed7c621e0b9163fbcb5f34b363f22fd6be96ed4a9c5aacbc9d6e30de4e97090a5758f89b6ae61b45658b2f79ec26fc51")), - (b"5", &hex!("ad6fa2a0f8e35189d5d070559124bd6cbb1170969356165dfda720b4ded83fd14ee8d81a2ef30d918ebcfc01d668950ba681bedcc3e1180b76c06a55e9a11497")), - (b"6", &hex!("2e2bb4d681f61821c6c470064b83b924cf691de74ed05bd8610cef5397d7e2c4aeda1930446f306dece4bbefe4fc87168d7a15ab80c890672b676a532739bc67")), - (b"7", &hex!("adb9009ae9abf8444d45a62b7adafcaef48c6ee7c48fa65d206d7a58ac3a5993e2eb81120d45338b9f9aa1b100365e2a98cd59fd7062783e5d23088b562176c3")), - (b"8", &hex!("516315942af5bbd028a533420a6496b77ca707a0b5dd0b473359d9bb74bdd00a59987a881c774a59dd2c62f1759f570713b881a622a70894ff319881e07cfd34")), - (b"9", &hex!("b98f4b7c5cecda77117180a38be5bda00bf72b7e4106c0d00137d269a0d48eb571004a8069f25fab4c2b4b16ab118af881eb904f9f32331dc726c1a404489604")), - (b"md6", &hex!("e94595891b2b3e2b2e3ae6943c17a34703c4230296f12f1689264e46518e0e1b0106996387ad6d8ec9b9c86e54301a71e6f4dab6e7369db4e503daae64f2e0a1")), - (b"md6 FTW", &hex!("75df3b6031e8241ef59d01628b093b05906f1a2d80c43908cb2883f7db6fbdd1cadffd7d643505c20b9529b6a5d19f8b6ff1623cabbc14a606caa7bcb239611a")), + ( + b"a", + &hex!( + "c0e4e18acb69cd1a7e5a20981fe6cc6f7b5b70e814d3a13b05ac292aba74c0d8c9d34c211414e7ab755a9559c27211cd749fc3eb09ae670e138881743b8d5051" + ), + ), + ( + b"aa", + &hex!( + "2afa253b05702770343e5c46e9d47231812a741d7bba479539a3c5484a412ea419f0d0ca96e124ba92e4ca506ca12684579323051d9d52fe5a669d079a226683" + ), + ), + ( + b"aaa", + &hex!( + "56b0131875d458f6d30ed1c594991df1efa8d6cae0c8abb36a9b811df23ac476c58e36d9adbe845e840d3de9175a8ceda11235144c3222587af108b902ce0fc5" + ), + ), + ( + b"aaaa", + &hex!( + "26a0bbf7df198fef1aa1945ebb91e7a9436e0892f4cdd5ee18e8dfe533f45da50c36debe4d98d0eae21925403e0d37603ea67f136b3076a1e053421052971480" + ), + ), + ( + b"aaaaa", + &hex!( + "86da00c33edf5d1daff144312af7e1a37f6441fc9905feb8caf4023fb6b34951464dc276a29925e3ad796cbdb7a09febd7d985c21702cc1b1c849e604de6580b" + ), + ), + ( + b"aaaaaa", + &hex!( + "7e67f0540f2afd27a17ff7a8be74039b79ff060a69b6f8fb98e3afc8e0a828fffb35aff2f3e20569933ef7c418fb3a8d7cfc7c17f3360a6ecca2a800c6657592" + ), + ), + ( + b"aaaaaaa", + &hex!( + "08d8eb85e5fe6b8e0f81841e9373de9ed18f14e911506a81cbd4e388535632edc425c88c1acbaefd61e98ea59fcda024acf662f79791acb3d15e935aa482dfef" + ), + ), + ( + b"aaaaaaaa", + &hex!( + "2db495253418869d64c3be65f304f0f73f87da659d1aa3ad457fa437e9370bf24f88b5c28c3c0dd4e67b351499ea380b60cb0010ffd28ac2449d5361925c8ce7" + ), + ), + ( + b"aaaaaaaaa", + &hex!( + "6d12438e615b0c1171678d262ba429a6ee58a87e24eb7b2fa0d5bec70bba1ea2e43acef122b1ca5de1a414153b0a12d795abed88cf3e88f26bf59a3222b04b99" + ), + ), + ( + b"aaaaaaaaaa", + &hex!( + "c4451dcd12d3847e1f2408ed3c9cc2f79a179ddf5a0a9246b68adcf918bbcea67f6c8721cc226599d587313895b8a8d53881061014b6444f3d3464b03602ecc2" + ), + ), + ( + b"0", + &hex!( + "057e1c40468ab5661defdbcd3bf671d398116373db2e7ab0adc6b0871d603eda39cf7255361ca456543157fbe09847b501586d701d53564fab651bd2f49dcda4" + ), + ), + ( + b"1", + &hex!( + "0f19bc75955c2e405620d5a69d3ce7078c11c3805523cbd5ff834704af67d40c65e9f011fdd3723fea365eb6fa744b981fc9cd53928edae43eaa942158a649d5" + ), + ), + ( + b"2", + &hex!( + "5f68d3c677d9cde81417f92889287e94141ff212080b1bb8d4485b01061dc0bccd8eed96fe728ea5ff3596201225337ebbf06ae6cf6162290843dfd226f7d647" + ), + ), + ( + b"3", + &hex!( + "f4243d7945b667900c78b894d83a343b2e8865ff62cef11e51a20472600df8a17a026d3ce09cb85925540a1515b34210bdd8eed76b8fe37f35cdc5350bb7bd19" + ), + ), + ( + b"4", + &hex!( + "8a1b250daf9fc0b2b5878504991b8950ed7c621e0b9163fbcb5f34b363f22fd6be96ed4a9c5aacbc9d6e30de4e97090a5758f89b6ae61b45658b2f79ec26fc51" + ), + ), + ( + b"5", + &hex!( + "ad6fa2a0f8e35189d5d070559124bd6cbb1170969356165dfda720b4ded83fd14ee8d81a2ef30d918ebcfc01d668950ba681bedcc3e1180b76c06a55e9a11497" + ), + ), + ( + b"6", + &hex!( + "2e2bb4d681f61821c6c470064b83b924cf691de74ed05bd8610cef5397d7e2c4aeda1930446f306dece4bbefe4fc87168d7a15ab80c890672b676a532739bc67" + ), + ), + ( + b"7", + &hex!( + "adb9009ae9abf8444d45a62b7adafcaef48c6ee7c48fa65d206d7a58ac3a5993e2eb81120d45338b9f9aa1b100365e2a98cd59fd7062783e5d23088b562176c3" + ), + ), + ( + b"8", + &hex!( + "516315942af5bbd028a533420a6496b77ca707a0b5dd0b473359d9bb74bdd00a59987a881c774a59dd2c62f1759f570713b881a622a70894ff319881e07cfd34" + ), + ), + ( + b"9", + &hex!( + "b98f4b7c5cecda77117180a38be5bda00bf72b7e4106c0d00137d269a0d48eb571004a8069f25fab4c2b4b16ab118af881eb904f9f32331dc726c1a404489604" + ), + ), + ( + b"md6", + &hex!( + "e94595891b2b3e2b2e3ae6943c17a34703c4230296f12f1689264e46518e0e1b0106996387ad6d8ec9b9c86e54301a71e6f4dab6e7369db4e503daae64f2e0a1" + ), + ), + ( + b"md6 FTW", + &hex!( + "75df3b6031e8241ef59d01628b093b05906f1a2d80c43908cb2883f7db6fbdd1cadffd7d643505c20b9529b6a5d19f8b6ff1623cabbc14a606caa7bcb239611a" + ), + ), ]; for (msg, expected_hash) in TEST_VECTOR.iter() { @@ -347,7 +567,7 @@ fn test_md6_512() { hasher.update(msg); let output = hasher.finalize(); - assert!(output.to_vec() == *expected_hash); + assert!(output[..] == **expected_hash); } } From fea993efaaba339cb0ac9e9f70b0c0efd7de33e3 Mon Sep 17 00:00:00 2001 From: truthixify Date: Mon, 24 Mar 2025 13:36:25 +0100 Subject: [PATCH 13/16] fixed workflow build --- Cargo.lock | 1 - md6/Cargo.toml | 1 - md6/README.md | 2 +- md6/benches/mod.rs | 18 +---------- md6/src/consts.rs | 4 +-- md6/src/lib.rs | 6 +--- md6/src/md6.rs | 5 ++- md6/tests/mod.rs | 80 +++------------------------------------------- 8 files changed, 13 insertions(+), 104 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 53dfd4415..a93b0f289 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -242,7 +242,6 @@ dependencies = [ name = "md6" version = "0.11.0-pre.5" dependencies = [ - "base16ct", "digest", "hex-literal 0.4.1", ] diff --git a/md6/Cargo.toml b/md6/Cargo.toml index eb9500620..7e36baf86 100644 --- a/md6/Cargo.toml +++ b/md6/Cargo.toml @@ -17,7 +17,6 @@ digest = "=0.11.0-pre.10" [dev-dependencies] digest = { version = "=0.11.0-pre.10", features = ["dev"] } hex-literal = "0.4" -base16ct = { version = "0.2", features = ["alloc"] } [features] default = ["oid", "std"] diff --git a/md6/README.md b/md6/README.md index 6955f0d4b..32fccd89f 100644 --- a/md6/README.md +++ b/md6/README.md @@ -19,7 +19,7 @@ hasher.update(b"hello world"); // read hash digest and consume hasher let hash = hasher.finalize(); -assert_eq!(hash.to_vec(), hex!( +assert_eq!(hash[..], hex!( "9ae602639631cc2c60adaa7a952aae8756141f31a7e6a9b76adc1de121db2230" )); ``` diff --git a/md6/benches/mod.rs b/md6/benches/mod.rs index 66dd6936e..1b17e5e15 100644 --- a/md6/benches/mod.rs +++ b/md6/benches/mod.rs @@ -2,25 +2,9 @@ extern crate test; use digest::bench_update; -use md6::{Md6_64, Md6_128, Md6_224, Md6_256, Md6_384, Md6_512}; +use md6::{Md6_224, Md6_256, Md6_384, Md6_512}; use test::Bencher; -bench_update!( - Md6_64::default(); - md6_64_10 10; - md6_64_100 100; - md6_64_1000 1000; - md6_64_10000 10000; -); - -bench_update!( - Md6_128::default(); - md6_128_10 10; - md6_128_100 100; - md6_128_1000 1000; - md6_128_10000 10000; -); - bench_update!( Md6_224::default(); md6_224_10 10; diff --git a/md6/src/consts.rs b/md6/src/consts.rs index f237b0b57..cb5f24044 100644 --- a/md6/src/consts.rs +++ b/md6/src/consts.rs @@ -17,8 +17,8 @@ pub const MD6_C: usize = 16; /// Size of compression input block in words pub const MD6_N: usize = 89; -/// These five values give lengths of the components of compression -/// input block; they should sum to MD6_N. +// These five values give lengths of the components of compression +// input block; they should sum to MD6_N. /// Q words in a compression block (>= 0) pub const MD6_Q: usize = 15; /// Key words per compression block (>= 0) diff --git a/md6/src/lib.rs b/md6/src/lib.rs index c6d956376..7df62e454 100644 --- a/md6/src/lib.rs +++ b/md6/src/lib.rs @@ -12,7 +12,7 @@ pub(crate) mod consts; mod md6; use digest::{ - consts::{U8, U16, U28, U32, U48, U64}, + consts::{U28, U32, U48, U64}, core_api::{CoreWrapper, CtVariableCoreWrapper, RtVariableCoreWrapper}, }; @@ -26,10 +26,6 @@ pub type Md6Var = RtVariableCoreWrapper; pub type Md6Core = CtVariableCoreWrapper; /// Md6 generic over output size. pub type Md6 = CoreWrapper>; -/// Md6 with 64-bit output -pub type Md6_64 = CoreWrapper>; -/// Md6 with 128-bit output -pub type Md6_128 = CoreWrapper>; /// Md6 with 224-bit output pub type Md6_224 = CoreWrapper>; /// Md6 with 256-bit output diff --git a/md6/src/md6.rs b/md6/src/md6.rs index 0fecfdea8..2e3f1bf8f 100644 --- a/md6/src/md6.rs +++ b/md6/src/md6.rs @@ -13,6 +13,9 @@ use digest::{ typenum::{U64, U128, Unsigned}, }; +#[cfg(feature = "zeroize")] +use digest::zeroize::{Zeroize, ZeroizeOnDrop}; + pub struct Md6VarCore { d: usize, hashbitlen: usize, @@ -659,7 +662,7 @@ const fn get_round_constants(w: usize) -> &'static [Md6Word] { 0x995a, 0xd117, 0x8bd2, 0x5c31, 0xc878, 0xc1dd, 0x04c4, 0xb633, 0x3b72, 0x066c, 0x7a15, 0x52ac, 0x0d6f, 0x3522, 0x631e, 0xffcb, ] - } else if W == 8 { + } else if w == 8 { &[ 0x73, 0x11, 0xc2, 0x81, 0x24, 0x25, 0xcf, 0xa0, 0x64, 0x32, 0x28, 0x64, 0x34, 0xaa, 0xc8, 0xe7, 0xb6, 0x04, 0x50, 0xe9, 0xef, 0x68, 0xb7, 0xc1, 0xe8, 0xfb, 0x23, 0x90, diff --git a/md6/tests/mod.rs b/md6/tests/mod.rs index 956e6d18c..2609d1e20 100644 --- a/md6/tests/mod.rs +++ b/md6/tests/mod.rs @@ -3,78 +3,6 @@ use hex_literal::hex; // Test vectors from https://github.com/Snack-X/md6/blob/master/test/result.csv -#[test] -fn test_md6_64() { - const TEST_VECTOR: &[(&[u8], &[u8; 8])] = &[ - (b"a", &hex!("32d13030a6815e95")), - (b"aa", &hex!("af7966908a5d9c13")), - (b"aaa", &hex!("3d8a4ff7a21eb0c6")), - (b"aaaa", &hex!("5aafda0f42635bbe")), - (b"aaaaa", &hex!("c370f6eceefb2c04")), - (b"aaaaaa", &hex!("453f31fe99e3365d")), - (b"aaaaaaa", &hex!("9d52c725c926756b")), - (b"aaaaaaaa", &hex!("836d56b5756bd4d3")), - (b"aaaaaaaaa", &hex!("2d27ed075595d38f")), - (b"aaaaaaaaaa", &hex!("e31280f1a2fc2528")), - (b"0", &hex!("17d073d4d38b5400")), - (b"1", &hex!("870f87ac0bd00aee")), - (b"2", &hex!("0d70630287b9031a")), - (b"3", &hex!("f60aa0d9fa94116d")), - (b"4", &hex!("1e6b0691ef4d4705")), - (b"5", &hex!("6305b39e912c144b")), - (b"6", &hex!("b47486289e236138")), - (b"7", &hex!("dd018e6e7363124a")), - (b"8", &hex!("eb456a3ae7348bf8")), - (b"9", &hex!("15bc9eac62570fe7")), - (b"md6", &hex!("b2f36109e52bd99f")), - (b"md6 FTW", &hex!("47cda109418592ca")), - ]; - - for (msg, expected_hash) in TEST_VECTOR.iter() { - let mut hasher = md6::Md6_64::new(); - hasher.update(msg); - let output = hasher.finalize(); - - assert!(output[..] == **expected_hash); - } -} - -#[test] -fn test_md6_128() { - const TEST_VECTOR: &[(&[u8], &[u8; 16])] = &[ - (b"a", &hex!("bb691c1bfa4b4345292eb35f364919ea")), - (b"aa", &hex!("19487e566f9ae2584d62628af2795f8c")), - (b"aaa", &hex!("319f1b026f76f9caf62320b4e2e79e29")), - (b"aaaa", &hex!("eb94dae524df4b84ba4a14115c3d0448")), - (b"aaaaa", &hex!("07d01330b8af7013284b9b339378aac1")), - (b"aaaaaa", &hex!("5638b2a1b7c5b66e963ea7744d1c9876")), - (b"aaaaaaa", &hex!("2ad627c7c0e089c28824a354841e9215")), - (b"aaaaaaaa", &hex!("1f7d2461fcfe705a7afadfabc9c95eb6")), - (b"aaaaaaaaa", &hex!("aa74a4962cdc8b3ae4bacf8995e9fa68")), - (b"aaaaaaaaaa", &hex!("623522019a5e40188a3b8956d44ea57d")), - (b"0", &hex!("7464cb2427a4b04bc0ca92653711e3a5")), - (b"1", &hex!("84a229d23cf5f380527c7dd9a887a384")), - (b"2", &hex!("44bf1a90a89c4bf3d6668e7886226127")), - (b"3", &hex!("cad8b9e548056c8ffd19cf469d1ac1ee")), - (b"4", &hex!("78746de94a7ff50fa11d22119a3d6545")), - (b"5", &hex!("ccc274bde4ebb8a38b6f19a8e0c022c0")), - (b"6", &hex!("b19533319a23aa00af9d143db6655041")), - (b"7", &hex!("3c049e4e57a5661b66c5235a07393bd1")), - (b"8", &hex!("ba73bb10cf0fee5758f3f8b37cd9fdd4")), - (b"9", &hex!("cc5f60133f81e505343174fa672d9f96")), - (b"md6", &hex!("98b4a2b7363159f810a60432df277b7c")), - (b"md6 FTW", &hex!("e866b430fa07b5bea28981db1f9b24a6")), - ]; - - for (msg, expected_hash) in TEST_VECTOR.iter() { - let mut hasher = md6::Md6_128::new(); - hasher.update(msg); - let output = hasher.finalize(); - - assert!(output[..] == **expected_hash); - } -} - #[test] fn test_md6_224() { const TEST_VECTOR: &[(&[u8], &[u8; 28])] = &[ @@ -173,7 +101,7 @@ fn test_md6_224() { hasher.update(msg); let output = hasher.finalize(); - assert!(output[..] == **expected_hash); + assert!(output[..] == expected_hash[..]); } } @@ -275,7 +203,7 @@ fn test_md6_256() { hasher.update(msg); let output = hasher.finalize(); - assert!(output[..] == **expected_hash); + assert!(output[..] == expected_hash[..]); } } @@ -421,7 +349,7 @@ fn test_md6_384() { hasher.update(msg); let output = hasher.finalize(); - assert!(output[..] == **expected_hash); + assert!(output[..] == expected_hash[..]); } } @@ -567,7 +495,7 @@ fn test_md6_512() { hasher.update(msg); let output = hasher.finalize(); - assert!(output[..] == **expected_hash); + assert!(output[..] == expected_hash[..]); } } From 90515941549a8afd57f489d147cfabce3d0ab56a Mon Sep 17 00:00:00 2001 From: truthixify Date: Mon, 24 Mar 2025 13:49:08 +0100 Subject: [PATCH 14/16] removed redundant constants --- md6/src/consts.rs | 42 ++++++++++++++---------------------------- md6/src/md6.rs | 2 +- 2 files changed, 15 insertions(+), 29 deletions(-) diff --git a/md6/src/consts.rs b/md6/src/consts.rs index cb5f24044..f7ebefc12 100644 --- a/md6/src/consts.rs +++ b/md6/src/consts.rs @@ -10,42 +10,28 @@ pub const MD6_MAX_R: usize = 255; /// Large so that MD6 is fully hierarchical pub const MD6_DEFAULT_L: usize = 64; -/// Number of bits in a word -pub const MD6_W: usize = 64; -/// Size of compression output in words -pub const MD6_C: usize = 16; -/// Size of compression input block in words -pub const MD6_N: usize = 89; - -// These five values give lengths of the components of compression -// input block; they should sum to MD6_N. -/// Q words in a compression block (>= 0) -pub const MD6_Q: usize = 15; -/// Key words per compression block (>= 0) -pub const MD6_K: usize = 8; -/// Words for unique node ID (0 or 64/w) -pub const MD6_U: usize = 64 / MD6_W; -/// Words for control word (0 or 64/w) -pub const MD6_V: usize = 64 / MD6_W; -/// Data words per compression block (> 0) -pub const MD6_B: usize = 64; - /// Number of bits in a word (64) -pub const W: usize = MD6_W; +pub const W: usize = 64; /// Size of compression output in words (16) -pub const C: usize = MD6_C; +pub const C: usize = 16; /// Size of compression input block in words (89) -pub const N: usize = MD6_N; +pub const N: usize = 89; /// Q words in a compression block (>= 0) (15) -pub const Q: usize = MD6_Q; +pub const Q: usize = 15; /// Key words per compression block (>= 0) (8) -pub const K: usize = MD6_K; +pub const K: usize = 8; /// Words for unique node ID (0 or 64/w) -pub const U: usize = MD6_U; +pub const U: usize = 1; /// Words for control word (0 or 64/w) -pub const V: usize = MD6_V; +pub const V: usize = 1; /// Data words per compression block (> 0) (64) -pub const B: usize = MD6_B; +pub const B: usize = 64; + +const _: () = { + if Q + K + U + V + B != N { + panic!("`Q + K + U + V` must be equal to `N`"); + } +}; /// Index for linear feedback pub const T0: usize = 17; diff --git a/md6/src/md6.rs b/md6/src/md6.rs index 2e3f1bf8f..de2cf2eb6 100644 --- a/md6/src/md6.rs +++ b/md6/src/md6.rs @@ -359,7 +359,7 @@ impl Md6VarCore { p: usize, z: usize, ) { - let mut n = [0; MD6_N]; + let mut n = [0; N]; let mut a = [0; 5000]; // check that the input values are sensible From 444200c40e980307aa970eb1e349eba9fac4ecd3 Mon Sep 17 00:00:00 2001 From: truthixify Date: Mon, 24 Mar 2025 23:43:06 +0100 Subject: [PATCH 15/16] added compilation target pointer width --- md6/src/compress.rs | 34 ---------------------------------- md6/src/consts.rs | 7 +++++-- 2 files changed, 5 insertions(+), 36 deletions(-) diff --git a/md6/src/compress.rs b/md6/src/compress.rs index 42bcea16f..0139f66b7 100644 --- a/md6/src/compress.rs +++ b/md6/src/compress.rs @@ -36,40 +36,6 @@ macro_rules! call_loop_bodies { loop_body!(6, 8, 13, $s, $i); loop_body!(7, 2, 14, $s, $i); loop_body!(5, 11, 15, $s, $i); - } else if $w == 16 { - loop_body!(5, 6, 0, $s, $i); - loop_body!(4, 7, 1, $s, $i); - loop_body!(3, 2, 2, $s, $i); - loop_body!(5, 4, 3, $s, $i); - loop_body!(7, 2, 4, $s, $i); - loop_body!(5, 6, 5, $s, $i); - loop_body!(5, 3, 6, $s, $i); - loop_body!(2, 7, 7, $s, $i); - loop_body!(4, 5, 8, $s, $i); - loop_body!(3, 7, 9, $s, $i); - loop_body!(4, 6, 10, $s, $i); - loop_body!(3, 5, 11, $s, $i); - loop_body!(4, 5, 12, $s, $i); - loop_body!(7, 6, 13, $s, $i); - loop_body!(7, 4, 14, $s, $i); - loop_body!(2, 3, 15, $s, $i); - } else if $w == 8 { - loop_body!(3, 2, 0, $s, $i); - loop_body!(3, 4, 1, $s, $i); - loop_body!(3, 2, 2, $s, $i); - loop_body!(4, 3, 3, $s, $i); - loop_body!(3, 2, 4, $s, $i); - loop_body!(3, 2, 5, $s, $i); - loop_body!(3, 2, 6, $s, $i); - loop_body!(3, 4, 7, $s, $i); - loop_body!(2, 3, 8, $s, $i); - loop_body!(2, 3, 9, $s, $i); - loop_body!(3, 2, 10, $s, $i); - loop_body!(2, 3, 11, $s, $i); - loop_body!(2, 3, 12, $s, $i); - loop_body!(3, 4, 13, $s, $i); - loop_body!(2, 3, 14, $s, $i); - loop_body!(3, 4, 15, $s, $i); } }; } diff --git a/md6/src/consts.rs b/md6/src/consts.rs index f7ebefc12..2c0439199 100644 --- a/md6/src/consts.rs +++ b/md6/src/consts.rs @@ -11,7 +11,10 @@ pub const MD6_MAX_R: usize = 255; pub const MD6_DEFAULT_L: usize = 64; /// Number of bits in a word (64) +#[cfg(target_pointer_width = "64")] pub const W: usize = 64; +#[cfg(target_pointer_width = "32")] +pub const W: usize = 32; /// Size of compression output in words (16) pub const C: usize = 16; /// Size of compression input block in words (89) @@ -21,9 +24,9 @@ pub const Q: usize = 15; /// Key words per compression block (>= 0) (8) pub const K: usize = 8; /// Words for unique node ID (0 or 64/w) -pub const U: usize = 1; +pub const U: usize = 64 / W; /// Words for control word (0 or 64/w) -pub const V: usize = 1; +pub const V: usize = 64 / W; /// Data words per compression block (> 0) (64) pub const B: usize = 64; From 3115b2602b232d0edb5516cce00671b5ef1d1733 Mon Sep 17 00:00:00 2001 From: truthixify Date: Tue, 25 Mar 2025 00:45:39 +0100 Subject: [PATCH 16/16] made some updates for W=32 --- md6/src/consts.rs | 6 ------ md6/src/md6.rs | 23 +---------------------- 2 files changed, 1 insertion(+), 28 deletions(-) diff --git a/md6/src/consts.rs b/md6/src/consts.rs index 2c0439199..1ecbf2b00 100644 --- a/md6/src/consts.rs +++ b/md6/src/consts.rs @@ -30,12 +30,6 @@ pub const V: usize = 64 / W; /// Data words per compression block (> 0) (64) pub const B: usize = 64; -const _: () = { - if Q + K + U + V + B != N { - panic!("`Q + K + U + V` must be equal to `N`"); - } -}; - /// Index for linear feedback pub const T0: usize = 17; /// Index for first input to first and diff --git a/md6/src/md6.rs b/md6/src/md6.rs index de2cf2eb6..d1e6702ab 100644 --- a/md6/src/md6.rs +++ b/md6/src/md6.rs @@ -397,7 +397,7 @@ impl Md6VarCore { self.bits[ell] = 0; // clear bits used count this level self.i_for_level[ell] += 1; // increment i for this level - self.b[ell] = [0; W]; // clear B for this level + self.b[ell] = [0; B]; // clear b for this level } #[inline] @@ -653,27 +653,6 @@ const fn get_round_constants(w: usize) -> &'static [Md6Word] { 0x3fb50c2c, 0x995ad117, 0x8bd25c31, 0xc878c1dd, 0x04c4b633, 0x3b72066c, 0x7a1552ac, 0x0d6f3522, 0x631effcb, ] - } else if w == 16 { - &[ - 0x7311, 0xc281, 0x2425, 0xcfa0, 0x6432, 0x2864, 0x34aa, 0xc8e7, 0xb604, 0x50e9, 0xef68, - 0xb7c1, 0xe8fb, 0x2390, 0x8d9f, 0x06f1, 0xdd2e, 0x76cb, 0xa691, 0xe5bf, 0x0cd0, 0xd63b, - 0x2c30, 0xbc41, 0x1f8c, 0xcf68, 0x2305, 0x8f8a, 0x54e5, 0xed5b, 0x88e3, 0x775d, 0x4ad1, - 0x2aae, 0x0a6d, 0x6031, 0x3e7f, 0x16bb, 0x8822, 0x2e0d, 0x8af8, 0x671d, 0x3fb5, 0x0c2c, - 0x995a, 0xd117, 0x8bd2, 0x5c31, 0xc878, 0xc1dd, 0x04c4, 0xb633, 0x3b72, 0x066c, 0x7a15, - 0x52ac, 0x0d6f, 0x3522, 0x631e, 0xffcb, - ] - } else if w == 8 { - &[ - 0x73, 0x11, 0xc2, 0x81, 0x24, 0x25, 0xcf, 0xa0, 0x64, 0x32, 0x28, 0x64, 0x34, 0xaa, - 0xc8, 0xe7, 0xb6, 0x04, 0x50, 0xe9, 0xef, 0x68, 0xb7, 0xc1, 0xe8, 0xfb, 0x23, 0x90, - 0x8d, 0x9f, 0x06, 0xf1, 0xdd, 0x2e, 0x76, 0xcb, 0xa6, 0x91, 0xe5, 0xbf, 0x0c, 0xd0, - 0xd6, 0x3b, 0x2c, 0x30, 0xbc, 0x41, 0x1f, 0x8c, 0xcf, 0x68, 0x23, 0x05, 0x8f, 0x8a, - 0x54, 0xe5, 0xed, 0x5b, 0x88, 0xe3, 0x77, 0x5d, 0x4a, 0xd1, 0x2a, 0xae, 0x0a, 0x6d, - 0x60, 0x31, 0x3e, 0x7f, 0x16, 0xbb, 0x88, 0x22, 0x2e, 0x0d, 0x8a, 0xf8, 0x67, 0x1d, - 0x3f, 0xb5, 0x0c, 0x2c, 0x99, 0x5a, 0xd1, 0x17, 0x8b, 0xd2, 0x5c, 0x31, 0xc8, 0x78, - 0xc1, 0xdd, 0x04, 0xc4, 0xb6, 0x33, 0x3b, 0x72, 0x06, 0x6c, 0x7a, 0x15, 0x52, 0xac, - 0x0d, 0x6f, 0x35, 0x22, 0x63, 0x1e, 0xff, 0xcb, - ] } else { panic!("bad w") }