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