Add and use prf_addr() for sprout key derivation

This commit is contained in:
Deirdre Connolly 2020-04-02 21:43:10 -04:00 committed by Deirdre Connolly
parent 13f2c229d9
commit 786677e07b
1 changed files with 25 additions and 22 deletions

View File

@ -29,6 +29,29 @@ mod sk_magics {
pub const TESTNET: [u8; 2] = [0xAC, 0x08];
}
/// PRF^addr is used to derive a Sprout shielded payment address from
/// a spending key, and instantiated using the SHA-256 compression
/// function.
///
/// https://zips.z.cash/protocol/protocol.pdf#abstractprfs
/// https://zips.z.cash/protocol/protocol.pdf#sproutkeycomponents
fn prf_addr(x: [u8; 32], t: u8) -> [u8; 32] {
let mut state = [0u32; 8];
let mut block = [0u8; 64];
block[0..32].copy_from_slice(&x[..]);
block[0] |= 0b1100_0000;
block[32] = t;
sha2::compress256(&mut state, &block);
let mut derived_bytes = [0u8; 32];
LittleEndian::write_u32_into(&state, &mut derived_bytes);
return derived_bytes;
}
/// Our root secret key of the Sprout key derivation tree.
///
/// All other Sprout key types derive from the SpendingKey value.
@ -136,16 +159,7 @@ impl From<SpendingKey> for ReceivingKey {
/// https://zips.z.cash/protocol/protocol.pdf#sproutkeycomponents
/// https://zips.z.cash/protocol/protocol.pdf#concreteprfs
fn from(spending_key: SpendingKey) -> ReceivingKey {
let mut state = [0u32; 8];
let mut block = [0u8; 64]; // Thus, t = 0
block[0..32].copy_from_slice(&spending_key.bytes[..]);
block[0] |= 0b1100_0000;
sha2::compress256(&mut state, &block);
let mut derived_bytes = [0u8; 32];
LittleEndian::write_u32_into(&state, &mut derived_bytes);
let derived_bytes = prf_addr(spending_key.bytes, 0);
ReceivingKey::from(derived_bytes)
}
@ -169,18 +183,7 @@ impl From<SpendingKey> for PayingKey {
/// https://zips.z.cash/protocol/protocol.pdf#sproutkeycomponents
/// https://zips.z.cash/protocol/protocol.pdf#concreteprfs
fn from(spending_key: SpendingKey) -> PayingKey {
let mut state = [0u32; 8];
let mut block = [0u8; 64];
block[0..32].copy_from_slice(&spending_key.bytes[..]);
block[0] |= 0b1100_0000;
block[32] = 1u8; // t = 1
sha2::compress256(&mut state, &block);
let mut derived_bytes = [0u8; 32];
LittleEndian::write_u32_into(&state, &mut derived_bytes);
let derived_bytes = prf_addr(spending_key.bytes, 1);
PayingKey(derived_bytes)
}