From 0e1d4402872a00618e72c8c6fb242215acdf2f53 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 11 Jul 2018 12:29:39 +0100 Subject: [PATCH] Serialization and fingerprint for ExpandedSpendingKey and FullViewingKey --- src/lib.rs | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 88b8438..29599e3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,7 @@ extern crate pairing; extern crate sapling_crypto; use blake2_rfc::blake2b::{Blake2b, Blake2bResult}; -use pairing::bls12_381::Bls12; +use pairing::{bls12_381::Bls12, PrimeField, PrimeFieldRepr}; use sapling_crypto::{ jubjub::{FixedGenerators, JubjubBls12, JubjubEngine, JubjubParams, ToUniform}, primitives::ViewingKey, @@ -17,6 +17,7 @@ lazy_static! { pub const PRF_EXPAND_PERSONALIZATION: &'static [u8; 16] = b"Zcash_ExpandSeed"; pub const ZIP32_SAPLING_MASTER_PERSONALIZATION: &'static [u8; 16] = b"ZcashIP32Sapling"; +pub const ZIP32_SAPLING_FVFP_PERSONALIZATION: &'static [u8; 16] = b"ZcashSaplingFVFP"; // Sapling key components @@ -54,6 +55,20 @@ impl ExpandedSpendingKey { .copy_from_slice(&prf_expand(sk, &[0x02]).as_bytes()[..32]); ExpandedSpendingKey { ask, nsk, ovk } } + + fn to_bytes(&self) -> [u8; 96] { + let mut result = [0u8; 96]; + self.ask + .into_repr() + .write_le(&mut result[..32]) + .expect("length is 32 bytes"); + self.nsk + .into_repr() + .write_le(&mut result[32..64]) + .expect("length is 32 bytes"); + (&mut result[64..]).copy_from_slice(&self.ovk.0); + result + } } impl FullViewingKey { @@ -70,6 +85,20 @@ impl FullViewingKey { ovk: xsk.ovk, } } + + fn to_bytes(&self) -> [u8; 96] { + let mut result = [0u8; 96]; + self.vk + .ak + .write(&mut result[..32]) + .expect("length is 32 bytes"); + self.vk + .nk + .write(&mut result[32..64]) + .expect("length is 32 bytes"); + (&mut result[64..]).copy_from_slice(&self.ovk.0); + result + } } // ZIP 32 structures @@ -77,6 +106,16 @@ impl FullViewingKey { /// A Sapling full viewing key fingerprint struct FVKFingerprint([u8; 32]); +impl<'a, E: JubjubEngine> From<&'a FullViewingKey> for FVKFingerprint { + fn from(fvk: &FullViewingKey) -> Self { + let mut h = Blake2b::with_params(32, &[], &[], ZIP32_SAPLING_FVFP_PERSONALIZATION); + h.update(&fvk.to_bytes()); + let mut fvfp = [0u8; 32]; + fvfp.copy_from_slice(h.finalize().as_bytes()); + FVKFingerprint(fvfp) + } +} + /// A Sapling full viewing key tag #[derive(Clone, Copy)] struct FVKTag([u8; 4]);