Skip to content

Commit

Permalink
macros for blake
Browse files Browse the repository at this point in the history
  • Loading branch information
SymmetricChaos committed Sep 17, 2024
1 parent 0e7435c commit 92b1f9e
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 133 deletions.
25 changes: 10 additions & 15 deletions hashers/src/ascon/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ pub mod mac;
const DEBUG: bool = false;

fn padded_bytes_64(bytes: &[u8]) -> u64 {
if bytes.len() > 8 {
panic!("input block was too large")
} else if bytes.len() == 8 {
assert!(bytes.len() <= 8);
if bytes.len() == 8 {
u64::from_be_bytes(bytes.try_into().unwrap())
} else {
let mut word_bytes: [u8; 8] = [0; 8];
Expand All @@ -19,9 +18,8 @@ fn padded_bytes_64(bytes: &[u8]) -> u64 {
}

fn unpadded_bytes_64(bytes: &[u8]) -> u64 {
if bytes.len() > 8 {
panic!("input block was too large")
} else if bytes.len() == 8 {
assert!(bytes.len() <= 8);
if bytes.len() == 8 {
u64::from_be_bytes(bytes.try_into().unwrap())
} else {
let mut word_bytes: [u8; 8] = [0; 8];
Expand All @@ -33,9 +31,8 @@ fn unpadded_bytes_64(bytes: &[u8]) -> u64 {
}

fn unpadded_bytes_128(bytes: &[u8]) -> [u64; 2] {
if bytes.len() > 16 {
panic!("input block was too large")
} else if bytes.len() == 16 {
assert!(bytes.len() <= 16);
if bytes.len() == 16 {
[
u64::from_be_bytes(bytes[0..8].try_into().unwrap()),
u64::from_be_bytes(bytes[8..16].try_into().unwrap()),
Expand Down Expand Up @@ -67,9 +64,8 @@ fn unpadded_bytes_128(bytes: &[u8]) -> [u64; 2] {
// }

fn padded_bytes_256(bytes: &[u8]) -> [u64; 4] {
if bytes.len() > 32 {
panic!("input block was too large")
} else if bytes.len() == 32 {
assert!(bytes.len() <= 32);
if bytes.len() == 32 {
[
u64::from_be_bytes(bytes[0..8].try_into().unwrap()),
u64::from_be_bytes(bytes[8..16].try_into().unwrap()),
Expand Down Expand Up @@ -103,9 +99,8 @@ fn padded_bytes_256(bytes: &[u8]) -> [u64; 4] {
}

fn padded_bytes_320(bytes: &[u8]) -> [u64; 5] {
if bytes.len() > 40 {
panic!("input block was too large")
} else if bytes.len() == 40 {
assert!(bytes.len() <= 40);
if bytes.len() == 40 {
[
u64::from_be_bytes(bytes[0..8].try_into().unwrap()),
u64::from_be_bytes(bytes[8..16].try_into().unwrap()),
Expand Down
21 changes: 1 addition & 20 deletions hashers/src/blake/blake256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ use utils::byte_formatting::{fill_u32s_be, ByteFormat};

use crate::{errors::HasherError, traits::ClassicHasher};

use super::SIGMA;

// https://eprint.iacr.org/2012/351.pdf

// Constants for compression function, beginning digits of pi
Expand Down Expand Up @@ -118,25 +116,8 @@ impl Blake256 {
work[14] = C[6] ^ (counter >> 32) as u32; // Upper bits
work[15] = C[7] ^ (counter >> 32) as u32;

// At this point the working vector is correct, I have triple checked
// println!("work: {:08x?}\n", work);
for i in 0..14 {
let s = SIGMA[i % 10];

let a = [0, 1, 2, 3, 0, 1, 2, 3];
let b = [4, 5, 6, 7, 5, 6, 7, 4];
let c = [8, 9, 10, 11, 10, 11, 8, 9];
let d = [12, 13, 14, 15, 15, 12, 13, 14];

// Apply the mixing function eight times, xoring the constants with the chunks of message
for j in 0..8 {
let x = chunk[s[2 * j]] ^ C[s[2 * j + 1]];
let y = chunk[s[2 * j + 1]] ^ C[s[2 * j]];
Self::mix(&mut work, a[j], b[j], c[j], d[j], x, y);
}
crate::blake_compress!(&mut work, chunk, [16, 12, 8, 7], C, 14);

// println!("work {}:\n{:08x?}\n", i + 1, work);
}
for i in 0..8 {
state[i] ^= salt[i % 4] ^ work[i] ^ work[i + 8];
}
Expand Down
33 changes: 2 additions & 31 deletions hashers/src/blake/blake2b.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ use utils::byte_formatting::ByteFormat;

use crate::traits::ClassicHasher;

use super::SIGMA;

// https://eprint.iacr.org/2012/351.pdf

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -62,20 +60,6 @@ impl Blake2b {
self
}

pub fn mix(v: &mut [u64; 16], a: usize, b: usize, c: usize, d: usize, x: u64, y: u64) {
v[a] = v[a].wrapping_add(v[b]).wrapping_add(x);
v[d] = (v[d] ^ v[a]).rotate_right(32);

v[c] = v[c].wrapping_add(v[d]);
v[b] = (v[b] ^ v[c]).rotate_right(24);

v[a] = v[a].wrapping_add(v[b]).wrapping_add(y);
v[d] = (v[d] ^ v[a]).rotate_right(16);

v[c] = v[c].wrapping_add(v[d]);
v[b] = (v[b] ^ v[c]).rotate_right(63);
}

// https://datatracker.ietf.org/doc/html/rfc7693.html#appendix-A
pub fn compress(state: &mut [u64; 8], chunk: &[u64; 16], bytes_taken: u128, last_chunk: bool) {
// println!("Original Chunk:\n{chunk:016x?}\n");
Expand All @@ -94,21 +78,8 @@ impl Blake2b {
if last_chunk {
work[14] ^= u64::MAX;
}
// println!("Working Vector Before Compression:\n{work:016x?}\n");
for i in 0..12 {
let s = SIGMA[i % 10];

Self::mix(&mut work, 0, 4, 8, 12, chunk[s[0]], chunk[s[1]]);
Self::mix(&mut work, 1, 5, 9, 13, chunk[s[2]], chunk[s[3]]);
Self::mix(&mut work, 2, 6, 10, 14, chunk[s[4]], chunk[s[5]]);
Self::mix(&mut work, 3, 7, 11, 15, chunk[s[6]], chunk[s[7]]);

Self::mix(&mut work, 0, 5, 10, 15, chunk[s[8]], chunk[s[9]]);
Self::mix(&mut work, 1, 6, 11, 12, chunk[s[10]], chunk[s[11]]);
Self::mix(&mut work, 2, 7, 8, 13, chunk[s[12]], chunk[s[13]]);
Self::mix(&mut work, 3, 4, 9, 14, chunk[s[14]], chunk[s[15]]);
// println!("Working Vector at [{i}]:\n{work:016x?}\n");
}

crate::blake_compress!(&mut work, chunk, [32, 24, 16, 63], 12);

for i in 0..8 {
state[i] ^= work[i];
Expand Down
62 changes: 15 additions & 47 deletions hashers/src/blake/blake2s.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ use utils::byte_formatting::ByteFormat;

use crate::traits::ClassicHasher;

use super::SIGMA;

// https://eprint.iacr.org/2012/351.pdf

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -56,20 +54,6 @@ impl Blake2s {
self
}

pub fn mix(v: &mut [u32; 16], a: usize, b: usize, c: usize, d: usize, x: u32, y: u32) {
v[a] = v[a].wrapping_add(v[b]).wrapping_add(x);
v[d] = (v[d] ^ v[a]).rotate_right(16);

v[c] = v[c].wrapping_add(v[d]);
v[b] = (v[b] ^ v[c]).rotate_right(12);

v[a] = v[a].wrapping_add(v[b]).wrapping_add(y);
v[d] = (v[d] ^ v[a]).rotate_right(8);

v[c] = v[c].wrapping_add(v[d]);
v[b] = (v[b] ^ v[c]).rotate_right(7);
}

// https://datatracker.ietf.org/doc/html/rfc7693.html#appendix-A
pub fn compress(state: &mut [u32; 8], chunk: &[u32; 16], bytes_taken: u64, last_chunk: bool) {
// println!("Original Chunk:\n{chunk:016x?}\n");
Expand All @@ -88,21 +72,8 @@ impl Blake2s {
if last_chunk {
work[14] ^= u32::MAX;
}
// println!("Working Vector Before Compression:\n{work:016x?}\n");
for i in 0..10 {
let s = SIGMA[i];

Self::mix(&mut work, 0, 4, 8, 12, chunk[s[0]], chunk[s[1]]);
Self::mix(&mut work, 1, 5, 9, 13, chunk[s[2]], chunk[s[3]]);
Self::mix(&mut work, 2, 6, 10, 14, chunk[s[4]], chunk[s[5]]);
Self::mix(&mut work, 3, 7, 11, 15, chunk[s[6]], chunk[s[7]]);

Self::mix(&mut work, 0, 5, 10, 15, chunk[s[8]], chunk[s[9]]);
Self::mix(&mut work, 1, 6, 11, 12, chunk[s[10]], chunk[s[11]]);
Self::mix(&mut work, 2, 7, 8, 13, chunk[s[12]], chunk[s[13]]);
Self::mix(&mut work, 3, 4, 9, 14, chunk[s[14]], chunk[s[15]]);
// println!("Working Vector at [{i}]:\n{work:016x?}\n");
}

crate::blake_compress!(&mut work, chunk, [16, 12, 8, 7], 10);

for i in 0..8 {
state[i] ^= work[i];
Expand Down Expand Up @@ -178,19 +149,16 @@ impl ClassicHasher for Blake2s {
crate::hash_bytes_from_string! {}
}

#[cfg(test)]
mod blake2s_tests {
use super::*;

#[test]
fn test_empty() {
let mut hasher = Blake2s::default();
hasher.input_format = ByteFormat::Utf8;
hasher.output_format = ByteFormat::Hex;
hasher.hash_len = 32;
assert_eq!(
"69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9",
hasher.hash_bytes_from_string("").unwrap()
);
}
}
crate::basic_hash_tests!(
Blake2s::default().hash_len(32), empty_hash_len_32, "",
"69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9";
Blake2s::default().hash_len(32).input(ByteFormat::Hex), hash_8_len_32, "0001020304050607",
"c7e887b546623635e93e0495598f1726821996c2377705b93a1f636f872bfa2d";
Blake2s::default()
.input(ByteFormat::Hex)
.hash_len(32)
.key(ByteFormat::Hex.text_to_bytes("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap()),
keyed_hash_len_32,
"000102030405060708090a0b0c0d0e0f",
"19ba234f0a4f38637d1839f9d9f76ad91c8522307143c97d5f93f69274cec9a7";
);
21 changes: 1 addition & 20 deletions hashers/src/blake/blake512.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ use utils::byte_formatting::{fill_u64s_be, ByteFormat};

use crate::{errors::HasherError, traits::ClassicHasher};

use super::SIGMA;

// https://eprint.iacr.org/2012/351.pdf

// Constants for compression function, beginning digits of pi
Expand Down Expand Up @@ -144,25 +142,8 @@ impl Blake512 {
work[14] = C[6] ^ (counter >> 64) as u64; // Upper bits
work[15] = C[7] ^ (counter >> 64) as u64;

// At this point the working vector is correct, I have triple checked
// println!("work: {:016x?}\n", work);
for i in 0..16 {
let s = SIGMA[i % 10];

let a = [0, 1, 2, 3, 0, 1, 2, 3];
let b = [4, 5, 6, 7, 5, 6, 7, 4];
let c = [8, 9, 10, 11, 10, 11, 8, 9];
let d = [12, 13, 14, 15, 15, 12, 13, 14];

// Apply the mixing function eight times, xoring the constants with the chunks of message
for j in 0..8 {
let x = chunk[s[2 * j]] ^ C[s[2 * j + 1]];
let y = chunk[s[2 * j + 1]] ^ C[s[2 * j]];
Self::mix(&mut work, a[j], b[j], c[j], d[j], x, y);
}
crate::blake_compress!(&mut work, chunk, [32, 25, 16, 11], C, 16);

// println!("work {}:\n{:016x?}\n", i + 1, work);
}
for i in 0..8 {
state[i] ^= salt[i % 4] ^ work[i] ^ work[i + 8];
}
Expand Down
82 changes: 82 additions & 0 deletions hashers/src/blake/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,85 @@ const SIGMA: [[usize; 16]; 10] = [
[6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5],
[10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0],
];

// These are the constants for how BLAKE and BLAKE2 mix along columns then rows
const A: [usize; 8] = [0, 1, 2, 3, 0, 1, 2, 3];
const B: [usize; 8] = [4, 5, 6, 7, 5, 6, 7, 4];
const C: [usize; 8] = [8, 9, 10, 11, 10, 11, 8, 9];
const D: [usize; 8] = [12, 13, 14, 15, 15, 12, 13, 14];

// This is the mixing function (quarter round) used by BLAKE and BLAKE2 written in a type agnostic form
// information in $v (the working vector) is spread across four of its indexes ($a, $b, $c, $d) which
// are chosen to represent columns and rows of $v when it is viewed as a 4x4 array
#[macro_export]
macro_rules! blake_mix {
($v: expr, $a: expr, $b: expr, $c: expr, $d: expr, $x: expr, $y: expr, $r: expr) => {
$v[$a] = $v[$a].wrapping_add($v[$b]).wrapping_add($x);
$v[$d] = ($v[$d] ^ $v[$a]).rotate_right($r[0]);

$v[$c] = $v[$c].wrapping_add($v[$d]);
$v[$b] = ($v[$b] ^ $v[$c]).rotate_right($r[1]);

$v[$a] = $v[$a].wrapping_add($v[$b]).wrapping_add($y);
$v[$d] = ($v[$d] ^ $v[$a]).rotate_right($r[2]);

$v[$c] = $v[$c].wrapping_add($v[$d]);
$v[$b] = ($v[$b] ^ $v[$c]).rotate_right($r[3]);
};
}

// The double round in type agnosic form.
// Applies the quarter round eight times. The second variant of the
// macro XORs in values from a constant as in the original BLAKE
#[macro_export]
macro_rules! blake_double_round {
($v: expr, $chunk: ident, $r: expr, $s: ident) => {
for j in 0..8 {
let x = $chunk[$s[2 * j]];
let y = $chunk[$s[2 * j + 1]];
crate::blake_mix!(
$v,
super::A[j],
super::B[j],
super::C[j],
super::D[j],
x,
y,
$r
);
}
};
($v: expr, $chunk: ident, $r: expr, $s: ident, $c: ident) => {
for j in 0..8 {
let x = $chunk[$s[2 * j]] ^ $c[$s[2 * j + 1]];
let y = $chunk[$s[2 * j + 1]] ^ $c[$s[2 * j]];
crate::blake_mix!(
$v,
super::A[j],
super::B[j],
super::C[j],
super::D[j],
x,
y,
$r
);
}
};
}

// A sequence of compression rounds
#[macro_export]
macro_rules! blake_compress {
($v: expr, $chunk: ident, $r: expr, $n: literal) => {
for i in 0..$n {
let s = super::SIGMA[i % 10];
crate::blake_double_round!($v, $chunk, $r, s);
}
};
($v: expr, $chunk: ident, $r: expr, $c: ident, $n: literal) => {
for i in 0..$n {
let s = super::SIGMA[i % 10];
crate::blake_double_round!($v, $chunk, $r, s, $c);
}
};
}

0 comments on commit 92b1f9e

Please sign in to comment.