From 38767db686a39da8de89926f72e6b1512cb6cf12 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sat, 26 Dec 2015 16:17:46 -0700 Subject: [PATCH] WIP implementation of keccak with bellman --- readable_keccak/Makefile | 24 ++ readable_keccak/keccak.c | 109 +++++++++ readable_keccak/keccak.h | 25 +++ readable_keccak/main.c | 162 ++++++++++++++ src/keccak.rs | 472 +++++++++++++++++++++++++++++++++++++++ src/main.rs | 7 + 6 files changed, 799 insertions(+) create mode 100644 readable_keccak/Makefile create mode 100644 readable_keccak/keccak.c create mode 100644 readable_keccak/keccak.h create mode 100644 readable_keccak/main.c create mode 100644 src/keccak.rs diff --git a/readable_keccak/Makefile b/readable_keccak/Makefile new file mode 100644 index 0000000..fd77c7c --- /dev/null +++ b/readable_keccak/Makefile @@ -0,0 +1,24 @@ +# 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/readable_keccak/keccak.c b/readable_keccak/keccak.c new file mode 100644 index 0000000..38830b1 --- /dev/null +++ b/readable_keccak/keccak.c @@ -0,0 +1,109 @@ +// 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/readable_keccak/keccak.h b/readable_keccak/keccak.h new file mode 100644 index 0000000..34fc148 --- /dev/null +++ b/readable_keccak/keccak.h @@ -0,0 +1,25 @@ +// 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/readable_keccak/main.c b/readable_keccak/main.c new file mode 100644 index 0000000..f8cd21d --- /dev/null +++ b/readable_keccak/main.c @@ -0,0 +1,162 @@ +// main.c +// 19-Nov-11 Markku-Juhani O. Saarinen + +#include +#include +#include "keccak.h" + +// 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, + 0x9abcdef012345678, + 0x89abcdef01234567, + 0x789abcdef0123456, + 0x6789abcdef012345, + 0x56789abcdef01234, + 0x456789abcdef0123, + 0x3456789abcdef012, + 0x23456789abcdef01, + 0x123456789abcdef0, + 0x0123456789abcdef, + 0xf0123456789abcde, + 0xef0123456789abcd, + 0xdef0123456789abc, + 0xcdef0123456789ab, + 0xbcdef0123456789a, + 0xabcdef0123456789, + 0x9abcdef012345678, + 0x89abcdef01234567, + 0x789abcdef0123456, + 0x6789abcdef012345, + 0x56789abcdef01234, + 0x456789abcdef0123, + 0x3456789abcdef012, + 0x23456789abcdef01 + }; + + keccakf(st, 24); + + if(st[24] == 0x3300e5d2414b6a93) { + printf("wow good job\n"); + } +*/ +} diff --git a/src/keccak.rs b/src/keccak.rs new file mode 100644 index 0000000..ab98c0f --- /dev/null +++ b/src/keccak.rs @@ -0,0 +1,472 @@ +//use tinysnark::FieldT; + +const keccakf_rndc: [u64; 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 keccakf_rotc: [usize; 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 keccakf_piln: [usize; 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 +]; + +fn keccakf(st: &mut [Chunk; 25], rounds: usize) +{ + for round in 0..rounds { + /* + // Theta + for (i = 0; i < 5; i++) + bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20]; + */ + + // TODO: Rust arrays don't implement FromIterator. + let mut bc: [Option; 5] = [None, None, None, None, None]; + + for i in 0..5 { + bc[i] = Some(st[i] + .xor(&st[i+5]) + .xor(&st[i+10]) + .xor(&st[i+15]) + .xor(&st[i+20])); + } + + let mut bc: [Chunk; 5] = [bc[0].take().unwrap(), + bc[1].take().unwrap(), + bc[2].take().unwrap(), + bc[3].take().unwrap(), + bc[4].take().unwrap()]; + + /* + 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; + } + */ + + for i in 0..5 { + 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]); + } + } + + { + /* + // 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]; + } + */ + let mut tmp = st[1].clone(); + + 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(); + } + } + + { + /* + // 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]; + } + */ + + for j in (0..25).filter(|a| a % 5 == 0) { + for i in 0..5 { + bc[i] = st[j + i].clone(); + } + + for i in 0..5 { + st[j + i] = st[j + i].xor(&bc[(i + 1) % 5].notand(&bc[(i + 2) % 5])); + } + } + } + + /* + // Iota + st[0] ^= keccakf_rndc[round]; + */ + + st[0] = st[0].xor(&keccakf_rndc[round].into()); + } +} + +// TODO: don't return a vec. currently don't have any +// more patience for rust's awful arrays +fn keccak256(mut input: &[[Bit; 8]]) -> Vec { + assert_eq!(input.len(), 144); + + let mut st: [Chunk; 25] = [Chunk::from(0), Chunk::from(0), Chunk::from(0), Chunk::from(0), Chunk::from(0), + Chunk::from(0), Chunk::from(0), Chunk::from(0), Chunk::from(0), Chunk::from(0), + Chunk::from(0), Chunk::from(0), Chunk::from(0), Chunk::from(0), Chunk::from(0), + Chunk::from(0), Chunk::from(0), Chunk::from(0), Chunk::from(0), Chunk::from(0), + Chunk::from(0), Chunk::from(0), Chunk::from(0), Chunk::from(0), Chunk::from(0) + ]; + + 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)])); + } + + 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); + } + + assert!(v.len() == 256); + + v +} + +struct Chunk { + bits: [Bit; 64] +} + +impl Clone for Chunk { + fn clone(&self) -> Chunk { + let mut new_chunk = Chunk::from(0); + + for i in 0..64 { + new_chunk.bits[i] = self.bits[i].clone(); + } + + new_chunk + } +} + +impl Chunk { + fn xor(&self, other: &Chunk) -> Chunk { + let mut new_chunk = Chunk::from(0); + + for i in 0..64 { + new_chunk.bits[i] = self.bits[i].xor(&other.bits[i]); + } + + new_chunk + } + + fn notand(&self, other: &Chunk) -> Chunk { + let mut new_chunk = Chunk::from(0); + + for i in 0..64 { + new_chunk.bits[i] = self.bits[i].notand(&other.bits[i]); + } + + new_chunk + } + + fn rotl(&self, by: usize) -> Chunk { + assert!(by < 64); + let mut new_bits = vec![]; + + new_bits.extend_from_slice(&self.bits[by..]); + new_bits.extend_from_slice(&self.bits[0..by]); + + let mut clone = self.clone(); + clone.bits.clone_from_slice(&new_bits); + + clone + } +} + +impl PartialEq for Chunk { + fn eq(&self, other: &Chunk) -> bool { + for (a, b) in self.bits.iter().zip(other.bits.iter()) { + if a != b { return false; } + } + + true + } +} + +impl<'a> From<&'a [[Bit; 8]]> for Chunk { + fn from(bytes: &'a [[Bit; 8]]) -> Chunk { + assert!(bytes.len() == 8); // must be 64 bit + + let mut new_chunk = Chunk::from(0); + + for (i, byte) in bytes.iter().rev().enumerate() { + for (j, bit) in byte.iter().enumerate() { + new_chunk.bits[i*8 + j] = bit.clone(); + } + } + + new_chunk + } +} + +impl<'a> From<&'a [Bit]> for Chunk { + fn from(bits: &'a [Bit]) -> Chunk { + assert!(bits.len() == 64); // must be 64 bit + + let mut new_chunk = Chunk::from(0); + + for (i, bit) in bits.iter().enumerate() { + new_chunk.bits[i] = bit.clone(); + } + + new_chunk + } +} + +impl From for Chunk { + fn from(num: u64) -> Chunk { + use std::mem; + + fn bit_at(num: u64, i: usize) -> u8 { + ((num << i) >> 63) as u8 + } + + // TODO: initialize this with unsafe { } + // sadly... GET INTEGER GENERICS WORKING RUST + Chunk { + bits: [ + Bit::constant(bit_at(num, 0)), + Bit::constant(bit_at(num, 1)), + Bit::constant(bit_at(num, 2)), + Bit::constant(bit_at(num, 3)), + Bit::constant(bit_at(num, 4)), + Bit::constant(bit_at(num, 5)), + Bit::constant(bit_at(num, 6)), + Bit::constant(bit_at(num, 7)), + Bit::constant(bit_at(num, 8)), + Bit::constant(bit_at(num, 9)), + Bit::constant(bit_at(num, 10)), + Bit::constant(bit_at(num, 11)), + Bit::constant(bit_at(num, 12)), + Bit::constant(bit_at(num, 13)), + Bit::constant(bit_at(num, 14)), + Bit::constant(bit_at(num, 15)), + Bit::constant(bit_at(num, 16)), + Bit::constant(bit_at(num, 17)), + Bit::constant(bit_at(num, 18)), + Bit::constant(bit_at(num, 19)), + Bit::constant(bit_at(num, 20)), + Bit::constant(bit_at(num, 21)), + Bit::constant(bit_at(num, 22)), + Bit::constant(bit_at(num, 23)), + Bit::constant(bit_at(num, 24)), + Bit::constant(bit_at(num, 25)), + Bit::constant(bit_at(num, 26)), + Bit::constant(bit_at(num, 27)), + Bit::constant(bit_at(num, 28)), + Bit::constant(bit_at(num, 29)), + Bit::constant(bit_at(num, 30)), + Bit::constant(bit_at(num, 31)), + Bit::constant(bit_at(num, 32)), + Bit::constant(bit_at(num, 33)), + Bit::constant(bit_at(num, 34)), + Bit::constant(bit_at(num, 35)), + Bit::constant(bit_at(num, 36)), + Bit::constant(bit_at(num, 37)), + Bit::constant(bit_at(num, 38)), + Bit::constant(bit_at(num, 39)), + Bit::constant(bit_at(num, 40)), + Bit::constant(bit_at(num, 41)), + Bit::constant(bit_at(num, 42)), + Bit::constant(bit_at(num, 43)), + Bit::constant(bit_at(num, 44)), + Bit::constant(bit_at(num, 45)), + Bit::constant(bit_at(num, 46)), + Bit::constant(bit_at(num, 47)), + Bit::constant(bit_at(num, 48)), + Bit::constant(bit_at(num, 49)), + Bit::constant(bit_at(num, 50)), + Bit::constant(bit_at(num, 51)), + Bit::constant(bit_at(num, 52)), + Bit::constant(bit_at(num, 53)), + Bit::constant(bit_at(num, 54)), + Bit::constant(bit_at(num, 55)), + Bit::constant(bit_at(num, 56)), + Bit::constant(bit_at(num, 57)), + Bit::constant(bit_at(num, 58)), + Bit::constant(bit_at(num, 59)), + Bit::constant(bit_at(num, 60)), + Bit::constant(bit_at(num, 61)), + Bit::constant(bit_at(num, 62)), + Bit::constant(bit_at(num, 63)) + ] + } + } +} + +#[derive(Debug, PartialEq, Clone)] +enum Bit { + Constant(u8) +} + +impl Bit { + fn byte(byte: u8) -> [Bit; 8] { + [ + Bit::constant({if byte & 0b10000000 != 0 { 1 } else { 0 }}), + Bit::constant({if byte & 0b01000000 != 0 { 1 } else { 0 }}), + Bit::constant({if byte & 0b00100000 != 0 { 1 } else { 0 }}), + Bit::constant({if byte & 0b00010000 != 0 { 1 } else { 0 }}), + Bit::constant({if byte & 0b00001000 != 0 { 1 } else { 0 }}), + Bit::constant({if byte & 0b00000100 != 0 { 1 } else { 0 }}), + Bit::constant({if byte & 0b00000010 != 0 { 1 } else { 0 }}), + Bit::constant({if byte & 0b00000001 != 0 { 1 } else { 0 }}), + ] + } + + fn constant(num: u8) -> Bit { + assert_eq!((1 - num) * num, 0); // haha + + Bit::Constant(num) + } + + // self xor other + fn xor(&self, other: &Bit) -> Bit { + match (self, other) { + (&Bit::Constant(a), &Bit::Constant(b)) => { + Bit::constant(a ^ b) + }, + //_ => unimplemented!() + } + } + + // (not self) and other + fn notand(&self, other: &Bit) -> Bit { + match (self, other) { + (&Bit::Constant(a), &Bit::Constant(b)) => { + Bit::constant((a ^ 1) & b) + }, + //_ => unimplemented!() + } + } +} + +#[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() { + let mut a: [Chunk; 25] = + [ + Chunk::from(0xABCDEF0123456789), + Chunk::from(0x9ABCDEF012345678), + Chunk::from(0x89ABCDEF01234567), + Chunk::from(0x789ABCDEF0123456), + Chunk::from(0x6789ABCDEF012345), + Chunk::from(0x56789ABCDEF01234), + Chunk::from(0x456789ABCDEF0123), + Chunk::from(0x3456789ABCDEF012), + Chunk::from(0x23456789ABCDEF01), + Chunk::from(0x123456789ABCDEF0), + Chunk::from(0x0123456789ABCDEF), + Chunk::from(0xF0123456789ABCDE), + Chunk::from(0xEF0123456789ABCD), + Chunk::from(0xDEF0123456789ABC), + Chunk::from(0xCDEF0123456789AB), + Chunk::from(0xBCDEF0123456789A), + Chunk::from(0xABCDEF0123456789), + Chunk::from(0x9ABCDEF012345678), + Chunk::from(0x89ABCDEF01234567), + Chunk::from(0x789ABCDEF0123456), + Chunk::from(0x6789ABCDEF012345), + Chunk::from(0x56789ABCDEF01234), + Chunk::from(0x456789ABCDEF0123), + Chunk::from(0x3456789ABCDEF012), + Chunk::from(0x23456789ABCDEF01) + ]; + + keccakf(&mut a, 24); + /* + ebf3844f878a7d3b + 4c9a23df85c470ef + 4c2e69353217ca2b + a3ffa213a668ba9d + 34082fa7dc4c944b + b8bd0a4331665932 + bfcee841052def2d + 09e2f6993a65ac0b + ec78b15ef42a11e6 + 5088c480e6a77eb8 + 9c1ff840c7758823 + df8f367ad977a6b1 + 517b9c3505b4195a + 04624d3094c46c2c + e71674d1b70748e2 + 6739a678e25ae9f4 + 2e64f74a9528d091 + 9c17a1105709cbfe + 54678a20a3ac5925 + 0297df877fa4a559 + f55ec61b328a5cc5 + 56637274c0f2c301 + 33943408ffd9b9c5 + f4b87c711ed56d77 + 3300e5d2414b6a93 + */ + assert!(a[0] == Chunk::from(0xebf3844f878a7d3b)); + assert!(a[1] == Chunk::from(0x4c9a23df85c470ef)); + assert!(a[2] == Chunk::from(0x4c2e69353217ca2b)); + assert!(a[3] == Chunk::from(0xa3ffa213a668ba9d)); + assert!(a[24] == Chunk::from(0x3300e5d2414b6a93)); +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 1528dc0..473dcef 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,17 @@ +#![feature(clone_from_slice)] + extern crate tinysnark; extern crate rand; use tinysnark::{Proof, Keypair, FieldT, LinearTerm, ConstraintSystem}; +use std::marker::PhantomData; + +mod keccak; fn main() { tinysnark::init(); + /* let mut cs = ConstraintSystem::new(2, 1); // xor // (2*b) * c = b+c - a @@ -22,4 +28,5 @@ fn main() { let kp = Keypair::new(&cs); let proof = Proof::new(&kp, &prompt, &solution); assert!(proof.verify(&kp, &prompt)); + */ }