-
Notifications
You must be signed in to change notification settings - Fork 258
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1d959af
commit 6adbaba
Showing
11 changed files
with
781 additions
and
591 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ members = [ | |
"md2", | ||
"md4", | ||
"md5", | ||
"md6", | ||
"ripemd", | ||
"sha1", | ||
"sha1-checked", | ||
|
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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"] |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<Md6VarCore>; | ||
/// Core hash function for Md6 generic over output size | ||
pub type Md6Core<OutSize> = CtVariableCoreWrapper<Md6VarCore, OutSize>; | ||
/// Md6 with 64-bit output | ||
pub type Md6_64 = CoreWrapper<Md6Core<U8>>; | ||
/// Md6 with 128-bit output | ||
pub type Md6_128 = CoreWrapper<Md6Core<U16>>; | ||
/// Md6 with 224-bit output | ||
pub type Md6_224 = CoreWrapper<Md6Core<U28>>; | ||
/// Md6 with 256-bit output | ||
pub type Md6_256 = CoreWrapper<Md6Core<U32>>; | ||
/// Md6 with 384-bit output | ||
pub type Md6_384 = CoreWrapper<Md6Core<U48>>; | ||
/// Md6 with 512-bit output | ||
pub type Md6_512 = CoreWrapper<Md6Core<U64>>; |
Oops, something went wrong.