Skip to content

Commit

Permalink
cleanup LegacySwap swap decryption path (#4706)
Browse files Browse the repository at this point in the history
## 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
  • Loading branch information
redshiftzero committed Jul 23, 2024
1 parent 4d2fe9e commit 2ff25a6
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 49 deletions.
10 changes: 3 additions & 7 deletions crates/core/component/dex/src/swap/ciphertext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,13 @@ impl SwapCiphertext {
commitment: note::StateCommitment,
) -> Result<SwapPlaintext> {
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<SwapPlaintext> {
pub fn decrypt_with_payload_key(&self, payload_key: &PayloadKey) -> Result<SwapPlaintext> {
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
Expand Down
44 changes: 8 additions & 36 deletions crates/core/keys/src/symmetric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<StateCommitment>) -> [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
}
}
}
}
Expand Down Expand Up @@ -85,7 +71,7 @@ impl PayloadKey {
/// Encrypt a note, memo, or memo key using the `PayloadKey`.
pub fn encrypt(&self, plaintext: Vec<u8>, kind: PayloadKind) -> Vec<u8> {
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
Expand All @@ -97,7 +83,7 @@ impl PayloadKey {
pub fn decrypt(&self, ciphertext: Vec<u8>, kind: PayloadKind) -> Result<Vec<u8>> {
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
Expand All @@ -123,7 +109,7 @@ impl PayloadKey {
/// Encrypt a swap using the `PayloadKey`.
pub fn encrypt_swap(&self, plaintext: Vec<u8>) -> Vec<u8> {
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
Expand All @@ -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<u8>,
commitment: StateCommitment,
) -> Result<Vec<u8>> {
pub fn decrypt_swap(&self, ciphertext: Vec<u8>) -> Result<Vec<u8>> {
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"))
}
}
Expand Down Expand Up @@ -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
Expand All @@ -253,7 +225,7 @@ impl OutgoingCipherKey {
/// Decrypt key material using the `OutgoingCipherKey`.
pub fn decrypt(&self, ciphertext: Vec<u8>, kind: PayloadKind) -> Result<Vec<u8>> {
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
Expand Down
8 changes: 2 additions & 6 deletions crates/core/transaction/src/is_action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit 2ff25a6

Please sign in to comment.