penumbra_sdk_shielded_pool/
rseed.rs

1use decaf377::{Fq, Fr};
2use decaf377_ka as ka;
3use penumbra_sdk_keys::prf;
4use rand::{CryptoRng, RngCore};
5
6/// The rseed is a uniformly random 32-byte sequence included in the note plaintext.
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8pub struct Rseed(pub [u8; 32]);
9
10impl Rseed {
11    /// Generate a new rseed from a random source.
12    pub fn generate<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
13        let mut bytes = [0u8; 32];
14        rng.fill_bytes(&mut bytes);
15        Self(bytes)
16    }
17
18    /// Derive the ephemeral secret key from the rseed.
19    pub fn derive_esk(&self) -> ka::Secret {
20        let hash_result = prf::expand(b"Penumbra_DeriEsk", &self.0, &[4u8]);
21        ka::Secret::new_from_field(Fr::from_le_bytes_mod_order(hash_result.as_bytes()))
22    }
23
24    /// Derive note commitment randomness from the rseed.
25    pub fn derive_note_blinding(&self) -> Fq {
26        let hash_result = prf::expand(b"Penumbra_DeriRcm", &self.0, &[5u8]);
27        Fq::from_le_bytes_mod_order(hash_result.as_bytes())
28    }
29
30    pub fn to_bytes(&self) -> [u8; 32] {
31        self.0
32    }
33}