From 515b0a40ec06eb640fffa65b745166511bf56ecc Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Mon, 12 Sep 2022 22:52:54 +0100 Subject: [PATCH] zcash_note_encryption: Add API to prepare epk. Co-authored-by: Jack Grigg Signed-off-by: Daira Hopwood --- Cargo.toml | 1 + components/zcash_note_encryption/CHANGELOG.md | 13 ++++++++++--- components/zcash_note_encryption/Cargo.toml | 1 + components/zcash_note_encryption/src/batch.rs | 2 +- components/zcash_note_encryption/src/lib.rs | 19 ++++++++++++++----- 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0ddd568e4..0f2939d34 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,3 +21,4 @@ codegen-units = 1 [patch.crates-io] zcash_encoding = { path = "components/zcash_encoding" } zcash_note_encryption = { path = "components/zcash_note_encryption" } +group = { git = "https://github.com/zkcrypto/group.git", rev = "a7f3ceb2373e9fe536996f7b4d55c797f3e667f0" } diff --git a/components/zcash_note_encryption/CHANGELOG.md b/components/zcash_note_encryption/CHANGELOG.md index e3b485e95..4db12f98e 100644 --- a/components/zcash_note_encryption/CHANGELOG.md +++ b/components/zcash_note_encryption/CHANGELOG.md @@ -6,7 +6,17 @@ and this library adheres to Rust's notion of [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added +- `zcash_note_encryption::Domain`: + - `Domain::PreparedEphemeralPublicKey` associated type. + - `Domain::prepare_epk` method, which produces the above type. +### Changed +- MSRV is now 1.56.1. +- Migrated to `group 0.13`. +- `zcash_note_encryption::Domain` now requires `epk` to be converted to + `Domain::PreparedEphemeralPublicKey` before being passed to + `Domain::ka_agree_dec`. - Changes to batch decryption APIs: - The return types of `batch::try_note_decryption` and `batch::try_compact_note_decryption` have changed. Now, instead of @@ -16,8 +26,5 @@ and this library adheres to Rust's notion of argument to the function. Each successful result includes the index of the entry in `ivks` used to decrypt the value. -### Changed -- MSRV is now 1.56.1. - ## [0.1.0] - 2021-12-17 Initial release. diff --git a/components/zcash_note_encryption/Cargo.toml b/components/zcash_note_encryption/Cargo.toml index de440572c..413522fcb 100644 --- a/components/zcash_note_encryption/Cargo.toml +++ b/components/zcash_note_encryption/Cargo.toml @@ -21,6 +21,7 @@ rustdoc-args = ["--cfg", "docsrs"] [dependencies] chacha20 = { version = "0.8", default-features = false } chacha20poly1305 = { version = "0.9", default-features = false } +group = "0.12" rand_core = { version = "0.6", default-features = false } subtle = { version = "2.2.3", default-features = false } diff --git a/components/zcash_note_encryption/src/batch.rs b/components/zcash_note_encryption/src/batch.rs index 9742277a7..ad704167c 100644 --- a/components/zcash_note_encryption/src/batch.rs +++ b/components/zcash_note_encryption/src/batch.rs @@ -51,7 +51,7 @@ where return (0..outputs.len()).map(|_| None).collect(); }; - // Fetch the ephemeral keys for each output and batch-parse them. + // Fetch the ephemeral keys for each output, and batch-parse and prepare them. let ephemeral_keys = D::batch_epk(outputs.iter().map(|(_, output)| output.ephemeral_key())); // Derive the shared secrets for all combinations of (ivk, output). diff --git a/components/zcash_note_encryption/src/lib.rs b/components/zcash_note_encryption/src/lib.rs index 9627d05b2..b16146bb1 100644 --- a/components/zcash_note_encryption/src/lib.rs +++ b/components/zcash_note_encryption/src/lib.rs @@ -113,6 +113,7 @@ enum NoteValidity { pub trait Domain { type EphemeralSecretKey: ConstantTimeEq; type EphemeralPublicKey; + type PreparedEphemeralPublicKey; type SharedSecret; type SymmetricKey: AsRef<[u8]>; type Note; @@ -136,6 +137,9 @@ pub trait Domain { /// Extracts the `DiversifiedTransmissionKey` from the note. fn get_pk_d(note: &Self::Note) -> Self::DiversifiedTransmissionKey; + /// Prepare an ephemeral public key for more efficient scalar multiplication. + fn prepare_epk(epk: Self::EphemeralPublicKey) -> Self::PreparedEphemeralPublicKey; + /// Derives `EphemeralPublicKey` from `esk` and the note's diversifier. fn ka_derive_public( note: &Self::Note, @@ -152,7 +156,7 @@ pub trait Domain { /// decryption. fn ka_agree_dec( ivk: &Self::IncomingViewingKey, - epk: &Self::EphemeralPublicKey, + epk: &Self::PreparedEphemeralPublicKey, ) -> Self::SharedSecret; /// Derives the `SymmetricKey` used to encrypt the note plaintext. @@ -306,10 +310,15 @@ pub trait BatchDomain: Domain { /// them. fn batch_epk( ephemeral_keys: impl Iterator, - ) -> Vec<(Option, EphemeralKeyBytes)> { + ) -> Vec<(Option, EphemeralKeyBytes)> { // Default implementation: do the non-batched thing. ephemeral_keys - .map(|ephemeral_key| (Self::epk(&ephemeral_key), ephemeral_key)) + .map(|ephemeral_key| { + ( + Self::epk(&ephemeral_key).map(Self::prepare_epk), + ephemeral_key, + ) + }) .collect() } } @@ -514,7 +523,7 @@ pub fn try_note_decryption Option<(D::Note, D::Recipient, D::Memo)> { let ephemeral_key = output.ephemeral_key(); - let epk = D::epk(&ephemeral_key)?; + let epk = D::prepare_epk(D::epk(&ephemeral_key)?); let shared_secret = D::ka_agree_dec(ivk, &epk); let key = D::kdf(shared_secret, &ephemeral_key); @@ -611,7 +620,7 @@ pub fn try_compact_note_decryption Option<(D::Note, D::Recipient)> { let ephemeral_key = output.ephemeral_key(); - let epk = D::epk(&ephemeral_key)?; + let epk = D::prepare_epk(D::epk(&ephemeral_key)?); let shared_secret = D::ka_agree_dec(ivk, &epk); let key = D::kdf(shared_secret, &ephemeral_key);