From 2ff25a6cb1cb5b13601236c09b139d8d7ab6f103 Mon Sep 17 00:00:00 2001 From: redshiftzero Date: Tue, 23 Jul 2024 13:54:54 -0400 Subject: [PATCH] cleanup `LegacySwap` swap decryption path (#4706) ## Describe your changes This removes the `LegacySwap` symmetric encryption that is no longer used in Penumbra ## Issue ticket number and link Closes #4501 ## Checklist before requesting a review - [x] If this code contains consensus-breaking changes, I have added the "consensus-breaking" label. Otherwise, I declare my belief that there are not consensus-breaking changes, for the following reason: > Swaps were not encrypted using this `LegacySwap` method on mainnet --- .../core/component/dex/src/swap/ciphertext.rs | 10 ++--- crates/core/keys/src/symmetric.rs | 44 ++++--------------- crates/core/transaction/src/is_action.rs | 8 +--- 3 files changed, 13 insertions(+), 49 deletions(-) diff --git a/crates/core/component/dex/src/swap/ciphertext.rs b/crates/core/component/dex/src/swap/ciphertext.rs index 54d1941167..5594c9dcfd 100644 --- a/crates/core/component/dex/src/swap/ciphertext.rs +++ b/crates/core/component/dex/src/swap/ciphertext.rs @@ -15,17 +15,13 @@ impl SwapCiphertext { commitment: note::StateCommitment, ) -> Result { let payload_key = PayloadKey::derive_swap(ovk, commitment); - self.decrypt_with_payload_key(&payload_key, commitment) + self.decrypt_with_payload_key(&payload_key) } - pub fn decrypt_with_payload_key( - &self, - payload_key: &PayloadKey, - commitment: note::StateCommitment, - ) -> Result { + pub fn decrypt_with_payload_key(&self, payload_key: &PayloadKey) -> Result { let swap_ciphertext = self.0; let decryption_result = payload_key - .decrypt_swap(swap_ciphertext.to_vec(), commitment) + .decrypt_swap(swap_ciphertext.to_vec()) .map_err(|_| anyhow::anyhow!("unable to decrypt swap ciphertext"))?; // TODO: encapsulate plaintext encoding by making this a diff --git a/crates/core/keys/src/symmetric.rs b/crates/core/keys/src/symmetric.rs index 1e972609f9..4e383d15c3 100644 --- a/crates/core/keys/src/symmetric.rs +++ b/crates/core/keys/src/symmetric.rs @@ -24,29 +24,15 @@ pub enum PayloadKind { Memo, /// Swap is action-scoped. Swap, - /// A LegacySwap is action-scoped, and is the encryption method - /// used prior to the ECC May 2024 audit. This was added to facilitate - /// decryption of legacy swaps. - LegacySwap, } impl PayloadKind { - pub(crate) fn nonce(&self, commitment: Option) -> [u8; 12] { + pub(crate) fn nonce(&self) -> [u8; 12] { match self { Self::Note => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], Self::MemoKey => [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], Self::Swap => [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], Self::Memo => [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - Self::LegacySwap => { - let mut nonce = [0u8; 12]; - nonce[0..12].copy_from_slice( - &commitment - .expect("swaps use the prefix bytes of the swap commitment as a nonce") - .0 - .to_bytes()[0..12], - ); - nonce - } } } } @@ -85,7 +71,7 @@ impl PayloadKey { /// Encrypt a note, memo, or memo key using the `PayloadKey`. pub fn encrypt(&self, plaintext: Vec, kind: PayloadKind) -> Vec { let cipher = ChaCha20Poly1305::new(&self.0); - let nonce_bytes = kind.nonce(None); + let nonce_bytes = kind.nonce(); let nonce = Nonce::from_slice(&nonce_bytes); cipher @@ -97,7 +83,7 @@ impl PayloadKey { pub fn decrypt(&self, ciphertext: Vec, kind: PayloadKind) -> Result> { let cipher = ChaCha20Poly1305::new(&self.0); - let nonce_bytes = kind.nonce(None); + let nonce_bytes = kind.nonce(); let nonce = Nonce::from_slice(&nonce_bytes); cipher @@ -123,7 +109,7 @@ impl PayloadKey { /// Encrypt a swap using the `PayloadKey`. pub fn encrypt_swap(&self, plaintext: Vec) -> Vec { let cipher = ChaCha20Poly1305::new(&self.0); - let nonce_bytes = PayloadKind::Swap.nonce(None); + let nonce_bytes = PayloadKind::Swap.nonce(); let nonce = Nonce::from_slice(&nonce_bytes); cipher @@ -132,28 +118,14 @@ impl PayloadKey { } /// Decrypt a swap using the `PayloadKey`. - /// - /// In order to decrypt swaps encrypted using the legacy method wherein - /// the nonce used is the first 12 bytes of the swap commitment, we try - /// both decryption methods. - pub fn decrypt_swap( - &self, - ciphertext: Vec, - commitment: StateCommitment, - ) -> Result> { + pub fn decrypt_swap(&self, ciphertext: Vec) -> Result> { let cipher = ChaCha20Poly1305::new(&self.0); - let nonce_bytes = PayloadKind::Swap.nonce(None); + let nonce_bytes = PayloadKind::Swap.nonce(); let nonce = Nonce::from_slice(&nonce_bytes); - // First try new method, then try legacy method cipher .decrypt(nonce, ciphertext.as_ref()) - .or_else(|_| { - let nonce_bytes = PayloadKind::LegacySwap.nonce(Some(commitment)); - let nonce = Nonce::from_slice(&nonce_bytes); - cipher.decrypt(nonce, ciphertext.as_ref()) - }) .map_err(|_| anyhow::anyhow!("decryption error")) } } @@ -242,7 +214,7 @@ impl OutgoingCipherKey { // References: // * Section 5.4.3 of the ZCash protocol spec // * Section 2.3 RFC 7539 - let nonce_bytes = kind.nonce(None); + let nonce_bytes = kind.nonce(); let nonce = Nonce::from_slice(&nonce_bytes); cipher @@ -253,7 +225,7 @@ impl OutgoingCipherKey { /// Decrypt key material using the `OutgoingCipherKey`. pub fn decrypt(&self, ciphertext: Vec, kind: PayloadKind) -> Result> { let cipher = ChaCha20Poly1305::new(&self.0); - let nonce_bytes = kind.nonce(None); + let nonce_bytes = kind.nonce(); let nonce = Nonce::from_slice(&nonce_bytes); cipher diff --git a/crates/core/transaction/src/is_action.rs b/crates/core/transaction/src/is_action.rs index 9663bce511..8784d0987c 100644 --- a/crates/core/transaction/src/is_action.rs +++ b/crates/core/transaction/src/is_action.rs @@ -324,12 +324,8 @@ impl IsAction for Swap { let plaintext = txp.payload_keys.get(&commitment).and_then(|payload_key| { // Decrypt swap ciphertext - SwapCiphertext::decrypt_with_payload_key( - &self.body.payload.encrypted_swap, - payload_key, - commitment, - ) - .ok() + SwapCiphertext::decrypt_with_payload_key(&self.body.payload.encrypted_swap, payload_key) + .ok() }); ActionView::Swap(match plaintext {