2020-03-13 14:38:42 -07:00
|
|
|
|
//! Sprout key types
|
2020-03-13 15:58:02 -07:00
|
|
|
|
//!
|
|
|
|
|
//! "The receiving key sk_enc, the incoming viewing key ivk = (apk,
|
|
|
|
|
//! sk_enc), and the shielded payment address addr_pk = (a_pk, pk_enc) are
|
|
|
|
|
//! derived from a_sk, as described in [‘Sprout Key Components’][ps]
|
|
|
|
|
//!
|
|
|
|
|
//! [ps]: https://zips.z.cash/protocol/protocol.pdf#sproutkeycomponents
|
2020-03-13 14:38:42 -07:00
|
|
|
|
|
2020-02-25 15:14:59 -08:00
|
|
|
|
use std::{
|
|
|
|
|
fmt,
|
|
|
|
|
io::{self},
|
|
|
|
|
};
|
|
|
|
|
|
2020-03-24 01:49:27 -07:00
|
|
|
|
use byteorder::{ByteOrder, LittleEndian};
|
|
|
|
|
|
2020-02-25 15:14:59 -08:00
|
|
|
|
#[cfg(test)]
|
|
|
|
|
use proptest::{array, collection::vec, prelude::*};
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
use proptest_derive::Arbitrary;
|
|
|
|
|
|
2020-03-18 17:26:07 -07:00
|
|
|
|
use sha2::sha256_utils::compress256;
|
|
|
|
|
|
2020-02-25 15:14:59 -08:00
|
|
|
|
use crate::serialization::{SerializationError, ZcashDeserialize, ZcashSerialize};
|
|
|
|
|
|
2020-03-18 17:26:07 -07:00
|
|
|
|
/// Our root secret key of the Sprout key derivation tree.
|
|
|
|
|
///
|
2020-03-13 15:58:02 -07:00
|
|
|
|
/// All other Sprout key types derive from the SpendingKey value.
|
2020-03-18 17:26:07 -07:00
|
|
|
|
/// Actually 252 bits.
|
2020-03-24 01:49:27 -07:00
|
|
|
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
2020-03-18 17:26:07 -07:00
|
|
|
|
pub struct SpendingKey(pub [u8; 32]);
|
2020-03-13 15:58:02 -07:00
|
|
|
|
|
2020-03-18 11:57:23 -07:00
|
|
|
|
/// Derived from a _SpendingKey_.
|
|
|
|
|
pub type ReceivingKey = x25519_dalek::StaticSecret;
|
2020-03-13 15:58:02 -07:00
|
|
|
|
|
2020-03-18 17:26:07 -07:00
|
|
|
|
impl From<SpendingKey> for ReceivingKey {
|
|
|
|
|
fn from(spending_key: SpendingKey) -> ReceivingKey {
|
2020-03-24 01:49:27 -07:00
|
|
|
|
let mut state = [0u32; 8];
|
|
|
|
|
let mut block = [0u8; 64];
|
|
|
|
|
|
|
|
|
|
block[0..32].copy_from_slice(&spending_key.0[..]);
|
|
|
|
|
block[0] |= 0b11000000;
|
|
|
|
|
|
|
|
|
|
compress256(&mut state, &block);
|
|
|
|
|
|
|
|
|
|
let mut derived_bytes = [0u8; 32];
|
|
|
|
|
LittleEndian::write_u32_into(&state, &mut derived_bytes);
|
|
|
|
|
|
|
|
|
|
ReceivingKey::from(derived_bytes)
|
2020-03-18 17:26:07 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-18 11:57:23 -07:00
|
|
|
|
/// Derived from a _SpendingKey_.
|
2020-03-24 01:49:27 -07:00
|
|
|
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
2020-03-17 15:49:15 -07:00
|
|
|
|
pub struct PayingKey(pub [u8; 32]);
|
2020-03-13 15:58:02 -07:00
|
|
|
|
|
2020-03-18 11:57:23 -07:00
|
|
|
|
/// Derived from a _ReceivingKey_.
|
2020-03-17 15:49:15 -07:00
|
|
|
|
pub type TransmissionKey = x25519_dalek::PublicKey;
|
2020-03-13 15:58:02 -07:00
|
|
|
|
|
2020-03-17 15:49:15 -07:00
|
|
|
|
///
|
2020-03-13 15:58:02 -07:00
|
|
|
|
pub struct IncomingViewingKey {
|
|
|
|
|
paying_key: PayingKey,
|
|
|
|
|
receiving_key: ReceivingKey,
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-24 01:49:27 -07:00
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
|
|
|
|
|
use rand_core::{OsRng, RngCore};
|
|
|
|
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn derive_receiving_key() {
|
|
|
|
|
let mut bytes = [0u8; 32];
|
|
|
|
|
OsRng.fill_bytes(&mut bytes);
|
|
|
|
|
|
|
|
|
|
let spending_key = SpendingKey(bytes);
|
|
|
|
|
|
|
|
|
|
println!("{:?}", spending_key);
|
|
|
|
|
|
|
|
|
|
let receiving_key = ReceivingKey::from(spending_key);
|
|
|
|
|
|
|
|
|
|
// println!("{}", receiving_key);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-25 15:14:59 -08:00
|
|
|
|
#[cfg(test)]
|
|
|
|
|
proptest! {
|
|
|
|
|
|
2020-02-28 10:07:01 -08:00
|
|
|
|
// #[test]
|
|
|
|
|
// fn test() {}
|
2020-02-25 15:14:59 -08:00
|
|
|
|
}
|