pub mod hash;
use crate::belt::*;
use arrayref::array_ref;
pub const DIGEST_LENGTH: usize = 5;
pub const STATE_SIZE: usize = 16;
pub const NUM_SPLIT_AND_LOOKUP: usize = 4;
pub const LOG2_STATE_SIZE: usize = 4;
pub const CAPACITY: usize = 6;
pub const RATE: usize = 10;
pub const NUM_ROUNDS: usize = 7;
pub const R: u128 = 18446744073709551616;
pub const R2: u64 = 0xfffffffe00000001;
pub const R_MOD_P: u64 = 4294967295;
pub const RP: u128 = 0xffffffff000000010000000000000000;
pub const P: u64 = 0xffffffff00000001;
const LOOKUP_TABLE: [u8; 256] = [
0, 7, 26, 63, 124, 215, 85, 254, 214, 228, 45, 185, 140, 173, 33, 240, 29, 177, 176, 32, 8,
110, 87, 202, 204, 99, 150, 106, 230, 14, 235, 128, 213, 239, 212, 138, 23, 130, 208, 6, 44,
71, 93, 116, 146, 189, 251, 81, 199, 97, 38, 28, 73, 179, 95, 84, 152, 48, 35, 119, 49, 88,
242, 3, 148, 169, 72, 120, 62, 161, 166, 83, 175, 191, 137, 19, 100, 129, 112, 55, 221, 102,
218, 61, 151, 237, 68, 164, 17, 147, 46, 234, 203, 216, 22, 141, 65, 57, 123, 12, 244, 54, 219,
231, 96, 77, 180, 154, 5, 253, 133, 165, 98, 195, 205, 134, 245, 30, 9, 188, 59, 142, 186, 197,
181, 144, 92, 31, 224, 163, 111, 74, 58, 69, 113, 196, 67, 246, 225, 10, 121, 50, 60, 157, 90,
122, 2, 250, 101, 75, 178, 159, 24, 36, 201, 11, 243, 132, 198, 190, 114, 233, 39, 52, 21, 209,
108, 238, 91, 187, 18, 104, 194, 37, 153, 34, 200, 143, 126, 155, 236, 118, 64, 80, 172, 89,
94, 193, 135, 183, 86, 107, 252, 13, 167, 206, 136, 220, 207, 103, 171, 160, 76, 182, 227, 217,
158, 56, 174, 4, 66, 109, 139, 162, 184, 211, 249, 47, 125, 232, 117, 43, 16, 42, 127, 20, 241,
25, 149, 105, 156, 51, 53, 168, 145, 247, 223, 79, 78, 226, 15, 222, 82, 115, 70, 210, 27, 41,
1, 170, 40, 131, 192, 229, 248, 255,
];
const ROUND_CONSTANTS: [u64; NUM_ROUNDS * STATE_SIZE] = [
1332676891236936200,
16607633045354064669,
12746538998793080786,
15240351333789289931,
10333439796058208418,
986873372968378050,
153505017314310505,
703086547770691416,
8522628845961587962,
1727254290898686320,
199492491401196126,
2969174933639985366,
1607536590362293391,
16971515075282501568,
15401316942841283351,
14178982151025681389,
2916963588744282587,
5474267501391258599,
5350367839445462659,
7436373192934779388,
12563531800071493891,
12265318129758141428,
6524649031155262053,
1388069597090660214,
3049665785814990091,
5225141380721656276,
10399487208361035835,
6576713996114457203,
12913805829885867278,
10299910245954679423,
12980779960345402499,
593670858850716490,
12184128243723146967,
1315341360419235257,
9107195871057030023,
4354141752578294067,
8824457881527486794,
14811586928506712910,
7768837314956434138,
2807636171572954860,
9487703495117094125,
13452575580428891895,
14689488045617615844,
16144091782672017853,
15471922440568867245,
17295382518415944107,
15054306047726632486,
5708955503115886019,
9596017237020520842,
16520851172964236909,
8513472793890943175,
8503326067026609602,
9402483918549940854,
8614816312698982446,
7744830563717871780,
14419404818700162041,
8090742384565069824,
15547662568163517559,
17314710073626307254,
10008393716631058961,
14480243402290327574,
13569194973291808551,
10573516815088946209,
15120483436559336219,
3515151310595301563,
1095382462248757907,
5323307938514209350,
14204542692543834582,
12448773944668684656,
13967843398310696452,
14838288394107326806,
13718313940616442191,
15032565440414177483,
13769903572116157488,
17074377440395071208,
16931086385239297738,
8723550055169003617,
590842605971518043,
16642348030861036090,
10708719298241282592,
12766914315707517909,
11780889552403245587,
113183285481780712,
9019899125655375514,
3300264967390964820,
12802381622653377935,
891063765000023873,
15939045541699412539,
3240223189948727743,
4087221142360949772,
10980466041788253952,
18199914337033135244,
7168108392363190150,
16860278046098150740,
13088202265571714855,
4712275036097525581,
16338034078141228133,
1455012125527134274,
5024057780895012002,
9289161311673217186,
9401110072402537104,
11919498251456187748,
4173156070774045271,
15647643457869530627,
15642078237964257476,
1405048341078324037,
3059193199283698832,
1605012781983592984,
7134876918849821827,
5796994175286958720,
7251651436095127661,
4565856221886323991,
];
const MDS_MATRIX_I64: [[i64; STATE_SIZE]; STATE_SIZE] = [
[
61402, 17845, 26798, 59689, 12021, 40901, 41351, 27521, 56951, 12034, 53865, 43244, 7454,
33823, 28750, 1108,
],
[
1108, 61402, 17845, 26798, 59689, 12021, 40901, 41351, 27521, 56951, 12034, 53865, 43244,
7454, 33823, 28750,
],
[
28750, 1108, 61402, 17845, 26798, 59689, 12021, 40901, 41351, 27521, 56951, 12034, 53865,
43244, 7454, 33823,
],
[
33823, 28750, 1108, 61402, 17845, 26798, 59689, 12021, 40901, 41351, 27521, 56951, 12034,
53865, 43244, 7454,
],
[
7454, 33823, 28750, 1108, 61402, 17845, 26798, 59689, 12021, 40901, 41351, 27521, 56951,
12034, 53865, 43244,
],
[
43244, 7454, 33823, 28750, 1108, 61402, 17845, 26798, 59689, 12021, 40901, 41351, 27521,
56951, 12034, 53865,
],
[
53865, 43244, 7454, 33823, 28750, 1108, 61402, 17845, 26798, 59689, 12021, 40901, 41351,
27521, 56951, 12034,
],
[
12034, 53865, 43244, 7454, 33823, 28750, 1108, 61402, 17845, 26798, 59689, 12021, 40901,
41351, 27521, 56951,
],
[
56951, 12034, 53865, 43244, 7454, 33823, 28750, 1108, 61402, 17845, 26798, 59689, 12021,
40901, 41351, 27521,
],
[
27521, 56951, 12034, 53865, 43244, 7454, 33823, 28750, 1108, 61402, 17845, 26798, 59689,
12021, 40901, 41351,
],
[
41351, 27521, 56951, 12034, 53865, 43244, 7454, 33823, 28750, 1108, 61402, 17845, 26798,
59689, 12021, 40901,
],
[
40901, 41351, 27521, 56951, 12034, 53865, 43244, 7454, 33823, 28750, 1108, 61402, 17845,
26798, 59689, 12021,
],
[
12021, 40901, 41351, 27521, 56951, 12034, 53865, 43244, 7454, 33823, 28750, 1108, 61402,
17845, 26798, 59689,
],
[
59689, 12021, 40901, 41351, 27521, 56951, 12034, 53865, 43244, 7454, 33823, 28750, 1108,
61402, 17845, 26798,
],
[
26798, 59689, 12021, 40901, 41351, 27521, 56951, 12034, 53865, 43244, 7454, 33823, 28750,
1108, 61402, 17845,
],
[
17845, 26798, 59689, 12021, 40901, 41351, 27521, 56951, 12034, 53865, 43244, 7454, 33823,
28750, 1108, 61402,
],
];
pub fn permute(sponge: &mut [u64; 16]) {
for i in 0..NUM_ROUNDS {
let a = sbox_layer(array_ref![sponge, 0, STATE_SIZE]);
let b = linear_layer(&a);
for j in 0..STATE_SIZE {
let r_cons = (((ROUND_CONSTANTS[i * STATE_SIZE + j] as u128) * R) % PRIME_128) as u64;
sponge[j] = badd(r_cons, b[j]);
}
}
}
fn sbox_layer(state: &[u64; STATE_SIZE]) -> [u64; STATE_SIZE] {
let mut res: [u64; STATE_SIZE] = [0; STATE_SIZE];
for i in 0..NUM_SPLIT_AND_LOOKUP {
let mut bytes = state[i].to_le_bytes();
for i in 0..8 {
bytes[i] = LOOKUP_TABLE[bytes[i] as usize];
}
res[i] = u64::from_le_bytes(bytes);
}
for j in NUM_SPLIT_AND_LOOKUP..STATE_SIZE {
res[j] = bpow(state[j], 7);
}
res
}
fn linear_layer(state: &[u64; 16]) -> [u64; 16] {
let mut result = [0u64; 16];
for i in 0..16 {
for j in 0..16 {
let matrix_element = MDS_MATRIX_I64[i][j] as u64;
let product = bmul(matrix_element, state[j]);
result[i] = badd(result[i], product);
}
}
result
}