From 786677e07baf991f1a1f90c8087b2051f80af649 Mon Sep 17 00:00:00 2001 From: Deirdre Connolly Date: Thu, 2 Apr 2020 21:43:10 -0400 Subject: [PATCH] Add and use prf_addr() for sprout key derivation --- zebra-chain/src/keys/sprout.rs | 47 ++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/zebra-chain/src/keys/sprout.rs b/zebra-chain/src/keys/sprout.rs index be03085d9..c7d05b374 100644 --- a/zebra-chain/src/keys/sprout.rs +++ b/zebra-chain/src/keys/sprout.rs @@ -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 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 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) }