zcash_note_encryption: Switch to chacha20poly1305 crate

Extracted from: f03f05f251
This commit is contained in:
Jack Grigg 2021-08-30 15:03:39 +01:00
parent 6770db186b
commit b0ff1f9914
2 changed files with 66 additions and 49 deletions

View File

@ -14,7 +14,8 @@ edition = "2018"
[dependencies] [dependencies]
blake2b_simd = "0.5" blake2b_simd = "0.5"
byteorder = "1" byteorder = "1"
crypto_api_chachapoly = "0.4" chacha20 = "0.8"
chacha20poly1305 = "0.9"
ff = "0.10" ff = "0.10"
group = "0.10" group = "0.10"
rand_core = "0.6" rand_core = "0.6"

View File

@ -3,7 +3,16 @@
//! functionality that is shared between the Sapling and Orchard //! functionality that is shared between the Sapling and Orchard
//! protocols. //! protocols.
use crypto_api_chachapoly::{ChaCha20Ietf, ChachaPolyIetf}; use std::convert::TryInto;
use chacha20::{
cipher::{NewCipher, StreamCipher, StreamCipherSeek},
ChaCha20,
};
use chacha20poly1305::{
aead::{AeadInPlace, NewAead},
ChaCha20Poly1305,
};
use rand_core::RngCore; use rand_core::RngCore;
use subtle::{Choice, ConstantTimeEq}; use subtle::{Choice, ConstantTimeEq};
@ -307,12 +316,15 @@ impl<D: Domain> NoteEncryption<D> {
let input = D::note_plaintext_bytes(&self.note, &self.to, &self.memo); let input = D::note_plaintext_bytes(&self.note, &self.to, &self.memo);
let mut output = [0u8; ENC_CIPHERTEXT_SIZE]; let mut output = [0u8; ENC_CIPHERTEXT_SIZE];
assert_eq!( output[..NOTE_PLAINTEXT_SIZE].copy_from_slice(&input.0);
ChachaPolyIetf::aead_cipher() let tag = ChaCha20Poly1305::new(key.as_ref().into())
.seal_to(&mut output, &input.0, &[], key.as_ref(), &[0u8; 12]) .encrypt_in_place_detached(
.unwrap(), [0u8; 12][..].into(),
ENC_CIPHERTEXT_SIZE &[],
); &mut output[..NOTE_PLAINTEXT_SIZE],
)
.unwrap();
output[NOTE_PLAINTEXT_SIZE..].copy_from_slice(&tag);
output output
} }
@ -341,12 +353,11 @@ impl<D: Domain> NoteEncryption<D> {
}; };
let mut output = [0u8; OUT_CIPHERTEXT_SIZE]; let mut output = [0u8; OUT_CIPHERTEXT_SIZE];
assert_eq!( output[..OUT_PLAINTEXT_SIZE].copy_from_slice(&input.0);
ChachaPolyIetf::aead_cipher() let tag = ChaCha20Poly1305::new(ock.as_ref().into())
.seal_to(&mut output, &input.0, &[], ock.as_ref(), &[0u8; 12]) .encrypt_in_place_detached([0u8; 12][..].into(), &[], &mut output[..OUT_PLAINTEXT_SIZE])
.unwrap(), .unwrap();
OUT_CIPHERTEXT_SIZE output[OUT_PLAINTEXT_SIZE..].copy_from_slice(&tag);
);
output output
} }
@ -381,20 +392,20 @@ fn try_note_decryption_inner<D: Domain, Output: ShieldedOutput<D>>(
output: &Output, output: &Output,
key: D::SymmetricKey, key: D::SymmetricKey,
) -> Option<(D::Note, D::Recipient, D::Memo)> { ) -> Option<(D::Note, D::Recipient, D::Memo)> {
assert_eq!(output.enc_ciphertext().len(), ENC_CIPHERTEXT_SIZE); let enc_ciphertext = output.enc_ciphertext();
let mut plaintext = [0; ENC_CIPHERTEXT_SIZE]; assert_eq!(enc_ciphertext.len(), ENC_CIPHERTEXT_SIZE);
assert_eq!(
ChachaPolyIetf::aead_cipher() let mut plaintext: [u8; NOTE_PLAINTEXT_SIZE] =
.open_to( enc_ciphertext[..NOTE_PLAINTEXT_SIZE].try_into().unwrap();
&mut plaintext,
output.enc_ciphertext(), ChaCha20Poly1305::new(key.as_ref().into())
&[], .decrypt_in_place_detached(
key.as_ref(), [0u8; 12][..].into(),
&[0u8; 12] &[],
) &mut plaintext,
.ok()?, enc_ciphertext[NOTE_PLAINTEXT_SIZE..].into(),
NOTE_PLAINTEXT_SIZE )
); .ok()?;
let (note, to) = parse_note_plaintext_without_memo_ivk( let (note, to) = parse_note_plaintext_without_memo_ivk(
domain, domain,
@ -481,7 +492,9 @@ fn try_compact_note_decryption_inner<D: Domain, Output: ShieldedOutput<D>>(
// Start from block 1 to skip over Poly1305 keying output // Start from block 1 to skip over Poly1305 keying output
let mut plaintext = [0; COMPACT_NOTE_SIZE]; let mut plaintext = [0; COMPACT_NOTE_SIZE];
plaintext.copy_from_slice(output.enc_ciphertext()); plaintext.copy_from_slice(output.enc_ciphertext());
ChaCha20Ietf::xor(key.as_ref(), &[0u8; 12], 1, &mut plaintext); let mut keystream = ChaCha20::new(key.as_ref().into(), [0u8; 12][..].into());
keystream.seek(64);
keystream.apply_keystream(&mut plaintext);
parse_note_plaintext_without_memo_ivk( parse_note_plaintext_without_memo_ivk(
domain, domain,
@ -527,16 +540,21 @@ pub fn try_output_recovery_with_ock<D: Domain, Output: ShieldedOutput<D>>(
output: &Output, output: &Output,
out_ciphertext: &[u8], out_ciphertext: &[u8],
) -> Option<(D::Note, D::Recipient, D::Memo)> { ) -> Option<(D::Note, D::Recipient, D::Memo)> {
assert_eq!(output.enc_ciphertext().len(), ENC_CIPHERTEXT_SIZE); let enc_ciphertext = output.enc_ciphertext();
assert_eq!(enc_ciphertext.len(), ENC_CIPHERTEXT_SIZE);
assert_eq!(out_ciphertext.len(), OUT_CIPHERTEXT_SIZE); assert_eq!(out_ciphertext.len(), OUT_CIPHERTEXT_SIZE);
let mut op = [0; OUT_PLAINTEXT_SIZE]; let mut op = [0; OUT_PLAINTEXT_SIZE];
assert_eq!( op.copy_from_slice(&out_ciphertext[..OUT_PLAINTEXT_SIZE]);
ChachaPolyIetf::aead_cipher()
.open_to(&mut op, &out_ciphertext, &[], ock.as_ref(), &[0u8; 12]) ChaCha20Poly1305::new(ock.as_ref().into())
.ok()?, .decrypt_in_place_detached(
OUT_PLAINTEXT_SIZE [0u8; 12][..].into(),
); &[],
&mut op,
out_ciphertext[OUT_PLAINTEXT_SIZE..].into(),
)
.ok()?;
let pk_d = D::extract_pk_d(&op)?; let pk_d = D::extract_pk_d(&op)?;
let esk = D::extract_esk(&op)?; let esk = D::extract_esk(&op)?;
@ -548,19 +566,17 @@ pub fn try_output_recovery_with_ock<D: Domain, Output: ShieldedOutput<D>>(
// be okay. // be okay.
let key = D::kdf(shared_secret, &ephemeral_key); let key = D::kdf(shared_secret, &ephemeral_key);
let mut plaintext = [0; ENC_CIPHERTEXT_SIZE]; let mut plaintext = [0; NOTE_PLAINTEXT_SIZE];
assert_eq!( plaintext.copy_from_slice(&enc_ciphertext[..NOTE_PLAINTEXT_SIZE]);
ChachaPolyIetf::aead_cipher()
.open_to( ChaCha20Poly1305::new(key.as_ref().into())
&mut plaintext, .decrypt_in_place_detached(
output.enc_ciphertext(), [0u8; 12][..].into(),
&[], &[],
key.as_ref(), &mut plaintext,
&[0u8; 12] enc_ciphertext[NOTE_PLAINTEXT_SIZE..].into(),
) )
.ok()?, .ok()?;
NOTE_PLAINTEXT_SIZE
);
let (note, to) = let (note, to) =
domain.parse_note_plaintext_without_memo_ovk(&pk_d, &esk, &ephemeral_key, &plaintext)?; domain.parse_note_plaintext_without_memo_ovk(&pk_d, &esk, &ephemeral_key, &plaintext)?;