cairo_vm/hint_processor/builtin_hint_processor/
blake2s_hash.rs

1use crate::stdlib::{ops::Shl, prelude::*};
2
3pub const IV: [u32; 8] = [
4    0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19,
5];
6
7const SIGMA: [[usize; 16]; 10] = [
8    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
9    [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3],
10    [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4],
11    [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8],
12    [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13],
13    [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9],
14    [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11],
15    [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10],
16    [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5],
17    [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0],
18];
19
20fn right_rot(value: u32, n: u32) -> u32 {
21    (value >> n) | ((value & (1_u32.shl(n) - 1)) << (32 - n))
22}
23
24fn mix(a: u32, b: u32, c: u32, d: u32, m0: u32, m1: u32) -> (u32, u32, u32, u32) {
25    let a = a.wrapping_add(b).wrapping_add(m0);
26    let d = right_rot(d ^ a, 16);
27    let c = c.wrapping_add(d);
28    let b = right_rot(b ^ c, 12);
29    let a = a.wrapping_add(b).wrapping_add(m1);
30    let d = right_rot(d ^ a, 8);
31    let c = c.wrapping_add(d);
32    let b = right_rot(b ^ c, 7);
33    (a, b, c, d)
34}
35
36fn blake_round(mut state: Vec<u32>, message: &[u32; 16], sigma: [usize; 16]) -> Vec<u32> {
37    (state[0], state[4], state[8], state[12]) = mix(
38        state[0],
39        state[4],
40        state[8],
41        state[12],
42        message[sigma[0]],
43        message[sigma[1]],
44    );
45    (state[1], state[5], state[9], state[13]) = mix(
46        state[1],
47        state[5],
48        state[9],
49        state[13],
50        message[sigma[2]],
51        message[sigma[3]],
52    );
53    (state[2], state[6], state[10], state[14]) = mix(
54        state[2],
55        state[6],
56        state[10],
57        state[14],
58        message[sigma[4]],
59        message[sigma[5]],
60    );
61    (state[3], state[7], state[11], state[15]) = mix(
62        state[3],
63        state[7],
64        state[11],
65        state[15],
66        message[sigma[6]],
67        message[sigma[7]],
68    );
69    (state[0], state[5], state[10], state[15]) = mix(
70        state[0],
71        state[5],
72        state[10],
73        state[15],
74        message[sigma[8]],
75        message[sigma[9]],
76    );
77    (state[1], state[6], state[11], state[12]) = mix(
78        state[1],
79        state[6],
80        state[11],
81        state[12],
82        message[sigma[10]],
83        message[sigma[11]],
84    );
85    (state[2], state[7], state[8], state[13]) = mix(
86        state[2],
87        state[7],
88        state[8],
89        state[13],
90        message[sigma[12]],
91        message[sigma[13]],
92    );
93    (state[3], state[4], state[9], state[14]) = mix(
94        state[3],
95        state[4],
96        state[9],
97        state[14],
98        message[sigma[14]],
99        message[sigma[15]],
100    );
101    state
102}
103
104pub fn blake2s_compress(
105    h: &[u32; 8],
106    message: &[u32; 16],
107    t0: u32,
108    t1: u32,
109    f0: u32,
110    f1: u32,
111) -> Vec<u32> {
112    let mut state = h.to_vec();
113    state.extend(&IV[0..4]);
114    state.extend(&vec![
115        (IV[4] ^ t0),
116        (IV[5] ^ t1),
117        (IV[6] ^ f0),
118        (IV[7] ^ f1),
119    ]);
120    for sigma_list in SIGMA {
121        state = blake_round(state, message, sigma_list);
122    }
123    let mut new_state = Vec::<u32>::new();
124    for i in 0..8 {
125        new_state.push(h[i] ^ state[i] ^ state[8 + i]);
126    }
127    new_state
128}
129
130#[cfg(test)]
131mod tests {
132    use super::*;
133
134    #[cfg(target_arch = "wasm32")]
135    use wasm_bindgen_test::*;
136
137    #[test]
138    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
139    fn blake2s_compress_test_a() {
140        let h: [u32; 8] = [
141            1795745351, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635,
142            1541459225,
143        ];
144        let message: [u32; 16] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
145        let new_state: [u32; 8] = blake2s_compress(&h, &message, 2, 0, 4294967295, 0)
146            .try_into()
147            .unwrap();
148        assert_eq!(
149            new_state,
150            [
151                412110711, 3234706100, 3894970767, 982912411, 937789635, 742982576, 3942558313,
152                1407547065
153            ]
154        )
155    }
156
157    #[test]
158    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
159    fn blake2s_compress_test_b() {
160        let h: [u32; 8] = [
161            1795745351, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635,
162            1541459225,
163        ];
164        let message: [u32; 16] = [456710651, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
165        let new_state: [u32; 8] = blake2s_compress(&h, &message, 2, 0, 4294967295, 0)
166            .try_into()
167            .unwrap();
168        assert_eq!(
169            new_state,
170            [
171                1061041453, 3663967611, 2158760218, 836165556, 3696892209, 3887053585, 2675134684,
172                2201582556
173            ]
174        )
175    }
176
177    #[test]
178    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
179    fn blake2s_compress_test_c() {
180        //Hashing "Hello World"
181        let h: [u32; 8] = [
182            1795745351, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635,
183            1541459225,
184        ];
185        let message: [u32; 16] = [
186            1819043144, 1870078063, 6581362, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
187        ];
188        let new_state: [u32; 8] = blake2s_compress(&h, &message, 9, 0, 4294967295, 0)
189            .try_into()
190            .unwrap();
191        assert_eq!(
192            new_state,
193            [
194                939893662, 3935214984, 1704819782, 3912812968, 4211807320, 3760278243, 674188535,
195                2642110762
196            ]
197        )
198    }
199
200    #[test]
201    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
202    fn blake2s_compress_test_d() {
203        let h: [u32; 8] = [
204            1795745351, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635,
205            1541459225,
206        ];
207        let message: [u32; 16] = [
208            1819043144, 1870078063, 6581362, 274628678, 715791845, 175498643, 871587583, 0, 0, 0,
209            0, 0, 0, 0, 0, 0,
210        ];
211        let new_state: [u32; 8] = blake2s_compress(&h, &message, 28, 0, 4294967295, 0)
212            .try_into()
213            .unwrap();
214        assert_eq!(
215            new_state,
216            [
217                3980510537, 3982966407, 1593299263, 2666882356, 3288094120, 2682988286, 1666615862,
218                378086837
219            ]
220        )
221    }
222
223    #[test]
224    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
225    fn blake2s_compress_test_e() {
226        let h: [u32; 8] = [
227            1795745351, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635,
228            1541459225,
229        ];
230        let message: [u32; 16] = [
231            1819043144, 1870078063, 6581362, 274628678, 715791845, 175498643, 871587583, 635963558,
232            557369694, 1576875962, 215769785, 0, 0, 0, 0, 0,
233        ];
234        let new_state: [u32; 8] = blake2s_compress(&h, &message, 44, 0, 4294967295, 0)
235            .try_into()
236            .unwrap();
237        assert_eq!(
238            new_state,
239            [
240                3251785223, 1946079609, 2665255093, 3508191500, 3630835628, 3067307230, 3623370123,
241                656151356
242            ]
243        )
244    }
245
246    #[test]
247    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
248    fn blake2s_compress_test_f() {
249        let h: [u32; 8] = [
250            1795745351, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635,
251            1541459225,
252        ];
253        let message: [u32; 16] = [
254            1819043144, 1870078063, 6581362, 274628678, 715791845, 175498643, 871587583, 635963558,
255            557369694, 1576875962, 215769785, 152379578, 585849303, 764739320, 437383930, 74833930,
256        ];
257        let new_state: [u32; 8] = blake2s_compress(&h, &message, 64, 0, 4294967295, 0)
258            .try_into()
259            .unwrap();
260        assert_eq!(
261            new_state,
262            [
263                2593218707, 3238077801, 914875393, 3462286058, 4028447058, 3174734057, 2001070146,
264                3741410512
265            ]
266        )
267    }
268
269    #[test]
270    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
271    fn blake2s_compress_test_g() {
272        let h: [u32; 8] = [
273            1795745351, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635,
274            1541459225,
275        ];
276        let message: [u32; 16] = [
277            11563522, 43535528, 653255322, 274628678, 73471943, 17549868, 87158958, 635963558,
278            343656565, 1576875962, 215769785, 152379578, 585849303, 76473202, 437253230, 74833930,
279        ];
280        let new_state: [u32; 8] = blake2s_compress(&h, &message, 64, 0, 4294967295, 0)
281            .try_into()
282            .unwrap();
283        assert_eq!(
284            new_state,
285            [
286                3496615692, 3252241979, 3771521549, 2125493093, 3240605752, 2885407061, 3962009872,
287                3845288240
288            ]
289        )
290    }
291}