diff --git a/zebra-chain/src/sapling/commitment.rs b/zebra-chain/src/sapling/commitment.rs index 562b83b1d..5a5a0a51b 100644 --- a/zebra-chain/src/sapling/commitment.rs +++ b/zebra-chain/src/sapling/commitment.rs @@ -21,6 +21,24 @@ use super::keys::{find_group_hash, Diversifier, TransmissionKey}; use pedersen_hashes::*; +/// Generates a random scalar from the scalar field 𝔽_{r_𝕁}. +/// +/// The prime order subgroup 𝕁^(r) is the order-r_𝕁 subgroup of 𝕁 that consists +/// of the points whose order divides r. This function is useful when generating +/// the uniform distribution on 𝔽_{r_𝕁} needed for Sapling commitment schemes' +/// trapdoor generators. +/// +/// https://zips.z.cash/protocol/protocol.pdf#jubjub +pub fn generate_trapdoor(csprng: &mut T) -> jubjub::Fr +where + T: RngCore + CryptoRng, +{ + let mut bytes = [0u8; 64]; + csprng.fill_bytes(&mut bytes); + // Fr::from_bytes_wide() reduces the input modulo r via Fr::from_u512() + jubjub::Fr::from_bytes_wide(&bytes) +} + /// The randomness used in the Pedersen Hash for note commitment. #[derive(Copy, Clone, Debug, PartialEq)] pub struct CommitmentRandomness(jubjub::Fr); diff --git a/zebra-chain/src/sapling/commitment/pedersen_hashes.rs b/zebra-chain/src/sapling/commitment/pedersen_hashes.rs index 1d74cdd03..912a4bb1f 100644 --- a/zebra-chain/src/sapling/commitment/pedersen_hashes.rs +++ b/zebra-chain/src/sapling/commitment/pedersen_hashes.rs @@ -1,7 +1,6 @@ //! Pedersen hash functions and helpers. use bitvec::prelude::*; -use rand_core::{CryptoRng, RngCore}; use super::super::keys::find_group_hash; @@ -127,21 +126,3 @@ pub fn windowed_pedersen_commitment(r: jubjub::Fr, s: &BitVec) -> jubj pedersen_hash_to_point(D, &s) + find_group_hash(D, b"r") * r } - -/// Generates a random scalar from the scalar field 𝔽_{r_𝕁}. -/// -/// The prime order subgroup 𝕁^(r) is the order-r_𝕁 subgroup of 𝕁 that consists -/// of the points whose order divides r. This function is useful when generating -/// the uniform distribution on 𝔽_{r_𝕁} needed for Sapling commitment schemes' -/// trapdoor generators. -/// -/// https://zips.z.cash/protocol/protocol.pdf#jubjub -pub fn generate_trapdoor(csprng: &mut T) -> jubjub::Fr -where - T: RngCore + CryptoRng, -{ - let mut bytes = [0u8; 64]; - csprng.fill_bytes(&mut bytes); - // Fr::from_bytes_wide() reduces the input modulo r via Fr::from_u512() - jubjub::Fr::from_bytes_wide(&bytes) -} diff --git a/zebra-chain/src/sapling/keys.rs b/zebra-chain/src/sapling/keys.rs index 4cf2c9212..8dedc122b 100644 --- a/zebra-chain/src/sapling/keys.rs +++ b/zebra-chain/src/sapling/keys.rs @@ -63,6 +63,25 @@ fn prf_expand(sk: [u8; 32], t: &[u8]) -> [u8; 64] { *hash.as_array() } +/// Used to derive the outgoing cipher key _ock_ used to encrypt an Output ciphertext. +/// +/// PRF^ock(ovk, cv, cm_u, ephemeralKey) := BLAKE2b-256(“Zcash_Derive_ock”, ovk || cv || cm_u || ephemeralKey) +/// +/// https://zips.z.cash/protocol/nu5.pdf#concreteprfs +fn prf_ock(ovk: [u8; 32], cv: [u8; 32], cm_u: [u8; 32], ephemeral_key: [u8; 32]) -> [u8; 32] { + let hash = blake2b_simd::Params::new() + .hash_length(32) + .personal(b"Zcash_Derive_ock") + .to_state() + .update(ovk) + .update(cv) + .update(cm_u) + .update(ephemeral_key) + .finalize(); + + *hash.as_array() +} + /// Invokes Blake2s-256 as _CRH^ivk_, to derive the IncomingViewingKey /// bytes from an AuthorizingKey and NullifierDerivingKey. ///