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:
str4d 2022-02-15 22:16:49 +00:00 committed by GitHub
commit d0ed65c37c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 39 additions and 37 deletions

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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);

View File

@ -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)
}
}
}

View File

@ -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),

View File

@ -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);

View File

@ -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());

View File

@ -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,

View File

@ -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(&note.value().to_bytes());
np[20..52].copy_from_slice(note.rseed().to_bytes());
np[52..].copy_from_slice(memo);