arnaucube
arnaucube/miden-cryptoPublic Self-hosted repository
miden-crypto/src/dsa/rpo_falcon512/hash_to_point.rs
src/dsa/rpo_falcon512/hash_to_point.rsRaw
 1use alloc::vec::Vec;
 2
 3use num::Zero;
 4
 5use super::{math::FalconFelt, Nonce, Polynomial, Rpo256, Word, MODULUS, N, ZERO};
 6
 7// HASH-TO-POINT FUNCTIONS
 8// ================================================================================================
 9
10/// Returns a polynomial in Z_p[x]/(phi) representing the hash of the provided message and
11/// nonce using RPO256.
12pub fn hash_to_point_rpo256(message: Word, nonce: &Nonce) -> Polynomial<FalconFelt> {
13    let mut state = [ZERO; Rpo256::STATE_WIDTH];
14
15    // absorb the nonce into the state
16    let nonce_elements = nonce.to_elements();
17    for (&n, s) in nonce_elements.iter().zip(state[Rpo256::RATE_RANGE].iter_mut()) {
18        *s = n;
19    }
20    Rpo256::apply_permutation(&mut state);
21
22    // absorb message into the state
23    for (&m, s) in message.iter().zip(state[Rpo256::RATE_RANGE].iter_mut()) {
24        *s = m;
25    }
26
27    // squeeze the coefficients of the polynomial
28    let mut i = 0;
29    let mut res = [FalconFelt::zero(); N];
30    for _ in 0..64 {
31        Rpo256::apply_permutation(&mut state);
32        for a in &state[Rpo256::RATE_RANGE] {
33            res[i] = FalconFelt::new((a.as_int() % MODULUS as u64) as i16);
34            i += 1;
35        }
36    }
37
38    Polynomial::new(res.to_vec())
39}
40
41/// Returns a polynomial in Z_p[x]/(phi) representing the hash of the provided message and
42/// nonce using SHAKE256. This is the hash-to-point algorithm used in the reference implementation.
43#[allow(dead_code)]
44pub fn hash_to_point_shake256(message: &[u8], nonce: &Nonce) -> Polynomial<FalconFelt> {
45    use sha3::{
46        digest::{ExtendableOutput, Update, XofReader},
47        Shake256,
48    };
49
50    let mut data = vec![];
51    data.extend_from_slice(nonce.as_bytes());
52    data.extend_from_slice(message);
53    const K: u32 = (1u32 << 16) / MODULUS as u32;
54
55    let mut hasher = Shake256::default();
56    hasher.update(&data);
57    let mut reader = hasher.finalize_xof();
58
59    let mut coefficients: Vec<FalconFelt> = Vec::with_capacity(N);
60    while coefficients.len() != N {
61        let mut randomness = [0u8; 2];
62        reader.read(&mut randomness);
63        let t = ((randomness[0] as u32) << 8) | (randomness[1] as u32);
64        if t < K * MODULUS as u32 {
65            coefficients.push(FalconFelt::new((t % MODULUS as u32) as i16));
66        }
67    }
68
69    Polynomial { coefficients }
70}