Massive refactor of keccakf
This commit is contained in:
parent
4eac6417c3
commit
316b65514c
194
src/keccak.rs
194
src/keccak.rs
@ -22,9 +22,89 @@ const KECCAKF_PILN: [usize; 24] =
|
||||
15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
|
||||
];
|
||||
|
||||
fn keccakf(st: &mut [Chunk], rounds: usize)
|
||||
fn keccakf(st: &mut [Byte], rounds: usize)
|
||||
{
|
||||
use std::borrow::Borrow;
|
||||
|
||||
struct State<B: Borrow<Bit>> {
|
||||
bits: Vec<B>
|
||||
}
|
||||
|
||||
impl<'a> State<&'a mut Bit> {
|
||||
fn new(bytes: &'a mut [Byte]) -> State<&'a mut Bit> {
|
||||
assert_eq!(bytes.len(), 8); // 64 bit lanes
|
||||
|
||||
State {
|
||||
bits: bytes.iter_mut()
|
||||
.rev() // Endianness
|
||||
.flat_map(|b| b.bits.iter_mut())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
fn set(&mut self, to: State<Bit>) {
|
||||
for (a, b) in self.bits.iter_mut()
|
||||
.zip(to.bits.into_iter()) {
|
||||
**a = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for State<Bit> {
|
||||
fn from(num: u64) -> State<Bit> {
|
||||
fn bit_at(num: u64, i: usize) -> u8 {
|
||||
((num << i) >> 63) as u8
|
||||
}
|
||||
|
||||
State {
|
||||
bits: (0..64).map(|i| Bit::constant(bit_at(num, i))).collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Borrow<Bit>> State<A> {
|
||||
fn duplicate(&self) -> State<Bit> {
|
||||
State {
|
||||
bits: self.bits.iter().map(|a| a.borrow())
|
||||
.map(|a| (*a).clone())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
fn xor<B: Borrow<Bit>>(&self, other: &State<B>) -> State<Bit> {
|
||||
State {
|
||||
bits: self.bits.iter().map(|a| a.borrow())
|
||||
.zip(other.bits.iter().map(|a| a.borrow()))
|
||||
.map(|(a, b)| a.xor(b))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
fn notand<B: Borrow<Bit>>(&self, other: &State<B>) -> State<Bit> {
|
||||
State {
|
||||
bits: self.bits.iter().map(|a| a.borrow())
|
||||
.zip(other.bits.iter().map(|a| a.borrow()))
|
||||
.map(|(a, b)| a.notand(b))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
fn rotl(&self, by: usize) -> State<Bit> {
|
||||
let by = by % 64;
|
||||
|
||||
State {
|
||||
bits: self.bits[by..].iter().map(|a| a.borrow())
|
||||
.chain(self.bits[0..by].iter().map(|a| a.borrow()))
|
||||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut st: Vec<_> = st.chunks_mut(8).map(|c| State::new(c)).collect();
|
||||
|
||||
assert_eq!(st.len(), 25);
|
||||
|
||||
for round in 0..rounds {
|
||||
/*
|
||||
// Theta
|
||||
@ -32,7 +112,7 @@ fn keccakf(st: &mut [Chunk], rounds: usize)
|
||||
bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20];
|
||||
*/
|
||||
|
||||
let mut bc: Vec<Chunk> = (0..5).map(|i| st[i]
|
||||
let mut bc: Vec<State<Bit>> = (0..5).map(|i| st[i]
|
||||
.xor(&st[i+5])
|
||||
.xor(&st[i+10])
|
||||
.xor(&st[i+15])
|
||||
@ -51,7 +131,8 @@ fn keccakf(st: &mut [Chunk], rounds: usize)
|
||||
let tmp = bc[(i + 4) % 5].xor(&bc[(i + 1) % 5].rotl(1));
|
||||
|
||||
for j in (0..25).filter(|a| a % 5 == 0) {
|
||||
st[j + i] = tmp.xor(&st[j + i]);
|
||||
let new = tmp.xor(&st[j + i]);
|
||||
st[j + i].set(new);
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,14 +147,14 @@ fn keccakf(st: &mut [Chunk], rounds: usize)
|
||||
t = bc[0];
|
||||
}
|
||||
*/
|
||||
let mut tmp = st[1].clone();
|
||||
let mut tmp = st[1].duplicate();
|
||||
|
||||
for i in 0..24 {
|
||||
let j = KECCAKF_PILN[i];
|
||||
|
||||
bc[0] = st[j].clone();
|
||||
st[j] = tmp.rotl(KECCAKF_ROTC[i]);
|
||||
tmp = bc[0].clone();
|
||||
bc[0] = st[j].duplicate();
|
||||
st[j].set(tmp.rotl(KECCAKF_ROTC[i]));
|
||||
tmp = bc[0].duplicate();
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,11 +171,12 @@ fn keccakf(st: &mut [Chunk], rounds: usize)
|
||||
|
||||
for j in (0..25).filter(|a| a % 5 == 0) {
|
||||
for i in 0..5 {
|
||||
bc[i] = st[j + i].clone();
|
||||
bc[i] = st[j + i].duplicate();
|
||||
}
|
||||
|
||||
for i in 0..5 {
|
||||
st[j + i] = st[j + i].xor(&bc[(i + 1) % 5].notand(&bc[(i + 2) % 5]));
|
||||
let n = st[j + i].xor(&bc[(i + 1) % 5].notand(&bc[(i + 2) % 5]));
|
||||
st[j + i].set(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -104,16 +186,17 @@ fn keccakf(st: &mut [Chunk], rounds: usize)
|
||||
st[0] ^= keccakf_rndc[round];
|
||||
*/
|
||||
|
||||
st[0] = st[0].xor(&KECCAKF_RNDC[round].into());
|
||||
let n = st[0].xor(&KECCAKF_RNDC[round].into());
|
||||
st[0].set(n);
|
||||
}
|
||||
}
|
||||
|
||||
fn sha3_256(message: &[Byte]) -> Vec<Byte> {
|
||||
// As defined by FIPS202
|
||||
keccak(1088, 512, message, 0x06, 32)
|
||||
keccak(1088, 512, message, 0x06, 32, 24)
|
||||
}
|
||||
|
||||
fn keccak(rate: usize, capacity: usize, mut input: &[Byte], delimited_suffix: u8, mut mdlen: usize)
|
||||
fn keccak(rate: usize, capacity: usize, mut input: &[Byte], delimited_suffix: u8, mut mdlen: usize, num_rounds: usize)
|
||||
-> Vec<Byte>
|
||||
{
|
||||
use std::cmp::min;
|
||||
@ -139,7 +222,7 @@ fn keccak(rate: usize, capacity: usize, mut input: &[Byte], delimited_suffix: u8
|
||||
inputByteLen -= blockSize;
|
||||
|
||||
if blockSize == rateInBytes {
|
||||
temporary_shim(&mut st);
|
||||
keccakf(&mut st, num_rounds);
|
||||
blockSize = 0;
|
||||
}
|
||||
}
|
||||
@ -147,12 +230,12 @@ fn keccak(rate: usize, capacity: usize, mut input: &[Byte], delimited_suffix: u8
|
||||
st[blockSize] = st[blockSize].xor(&Bit::byte(delimited_suffix));
|
||||
|
||||
if ((delimited_suffix & 0x80) != 0) && (blockSize == (rateInBytes-1)) {
|
||||
temporary_shim(&mut st);
|
||||
keccakf(&mut st, num_rounds);
|
||||
}
|
||||
|
||||
st[rateInBytes-1] = st[rateInBytes-1].xor(&Bit::byte(0x80));
|
||||
|
||||
temporary_shim(&mut st);
|
||||
keccakf(&mut st, num_rounds);
|
||||
|
||||
let mut output = Vec::with_capacity(mdlen);
|
||||
|
||||
@ -162,39 +245,13 @@ fn keccak(rate: usize, capacity: usize, mut input: &[Byte], delimited_suffix: u8
|
||||
mdlen -= blockSize;
|
||||
|
||||
if mdlen > 0 {
|
||||
temporary_shim(&mut st);
|
||||
keccakf(&mut st, num_rounds);
|
||||
}
|
||||
}
|
||||
|
||||
output
|
||||
}
|
||||
|
||||
fn temporary_shim(state: &mut [Byte]) {
|
||||
assert_eq!(state.len(), 200);
|
||||
|
||||
println!("RUNNING TEMPORARY SHIM!");
|
||||
|
||||
let mut chunks = Vec::with_capacity(25);
|
||||
for i in 0..25 {
|
||||
chunks.push(Chunk::from(0x0000000000000000));
|
||||
}
|
||||
|
||||
for (chunk_bit, input_bit) in chunks.iter_mut().flat_map(|c| c.bits.iter_mut())
|
||||
//.zip(state.iter().flat_map(|c| c.bits.iter()))
|
||||
.zip(state.chunks(8).flat_map(|e| e.iter().rev()).flat_map(|c| c.bits.iter()))
|
||||
{
|
||||
*chunk_bit = input_bit.clone();
|
||||
}
|
||||
|
||||
keccakf(&mut chunks, 24);
|
||||
|
||||
for (chunk_bit, input_bit) in chunks.iter().flat_map(|c| c.bits.iter())
|
||||
.zip(state.chunks_mut(8).flat_map(|e| e.iter_mut().rev()).flat_map(|c| c.bits.iter_mut()))
|
||||
{
|
||||
*input_bit = chunk_bit.clone();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Chunk {
|
||||
bits: Vec<Bit>
|
||||
@ -287,7 +344,8 @@ struct Byte {
|
||||
}
|
||||
|
||||
impl Byte {
|
||||
fn grab(&self) -> u8 {
|
||||
// TODO: change this name
|
||||
fn unwrap_constant(&self) -> u8 {
|
||||
let mut cur = 7;
|
||||
let mut acc = 0;
|
||||
|
||||
@ -372,57 +430,21 @@ fn test_sha3_256() {
|
||||
];
|
||||
|
||||
for (i, &(ref message, ref expected)) in test_vector.iter().enumerate() {
|
||||
let result: Vec<u8> = sha3_256(message).into_iter().map(|a| a.grab()).collect();
|
||||
let result: Vec<u8> = sha3_256(message).into_iter().map(|a| a.unwrap_constant()).collect();
|
||||
|
||||
if &*result != expected {
|
||||
print!("Expected: ");
|
||||
print!("Got: ");
|
||||
for i in result.iter() {
|
||||
print!("0x{:02x},", i);
|
||||
}
|
||||
print!("\nExpected: ");
|
||||
for i in expected.iter() {
|
||||
print!("0x{:02x},", i);
|
||||
}
|
||||
println!("");
|
||||
panic!("Hash {} failed!", i+1);
|
||||
} else {
|
||||
println!("--- HASH {} SUCCESS ---", i+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keccakf() {
|
||||
let base = Chunk::from(0xABCDEF0123456789);
|
||||
|
||||
let mut a: Vec<Chunk> = (0..25).map(|i| base.rotl(i*4)).collect();
|
||||
|
||||
keccakf(&mut a, 24);
|
||||
|
||||
const TEST_VECTOR: [u64; 25] = [
|
||||
0x4c8948fcb6616044,
|
||||
0x75642a21f8bd1299,
|
||||
0xb2e949825ace668e,
|
||||
0x9b73a04c53826c35,
|
||||
0x914989b8d38ea4d1,
|
||||
0xdc73480ade4e2664,
|
||||
0x931394137c6fbd69,
|
||||
0x234fa173896019f5,
|
||||
0x906da29a7796b157,
|
||||
0x7666ebe222445610,
|
||||
0x41d77796738c884e,
|
||||
0x8861db16234437fa,
|
||||
0xf07cb925b71f27f2,
|
||||
0xfec25b4810a2202c,
|
||||
0xa8ba9bbfa9076b54,
|
||||
0x18d9b9e748d655b9,
|
||||
0xa2172c0059955be6,
|
||||
0xea602c863b7947b8,
|
||||
0xc77f9f23851bc2bd,
|
||||
0x0e8ab0a29b3fef79,
|
||||
0xfd73c2cd3b443de4,
|
||||
0x447892bf2c03c2ef,
|
||||
0xd5b3dae382c238b1,
|
||||
0x2103d8a64e9f4cb6,
|
||||
0xfe1f57d88e2de92f
|
||||
];
|
||||
|
||||
for i in 0..25 {
|
||||
assert!(a[i] == Chunk::from(TEST_VECTOR[i]));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user