arnaucube
arnaucube/miden-cryptoPublic Self-hosted repository
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}