Refactor Sapling nullifier derivation

This commit is contained in:
Jack Grigg 2023-01-06 16:13:23 +00:00
parent f1d3e03a9b
commit 65271b49e5
4 changed files with 57 additions and 17 deletions

View File

@ -8,6 +8,7 @@ pub mod note_encryption;
pub mod pedersen_hash;
pub mod prover;
pub mod redjubjub;
mod spec;
mod tree;
pub mod util;
pub mod value;

View File

@ -1,4 +1,3 @@
use blake2s_simd::Params as Blake2sParams;
use byteorder::{LittleEndian, WriteBytesExt};
use group::{
ff::{Field, PrimeField},
@ -84,22 +83,7 @@ impl Note {
/// Computes the nullifier given the nullifier deriving key and
/// note position
pub fn nf(&self, nk: &NullifierDerivingKey, position: u64) -> Nullifier {
// Compute rho = cm + position.G
let rho = self.cm_full_point()
+ (constants::NULLIFIER_POSITION_GENERATOR * jubjub::Fr::from(position));
// Compute nf = BLAKE2s(nk | rho)
Nullifier::from_slice(
Blake2sParams::new()
.hash_length(32)
.personal(constants::PRF_NF_PERSONALIZATION)
.to_state()
.update(&nk.0.to_bytes())
.update(&rho.to_bytes())
.finalize()
.as_bytes(),
)
.unwrap()
Nullifier::derive(nk, self.cm_full_point(), position)
}
/// Computes the note commitment

View File

@ -2,6 +2,11 @@ use std::array::TryFromSliceError;
use subtle::{Choice, ConstantTimeEq};
use crate::sapling::{
keys::NullifierDerivingKey,
spec::{mixing_pedersen_hash, prf_nf},
};
/// Typesafe wrapper for nullifier values.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Nullifier(pub [u8; 32]);
@ -14,6 +19,20 @@ impl Nullifier {
pub fn to_vec(&self) -> Vec<u8> {
self.0.to_vec()
}
/// $DeriveNullifier$.
///
/// Defined in [Zcash Protocol Spec § 4.16: Note Commitments and Nullifiers][commitmentsandnullifiers].
///
/// [commitmentsandnullifiers]: https://zips.z.cash/protocol/protocol.pdf#commitmentsandnullifiers
pub(super) fn derive(
nk: &NullifierDerivingKey,
cm: jubjub::SubgroupPoint,
position: u64,
) -> Self {
let rho = mixing_pedersen_hash(cm, position);
Nullifier(prf_nf(&nk.0, &rho))
}
}
impl AsRef<[u8]> for Nullifier {

View File

@ -0,0 +1,36 @@
//! Helper functions defined in the Zcash Protocol Specification.
use blake2s_simd::Params as Blake2sParams;
use group::GroupEncoding;
use crate::constants::{NULLIFIER_POSITION_GENERATOR, PRF_NF_PERSONALIZATION};
/// $MixingPedersenHash$.
///
/// Defined in [Zcash Protocol Spec § 5.4.1.8: Mixing Pedersen Hash Function][concretemixinghash].
///
/// [concretemixinghash]: https://zips.z.cash/protocol/protocol.pdf#concretemixinghash
pub(crate) fn mixing_pedersen_hash(
cm: jubjub::SubgroupPoint,
position: u64,
) -> jubjub::SubgroupPoint {
cm + (NULLIFIER_POSITION_GENERATOR * jubjub::Fr::from(position))
}
/// $PRF^\mathsf{nfSapling}_{nk}(\rho)$
///
/// Defined in [Zcash Protocol Spec § 5.4.2: Pseudo Random Functions][concreteprfs].
///
/// [concreteprfs]: https://zips.z.cash/protocol/protocol.pdf#concreteprfs
pub(crate) fn prf_nf(nk: &jubjub::SubgroupPoint, rho: &jubjub::SubgroupPoint) -> [u8; 32] {
Blake2sParams::new()
.hash_length(32)
.personal(PRF_NF_PERSONALIZATION)
.to_state()
.update(&nk.to_bytes())
.update(&rho.to_bytes())
.finalize()
.as_bytes()
.try_into()
.expect("output length is correct")
}