light_hasher/
bigint.rs

1use num_bigint::BigUint;
2
3use crate::HasherError;
4
5/// Converts the given [`num_bigint::BigUint`](num_bigint::BigUint) into a little-endian
6/// byte array.
7pub fn bigint_to_le_bytes_array<const BYTES_SIZE: usize>(
8    bigint: &BigUint,
9) -> Result<[u8; BYTES_SIZE], HasherError> {
10    let mut array = [0u8; BYTES_SIZE];
11    let bytes = bigint.to_bytes_le();
12
13    if bytes.len() > BYTES_SIZE {
14        return Err(HasherError::InvalidInputLength(BYTES_SIZE, bytes.len()));
15    }
16
17    array[..bytes.len()].copy_from_slice(bytes.as_slice());
18    Ok(array)
19}
20
21/// Converts the given [`ark_ff::BigUint`](ark_ff::BigUint) into a big-endian
22/// byte array.
23pub fn bigint_to_be_bytes_array<const BYTES_SIZE: usize>(
24    bigint: &BigUint,
25) -> Result<[u8; BYTES_SIZE], HasherError> {
26    let mut array = [0u8; BYTES_SIZE];
27    let bytes = bigint.to_bytes_be();
28
29    if bytes.len() > BYTES_SIZE {
30        return Err(HasherError::InvalidInputLength(BYTES_SIZE, bytes.len()));
31    }
32
33    let start_pos = BYTES_SIZE - bytes.len();
34    array[start_pos..].copy_from_slice(bytes.as_slice());
35    Ok(array)
36}
37
38#[cfg(test)]
39mod test {
40    use num_bigint::{RandBigInt, ToBigUint};
41    use rand::thread_rng;
42
43    use super::*;
44
45    const ITERATIONS: usize = 64;
46
47    #[test]
48    fn test_bigint_conversion_rand() {
49        let mut rng = thread_rng();
50
51        for _ in 0..ITERATIONS {
52            let b64 = rng.gen_biguint(32);
53            let b64_converted: [u8; 8] = bigint_to_be_bytes_array(&b64).unwrap();
54            let b64_converted = BigUint::from_bytes_be(&b64_converted);
55            assert_eq!(b64, b64_converted);
56            let b64_converted: [u8; 8] = bigint_to_le_bytes_array(&b64).unwrap();
57            let b64_converted = BigUint::from_bytes_le(&b64_converted);
58            assert_eq!(b64, b64_converted);
59
60            let b128 = rng.gen_biguint(128);
61            let b128_converted: [u8; 16] = bigint_to_be_bytes_array(&b128).unwrap();
62            let b128_converted = BigUint::from_bytes_be(&b128_converted);
63            assert_eq!(b128, b128_converted);
64            let b128_converted: [u8; 16] = bigint_to_le_bytes_array(&b128).unwrap();
65            let b128_converted = BigUint::from_bytes_le(&b128_converted);
66            assert_eq!(b128, b128_converted);
67
68            let b256 = rng.gen_biguint(256);
69            let b256_converted: [u8; 32] = bigint_to_be_bytes_array(&b256).unwrap();
70            let b256_converted = BigUint::from_bytes_be(&b256_converted);
71            assert_eq!(b256, b256_converted);
72            let b256_converted: [u8; 32] = bigint_to_le_bytes_array(&b256).unwrap();
73            let b256_converted = BigUint::from_bytes_le(&b256_converted);
74            assert_eq!(b256, b256_converted);
75
76            let b320 = rng.gen_biguint(320);
77            let b320_converted: [u8; 40] = bigint_to_be_bytes_array(&b320).unwrap();
78            let b320_converted = BigUint::from_bytes_be(&b320_converted);
79            assert_eq!(b320, b320_converted);
80            let b320_converted: [u8; 40] = bigint_to_le_bytes_array(&b320).unwrap();
81            let b320_converted = BigUint::from_bytes_le(&b320_converted);
82            assert_eq!(b320, b320_converted);
83
84            let b384 = rng.gen_biguint(384);
85            let b384_converted: [u8; 48] = bigint_to_be_bytes_array(&b384).unwrap();
86            let b384_converted = BigUint::from_bytes_be(&b384_converted);
87            assert_eq!(b384, b384_converted);
88            let b384_converted: [u8; 48] = bigint_to_le_bytes_array(&b384).unwrap();
89            let b384_converted = BigUint::from_bytes_le(&b384_converted);
90            assert_eq!(b384, b384_converted);
91
92            let b448 = rng.gen_biguint(448);
93            let b448_converted: [u8; 56] = bigint_to_be_bytes_array(&b448).unwrap();
94            let b448_converted = BigUint::from_bytes_be(&b448_converted);
95            assert_eq!(b448, b448_converted);
96            let b448_converted: [u8; 56] = bigint_to_le_bytes_array(&b448).unwrap();
97            let b448_converted = BigUint::from_bytes_le(&b448_converted);
98            assert_eq!(b448, b448_converted);
99
100            let b768 = rng.gen_biguint(768);
101            let b768_converted: [u8; 96] = bigint_to_be_bytes_array(&b768).unwrap();
102            let b768_converted = BigUint::from_bytes_be(&b768_converted);
103            assert_eq!(b768, b768_converted);
104            let b768_converted: [u8; 96] = bigint_to_le_bytes_array(&b768).unwrap();
105            let b768_converted = BigUint::from_bytes_le(&b768_converted);
106            assert_eq!(b768, b768_converted);
107
108            let b832 = rng.gen_biguint(832);
109            let b832_converted: [u8; 104] = bigint_to_be_bytes_array(&b832).unwrap();
110            let b832_converted = BigUint::from_bytes_be(&b832_converted);
111            assert_eq!(b832, b832_converted);
112            let b832_converted: [u8; 104] = bigint_to_le_bytes_array(&b832).unwrap();
113            let b832_converted = BigUint::from_bytes_le(&b832_converted);
114            assert_eq!(b832, b832_converted);
115        }
116    }
117
118    #[test]
119    fn test_bigint_conversion_zero() {
120        let zero = 0_u32.to_biguint().unwrap();
121
122        let b64_converted: [u8; 8] = bigint_to_be_bytes_array(&zero).unwrap();
123        let b64_converted = BigUint::from_bytes_be(&b64_converted);
124        assert_eq!(zero, b64_converted);
125        let b64_converted: [u8; 8] = bigint_to_le_bytes_array(&zero).unwrap();
126        let b64_converted = BigUint::from_bytes_le(&b64_converted);
127        assert_eq!(zero, b64_converted);
128
129        let b128_converted: [u8; 16] = bigint_to_be_bytes_array(&zero).unwrap();
130        let b128_converted = BigUint::from_bytes_be(&b128_converted);
131        assert_eq!(zero, b128_converted);
132        let b128_converted: [u8; 16] = bigint_to_le_bytes_array(&zero).unwrap();
133        let b128_converted = BigUint::from_bytes_le(&b128_converted);
134        assert_eq!(zero, b128_converted);
135
136        let b256_converted: [u8; 32] = bigint_to_be_bytes_array(&zero).unwrap();
137        let b256_converted = BigUint::from_bytes_be(&b256_converted);
138        assert_eq!(zero, b256_converted);
139        let b256_converted: [u8; 32] = bigint_to_le_bytes_array(&zero).unwrap();
140        let b256_converted = BigUint::from_bytes_le(&b256_converted);
141        assert_eq!(zero, b256_converted);
142
143        let b320_converted: [u8; 40] = bigint_to_be_bytes_array(&zero).unwrap();
144        let b320_converted = BigUint::from_bytes_be(&b320_converted);
145        assert_eq!(zero, b320_converted);
146        let b320_converted: [u8; 40] = bigint_to_le_bytes_array(&zero).unwrap();
147        let b320_converted = BigUint::from_bytes_le(&b320_converted);
148        assert_eq!(zero, b320_converted);
149
150        let b384_converted: [u8; 48] = bigint_to_be_bytes_array(&zero).unwrap();
151        let b384_converted = BigUint::from_bytes_be(&b384_converted);
152        assert_eq!(zero, b384_converted);
153        let b384_converted: [u8; 48] = bigint_to_le_bytes_array(&zero).unwrap();
154        let b384_converted = BigUint::from_bytes_le(&b384_converted);
155        assert_eq!(zero, b384_converted);
156
157        let b448_converted: [u8; 56] = bigint_to_be_bytes_array(&zero).unwrap();
158        let b448_converted = BigUint::from_bytes_be(&b448_converted);
159        assert_eq!(zero, b448_converted);
160        let b448_converted: [u8; 56] = bigint_to_le_bytes_array(&zero).unwrap();
161        let b448_converted = BigUint::from_bytes_le(&b448_converted);
162        assert_eq!(zero, b448_converted);
163
164        let b768_converted: [u8; 96] = bigint_to_be_bytes_array(&zero).unwrap();
165        let b768_converted = BigUint::from_bytes_be(&b768_converted);
166        assert_eq!(zero, b768_converted);
167        let b768_converted: [u8; 96] = bigint_to_le_bytes_array(&zero).unwrap();
168        let b768_converted = BigUint::from_bytes_le(&b768_converted);
169        assert_eq!(zero, b768_converted);
170
171        let b832_converted: [u8; 104] = bigint_to_be_bytes_array(&zero).unwrap();
172        let b832_converted = BigUint::from_bytes_be(&b832_converted);
173        assert_eq!(zero, b832_converted);
174        let b832_converted: [u8; 104] = bigint_to_le_bytes_array(&zero).unwrap();
175        let b832_converted = BigUint::from_bytes_le(&b832_converted);
176        assert_eq!(zero, b832_converted);
177    }
178
179    #[test]
180    fn test_bigint_conversion_one() {
181        let one = 1_u32.to_biguint().unwrap();
182
183        let b64_converted: [u8; 8] = bigint_to_be_bytes_array(&one).unwrap();
184        let b64_converted = BigUint::from_bytes_be(&b64_converted);
185        assert_eq!(one, b64_converted);
186        let b64_converted: [u8; 8] = bigint_to_le_bytes_array(&one).unwrap();
187        let b64_converted = BigUint::from_bytes_le(&b64_converted);
188        assert_eq!(one, b64_converted);
189        let b64 = BigUint::from_bytes_be(&[0, 0, 0, 0, 0, 0, 0, 1]);
190        assert_eq!(one, b64);
191        let b64 = BigUint::from_bytes_le(&[1, 0, 0, 0, 0, 0, 0, 0]);
192        assert_eq!(one, b64);
193
194        let b128_converted: [u8; 16] = bigint_to_be_bytes_array(&one).unwrap();
195        let b128_converted = BigUint::from_bytes_be(&b128_converted);
196        assert_eq!(one, b128_converted);
197        let b128_converted: [u8; 16] = bigint_to_le_bytes_array(&one).unwrap();
198        let b128_converted = BigUint::from_bytes_le(&b128_converted);
199        assert_eq!(one, b128_converted);
200
201        let b256_converted: [u8; 32] = bigint_to_be_bytes_array(&one).unwrap();
202        let b256_converted = BigUint::from_bytes_be(&b256_converted);
203        assert_eq!(one, b256_converted);
204        let b256_converted: [u8; 32] = bigint_to_le_bytes_array(&one).unwrap();
205        let b256_converted = BigUint::from_bytes_le(&b256_converted);
206        assert_eq!(one, b256_converted);
207
208        let b320_converted: [u8; 40] = bigint_to_be_bytes_array(&one).unwrap();
209        let b320_converted = BigUint::from_bytes_be(&b320_converted);
210        assert_eq!(one, b320_converted);
211        let b320_converted: [u8; 40] = bigint_to_le_bytes_array(&one).unwrap();
212        let b320_converted = BigUint::from_bytes_le(&b320_converted);
213        assert_eq!(one, b320_converted);
214
215        let b384_converted: [u8; 48] = bigint_to_be_bytes_array(&one).unwrap();
216        let b384_converted = BigUint::from_bytes_be(&b384_converted);
217        assert_eq!(one, b384_converted);
218        let b384_converted: [u8; 48] = bigint_to_le_bytes_array(&one).unwrap();
219        let b384_converted = BigUint::from_bytes_le(&b384_converted);
220        assert_eq!(one, b384_converted);
221
222        let b448_converted: [u8; 56] = bigint_to_be_bytes_array(&one).unwrap();
223        let b448_converted = BigUint::from_bytes_be(&b448_converted);
224        assert_eq!(one, b448_converted);
225        let b448_converted: [u8; 56] = bigint_to_le_bytes_array(&one).unwrap();
226        let b448_converted = BigUint::from_bytes_le(&b448_converted);
227        assert_eq!(one, b448_converted);
228
229        let b768_converted: [u8; 96] = bigint_to_be_bytes_array(&one).unwrap();
230        let b768_converted = BigUint::from_bytes_be(&b768_converted);
231        assert_eq!(one, b768_converted);
232        let b768_converted: [u8; 96] = bigint_to_le_bytes_array(&one).unwrap();
233        let b768_converted = BigUint::from_bytes_le(&b768_converted);
234        assert_eq!(one, b768_converted);
235
236        let b832_converted: [u8; 104] = bigint_to_be_bytes_array(&one).unwrap();
237        let b832_converted = BigUint::from_bytes_be(&b832_converted);
238        assert_eq!(one, b832_converted);
239        let b832_converted: [u8; 104] = bigint_to_le_bytes_array(&one).unwrap();
240        let b832_converted = BigUint::from_bytes_le(&b832_converted);
241        assert_eq!(one, b832_converted);
242    }
243
244    #[test]
245    fn test_bigint_conversion_invalid_size() {
246        let b8 = BigUint::from_bytes_be(&[1; 8]);
247        let res: Result<[u8; 1], HasherError> = bigint_to_be_bytes_array(&b8);
248        assert!(matches!(res, Err(HasherError::InvalidInputLength(1, 8))));
249        let res: Result<[u8; 7], HasherError> = bigint_to_be_bytes_array(&b8);
250        assert!(matches!(res, Err(HasherError::InvalidInputLength(7, 8))));
251        let res: Result<[u8; 8], HasherError> = bigint_to_be_bytes_array(&b8);
252        assert!(res.is_ok());
253
254        let b8 = BigUint::from_bytes_le(&[1; 8]);
255        let res: Result<[u8; 1], HasherError> = bigint_to_le_bytes_array(&b8);
256        assert!(matches!(res, Err(HasherError::InvalidInputLength(1, 8))));
257        let res: Result<[u8; 7], HasherError> = bigint_to_le_bytes_array(&b8);
258        assert!(matches!(res, Err(HasherError::InvalidInputLength(7, 8))));
259        let res: Result<[u8; 8], HasherError> = bigint_to_le_bytes_array(&b8);
260        assert!(res.is_ok());
261
262        let b16 = BigUint::from_bytes_be(&[1; 16]);
263        let res: Result<[u8; 1], HasherError> = bigint_to_be_bytes_array(&b16);
264        assert!(matches!(res, Err(HasherError::InvalidInputLength(1, 16))));
265        let res: Result<[u8; 15], HasherError> = bigint_to_be_bytes_array(&b16);
266        assert!(matches!(res, Err(HasherError::InvalidInputLength(15, 16))));
267        let res: Result<[u8; 16], HasherError> = bigint_to_be_bytes_array(&b16);
268        assert!(res.is_ok());
269
270        let b16 = BigUint::from_bytes_le(&[1; 16]);
271        let res: Result<[u8; 1], HasherError> = bigint_to_le_bytes_array(&b16);
272        assert!(matches!(res, Err(HasherError::InvalidInputLength(1, 16))));
273        let res: Result<[u8; 15], HasherError> = bigint_to_le_bytes_array(&b16);
274        assert!(matches!(res, Err(HasherError::InvalidInputLength(15, 16))));
275        let res: Result<[u8; 16], HasherError> = bigint_to_le_bytes_array(&b16);
276        assert!(res.is_ok());
277
278        let b32 = BigUint::from_bytes_be(&[1; 32]);
279        let res: Result<[u8; 1], HasherError> = bigint_to_be_bytes_array(&b32);
280        assert!(matches!(res, Err(HasherError::InvalidInputLength(1, 32))));
281        let res: Result<[u8; 31], HasherError> = bigint_to_be_bytes_array(&b32);
282        assert!(matches!(res, Err(HasherError::InvalidInputLength(31, 32))));
283        let res: Result<[u8; 32], HasherError> = bigint_to_be_bytes_array(&b32);
284        assert!(res.is_ok());
285
286        let b32 = BigUint::from_bytes_le(&[1; 32]);
287        let res: Result<[u8; 1], HasherError> = bigint_to_le_bytes_array(&b32);
288        assert!(matches!(res, Err(HasherError::InvalidInputLength(1, 32))));
289        let res: Result<[u8; 31], HasherError> = bigint_to_le_bytes_array(&b32);
290        assert!(matches!(res, Err(HasherError::InvalidInputLength(31, 32))));
291        let res: Result<[u8; 32], HasherError> = bigint_to_le_bytes_array(&b32);
292        assert!(res.is_ok());
293
294        let b64 = BigUint::from_bytes_be(&[1; 64]);
295        let res: Result<[u8; 1], HasherError> = bigint_to_be_bytes_array(&b64);
296        assert!(matches!(res, Err(HasherError::InvalidInputLength(1, 64))));
297        let res: Result<[u8; 63], HasherError> = bigint_to_be_bytes_array(&b64);
298        assert!(matches!(res, Err(HasherError::InvalidInputLength(63, 64))));
299        let res: Result<[u8; 64], HasherError> = bigint_to_be_bytes_array(&b64);
300        assert!(res.is_ok());
301
302        let b64 = BigUint::from_bytes_le(&[1; 64]);
303        let res: Result<[u8; 1], HasherError> = bigint_to_le_bytes_array(&b64);
304        assert!(matches!(res, Err(HasherError::InvalidInputLength(1, 64))));
305        let res: Result<[u8; 63], HasherError> = bigint_to_le_bytes_array(&b64);
306        assert!(matches!(res, Err(HasherError::InvalidInputLength(63, 64))));
307        let res: Result<[u8; 64], HasherError> = bigint_to_le_bytes_array(&b64);
308        assert!(res.is_ok());
309
310        let b128 = BigUint::from_bytes_be(&[1; 128]);
311        let res: Result<[u8; 1], HasherError> = bigint_to_be_bytes_array(&b128);
312        assert!(matches!(res, Err(HasherError::InvalidInputLength(1, 128))));
313        let res: Result<[u8; 127], HasherError> = bigint_to_be_bytes_array(&b128);
314        assert!(matches!(
315            res,
316            Err(HasherError::InvalidInputLength(127, 128))
317        ));
318        let res: Result<[u8; 128], HasherError> = bigint_to_be_bytes_array(&b128);
319        assert!(res.is_ok());
320
321        let b128 = BigUint::from_bytes_le(&[1; 128]);
322        let res: Result<[u8; 1], HasherError> = bigint_to_le_bytes_array(&b128);
323        assert!(matches!(res, Err(HasherError::InvalidInputLength(1, 128))));
324        let res: Result<[u8; 127], HasherError> = bigint_to_le_bytes_array(&b128);
325        assert!(matches!(
326            res,
327            Err(HasherError::InvalidInputLength(127, 128))
328        ));
329        let res: Result<[u8; 128], HasherError> = bigint_to_le_bytes_array(&b128);
330        assert!(res.is_ok());
331
332        let b256 = BigUint::from_bytes_be(&[1; 256]);
333        let res: Result<[u8; 1], HasherError> = bigint_to_be_bytes_array(&b256);
334        assert!(matches!(res, Err(HasherError::InvalidInputLength(1, 256))));
335        let res: Result<[u8; 255], HasherError> = bigint_to_be_bytes_array(&b256);
336        assert!(matches!(
337            res,
338            Err(HasherError::InvalidInputLength(255, 256))
339        ));
340        let res: Result<[u8; 256], HasherError> = bigint_to_be_bytes_array(&b256);
341        assert!(res.is_ok());
342
343        let b256 = BigUint::from_bytes_le(&[1; 256]);
344        let res: Result<[u8; 1], HasherError> = bigint_to_le_bytes_array(&b256);
345        assert!(matches!(res, Err(HasherError::InvalidInputLength(1, 256))));
346        let res: Result<[u8; 255], HasherError> = bigint_to_le_bytes_array(&b256);
347        assert!(matches!(
348            res,
349            Err(HasherError::InvalidInputLength(255, 256))
350        ));
351        let res: Result<[u8; 256], HasherError> = bigint_to_le_bytes_array(&b256);
352        assert!(res.is_ok());
353
354        let b512 = BigUint::from_bytes_be(&[1; 512]);
355        let res: Result<[u8; 1], HasherError> = bigint_to_be_bytes_array(&b512);
356        assert!(matches!(res, Err(HasherError::InvalidInputLength(1, 512))));
357        let res: Result<[u8; 511], HasherError> = bigint_to_be_bytes_array(&b512);
358        assert!(matches!(
359            res,
360            Err(HasherError::InvalidInputLength(511, 512))
361        ));
362        let res: Result<[u8; 512], HasherError> = bigint_to_be_bytes_array(&b512);
363        assert!(res.is_ok());
364
365        let b512 = BigUint::from_bytes_le(&[1; 512]);
366        let res: Result<[u8; 1], HasherError> = bigint_to_le_bytes_array(&b512);
367        assert!(matches!(res, Err(HasherError::InvalidInputLength(1, 512))));
368        let res: Result<[u8; 511], HasherError> = bigint_to_le_bytes_array(&b512);
369        assert!(matches!(
370            res,
371            Err(HasherError::InvalidInputLength(511, 512))
372        ));
373        let res: Result<[u8; 512], HasherError> = bigint_to_le_bytes_array(&b512);
374        assert!(res.is_ok());
375
376        let b768 = BigUint::from_bytes_be(&[1; 768]);
377        let res: Result<[u8; 1], HasherError> = bigint_to_be_bytes_array(&b768);
378        assert!(matches!(res, Err(HasherError::InvalidInputLength(1, 768))));
379        let res: Result<[u8; 767], HasherError> = bigint_to_be_bytes_array(&b768);
380        assert!(matches!(
381            res,
382            Err(HasherError::InvalidInputLength(767, 768))
383        ));
384        let res: Result<[u8; 768], HasherError> = bigint_to_be_bytes_array(&b768);
385        assert!(res.is_ok());
386
387        let b768 = BigUint::from_bytes_le(&[1; 768]);
388        let res: Result<[u8; 1], HasherError> = bigint_to_le_bytes_array(&b768);
389        assert!(matches!(res, Err(HasherError::InvalidInputLength(1, 768))));
390        let res: Result<[u8; 767], HasherError> = bigint_to_le_bytes_array(&b768);
391        assert!(matches!(
392            res,
393            Err(HasherError::InvalidInputLength(767, 768))
394        ));
395        let res: Result<[u8; 768], HasherError> = bigint_to_le_bytes_array(&b768);
396        assert!(res.is_ok());
397
398        let b1024 = BigUint::from_bytes_be(&[1; 1024]);
399        let res: Result<[u8; 1], HasherError> = bigint_to_be_bytes_array(&b1024);
400        assert!(matches!(res, Err(HasherError::InvalidInputLength(1, 1024))));
401        let res: Result<[u8; 1023], HasherError> = bigint_to_be_bytes_array(&b1024);
402        assert!(matches!(
403            res,
404            Err(HasherError::InvalidInputLength(1023, 1024))
405        ));
406        let res: Result<[u8; 1024], HasherError> = bigint_to_be_bytes_array(&b1024);
407        assert!(res.is_ok());
408
409        let b1024 = BigUint::from_bytes_le(&[1; 1024]);
410        let res: Result<[u8; 1], HasherError> = bigint_to_le_bytes_array(&b1024);
411        assert!(matches!(res, Err(HasherError::InvalidInputLength(1, 1024))));
412        let res: Result<[u8; 1023], HasherError> = bigint_to_le_bytes_array(&b1024);
413        assert!(matches!(
414            res,
415            Err(HasherError::InvalidInputLength(1023, 1024))
416        ));
417        let res: Result<[u8; 1024], HasherError> = bigint_to_le_bytes_array(&b1024);
418        assert!(res.is_ok());
419    }
420}