You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm using Shake in a setting where all input data is known at compile-time, a case where the hash value could be computed at compile-time too.
I feel that Rust has everything needed for it, so I've been toying with const fn for all the things.
Main hurdles:
The "rounds" for loop. Solved by a macro that transforms the for loop into a while loop. We could just manually make it a while loop too, probably simpler. The other for loops are unrolled, so nothing more needed. keccakf is now const fn.
The Permutation trait. A trait function cannot be const. Not sure how to solve; we could get rid of the trait entirely (since there's only one permutation).
Would a const implementation be welcome? If so, do you have an idea to get around the trait problem?
My WIP const implementation
diff --git a/src/lib.rs b/src/lib.rs
index 9329fd3..a46aa79 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -38,6 +38,7 @@
//! [`@oleganza`]: https://github.com/oleganza
//! [`CC0`]: https://github.com/debris/tiny-keccak/blob/master/LICENSE
+#![feature(const_mut_refs)]
#![no_std]
#![deny(missing_docs)]
@@ -51,71 +52,83 @@ const PI: [usize; 24] = [
const WORDS: usize = 25;
+macro_rules! const_for {
+ (for $i:ident in $begin:tt..$end:tt { $($body:tt)* }) => {
+ let mut $i = $begin;
+ while $i < $end {
+ $($body)*
+ $i += 1;
+ }
+ };
+}
+
macro_rules! keccak_function {
($doc: expr, $name: ident, $rounds: expr, $rc: expr) => {
#[doc = $doc]
#[allow(unused_assignments)]
#[allow(non_upper_case_globals)]
- pub fn $name(a: &mut [u64; $crate::WORDS]) {
+ pub const fn $name(a: &mut [u64; $crate::WORDS]) {
use crunchy::unroll;
- for i in 0..$rounds {
- let mut array: [u64; 5] = [0; 5];
-
- // Theta
- unroll! {
- for x in 0..5 {
- unroll! {
- for y_count in 0..5 {
- let y = y_count * 5;
- array[x] ^= a[x + y];
+ const_for! {
+ for i in 0..$rounds {
+ let mut array: [u64; 5] = [0; 5];
+
+ // Theta
+ unroll! {
+ for x in 0..5 {
+ unroll! {
+ for y_count in 0..5 {
+ let y = y_count * 5;
+ array[x] ^= a[x + y];
+ }
}
}
}
- }
- unroll! {
- for x in 0..5 {
- unroll! {
- for y_count in 0..5 {
- let y = y_count * 5;
- a[y + x] ^= array[(x + 4) % 5] ^ array[(x + 1) % 5].rotate_left(1);
+ unroll! {
+ for x in 0..5 {
+ unroll! {
+ for y_count in 0..5 {
+ let y = y_count * 5;
+ a[y + x] ^= array[(x + 4) % 5] ^ array[(x + 1) % 5].rotate_left(1);
+ }
}
}
}
- }
- // Rho and pi
- let mut last = a[1];
- unroll! {
- for x in 0..24 {
- array[0] = a[$crate::PI[x]];
- a[$crate::PI[x]] = last.rotate_left($crate::RHO[x]);
- last = array[0];
+ // Rho and pi
+ let mut last = a[1];
+ unroll! {
+ for x in 0..24 {
+ array[0] = a[$crate::PI[x]];
+ a[$crate::PI[x]] = last.rotate_left($crate::RHO[x]);
+ last = array[0];
+ }
}
- }
- // Chi
- unroll! {
- for y_step in 0..5 {
- let y = y_step * 5;
+ // Chi
+ unroll! {
+ for y_step in 0..5 {
+ let y = y_step * 5;
- unroll! {
- for x in 0..5 {
- array[x] = a[y + x];
+ unroll! {
+ for x in 0..5 {
+ array[x] = a[y + x];
+ }
}
- }
- unroll! {
- for x in 0..5 {
- a[y + x] = array[x] ^ ((!array[(x + 1) % 5]) & (array[(x + 2) % 5]));
+ unroll! {
+ for x in 0..5 {
+ a[y + x] = array[x] ^ ((!array[(x + 1) % 5]) & (array[(x + 2) % 5]));
+ }
}
}
- }
- };
+ };
- // Iota
- a[0] ^= $rc[i];
+ // Iota
+ a[0] ^= $rc[i];
+ }
}
}
}
@@ -301,7 +314,7 @@ fn right_encode(len: usize) -> EncodedLen {
struct Buffer([u64; WORDS]);
impl Buffer {
- fn words(&mut self) -> &mut [u64; WORDS] {
+ const fn words(&mut self) -> &mut [u64; WORDS] {
&mut self.0
}
Best regards,
Ruben
The text was updated successfully, but these errors were encountered:
Hi!
I'm using
Shake
in a setting where all input data is known at compile-time, a case where the hash value could be computed at compile-time too.I feel that Rust has everything needed for it, so I've been toying with
const fn
for all the things.Main hurdles:
keccakf
is nowconst fn
.Permutation
trait. A trait function cannot beconst
. Not sure how to solve; we could get rid of the trait entirely (since there's only one permutation).Would a
const
implementation be welcome? If so, do you have an idea to get around the trait problem?My WIP const implementation
Best regards,
Ruben
The text was updated successfully, but these errors were encountered: