mirror of https://github.com/zcash/orchard.git
Merge pull request #283 from nuttycom/ivk_expose_dk
Allow decryption of the diversifier index for an an address using the IVK.
This commit is contained in:
commit
d0ed65c37c
|
@ -53,7 +53,7 @@ proptest = "1.0.0"
|
|||
zcash_note_encryption = { version = "0.1", features = ["pre-zip-212"] }
|
||||
|
||||
[target.'cfg(unix)'.dev-dependencies]
|
||||
pprof = { version = "0.6", features = ["criterion", "flamegraph"] }
|
||||
pprof = { version = "=0.6.1", features = ["criterion", "flamegraph"] }
|
||||
|
||||
[lib]
|
||||
bench = false
|
||||
|
|
|
@ -20,7 +20,7 @@ fn criterion_benchmark(c: &mut Criterion) {
|
|||
let rng = OsRng;
|
||||
|
||||
let sk = SpendingKey::from_bytes([7; 32]).unwrap();
|
||||
let recipient = FullViewingKey::from(&sk).default_address();
|
||||
let recipient = FullViewingKey::from(&sk).address_at(0u32);
|
||||
|
||||
let vk = VerifyingKey::build();
|
||||
let pk = ProvingKey::build();
|
||||
|
|
|
@ -22,7 +22,7 @@ fn bench_note_decryption(c: &mut Criterion) {
|
|||
|
||||
let fvk = FullViewingKey::from(&SpendingKey::from_bytes([7; 32]).unwrap());
|
||||
let valid_ivk = IncomingViewingKey::from(&fvk);
|
||||
let recipient = fvk.default_address();
|
||||
let recipient = fvk.address_at(0u32);
|
||||
|
||||
// Compact actions don't have the full AEAD ciphertext, so ZIP 307 trial-decryption
|
||||
// relies on an invalid ivk resulting in random noise for which the note commitment
|
||||
|
|
|
@ -12,7 +12,7 @@ fn key_derivation(c: &mut Criterion) {
|
|||
let fvk = FullViewingKey::from(&sk);
|
||||
|
||||
c.bench_function("derive_fvk", |b| b.iter(|| FullViewingKey::from(&sk)));
|
||||
c.bench_function("default_address", |b| b.iter(|| fvk.default_address()));
|
||||
c.bench_function("default_address", |b| b.iter(|| fvk.address_at(0u32)));
|
||||
}
|
||||
|
||||
criterion_group!(benches, key_derivation);
|
||||
|
|
|
@ -15,7 +15,7 @@ use crate::{
|
|||
/// use orchard::keys::{SpendingKey, FullViewingKey};
|
||||
///
|
||||
/// let sk = SpendingKey::from_bytes([7; 32]).unwrap();
|
||||
/// let address = FullViewingKey::from(&sk).default_address();
|
||||
/// let address = FullViewingKey::from(&sk).address_at(0u32);
|
||||
/// ```
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct Address {
|
||||
|
@ -32,7 +32,7 @@ impl Address {
|
|||
Address { d, pk_d }
|
||||
}
|
||||
|
||||
pub(crate) fn diversifer(&self) -> Diversifier {
|
||||
pub(crate) fn diversifier(&self) -> Diversifier {
|
||||
self.d
|
||||
}
|
||||
|
||||
|
@ -71,15 +71,18 @@ impl Address {
|
|||
pub mod testing {
|
||||
use proptest::prelude::*;
|
||||
|
||||
use crate::keys::{testing::arb_spending_key, FullViewingKey};
|
||||
use crate::keys::{
|
||||
testing::{arb_diversifier_index, arb_spending_key},
|
||||
FullViewingKey,
|
||||
};
|
||||
|
||||
use super::Address;
|
||||
|
||||
prop_compose! {
|
||||
/// Generates an arbitrary payment address.
|
||||
pub(crate) fn arb_address()(sk in arb_spending_key()) -> Address {
|
||||
pub(crate) fn arb_address()(sk in arb_spending_key(), j in arb_diversifier_index()) -> Address {
|
||||
let fvk = FullViewingKey::from(&sk);
|
||||
fvk.default_address()
|
||||
fvk.address_at(j)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ impl RecipientInfo {
|
|||
/// [orcharddummynotes]: https://zips.z.cash/protocol/nu5.pdf#orcharddummynotes
|
||||
fn dummy(rng: &mut impl RngCore) -> Self {
|
||||
let fvk: FullViewingKey = (&SpendingKey::random(rng)).into();
|
||||
let recipient = fvk.default_address();
|
||||
let recipient = fvk.address_at(0u32);
|
||||
|
||||
RecipientInfo {
|
||||
ovk: None,
|
||||
|
@ -133,7 +133,7 @@ impl ActionInfo {
|
|||
let cv_net = ValueCommitment::derive(v_net, self.rcv.clone());
|
||||
|
||||
let nf_old = self.spend.note.nullifier(&self.spend.fvk);
|
||||
let sender_address = self.spend.fvk.default_address();
|
||||
let sender_address = self.spend.note.recipient();
|
||||
let rho_old = self.spend.note.rho();
|
||||
let psi_old = self.spend.note.rseed().psi(&rho_old);
|
||||
let rcm_old = self.spend.note.rseed().rcm(&rho_old);
|
||||
|
@ -724,7 +724,7 @@ mod tests {
|
|||
|
||||
let sk = SpendingKey::random(&mut rng);
|
||||
let fvk = FullViewingKey::from(&sk);
|
||||
let recipient = fvk.default_address();
|
||||
let recipient = fvk.address_at(0u32);
|
||||
|
||||
let mut builder = Builder::new(
|
||||
Flags::from_parts(true, true),
|
||||
|
|
|
@ -961,7 +961,7 @@ mod tests {
|
|||
.map(|()| {
|
||||
let (_, fvk, spent_note) = Note::dummy(&mut rng, None);
|
||||
|
||||
let sender_address = fvk.default_address();
|
||||
let sender_address = spent_note.recipient();
|
||||
let nk = *fvk.nk();
|
||||
let rivk = *fvk.rivk();
|
||||
let nf_old = spent_note.nullifier(&fvk);
|
||||
|
|
43
src/keys.rs
43
src/keys.rs
|
@ -333,11 +333,6 @@ impl FullViewingKey {
|
|||
)
|
||||
}
|
||||
|
||||
/// Returns the default payment address for this key.
|
||||
pub fn default_address(&self) -> Address {
|
||||
IncomingViewingKey::from(self).default_address()
|
||||
}
|
||||
|
||||
/// Returns the payment address for this key at the given index.
|
||||
pub fn address_at(&self, j: impl Into<DiversifierIndex>) -> Address {
|
||||
IncomingViewingKey::from(self).address_at(j)
|
||||
|
@ -404,13 +399,7 @@ impl FullViewingKey {
|
|||
///
|
||||
/// [orchardkeycomponents]: https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct DiversifierKey([u8; 32]);
|
||||
|
||||
impl From<&FullViewingKey> for DiversifierKey {
|
||||
fn from(fvk: &FullViewingKey) -> Self {
|
||||
fvk.derive_dk_ovk().0
|
||||
}
|
||||
}
|
||||
pub(crate) struct DiversifierKey([u8; 32]);
|
||||
|
||||
/// The index for a particular diversifier.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
|
@ -437,12 +426,14 @@ impl From<[u8; 11]> for DiversifierIndex {
|
|||
}
|
||||
}
|
||||
|
||||
impl DiversifierKey {
|
||||
/// Returns the diversifier at index 0.
|
||||
pub fn default_diversifier(&self) -> Diversifier {
|
||||
self.get(0u32)
|
||||
impl DiversifierIndex {
|
||||
/// Returns the raw bytes of the diversifier index.
|
||||
pub fn to_bytes(&self) -> &[u8; 11] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DiversifierKey {
|
||||
/// Returns the diversifier at the given index.
|
||||
pub fn get(&self, j: impl Into<DiversifierIndex>) -> Diversifier {
|
||||
let ff = FF1::<Aes256>::new(&self.0, 2).expect("valid radix");
|
||||
|
@ -556,7 +547,7 @@ pub struct IncomingViewingKey {
|
|||
impl From<&FullViewingKey> for IncomingViewingKey {
|
||||
fn from(fvk: &FullViewingKey) -> Self {
|
||||
IncomingViewingKey {
|
||||
dk: fvk.into(),
|
||||
dk: fvk.derive_dk_ovk().0,
|
||||
ivk: fvk.into(),
|
||||
}
|
||||
}
|
||||
|
@ -583,9 +574,16 @@ impl IncomingViewingKey {
|
|||
})
|
||||
}
|
||||
|
||||
/// Returns the default payment address for this key.
|
||||
pub fn default_address(&self) -> Address {
|
||||
self.address(self.dk.default_diversifier())
|
||||
/// Checks whether the given address was derived from this incoming viewing
|
||||
/// key, and returns the diversifier index used to derive the address if
|
||||
/// so. Returns `None` if the address was not derived from this key.
|
||||
pub fn diversifier_index(&self, addr: &Address) -> Option<DiversifierIndex> {
|
||||
let j = self.dk.diversifier_index(&addr.diversifier());
|
||||
if &self.address_at(j) == addr {
|
||||
Some(j)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the payment address for this key at the given index.
|
||||
|
@ -837,7 +835,7 @@ pub mod testing {
|
|||
|
||||
prop_compose! {
|
||||
/// Generate a uniformly distributed Orchard diversifier key.
|
||||
pub fn arb_diversifier_key()(
|
||||
pub(crate) fn arb_diversifier_key()(
|
||||
dk_bytes in prop::array::uniform32(prop::num::u8::ANY)
|
||||
) -> DiversifierKey {
|
||||
DiversifierKey::from_bytes(dk_bytes)
|
||||
|
@ -890,9 +888,10 @@ mod tests {
|
|||
fn key_agreement(
|
||||
sk in arb_spending_key(),
|
||||
esk in arb_esk(),
|
||||
j in arb_diversifier_index(),
|
||||
) {
|
||||
let ivk = IncomingViewingKey::from(&(&sk).into());
|
||||
let addr = ivk.default_address();
|
||||
let addr = ivk.address_at(j);
|
||||
|
||||
let epk = esk.derive_public(addr.g_d());
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ impl Note {
|
|||
) -> (SpendingKey, FullViewingKey, Self) {
|
||||
let sk = SpendingKey::random(rng);
|
||||
let fvk: FullViewingKey = (&sk).into();
|
||||
let recipient = fvk.default_address();
|
||||
let recipient = fvk.address_at(0u32);
|
||||
|
||||
let note = Note::new(
|
||||
recipient,
|
||||
|
|
|
@ -149,7 +149,7 @@ impl Domain for OrchardDomain {
|
|||
) -> NotePlaintextBytes {
|
||||
let mut np = [0; NOTE_PLAINTEXT_SIZE];
|
||||
np[0] = 0x02;
|
||||
np[1..12].copy_from_slice(note.recipient().diversifer().as_array());
|
||||
np[1..12].copy_from_slice(note.recipient().diversifier().as_array());
|
||||
np[12..20].copy_from_slice(¬e.value().to_bytes());
|
||||
np[20..52].copy_from_slice(note.rseed().to_bytes());
|
||||
np[52..].copy_from_slice(memo);
|
||||
|
|
Loading…
Reference in New Issue