ExtendedSpendingKey::master()

This commit is contained in:
Jack Grigg 2018-07-11 01:28:10 +01:00
parent 8db848139b
commit 2fdfa4b671
No known key found for this signature in database
GPG Key ID: 1B8D649257DB0829
2 changed files with 69 additions and 1 deletions

View File

@ -15,6 +15,10 @@ repository = "https://github.com/zcash-hackworks/zip32"
lazy_static = "1.0"
pairing = "0.14.2"
[dependencies.blake2-rfc]
git = "https://github.com/gtank/blake2-rfc"
rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9"
[dependencies.sapling-crypto]
git = "https://github.com/zcash-hackworks/sapling-crypto"
rev = "21084bde2019c04bd34208e63c3560fe2c02fb0e"

View File

@ -1,19 +1,33 @@
extern crate blake2_rfc;
#[macro_use]
extern crate lazy_static;
extern crate pairing;
extern crate sapling_crypto;
use blake2_rfc::blake2b::{Blake2b, Blake2bResult};
use pairing::bls12_381::Bls12;
use sapling_crypto::{
jubjub::{FixedGenerators, JubjubBls12, JubjubEngine, JubjubParams}, primitives::ViewingKey,
jubjub::{FixedGenerators, JubjubBls12, JubjubEngine, JubjubParams, ToUniform},
primitives::ViewingKey,
};
lazy_static! {
static ref JUBJUB: JubjubBls12 = { JubjubBls12::new() };
}
pub const PRF_EXPAND_PERSONALIZATION: &'static [u8; 16] = b"Zcash_ExpandSeed";
pub const ZIP32_SAPLING_MASTER_PERSONALIZATION: &'static [u8; 16] = b"ZcashIP32Sapling";
// Sapling key components
/// PRF^expand(sk, t) := BLAKE2b-512("Zcash_ExpandSeed", sk || t)
fn prf_expand(sk: &[u8], t: &[u8]) -> Blake2bResult {
let mut h = Blake2b::with_params(64, &[], &[], PRF_EXPAND_PERSONALIZATION);
h.update(sk);
h.update(t);
h.finalize()
}
/// An outgoing viewing key
#[derive(Clone, Copy)]
struct OutgoingViewingKey([u8; 32]);
@ -31,6 +45,17 @@ struct FullViewingKey<E: JubjubEngine> {
ovk: OutgoingViewingKey,
}
impl<E: JubjubEngine> ExpandedSpendingKey<E> {
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 }
}
}
impl<E: JubjubEngine> FullViewingKey<E> {
fn from_expanded_spending_key(xsk: &ExpandedSpendingKey<E>, params: &E::Params) -> Self {
FullViewingKey {
@ -70,6 +95,12 @@ impl From<FVKFingerprint> for FVKTag {
}
}
impl FVKTag {
fn master() -> Self {
FVKTag([0u8; 4])
}
}
/// A child index for a derived key
#[derive(Clone, Copy)]
pub enum ChildIndex {
@ -84,6 +115,10 @@ impl ChildIndex {
n => ChildIndex::NonHardened(n),
}
}
fn master() -> Self {
ChildIndex::from_index(0)
}
}
/// A chain code
@ -94,6 +129,14 @@ struct ChainCode([u8; 32]);
#[derive(Clone, Copy)]
struct DiversifierKey([u8; 32]);
impl DiversifierKey {
fn master(sk_m: &[u8]) -> Self {
let mut dk_m = [0u8; 32];
dk_m.copy_from_slice(&prf_expand(sk_m, &[0x10]).as_bytes()[..32]);
DiversifierKey(dk_m)
}
}
/// A Sapling extended spending key
pub struct ExtendedSpendingKey {
depth: u8,
@ -114,6 +157,27 @@ pub struct ExtendedFullViewingKey {
dk: DiversifierKey,
}
impl ExtendedSpendingKey {
pub fn master(seed: &[u8]) -> Self {
let mut h = Blake2b::with_params(64, &[], &[], ZIP32_SAPLING_MASTER_PERSONALIZATION);
h.update(seed);
let i = h.finalize();
let sk_m = &i.as_bytes()[..32];
let mut c_m = [0u8; 32];
c_m.copy_from_slice(&i.as_bytes()[32..]);
ExtendedSpendingKey {
depth: 0,
parent_fvk_tag: FVKTag::master(),
child_index: ChildIndex::master(),
chain_code: ChainCode(c_m),
xsk: ExpandedSpendingKey::from_spending_key(sk_m),
dk: DiversifierKey::master(sk_m),
}
}
}
impl<'a> From<&'a ExtendedSpendingKey> for ExtendedFullViewingKey {
fn from(xsk: &ExtendedSpendingKey) -> Self {
ExtendedFullViewingKey {