Derive a Sprout nullifier from a nullifier seed (rho) and spending key
This commit is contained in:
parent
0d618a3abf
commit
fa053e2b0b
|
@ -40,6 +40,9 @@ fn prf_addr(x: [u8; 32], t: u8) -> [u8; 32] {
|
|||
let mut block = [0u8; 64];
|
||||
|
||||
block[0..32].copy_from_slice(&x[..]);
|
||||
// The first four bits –i.e. the most signicant four bits of the
|
||||
// first byte– are used to separate distinct uses
|
||||
// ofSHA256Compress, ensuring that the functions are independent.
|
||||
block[0] |= 0b1100_0000;
|
||||
|
||||
block[32] = t;
|
||||
|
@ -107,19 +110,6 @@ impl fmt::Display for SpendingKey {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for SpendingKey {
|
||||
type Err = SerializationError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let result = &bs58::decode(s).with_check(None).into_vec();
|
||||
|
||||
match result {
|
||||
Ok(bytes) => Self::zcash_deserialize(&bytes[..]),
|
||||
Err(_) => Err(SerializationError::Parse("bs58 decoding error")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; 32]> for SpendingKey {
|
||||
/// Generate a _SpendingKey_ from existing bytes, with the high 4
|
||||
/// bits of the first byte set to zero (ie, 256 bits clamped to
|
||||
|
@ -134,6 +124,25 @@ impl From<[u8; 32]> for SpendingKey {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<SpendingKey> for [u8; 32] {
|
||||
fn from(spending_key: SpendingKey) -> [u8; 32] {
|
||||
spending_key.bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for SpendingKey {
|
||||
type Err = SerializationError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let result = &bs58::decode(s).with_check(None).into_vec();
|
||||
|
||||
match result {
|
||||
Ok(bytes) => Self::zcash_deserialize(&bytes[..]),
|
||||
Err(_) => Err(SerializationError::Parse("bs58 decoding error")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SpendingKey {
|
||||
/// Generate a new _SpendingKey_ with the high 4 bits of the first
|
||||
/// byte set to zero (ie, 256 random bits, clamped to 252).
|
||||
|
|
|
@ -4,11 +4,12 @@
|
|||
|
||||
use std::{fmt, io};
|
||||
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
use crate::{
|
||||
keys::sprout::PayingKey,
|
||||
keys::sprout::{PayingKey, SpendingKey},
|
||||
serde_helpers,
|
||||
serialization::{ReadZcashExt, SerializationError, ZcashDeserialize, ZcashSerialize},
|
||||
types::amount::{Amount, NonNegative},
|
||||
|
@ -16,6 +17,32 @@ use crate::{
|
|||
|
||||
use super::memo::Memo;
|
||||
|
||||
/// PRF^nf is used to derive a Sprout nullifer from the receiver's
|
||||
/// spending key a_sk and a nullifier seed ρ, instantiated using the
|
||||
/// SHA-256 compression function.
|
||||
///
|
||||
/// https://zips.z.cash/protocol/protocol.pdf#abstractprfs
|
||||
/// https://zips.z.cash/protocol/protocol.pdf#commitmentsandnullifiers
|
||||
fn prf_nf(a_sk: [u8; 32], rho: [u8; 32]) -> [u8; 32] {
|
||||
let mut state = [0u32; 8];
|
||||
let mut block = [0u8; 64];
|
||||
|
||||
block[0..32].copy_from_slice(&a_sk[..]);
|
||||
// The first four bits –i.e. the most signicant four bits of the
|
||||
// first byte– are used to separate distinct uses
|
||||
// ofSHA256Compress, ensuring that the functions are independent.
|
||||
block[0] |= 0b1110_0000;
|
||||
|
||||
block[32..].copy_from_slice(&rho[..]);
|
||||
|
||||
sha2::compress256(&mut state, &block);
|
||||
|
||||
let mut derived_bytes = [0u8; 32];
|
||||
LittleEndian::write_u32_into(&state, &mut derived_bytes);
|
||||
|
||||
derived_bytes
|
||||
}
|
||||
|
||||
/// Nullifier seed, named rho in the [spec][ps].
|
||||
///
|
||||
/// [ps]: https://zips.z.cash/protocol/protocol.pdf#sproutkeycomponents
|
||||
|
@ -28,14 +55,26 @@ impl AsRef<[u8]> for NullifierSeed {
|
|||
}
|
||||
}
|
||||
|
||||
/// A Nullifier Set for Sprout transactions
|
||||
impl From<[u8; 32]> for NullifierSeed {
|
||||
fn from(bytes: [u8; 32]) -> Self {
|
||||
Self(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
/// A Nullifier for Sprout transactions
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
|
||||
pub struct Nullifier([u8; 32]);
|
||||
|
||||
impl From<[u8; 32]> for Nullifier {
|
||||
fn from(buf: [u8; 32]) -> Self {
|
||||
Self(buf)
|
||||
impl From<NullifierSeed> for [u8; 32] {
|
||||
fn from(rho: NullifierSeed) -> Self {
|
||||
rho.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(SpendingKey, NullifierSeed)> for Nullifier {
|
||||
fn from((a_sk, rho): (SpendingKey, NullifierSeed)) -> Self {
|
||||
Self(prf_nf(a_sk.into(), rho.into()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue