Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
02f2e38
fix: various fixes to syntax and comptime flags
TomAFrench Nov 4, 2022
e2a5497
refactor: use global values for array sizes
TomAFrench Nov 4, 2022
3d25e8d
refactor: split logic into a lib crate to allow testing
TomAFrench Oct 24, 2022
edf3266
Merge branch 'master' into absorb
vezenovm Nov 4, 2022
db74440
Merge pull request #2 from TomAFrench/testing
TomAFrench Nov 4, 2022
88f5c19
preliminary absorb and squeeze
vezenovm Nov 4, 2022
c21be24
feat: use constant for lengths of lane offset values
TomAFrench Nov 4, 2022
e9b9012
Merge branch 'master' into array-size-expressions
TomAFrench Nov 4, 2022
327348f
override state in keccakf func rather than copying over
vezenovm Nov 5, 2022
0f9a2bc
refactor: move constants to a single file
TomAFrench Nov 4, 2022
0edd8a7
fix: remove some usages of NUM_LANES which isn't supported
TomAFrench Nov 9, 2022
67e2f0c
Merge pull request #1 from TomAFrench/array-size-expressions
TomAFrench Nov 9, 2022
009e9b4
Merge branch 'master' into constants
TomAFrench Nov 9, 2022
5053b00
fix: add missing import to padding test
TomAFrench Nov 9, 2022
9f5cb1b
Merge pull request #3 from TomAFrench/constants
TomAFrench Nov 9, 2022
02e408c
Merge branch 'master' into mv/squeeze
TomAFrench Nov 9, 2022
92947da
feat: add OUTPUT_SIZE constant
TomAFrench Nov 9, 2022
bc36aff
refactor: simplify pulling out first 256 bits of state
TomAFrench Nov 9, 2022
508677d
chore: remove stale comment
TomAFrench Nov 9, 2022
f878bb5
chore: delete committed Verifier.toml
TomAFrench Nov 10, 2022
64dbafa
Merge branch 'master' into mv/squeeze
TomAFrench Nov 10, 2022
ae07405
refactor: remove noop renamings of imports (#7)
TomAFrench Nov 10, 2022
3873942
Merge branch 'master' into mv/squeeze
TomAFrench Nov 10, 2022
407cfc3
refactor: remove useless renaming
TomAFrench Nov 10, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions circuits/Nargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ authors = [""]
compiler_version = "0.1"

[dependencies]
keccak = { path = "../lib" }
4 changes: 2 additions & 2 deletions circuits/Prover.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
input = [1,0,0,0,0,0,0,0,0,0]
return = [1,1,0,0,0,0,0,0,0,1]
input = [1, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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]
return = [1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0]
input_length = 1
1 change: 0 additions & 1 deletion circuits/Verifier.toml

This file was deleted.

13 changes: 4 additions & 9 deletions circuits/src/main.nr
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
mod padding;

// TODO: Change to final value (<= BLOCK_SIZE - 2).
global INPUT_SIZE: Field = 10;

// TODO: Change to final value (1088)
global BLOCK_SIZE: Field = 10; // Blocks are 136 bytes. 138 * 8 = 1088 bits.
use dep::keccak::permutations::keccak;
use dep::keccak::constants;

// This is a simplified implementation of the Keccak256 hash function.
// In particular we assume that the `input_length` will be less than the size of the absorb step's block size.
fn main(input: [u1; INPUT_SIZE], input_length: u64) -> pub [u1; BLOCK_SIZE] {
padding::pad(input, input_length)
fn main(input: [u1; constants::INPUT_SIZE], input_length: u64) -> pub [u1; constants::OUTPUT_SIZE] {
keccak(input, input_length)
}
23 changes: 0 additions & 23 deletions circuits/src/permutations.nr

This file was deleted.

20 changes: 0 additions & 20 deletions circuits/src/permutations/chi.nr

This file was deleted.

56 changes: 0 additions & 56 deletions circuits/src/permutations/theta.nr

This file was deleted.

5 changes: 5 additions & 0 deletions lib/Nargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[package]
authors = [""]
compiler_version = "0.1"

[dependencies]
17 changes: 17 additions & 0 deletions lib/src/constants.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Input size related

// The input must be at least 2 bits smaller than the block size to accommodate the padding bits.
global INPUT_SIZE: Field = 1086;
// Blocks are 136 bytes. 138 * 8 = 1088 bits.
global BLOCK_SIZE: Field = 1088;

global OUTPUT_SIZE: Field = 256;

// State size related
global STATE_SIZE: Field = 1600;
global LANE_LENGTH: Field = 64;
global COLUMN_LENGTH: Field = 5;
global NUM_LANES: Field = 25;

// Misc
global NUM_ROUNDS: Field = 24;
3 changes: 3 additions & 0 deletions lib/src/lib.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod constants;
mod padding;
mod permutations;
15 changes: 5 additions & 10 deletions circuits/src/padding.nr → lib/src/padding.nr
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
// TODO: Change to final value (<= BLOCK_SIZE - 2).
// Could likely make this generic even (need to check on language support).
global INPUT_SIZE: Field = 10;

// TODO: Change to final value (1088)
global BLOCK_SIZE: Field = 10; // Blocks are 136 bytes. 138 * 8 = 1088 bits.
use crate::constants;

// This is a simplified implementation of the pad10*1 algorithm.
// As we assume that the input length is smaller than the block size, we can ignore the potential for the padding
// sequence to be spread over multiple blocks.
fn pad(input: [u1; INPUT_SIZE], input_length: u64) -> [u1; BLOCK_SIZE] {
fn pad(input: [u1; constants::INPUT_SIZE], input_length: u64) -> [u1; constants::BLOCK_SIZE] {
// We require 2 bits of space after the message in order to include the padding bits.
// constrain input_length < BLOCK_SIZE - 2;

let mut padded_input: [u1; BLOCK_SIZE] = [0 as u1; 10];
for i in 0..BLOCK_SIZE {
let mut padded_input: [u1; constants::BLOCK_SIZE] = [0 as u1; constants::BLOCK_SIZE];
for i in 0..constants::INPUT_SIZE {
if (i as u64) < input_length {
// Copy input into padded array.
padded_input[i] = input[i];
Expand All @@ -28,7 +23,7 @@ fn pad(input: [u1; INPUT_SIZE], input_length: u64) -> [u1; BLOCK_SIZE] {
}
};
// Place the second 1 bit of the padding in the last bit of the block.
padded_input[BLOCK_SIZE - 1] = 1;
padded_input[constants::BLOCK_SIZE - 1] = 1;

padded_input
}
71 changes: 71 additions & 0 deletions lib/src/permutations.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use crate::constants;

mod chi;
mod iota;
mod rhoPi;
mod theta;

// This is a simplified implementation of the Keccak256 absorb function where we assume the input is smaller than the
// internal state size.
fn absorb(input: [u1; constants::BLOCK_SIZE]) -> [u1; constants::STATE_SIZE] {
let mut state: [u1; constants::STATE_SIZE] = [0 as u1; constants::STATE_SIZE];

// We should in theory XOR the input with the internal state. However we know that X ^ 0 = X so we can just write
// the input into the state. We can do this as the input is guaranteed to be smaller than the state size.
for i in 0..constants::BLOCK_SIZE {
state[i] = input[i];
};

// TODO: apply keccak-p functions
state = keccakf(state);

state
}

fn squeeze(input: [u1; constants::STATE_SIZE]) -> [u1; constants::OUTPUT_SIZE] {

let mut result: [u1; constants::OUTPUT_SIZE] = [0 as u1; constants::OUTPUT_SIZE];

for i in 0..constants::OUTPUT_SIZE {
result[i] = input[i];
};
result
}

fn keccakfRound(state: [u1; constants::STATE_SIZE], round_number: comptime Field) -> [u1; constants::STATE_SIZE] {

let state_after_theta = theta::theta(state);
let state_after_rhoPi = rhoPi::rhoPi(state_after_theta);
let state_after_chi = chi::chi(state_after_rhoPi);
let new_state = iota::iota(state_after_chi, round_number);

new_state
}

fn keccakf(input: [u1; constants::STATE_SIZE]) -> [u1; constants::STATE_SIZE] {
let mut state: [u1; constants::STATE_SIZE] = [0 as u1; constants::STATE_SIZE];
for j in 0..constants::STATE_SIZE {
state[j] = input[j];
};
for i in 0..constants::NUM_ROUNDS {
state = keccakfRound(state, i);
};
state
}

fn keccakFinal(input: [u1; constants::INPUT_SIZE], input_length: u64) -> [u1; constants::STATE_SIZE] {
let padded_input: [u1; constants::BLOCK_SIZE] = crate::padding::pad(input, input_length);

let absorb_result: [u1; constants::STATE_SIZE] = absorb(padded_input);

absorb_result
}

fn keccak(input: [u1; constants::INPUT_SIZE], input_length: u64) -> [u1; constants::OUTPUT_SIZE] {

let final_state = keccakFinal(input, input_length);

let squeezed_state = squeeze(final_state);

squeezed_state
}
20 changes: 20 additions & 0 deletions lib/src/permutations/chi.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use crate::constants;

fn chi(state: [u1; constants::STATE_SIZE]) -> [u1; constants::STATE_SIZE] {
// The labelling convention for the state array is `state[x, y, z] = state[LANE_LENGTH * (5y + x) + z]`.
let mut new_state = state;
for z in 0..constants::LANE_LENGTH {
// Iterate over each slice...
for y in 0..constants::COLUMN_LENGTH {
// and write updated values for each row.
// new_state[x, y, z] = new_state[x, y, z] ^ new_state[(x + 1) % 5, y, z] ^ new_state[(x + 2) % 5, y, z]
new_state[constants::LANE_LENGTH * (5 * y + 0) + z] = state[constants::LANE_LENGTH * (5 * y + 0) + z] ^ state[constants::LANE_LENGTH * (5 * y + 1) + z] ^ state[constants::LANE_LENGTH * (5 * y + 2) + z];
new_state[constants::LANE_LENGTH * (5 * y + 1) + z] = state[constants::LANE_LENGTH * (5 * y + 1) + z] ^ state[constants::LANE_LENGTH * (5 * y + 2) + z] ^ state[constants::LANE_LENGTH * (5 * y + 3) + z];
new_state[constants::LANE_LENGTH * (5 * y + 2) + z] = state[constants::LANE_LENGTH * (5 * y + 2) + z] ^ state[constants::LANE_LENGTH * (5 * y + 3) + z] ^ state[constants::LANE_LENGTH * (5 * y + 4) + z];
new_state[constants::LANE_LENGTH * (5 * y + 3) + z] = state[constants::LANE_LENGTH * (5 * y + 3) + z] ^ state[constants::LANE_LENGTH * (5 * y + 4) + z] ^ state[constants::LANE_LENGTH * (5 * y + 0) + z];
new_state[constants::LANE_LENGTH * (5 * y + 4) + z] = state[constants::LANE_LENGTH * (5 * y + 4) + z] ^ state[constants::LANE_LENGTH * (5 * y + 0) + z] ^ state[constants::LANE_LENGTH * (5 * y + 1) + z];
};
};

new_state
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
global STATE_SIZE: Field = 1600;
global LANE_LENGTH: Field = 64;
global NUM_ROUNDS: Field = 24;
use crate::constants;

fn iota(state: [u1; STATE_SIZE], round_number: Field) -> [u1; STATE_SIZE] {
fn iota(state: [u1; constants::STATE_SIZE], round_number: comptime Field) -> [u1; constants::STATE_SIZE] {
// Each element of RC is a bitmap for the mask to apply to the lane.
let RC: [u64; NUM_ROUNDS] = [
let RC: [u64; constants::NUM_ROUNDS] = [
0x0000000000000001, 0x0000000000008082, 0x800000000000808A,
0x8000000080008000, 0x000000000000808B, 0x0000000080000001,
0x8000000080008081, 0x8000000000008009, 0x000000000000008A,
Expand All @@ -19,8 +17,8 @@ fn iota(state: [u1; STATE_SIZE], round_number: Field) -> [u1; STATE_SIZE] {
// The labelling convention for the state array is `state[x, y, z] = state[LANE_LENGTH * (5y + x) + z]`.
// In order to update Lane(0,0) we must only update the first `LANE_LENGTH` values of the state array.
let mut new_state = state;
for i in 0..LANE_LENGTH {
new_state[i] = state[i] ^ (rc & 1);
for i in 0..constants::LANE_LENGTH {
new_state[i] = state[i] ^ (rc as u1);
// Equivalent to a bitshift right.
rc = rc / 2;
};
Expand Down
Loading