Skip to content

Commit

Permalink
Merge pull request facebook#5 from novifinancial/rescue
Browse files Browse the repository at this point in the history
Rescue hash function
  • Loading branch information
irakliyk committed Sep 25, 2020
2 parents ee52e54 + 9acfef0 commit eb7f4fc
Show file tree
Hide file tree
Showing 8 changed files with 546 additions and 3 deletions.
1 change: 1 addition & 0 deletions crypto/Cargo.toml
Expand Up @@ -14,6 +14,7 @@ harness = false
blake3 = "0.3.6"
sha3 = "0.9.1"
serde = { version = "1.0.114", features = ["derive"] }
math = { path = "../math" }

[dev-dependencies]
criterion = "0.3.3"
Expand Down
29 changes: 26 additions & 3 deletions crypto/benches/hash.rs
Expand Up @@ -8,7 +8,7 @@ pub fn blake3(c: &mut Criterion) {
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
];
let mut r = [0u8; 32];
c.bench_function("Blake3", |bench| {
c.bench_function("hash_blake3", |bench| {
bench.iter(|| hash::blake3(black_box(&v), black_box(&mut r)))
});
}
Expand All @@ -20,10 +20,33 @@ pub fn sha3(c: &mut Criterion) {
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
];
let mut r = [0u8; 32];
c.bench_function("Sha3", |bench| {
c.bench_function("hash_sha3", |bench| {
bench.iter(|| hash::sha3(black_box(&v), black_box(&mut r)))
});
}

criterion_group!(hash_group, blake3, sha3);
pub fn rescue_s(c: &mut Criterion) {
let v: [u8; 32] = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32,
];
let mut r = [0u8; 32];
c.bench_function("hash_rescue_s", |bench| {
bench.iter(|| hash::rescue_s(black_box(&v), black_box(&mut r)))
});
}

pub fn rescue_d(c: &mut Criterion) {
let v: [u8; 64] = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
];
let mut r = [0u8; 32];
c.bench_function("hash_rescue_d", |bench| {
bench.iter(|| hash::rescue_d(black_box(&v), black_box(&mut r)))
});
}

criterion_group!(hash_group, blake3, sha3, rescue_s, rescue_d);
criterion_main!(hash_group);
3 changes: 3 additions & 0 deletions crypto/src/hash/mod.rs
@@ -1,5 +1,8 @@
use sha3::Digest;

mod rescue;
pub use rescue::{rescue_d, rescue_s};

/// Wrapper around blake3 hash function
pub fn blake3(values: &[u8], result: &mut [u8]) {
debug_assert!(
Expand Down
251 changes: 251 additions & 0 deletions crypto/src/hash/rescue/double.rs
@@ -0,0 +1,251 @@
use crate::utils::as_bytes;
use math::field::{self, add, exp, mul};

/// Function state is set to 6 field elements or 96 bytes; 4 elements are reserved for rate
/// and 2 elements are reserved for capacity.
const STATE_WIDTH: usize = 6;
const STATE_BYTES: usize = STATE_WIDTH * 16;

/// Two elements (32-bytes) are returned as digest.
const DIGEST_SIZE: usize = 2;

/// The number of rounds is set to 8 to provide 128-bit security level.
/// computed using algorithm 7 from https://eprint.iacr.org/2020/1143.pdf
const NUM_ROUNDS: usize = 8;

// HELPER FUNCTIONS
// ================================================================================================

/// Rescue hash function for double input; This implementation accepts a 64-byte input
/// and returns a 32-byte digest.
pub fn rescue_d(values: &[u8], result: &mut [u8]) {
debug_assert!(
values.len() <= 64,
"expected 64 or fewer input bytes but received {}",
values.len()
);
debug_assert!(
result.len() == 32,
"expected result to be exactly 32 bytes but received {}",
result.len()
);

// copy values into state and set the remaining state elements to 0
let mut state = [field::ZERO; STATE_WIDTH];
#[allow(clippy::cast_ref_to_mut)]
let state_bytes: &mut [u8; STATE_BYTES] =
unsafe { &mut *(&state as *const _ as *mut [u8; STATE_BYTES]) };
state_bytes[..values.len()].copy_from_slice(values);

// apply round function 10 times; the round function implementation is based on
// algorithm 3 from https://eprint.iacr.org/2020/1143.pdf
for i in 0..NUM_ROUNDS {
// step 1
apply_sbox(&mut state);
apply_mds(&mut state);
add_constants(&mut state, i * 2 * STATE_WIDTH);

// step 2
apply_inv_sbox(&mut state);
apply_mds(&mut state);
add_constants(&mut state, (i * 2 + 1) * STATE_WIDTH);
}

// return the result
result.copy_from_slice(as_bytes(&state[..DIGEST_SIZE]));
}

// HELPER FUNCTIONS
// ================================================================================================

#[inline(always)]
#[allow(clippy::needless_range_loop)]
fn add_constants(state: &mut [u128; STATE_WIDTH], offset: usize) {
for i in 0..STATE_WIDTH {
state[i] = add(state[i], ARK[offset + i]);
}
}

#[inline(always)]
#[allow(clippy::needless_range_loop)]
fn apply_sbox(state: &mut [u128; STATE_WIDTH]) {
for i in 0..STATE_WIDTH {
state[i] = exp(state[i], ALPHA);
}
}

#[inline(always)]
#[allow(clippy::needless_range_loop)]
fn apply_inv_sbox(state: &mut [u128; STATE_WIDTH]) {
// TODO: optimize
for i in 0..STATE_WIDTH {
state[i] = exp(state[i], INV_ALPHA);
}
}

#[inline(always)]
#[allow(clippy::needless_range_loop)]
fn apply_mds(state: &mut [u128; STATE_WIDTH]) {
let mut result = [0u128; STATE_WIDTH];
let mut temp = [0u128; STATE_WIDTH];
for i in 0..STATE_WIDTH {
for j in 0..STATE_WIDTH {
temp[j] = mul(MDS[i * STATE_WIDTH + j], state[j]);
}

for j in 0..STATE_WIDTH {
result[i] = add(result[i], temp[j]);
}
}
state.copy_from_slice(&result);
}

// CONSTANTS
// ================================================================================================

/// S-Box and Inverse S-Box powers;
/// computed using algorithm 6 from https://eprint.iacr.org/2020/1143.pdf
const ALPHA: u128 = 5;
const INV_ALPHA: u128 = 272225893536750770770699646362995969229;

/// Rescue MDS matrix
/// Computed using algorithm 4 from https://eprint.iacr.org/2020/1143.pdf
const MDS: [u128; STATE_WIDTH * STATE_WIDTH] = [
340282366920938463463374557953730612630,
21493836,
340282366920938463463374557953736934518,
914760,
340282366920938463463374557953744928504,
364,
340282366920938463463374557948521959389,
7809407397,
340282366920938463463374557950844620457,
324945621,
340282366920938463463374557953733852285,
99463,
340282366920938463463374556526559624596,
2132618407920,
340282366920938463463374557163162978137,
88084432800,
340282366920938463463374557950784345879,
25095280,
340282366920938463463374197863906102577,
537966647357139,
340282366920938463463374358646073999137,
22165576349400,
340282366920938463463374557212857010097,
6174066262,
340282366920938463463285966851139685903,
132344277849702072,
340282366920938463463325536573199985698,
5448481182864720,
340282366920938463463374376171390478291,
1506472167928,
340282366920938463441758328918057706841,
32291274613403616174,
340282366920938463451414421516665416977,
1329039099788841441,
340282366920938463463330243139804660633,
366573514642546,
];

/// Rescue round constants;
/// computed using algorithm 5 from https://eprint.iacr.org/2020/1143.pdf
const ARK: [u128; STATE_WIDTH * NUM_ROUNDS * 2] = [
232350694689151131917165570858777669544,
297138716840883070166239111380460167036,
262280230220923724082396709497064092149,
172158049344191113832187131208632037738,
49064466045797039562408393043269857959,
310779117230843293557874990285120450495,
256706820970445617734149759518940865107,
79123538858040670180278455836284339197,
78750303544367952484014721485273250812,
288861383492149579433903883762711410179,
59801749333456280387477464033868461625,
21443300235508431203706748477819269958,
58568963110264836729315799795504150465,
330748576252425315826992430477036516321,
186265990460580587588657915966473647991,
33474186560709631768594728335471560699,
158848462530608412921046130349797355353,
103951280788776493556470655637893338265,
143328281743837680325887693977200434046,
84141533915622931968833899936597847300,
8289043147167319381038668861607412243,
182690551456641207603161012621368395791,
189966993584382842241685332212477020587,
32137923394454105763485467845755642950,
37831789571282423629213813309051107559,
128553631204082467137622394929811125529,
267986778741944677472811189878493395927,
16604948458564067211433039503683613987,
336102510949899388907937615764984494068,
269515689098362827313089599343791905108,
299424679105391259942771484229152481303,
204910193356347483970850685012209050540,
297547986861132400067173315704469727918,
90994669428470088728996184833134573519,
194832530917116381832912394976136685925,
3544879195102182108390682435201981399,
339480205126523778084089852053600037139,
7584482258985997923597941079175892345,
293411952222390873312400094181647328549,
199529004542042321671242096609546451065,
67129123347758775813781826519244753478,
262358775581253675478636059962684988488,
214578730175648891816936630380713062555,
298888476681892954783673663609236117055,
28713802418311531156758766332916445632,
1440134829402109711440873134882900954,
136568912729847804743104940208565395935,
282333114631262903665175684297593586626,
179980515973143677823617972256218090691,
262324617228293661450608983002445445851,
101457408539557988072857167265007764003,
135015365700146217343913438445165565670,
160037359781136723784361845515476884821,
182530253870899012049936279038476084254,
135879876810809726132885131537021449499,
232021530889024386996643355214152586646,
145764181560102807472161589832442506602,
30096323905520593555387863391076216460,
26964230850883304384940372063347292502,
248723932438838238159920468579438468564,
294269904099379916907622037481357861347,
68547751515194812125080398554316505804,
206967528806115588933607920597265054243,
218563991130423186053843420486943196637,
271753381570791699387473121354016967661,
280821616954361601859332610476339898658,
10004341245328361103806488533574675264,
102737972201824925757345477497905200949,
181579715086871199454198713448655357907,
334443686013848360201749831728546200670,
43930702221243327593116820380585481596,
16744004758332429127464852702179311517,
310201738135125726809998762242791360596,
155126893730515639579436939964032992002,
61238650483248463229462616021804212788,
6693212157784826508674787451860949238,
197651057967963974372308220503477603713,
174221476673212934077040088950046690415,
287511813733819668564695051918836002922,
304531189544765525159398110881793396421,
276777415462914862553995344360435589651,
241036817921529641113885285343669990717,
320958231309550951576801366383624382828,
242260690344880997681123448650535822378,
201589105262974747061391276271612166799,
21009766855942890883171267876432289297,
303226336248222109074995022589884483065,
105515432862530091605210357969101266504,
235097661610089805414814372959229370626,
210361497167001742816223425802317150493,
218546747003262668455051521918398855294,
280724473534270362895764829061545243190,
179926408118748249708833901850481685351,
168859451670725335987760025077648496937,
127174659756870191527945451601624140498,
290826558340641225374953827677533570165,
];
8 changes: 8 additions & 0 deletions crypto/src/hash/rescue/mod.rs
@@ -0,0 +1,8 @@
mod single;
pub use single::rescue_s;

mod double;
pub use double::rescue_d;

#[cfg(test)]
mod tests;

0 comments on commit eb7f4fc

Please sign in to comment.