1use {
4 ark_bn254::Fr,
5 ark_ff::{BigInt, Field, PrimeField},
6 seq_macro::seq,
7 std::{mem::swap, sync::LazyLock},
8 zerocopy::transmute,
9};
10
11seq!(I in 0..18 {
13 const ROUND_CONSTANTS: [Fr; 18] = [
14 #(Fr::new(BigInt(crate::constants::ROUND_CONSTANTS[I])), )*
15 ];
16});
17
18static SIGMA_INV: LazyLock<Fr> = LazyLock::new(|| {
23 "9915499612839321149637521777990102151350674507940716049588462388200839649614"
24 .parse()
25 .expect("valid field element")
26});
27
28pub fn compress_many(messages: &[u8], hashes: &mut [u8]) {
29 assert_eq!(messages.len() % 64, 0);
30 assert_eq!(hashes.len() % 32, 0);
31 assert_eq!(messages.len(), hashes.len() * 2);
32 for (message, hash) in messages.chunks_exact(64).zip(hashes.chunks_exact_mut(32)) {
33 let message: [u8; 64] = message.try_into().unwrap();
34 let [l, r] = transmute!(message);
35 let h = compress(l, r);
36 let h: [u8; 32] = transmute!(h);
37 hash.copy_from_slice(h.as_slice());
38 }
39}
40
41pub fn compress(l: [u64; 4], r: [u64; 4]) -> [u64; 4] {
42 let (l, r) = (Fr::new(BigInt(l)), Fr::new(BigInt(r)));
43 let t = l;
44 let (l, _) = permute(l, r);
45 (l + t).into_bigint().0
46}
47
48pub fn permute(l: Fr, r: Fr) -> (Fr, Fr) {
50 let (l, r) = ss(0, l, r);
51 let (l, r) = ss(2, l, r);
52 let (l, r) = ss(4, l, r);
53 let (l, r) = bb(6, l, r);
54 let (l, r) = ss(8, l, r);
55 let (l, r) = bb(10, l, r);
56 let (l, r) = ss(12, l, r);
57 let (l, r) = ss(14, l, r);
58 let (l, r) = ss(16, l, r);
59 (l, r)
60}
61
62fn ss(round: usize, mut l: Fr, mut r: Fr) -> (Fr, Fr) {
64 r += l.square() * *SIGMA_INV + ROUND_CONSTANTS[round];
65 swap(&mut l, &mut r);
66 r += l.square() * *SIGMA_INV + ROUND_CONSTANTS[round + 1];
67 swap(&mut l, &mut r);
68 (l, r)
69}
70
71fn bb(round: usize, mut l: Fr, mut r: Fr) -> (Fr, Fr) {
73 r += bar(l) + ROUND_CONSTANTS[round];
74 swap(&mut l, &mut r);
75 r += bar(l) + ROUND_CONSTANTS[round + 1];
76 swap(&mut l, &mut r);
77 (l, r)
78}
79
80fn bar(x: Fr) -> Fr {
81 let limbs: [u64; 4] = x.into_bigint().0;
83 let mut bytes: [u8; 32] = transmute!(limbs);
84
85 let (l, r) = bytes.split_at_mut(16);
87 l.swap_with_slice(r);
88
89 let bytes = bytes.map(sbox);
91
92 Fr::from_le_bytes_mod_order(bytes.as_slice())
94}
95
96pub fn sbox(v: u8) -> u8 {
97 (v ^ ((!v).rotate_left(1) & v.rotate_left(2) & v.rotate_left(3))).rotate_left(1)
98}
99
100#[cfg(test)]
101mod tests {
102 use {super::*, ark_ff::AdditiveGroup};
103
104 #[test]
105 fn test_ss_2() {
106 let l = "11818428481613126259506041491792444971306025298632020312923851211664140080269"
108 .parse()
109 .unwrap();
110 let r = "16089984100220651117533376273482359701319211672522891227502963383930673183481"
111 .parse()
112 .unwrap();
113 let el = "2897520731550929941842826131888578795995028656093850302425034320680216166225"
114 .parse()
115 .unwrap();
116 let er = "10274752619072178425540318899508997829349102488123199431506343228471746115261"
117 .parse()
118 .unwrap();
119 let (l, r) = ss(2, l, r);
120 assert_eq!(l, el);
121 assert_eq!(r, er);
122 }
123
124 #[test]
125 fn test_sbox() {
126 assert_eq!(sbox(0xcd), 0xd3);
128 assert_eq!(sbox(0x17), 0x0e);
129 assert_eq!(sbox(0x83), 0x17);
130 assert_eq!(sbox(0x14), 0x28);
131 assert_eq!(sbox(0x2b), 0x46);
132 assert_eq!(sbox(0x1e), 0xbc);
133 }
134
135 #[test]
136 fn test_bb_6() {
137 let l = "13251711941470795978907268022756015766767985221093713388330058285942871890923"
138 .parse()
139 .unwrap();
140 let r = "1017722258958995329580328739423576514309327442471989504101393158056883989572"
141 .parse()
142 .unwrap();
143 let el = "3193610555912363022088172260048956988022957239290210718020144819371540058981"
144 .parse()
145 .unwrap();
146 let er = "17363210535454321713488811303876243393424286347736908007836172565366081010820"
147 .parse()
148 .unwrap();
149 let (l, r) = bb(6, l, r);
150 assert_eq!(l, el);
151 assert_eq!(r, er);
152 }
153
154 #[test]
155 fn test_zero() {
156 let l = Fr::ZERO;
158 let r = Fr::ZERO;
159 let el = "5793276905781313965269111743763131906666794041798623267477617572701829069290"
160 .parse()
161 .unwrap();
162 let er = "12296274483727574983376829575121280934973829438414198530604912453551798647077"
163 .parse()
164 .unwrap();
165 let (l, r) = permute(l, r);
166 assert_eq!(l, el);
167 assert_eq!(r, er);
168 }
169
170 #[test]
171 fn test_random() {
172 let l = "50417215636675310123686652273432694184389644587803328798109154235492038730484"
174 .parse()
175 .unwrap();
176 let r = "14620920779025509970947930308416120371903474543120179490887326852503500806990"
177 .parse()
178 .unwrap();
179 let el = "8412949970293910117511617126618515787729842528183672400383899220234743146062"
180 .parse()
181 .unwrap();
182 let er = "11868175801025513844525564200589229804433722826344843184417708742749423276015"
183 .parse()
184 .unwrap();
185 let (l, r) = permute(l, r);
186 assert_eq!(l, el);
187 assert_eq!(r, er);
188 }
189}