From 4eac6417c3934ecbab2c974e28f2b6466dbca6a9 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Mon, 28 Dec 2015 00:45:11 -0700 Subject: [PATCH] Completely functional implementation with tests --- src/keccak.rs | 174 ++++++++++------------------------- src/readable_keccak/Makefile | 24 ----- src/readable_keccak/keccak.c | 109 ---------------------- src/readable_keccak/keccak.h | 25 ----- src/readable_keccak/main.c | 165 --------------------------------- 5 files changed, 51 insertions(+), 446 deletions(-) delete mode 100644 src/readable_keccak/Makefile delete mode 100644 src/readable_keccak/keccak.c delete mode 100644 src/readable_keccak/keccak.h delete mode 100644 src/readable_keccak/main.c diff --git a/src/keccak.rs b/src/keccak.rs index 7807240..bbcd77d 100644 --- a/src/keccak.rs +++ b/src/keccak.rs @@ -108,30 +108,8 @@ fn keccakf(st: &mut [Chunk], rounds: usize) } } -fn temporary_shim(state: &mut [Byte]) { - assert_eq!(state.len(), 200); - - 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())) - { - *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.iter_mut().flat_map(|c| c.bits.iter_mut())) - { - *input_bit = chunk_bit.clone(); - } -} - fn sha3_256(message: &[Byte]) -> Vec { + // As defined by FIPS202 keccak(1088, 512, message, 0x06, 32) } @@ -191,36 +169,30 @@ fn keccak(rate: usize, capacity: usize, mut input: &[Byte], delimited_suffix: u8 output } -fn keccak256(input: &[Byte]) -> Vec { - assert_eq!(input.len(), 144); +fn temporary_shim(state: &mut [Byte]) { + assert_eq!(state.len(), 200); - let mut st: Vec = Some(Chunk::from(0)).into_iter().cycle().take(25).collect(); + println!("RUNNING TEMPORARY SHIM!"); - let mdlen = 32; // 256 bit - let rsiz = 200 - 2 * mdlen; - let rsizw = rsiz / 8; - - for i in 0..rsizw { - let j = i * 8; - st[i] = st[i].xor(&Chunk::from(&input[j..(j+8)])); + let mut chunks = Vec::with_capacity(25); + for i in 0..25 { + chunks.push(Chunk::from(0x0000000000000000)); } - keccakf(&mut st, 24); - - let mut v = vec![]; - for i in 0..4 { - // due to endianness... - let tmp: Vec<_> = st[i].bits.chunks(8) - .rev() - .flat_map(|x| x.iter()) - .map(|x| x.clone()) - .collect(); - v.extend_from_slice(&tmp); + 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(); } - assert!(v.len() == 256); + keccakf(&mut chunks, 24); - v + 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)] @@ -377,95 +349,51 @@ impl Bit { } #[test] -fn test_shim() { - let mut chunks: Vec<_> = (0..25).map(|_| Chunk::from(0xABCDEF0123456789)).collect(); - keccakf(&mut chunks, 24); +fn test_sha3_256() { + let test_vector: Vec<(Vec, [u8; 32])> = vec![ + (vec![Bit::byte(0x30)], + [0xf9,0xe2,0xea,0xaa,0x42,0xd9,0xfe,0x9e,0x55,0x8a,0x9b,0x8e,0xf1,0xbf,0x36,0x6f,0x19,0x0a,0xac,0xaa,0x83,0xba,0xd2,0x64,0x1e,0xe1,0x06,0xe9,0x04,0x10,0x96,0xe4] + ), + (vec![Bit::byte(0x30),Bit::byte(0x30)], + [0x2e,0x16,0xaa,0xb4,0x83,0xcb,0x95,0x57,0x7c,0x50,0xd3,0x8c,0x8d,0x0d,0x70,0x40,0xf4,0x67,0x26,0x83,0x23,0x84,0x46,0xc9,0x90,0xba,0xbb,0xca,0x5a,0xe1,0x33,0xc8] + ), + ((0..64).map(|_| Bit::byte(0x30)).collect::>(), + [0xc6,0xfd,0xd7,0xa7,0xf7,0x08,0x62,0xb3,0x6a,0x26,0xcc,0xd1,0x47,0x52,0x26,0x80,0x61,0xe9,0x81,0x03,0x29,0x9b,0x28,0xfe,0x77,0x63,0xbd,0x96,0x29,0x92,0x6f,0x4b] + ), + ((0..128).map(|_| Bit::byte(0x30)).collect::>(), + [0x99,0x9d,0xb4,0xd4,0x28,0x7b,0x52,0x15,0x20,0x8d,0x11,0xe4,0x0a,0x27,0xca,0x54,0xac,0xa0,0x09,0xb2,0x5c,0x4f,0x7a,0xb9,0x1a,0xd8,0xaa,0x93,0x60,0xf0,0x63,0x71] + ), + ((0..256).map(|_| Bit::byte(0x30)).collect::>(), + [0x11,0xea,0x74,0x37,0x7b,0x74,0xf1,0x53,0x9f,0x2e,0xd9,0x0a,0xb8,0xca,0x9e,0xb1,0xe0,0x70,0x8a,0x4b,0xfb,0xad,0x4e,0x81,0xcc,0x77,0xd9,0xa1,0x61,0x9a,0x10,0xdb] + ), + ((0..512).map(|_| Bit::byte(0x30)).collect::>(), + [0x1c,0x80,0x1b,0x16,0x3a,0x2a,0xbe,0xd0,0xe8,0x07,0x1e,0x7f,0xf2,0x60,0x4e,0x98,0x11,0x22,0x80,0x54,0x14,0xf3,0xc8,0xfd,0x96,0x59,0x5d,0x7e,0xe1,0xd6,0x54,0xe2] + ), + ]; - let mut bytes: Vec = (0..200).map(|i| { - match i % 8 { - 0 => Bit::byte(0xAB), - 1 => Bit::byte(0xCD), - 2 => Bit::byte(0xEF), - 3 => Bit::byte(0x01), - 4 => Bit::byte(0x23), - 5 => Bit::byte(0x45), - 6 => Bit::byte(0x67), - 7 => Bit::byte(0x89), - _ => unreachable!() - } - }).collect(); + for (i, &(ref message, ref expected)) in test_vector.iter().enumerate() { + let result: Vec = sha3_256(message).into_iter().map(|a| a.grab()).collect(); - temporary_shim(&mut bytes); - - for (i, bit) in bytes.iter().flat_map(|c| c.bits.iter()).enumerate() { - //println!("i = {}", i); - if &chunks[i / 64].bits[i % 64] != bit { - panic!("fuck."); + if &*result != expected { + print!("Expected: "); + for i in result.iter() { + print!("0x{:02x},", i); + } + panic!("Hash {} failed!", i+1); + } else { + println!("--- HASH {} SUCCESS ---", i+1); } } } #[test] -fn byte_grab_works() { - { - let b = Bit::byte(0xef); - - assert_eq!(0xef, b.grab()); - } -} - -#[test] -fn woohoo() { - let message = [Bit::byte(0x30)]; - let test = sha3_256(&message); - - for i in 0..32 { - print!("{:02x} ", test[i].grab()); - } - println!(""); - panic!("fuck"); -} - -#[test] -fn testsha3() { - let bb = |x: usize| { - match x % 5 { - 0 => Bit::byte(0xBB), - 1 => Bit::byte(0x3B), - 2 => Bit::byte(0x1B), - 3 => Bit::byte(0x0B), - 4 => Bit::byte(0xFF), - _ => unreachable!() - } - }; - - let msg: Vec = (0..144).map(bb).collect(); - - let result = keccak256(&msg); - - let correct_result: [u64; 4] = - [0x6746c5f4559bc1dd, - 0x49d08e1adcf3be12, - 0x80a2fcca8ce98789, - 0x659f40a0053e2989 - ]; - - for i in 0..4 { - let j = i * 64; - let ours = Chunk::from(&result[j..(j+64)]); - let correct = Chunk::from(correct_result[i]); - - assert!(ours == correct); - } -} - -#[test] -fn testff() { +fn test_keccakf() { let base = Chunk::from(0xABCDEF0123456789); let mut a: Vec = (0..25).map(|i| base.rotl(i*4)).collect(); keccakf(&mut a, 24); + const TEST_VECTOR: [u64; 25] = [ 0x4c8948fcb6616044, 0x75642a21f8bd1299, diff --git a/src/readable_keccak/Makefile b/src/readable_keccak/Makefile deleted file mode 100644 index fd77c7c..0000000 --- a/src/readable_keccak/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -# Makefile -# 19-Nov-11 Markku-Juhani O. Saarinen - -BINARY = kctest -OBJS = keccak.o main.o -DIST = readable_keccak - -CC = gcc -CFLAGS = -Wall -O -LIBS = -LDFLAGS = -INCLUDES = - -$(BINARY): $(OBJS) - $(CC) $(LDFLAGS) -o $(BINARY) $(OBJS) $(LIBS) - -.c.o: - $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ - -clean: - rm -rf $(DIST).tgz $(OBJS) $(BINARY) *~ - -dist: clean - cd ..; tar cfvz $(DIST)/$(DIST).tgz $(DIST)/* diff --git a/src/readable_keccak/keccak.c b/src/readable_keccak/keccak.c deleted file mode 100644 index 38830b1..0000000 --- a/src/readable_keccak/keccak.c +++ /dev/null @@ -1,109 +0,0 @@ -// keccak.c -// 19-Nov-11 Markku-Juhani O. Saarinen -// A baseline Keccak (3rd round) implementation. - -#include "keccak.h" - -const uint64_t keccakf_rndc[24] = -{ - 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, - 0x8000000080008000, 0x000000000000808b, 0x0000000080000001, - 0x8000000080008081, 0x8000000000008009, 0x000000000000008a, - 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, - 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, - 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, - 0x000000000000800a, 0x800000008000000a, 0x8000000080008081, - 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 -}; - -const int keccakf_rotc[24] = -{ - 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, - 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 -}; - -const int keccakf_piln[24] = -{ - 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, - 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 -}; - -// update the state with given number of rounds - -void keccakf(uint64_t st[25], int rounds) -{ - int i, j, round; - uint64_t t, bc[5]; - - for (round = 0; round < rounds; round++) { - - // Theta - for (i = 0; i < 5; i++) - bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20]; - - for (i = 0; i < 5; i++) { - t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1); - for (j = 0; j < 25; j += 5) - st[j + i] ^= t; - } - - // Rho Pi - t = st[1]; - for (i = 0; i < 24; i++) { - j = keccakf_piln[i]; - bc[0] = st[j]; - st[j] = ROTL64(t, keccakf_rotc[i]); - t = bc[0]; - } - - // Chi - for (j = 0; j < 25; j += 5) { - for (i = 0; i < 5; i++) - bc[i] = st[j + i]; - for (i = 0; i < 5; i++) - st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5]; - } - - // Iota - st[0] ^= keccakf_rndc[round]; - } -} - -// compute a keccak hash (md) of given byte length from "in" - -int keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen) -{ - uint64_t st[25]; - //uint8_t temp[144]; - int i, rsiz, rsizw; - - rsiz = 200 - 2 * mdlen; - rsizw = rsiz / 8; - - memset(st, 0, sizeof(st)); - - /* - for ( ; inlen >= rsiz; inlen -= rsiz, in += rsiz) { - for (i = 0; i < rsizw; i++) - st[i] ^= ((uint64_t *) in)[i]; - keccakf(st, KECCAK_ROUNDS); - } - - // last block and padding - memcpy(temp, in, inlen); - temp[inlen++] = 1; - memset(temp + inlen, 0, rsiz - inlen); - temp[rsiz - 1] |= 0x80; - */ - - for (i = 0; i < rsizw; i++) { - st[i] ^= ((uint64_t *) in)[i]; - } - - keccakf(st, KECCAK_ROUNDS); - - memcpy(md, st, mdlen); - - return 0; -} - diff --git a/src/readable_keccak/keccak.h b/src/readable_keccak/keccak.h deleted file mode 100644 index 34fc148..0000000 --- a/src/readable_keccak/keccak.h +++ /dev/null @@ -1,25 +0,0 @@ -// keccak.h -// 19-Nov-11 Markku-Juhani O. Saarinen - -#ifndef KECCAK_H -#define KECCAK_H - -#include -#include - -#ifndef KECCAK_ROUNDS -#define KECCAK_ROUNDS 24 -#endif - -#ifndef ROTL64 -#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y)))) -#endif - -// compute a keccak hash (md) of given byte length from "in" -int keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen); - -// update the state -void keccakf(uint64_t st[25], int norounds); - -#endif - diff --git a/src/readable_keccak/main.c b/src/readable_keccak/main.c deleted file mode 100644 index a81b0bb..0000000 --- a/src/readable_keccak/main.c +++ /dev/null @@ -1,165 +0,0 @@ -// main.c -// 19-Nov-11 Markku-Juhani O. Saarinen - -#include -#include -#include "keccak.h" -#include - -// test each length - -typedef struct { - int mdlen; - char *msgstr; - uint8_t md[64]; -} test_triplet_t; - -// returns zero on success, nonzero + stderr messages on failure - -int keccak_test() -{ - test_triplet_t testvec[4] = { - { - 28, "Keccak-224 Test Hash", { - 0x30, 0x04, 0x5B, 0x34, 0x94, 0x6E, 0x1B, 0x2E, - 0x09, 0x16, 0x13, 0x36, 0x2F, 0xD2, 0x2A, 0xA0, - 0x8E, 0x2B, 0xEA, 0xFE, 0xC5, 0xE8, 0xDA, 0xEE, - 0x42, 0xC2, 0xE6, 0x65 } - }, { - 32, "Keccak-256 Test Hash", { - 0xA8, 0xD7, 0x1B, 0x07, 0xF4, 0xAF, 0x26, 0xA4, - 0xFF, 0x21, 0x02, 0x7F, 0x62, 0xFF, 0x60, 0x26, - 0x7F, 0xF9, 0x55, 0xC9, 0x63, 0xF0, 0x42, 0xC4, - 0x6D, 0xA5, 0x2E, 0xE3, 0xCF, 0xAF, 0x3D, 0x3C } - }, { - 48, "Keccak-384 Test Hash", { - 0xE2, 0x13, 0xFD, 0x74, 0xAF, 0x0C, 0x5F, 0xF9, - 0x1B, 0x42, 0x3C, 0x8B, 0xCE, 0xEC, 0xD7, 0x01, - 0xF8, 0xDD, 0x64, 0xEC, 0x18, 0xFD, 0x6F, 0x92, - 0x60, 0xFC, 0x9E, 0xC1, 0xED, 0xBD, 0x22, 0x30, - 0xA6, 0x90, 0x86, 0x65, 0xBC, 0xD9, 0xFB, 0xF4, - 0x1A, 0x99, 0xA1, 0x8A, 0x7D, 0x9E, 0x44, 0x6E } - }, { - 64, "Keccak-512 Test Hash", { - 0x96, 0xEE, 0x47, 0x18, 0xDC, 0xBA, 0x3C, 0x74, - 0x61, 0x9B, 0xA1, 0xFA, 0x7F, 0x57, 0xDF, 0xE7, - 0x76, 0x9D, 0x3F, 0x66, 0x98, 0xA8, 0xB3, 0x3F, - 0xA1, 0x01, 0x83, 0x89, 0x70, 0xA1, 0x31, 0xE6, - 0x21, 0xCC, 0xFD, 0x05, 0xFE, 0xFF, 0xBC, 0x11, - 0x80, 0xF2, 0x63, 0xC2, 0x7F, 0x1A, 0xDA, 0xB4, - 0x60, 0x95, 0xD6, 0xF1, 0x25, 0x33, 0x14, 0x72, - 0x4B, 0x5C, 0xBF, 0x78, 0x28, 0x65, 0x8E, 0x6A } - } - }; - int i, fails; - uint8_t md[64]; - - fails = 0; - for (i = 0; i < 4; i++) { - - keccak((uint8_t *) testvec[i].msgstr, - strlen(testvec[i].msgstr), - md, testvec[i].mdlen); - - if (memcmp(md, testvec[i].md, testvec[i].mdlen)) { - fails++; - fprintf(stderr, "Keccak-%d FAILED.", testvec[i].mdlen * 8); - } - } - - return fails; -} - -// main - -int main(int argc, char **argv) -{ - /* - if (keccak_test() == 0) - printf("Keccak self-test OK!\n"); - - return 0; - */ -/* - uint8_t in[144] = { - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B, 0xFF, - 0xBB, 0x3B, 0x1B, 0x0B - }; - - uint8_t md[32] = {0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 - }; - - keccak(in, 144, md, 32); - - for (int i = 0; i < 32; i++) { - printf("%02x ", md[i]); - } -*/ - uint64_t st[25] = { - 0xabcdef0123456789, - 0xbcdef0123456789a, - 0xcdef0123456789ab, - 0xdef0123456789abc, - 0xef0123456789abcd, - - 0xf0123456789abcde, - 0x0123456789abcdef, - 0x123456789abcdef0, - 0x23456789abcdef01, - 0x3456789abcdef012, - - 0x456789abcdef0123, - 0x56789abcdef01234, - 0x6789abcdef012345, - 0x789abcdef0123456, - 0x89abcdef01234567, - - 0x9abcdef012345678, - 0xabcdef0123456789, - 0xbcdef0123456789a, - 0xcdef0123456789ab, - 0xdef0123456789abc, - - 0xef0123456789abcd, - 0xf0123456789abcde, - 0x0123456789abcdef, - 0x123456789abcdef0, - 0x23456789abcdef01, - }; - - keccakf(st, 24); - - for (int i = 0; i < 25; i++) { - printf("%" PRIx64 "\n", st[i]); - } -}