miden-crypto/crypto/src/hash/rpo/tests.rs
crypto/src/hash/rpo/tests.rsRaw
1use super::{
2 ElementHasher, Felt, FieldElement, HashFn, Rpo, RpoDigest256, StarkField, ALPHA, INV_ALPHA,
3 INV_MDS, MDS, STATE_WIDTH, ZERO,
4};
5
6use core::convert::TryInto;
7
8use rand_utils::rand_value;
9
10#[test]
11fn mds_inv_test() {
12 let mut mul_result = [[Felt::new(0); STATE_WIDTH]; STATE_WIDTH];
13 for i in 0..STATE_WIDTH {
14 for j in 0..STATE_WIDTH {
15 let result = {
16 let mut result = Felt::new(0);
17 for k in 0..STATE_WIDTH {
18 result += MDS[i][k] * INV_MDS[k][j]
19 }
20 result
21 };
22 mul_result[i][j] = result;
23 if i == j {
24 assert_eq!(result, Felt::new(1));
25 } else {
26 assert_eq!(result, Felt::new(0));
27 }
28 }
29 }
30}
31#[test]
32fn test_alphas() {
33 let e: Felt = Felt::new(rand_value());
34 let e_exp = e.exp(ALPHA.into());
35 assert_eq!(e, e_exp.exp(INV_ALPHA));
36}
37
38#[test]
39fn test_sbox() {
40 let state = [Felt::new(rand_value()); STATE_WIDTH];
41
42 let mut expected = state;
43 expected.iter_mut().for_each(|v| *v = v.exp(ALPHA));
44
45 let mut actual = state;
46 Rpo::apply_sbox(&mut actual);
47
48 assert_eq!(expected, actual);
49}
50
51#[test]
52fn test_inv_sbox() {
53 let state = [Felt::new(rand_value()); STATE_WIDTH];
54
55 let mut expected = state;
56 expected.iter_mut().for_each(|v| *v = v.exp(INV_ALPHA));
57
58 let mut actual = state;
59 Rpo::apply_inv_sbox(&mut actual);
60
61 assert_eq!(expected, actual);
62}
63
64#[test]
65fn hash_elements_vs_merge() {
66 let elements = [Felt::new(rand_value()); 8];
67
68 let digests: [RpoDigest256; 2] = [
69 RpoDigest256::new(elements[..4].try_into().unwrap()),
70 RpoDigest256::new(elements[4..].try_into().unwrap()),
71 ];
72
73 let m_result = Rpo::merge(&digests);
74 let h_result = Rpo::hash_elements(&elements);
75 assert_eq!(m_result, h_result);
76}
77
78#[test]
79fn hash_elements_vs_merge_with_int() {
80 let tmp = [Felt::new(rand_value()); 4];
81 let seed = RpoDigest256::new(tmp);
82
83 // ----- value fits into a field element ------------------------------------------------------
84 let val: Felt = Felt::new(rand_value());
85 let m_result = Rpo::merge_with_int(seed, val.as_int());
86
87 let mut elements = seed.as_elements().to_vec();
88 elements.push(val);
89 let h_result = Rpo::hash_elements(&elements);
90
91 assert_eq!(m_result, h_result);
92
93 // ----- value does not fit into a field element ----------------------------------------------
94 let val = Felt::MODULUS + 2;
95 let m_result = Rpo::merge_with_int(seed, val);
96
97 let mut elements = seed.as_elements().to_vec();
98 elements.push(Felt::new(val));
99 elements.push(Felt::new(1));
100 let h_result = Rpo::hash_elements(&elements);
101
102 assert_eq!(m_result, h_result);
103}
104
105#[test]
106fn hash_padding() {
107 // adding a zero bytes at the end of a byte string should result in a different hash
108 let r1 = Rpo::hash(&[1_u8, 2, 3]);
109 let r2 = Rpo::hash(&[1_u8, 2, 3, 0]);
110 assert_ne!(r1, r2);
111
112 // same as above but with bigger inputs
113 let r1 = Rpo::hash(&[1_u8, 2, 3, 4, 5, 6]);
114 let r2 = Rpo::hash(&[1_u8, 2, 3, 4, 5, 6, 0]);
115 assert_ne!(r1, r2);
116
117 // same as above but with input splitting over two elements
118 let r1 = Rpo::hash(&[1_u8, 2, 3, 4, 5, 6, 7]);
119 let r2 = Rpo::hash(&[1_u8, 2, 3, 4, 5, 6, 7, 0]);
120 assert_ne!(r1, r2);
121
122 // same as above but with multiple zeros
123 let r1 = Rpo::hash(&[1_u8, 2, 3, 4, 5, 6, 7, 0, 0]);
124 let r2 = Rpo::hash(&[1_u8, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0]);
125 assert_ne!(r1, r2);
126}
127
128#[test]
129fn hash_elements_padding() {
130 let e1 = [Felt::new(rand_value()); 2];
131 let e2 = [e1[0], e1[1], ZERO];
132
133 let r1 = Rpo::hash_elements(&e1);
134 let r2 = Rpo::hash_elements(&e2);
135 assert_ne!(r1, r2);
136}
137
138#[test]
139fn hash_elements() {
140 let elements = [
141 Felt::new(0),
142 Felt::new(1),
143 Felt::new(2),
144 Felt::new(3),
145 Felt::new(4),
146 Felt::new(5),
147 Felt::new(6),
148 Felt::new(7),
149 ];
150
151 let digests: [RpoDigest256; 2] = [
152 RpoDigest256::new(elements[..4].try_into().unwrap()),
153 RpoDigest256::new(elements[4..8].try_into().unwrap()),
154 ];
155
156 let m_result = Rpo::merge(&digests);
157 let h_result = Rpo::hash_elements(&elements);
158 assert_eq!(m_result, h_result);
159}