mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-07-30 20:11:23 +00:00
Move Sapling key structs from zip32 to zcash_primitives
This commit is contained in:
174
zcash_primitives/src/keys.rs
Normal file
174
zcash_primitives/src/keys.rs
Normal file
@@ -0,0 +1,174 @@
|
||||
//! Sapling key components
|
||||
|
||||
use blake2_rfc::blake2b::{Blake2b, Blake2bResult};
|
||||
use ff::{PrimeField, PrimeFieldRepr};
|
||||
use sapling_crypto::{
|
||||
jubjub::{edwards, FixedGenerators, JubjubEngine, JubjubParams, ToUniform, Unknown},
|
||||
primitives::{ProofGenerationKey, ViewingKey},
|
||||
};
|
||||
use std::io::{self, Read, Write};
|
||||
|
||||
pub const PRF_EXPAND_PERSONALIZATION: &'static [u8; 16] = b"Zcash_ExpandSeed";
|
||||
|
||||
/// PRF^expand(sk, t) := BLAKE2b-512("Zcash_ExpandSeed", sk || t)
|
||||
pub fn prf_expand(sk: &[u8], t: &[u8]) -> Blake2bResult {
|
||||
prf_expand_vec(sk, &vec![t])
|
||||
}
|
||||
|
||||
pub fn prf_expand_vec(sk: &[u8], ts: &[&[u8]]) -> Blake2bResult {
|
||||
let mut h = Blake2b::with_params(64, &[], &[], PRF_EXPAND_PERSONALIZATION);
|
||||
h.update(sk);
|
||||
for t in ts {
|
||||
h.update(t);
|
||||
}
|
||||
h.finalize()
|
||||
}
|
||||
|
||||
/// An outgoing viewing key
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub struct OutgoingViewingKey(pub [u8; 32]);
|
||||
|
||||
/// A Sapling expanded spending key
|
||||
#[derive(Clone)]
|
||||
pub struct ExpandedSpendingKey<E: JubjubEngine> {
|
||||
pub ask: E::Fs,
|
||||
pub nsk: E::Fs,
|
||||
pub ovk: OutgoingViewingKey,
|
||||
}
|
||||
|
||||
/// A Sapling full viewing key
|
||||
pub struct FullViewingKey<E: JubjubEngine> {
|
||||
pub vk: ViewingKey<E>,
|
||||
pub ovk: OutgoingViewingKey,
|
||||
}
|
||||
|
||||
impl<E: JubjubEngine> ExpandedSpendingKey<E> {
|
||||
pub fn from_spending_key(sk: &[u8]) -> Self {
|
||||
let ask = E::Fs::to_uniform(prf_expand(sk, &[0x00]).as_bytes());
|
||||
let nsk = E::Fs::to_uniform(prf_expand(sk, &[0x01]).as_bytes());
|
||||
let mut ovk = OutgoingViewingKey([0u8; 32]);
|
||||
ovk.0
|
||||
.copy_from_slice(&prf_expand(sk, &[0x02]).as_bytes()[..32]);
|
||||
ExpandedSpendingKey { ask, nsk, ovk }
|
||||
}
|
||||
|
||||
pub fn proof_generation_key(&self, params: &E::Params) -> ProofGenerationKey<E> {
|
||||
ProofGenerationKey {
|
||||
ak: params
|
||||
.generator(FixedGenerators::SpendingKeyGenerator)
|
||||
.mul(self.ask, params),
|
||||
nsk: self.nsk,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
|
||||
let mut ask_repr = <E::Fs as PrimeField>::Repr::default();
|
||||
ask_repr.read_le(&mut reader)?;
|
||||
let ask = E::Fs::from_repr(ask_repr)
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||
|
||||
let mut nsk_repr = <E::Fs as PrimeField>::Repr::default();
|
||||
nsk_repr.read_le(&mut reader)?;
|
||||
let nsk = E::Fs::from_repr(nsk_repr)
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||
|
||||
let mut ovk = [0; 32];
|
||||
reader.read_exact(&mut ovk)?;
|
||||
|
||||
Ok(ExpandedSpendingKey {
|
||||
ask,
|
||||
nsk,
|
||||
ovk: OutgoingViewingKey(ovk),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
||||
self.ask.into_repr().write_le(&mut writer)?;
|
||||
self.nsk.into_repr().write_le(&mut writer)?;
|
||||
writer.write_all(&self.ovk.0)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> [u8; 96] {
|
||||
let mut result = [0u8; 96];
|
||||
self.write(&mut result[..])
|
||||
.expect("should be able to serialize an ExpandedSpendingKey");
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: JubjubEngine> Clone for FullViewingKey<E> {
|
||||
fn clone(&self) -> Self {
|
||||
FullViewingKey {
|
||||
vk: ViewingKey {
|
||||
ak: self.vk.ak.clone(),
|
||||
nk: self.vk.nk.clone(),
|
||||
},
|
||||
ovk: self.ovk.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: JubjubEngine> FullViewingKey<E> {
|
||||
pub fn from_expanded_spending_key(expsk: &ExpandedSpendingKey<E>, params: &E::Params) -> Self {
|
||||
FullViewingKey {
|
||||
vk: ViewingKey {
|
||||
ak: params
|
||||
.generator(FixedGenerators::SpendingKeyGenerator)
|
||||
.mul(expsk.ask, params),
|
||||
nk: params
|
||||
.generator(FixedGenerators::ProofGenerationKey)
|
||||
.mul(expsk.nsk, params),
|
||||
},
|
||||
ovk: expsk.ovk,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read<R: Read>(mut reader: R, params: &E::Params) -> io::Result<Self> {
|
||||
let ak = edwards::Point::<E, Unknown>::read(&mut reader, params)?;
|
||||
let ak = match ak.as_prime_order(params) {
|
||||
Some(p) => p,
|
||||
None => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"ak not of prime order",
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let nk = edwards::Point::<E, Unknown>::read(&mut reader, params)?;
|
||||
let nk = match nk.as_prime_order(params) {
|
||||
Some(p) => p,
|
||||
None => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"nk not of prime order",
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let mut ovk = [0; 32];
|
||||
reader.read_exact(&mut ovk)?;
|
||||
|
||||
Ok(FullViewingKey {
|
||||
vk: ViewingKey { ak, nk },
|
||||
ovk: OutgoingViewingKey(ovk),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
||||
self.vk.ak.write(&mut writer)?;
|
||||
self.vk.nk.write(&mut writer)?;
|
||||
writer.write_all(&self.ovk.0)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> [u8; 96] {
|
||||
let mut result = [0u8; 96];
|
||||
self.write(&mut result[..])
|
||||
.expect("should be able to serialize a FullViewingKey");
|
||||
result
|
||||
}
|
||||
}
|
@@ -13,6 +13,7 @@ extern crate sha2;
|
||||
use sapling_crypto::jubjub::JubjubBls12;
|
||||
|
||||
pub mod block;
|
||||
pub mod keys;
|
||||
pub mod sapling;
|
||||
mod serialize;
|
||||
pub mod transaction;
|
||||
|
Reference in New Issue
Block a user