Skip to main content

qssm_le/
crs.rs

1//! Transparent CRS: ring element \(A\) from `BLAKE3(DOMAIN_LE ‖ crs_seed)`.
2#![forbid(unsafe_code)]
3
4use qssm_utils::hashing::{hash_domain, DOMAIN_LE};
5
6use crate::algebra::ring::RqPoly;
7use crate::protocol::params::{N, Q};
8
9/// Verifying / proving key material (nothing-up-my-sleeve seed).
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub struct VerifyingKey {
12    pub crs_seed: [u8; 32],
13}
14
15impl VerifyingKey {
16    pub fn from_seed(crs_seed: [u8; 32]) -> Self {
17        Self { crs_seed }
18    }
19
20    /// Expand into a pseudorandom ring element \(A \in R_q\).
21    pub fn matrix_a_poly(&self) -> RqPoly {
22        let mut coeffs = [0u32; N];
23        for (i, c) in coeffs.iter_mut().enumerate() {
24            let ib = (i as u32).to_le_bytes();
25            let buf = hash_domain(
26                DOMAIN_LE,
27                &[b"A_row", self.crs_seed.as_slice(), ib.as_slice()],
28            );
29            let mut w = [0u8; 4];
30            w.copy_from_slice(&buf[..4]);
31            *c = u32::from_le_bytes(w) % Q;
32        }
33        RqPoly(coeffs)
34    }
35}