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]
blake2b_simd = "0.5"
byteorder = "1"
crypto_api_chachapoly = "0.4"
chacha20 = "0.8"
chacha20poly1305 = "0.9"
ff = "0.10"
group = "0.10"
rand_core = "0.6"

View File

@ -3,7 +3,16 @@
//! functionality that is shared between the Sapling and Orchard
//! 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 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 mut output = [0u8; ENC_CIPHERTEXT_SIZE];
assert_eq!(
ChachaPolyIetf::aead_cipher()
.seal_to(&mut output, &input.0, &[], key.as_ref(), &[0u8; 12])
.unwrap(),
ENC_CIPHERTEXT_SIZE
);
output[..NOTE_PLAINTEXT_SIZE].copy_from_slice(&input.0);
let tag = ChaCha20Poly1305::new(key.as_ref().into())
.encrypt_in_place_detached(
[0u8; 12][..].into(),
&[],
&mut output[..NOTE_PLAINTEXT_SIZE],
)
.unwrap();
output[NOTE_PLAINTEXT_SIZE..].copy_from_slice(&tag);
output
}
@ -341,12 +353,11 @@ impl<D: Domain> NoteEncryption<D> {
};
let mut output = [0u8; OUT_CIPHERTEXT_SIZE];
assert_eq!(
ChachaPolyIetf::aead_cipher()
.seal_to(&mut output, &input.0, &[], ock.as_ref(), &[0u8; 12])
.unwrap(),
OUT_CIPHERTEXT_SIZE
);
output[..OUT_PLAINTEXT_SIZE].copy_from_slice(&input.0);
let tag = ChaCha20Poly1305::new(ock.as_ref().into())
.encrypt_in_place_detached([0u8; 12][..].into(), &[], &mut output[..OUT_PLAINTEXT_SIZE])
.unwrap();
output[OUT_PLAINTEXT_SIZE..].copy_from_slice(&tag);
output
}
@ -381,20 +392,20 @@ fn try_note_decryption_inner<D: Domain, Output: ShieldedOutput<D>>(
output: &Output,
key: D::SymmetricKey,
) -> Option<(D::Note, D::Recipient, D::Memo)> {
assert_eq!(output.enc_ciphertext().len(), ENC_CIPHERTEXT_SIZE);
let mut plaintext = [0; ENC_CIPHERTEXT_SIZE];
assert_eq!(
ChachaPolyIetf::aead_cipher()
.open_to(
&mut plaintext,
output.enc_ciphertext(),
&[],
key.as_ref(),
&[0u8; 12]
)
.ok()?,
NOTE_PLAINTEXT_SIZE
);
let enc_ciphertext = output.enc_ciphertext();
assert_eq!(enc_ciphertext.len(), ENC_CIPHERTEXT_SIZE);
let mut plaintext: [u8; NOTE_PLAINTEXT_SIZE] =
enc_ciphertext[..NOTE_PLAINTEXT_SIZE].try_into().unwrap();
ChaCha20Poly1305::new(key.as_ref().into())
.decrypt_in_place_detached(
[0u8; 12][..].into(),
&[],
&mut plaintext,
enc_ciphertext[NOTE_PLAINTEXT_SIZE..].into(),
)
.ok()?;
let (note, to) = parse_note_plaintext_without_memo_ivk(
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
let mut plaintext = [0; COMPACT_NOTE_SIZE];
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(
domain,
@ -527,16 +540,21 @@ pub fn try_output_recovery_with_ock<D: Domain, Output: ShieldedOutput<D>>(
output: &Output,
out_ciphertext: &[u8],
) -> 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);
let mut op = [0; OUT_PLAINTEXT_SIZE];
assert_eq!(
ChachaPolyIetf::aead_cipher()
.open_to(&mut op, &out_ciphertext, &[], ock.as_ref(), &[0u8; 12])
.ok()?,
OUT_PLAINTEXT_SIZE
);
op.copy_from_slice(&out_ciphertext[..OUT_PLAINTEXT_SIZE]);
ChaCha20Poly1305::new(ock.as_ref().into())
.decrypt_in_place_detached(
[0u8; 12][..].into(),
&[],
&mut op,
out_ciphertext[OUT_PLAINTEXT_SIZE..].into(),
)
.ok()?;
let pk_d = D::extract_pk_d(&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.
let key = D::kdf(shared_secret, &ephemeral_key);
let mut plaintext = [0; ENC_CIPHERTEXT_SIZE];
assert_eq!(
ChachaPolyIetf::aead_cipher()
.open_to(
&mut plaintext,
output.enc_ciphertext(),
&[],
key.as_ref(),
&[0u8; 12]
)
.ok()?,
NOTE_PLAINTEXT_SIZE
);
let mut plaintext = [0; NOTE_PLAINTEXT_SIZE];
plaintext.copy_from_slice(&enc_ciphertext[..NOTE_PLAINTEXT_SIZE]);
ChaCha20Poly1305::new(key.as_ref().into())
.decrypt_in_place_detached(
[0u8; 12][..].into(),
&[],
&mut plaintext,
enc_ciphertext[NOTE_PLAINTEXT_SIZE..].into(),
)
.ok()?;
let (note, to) =
domain.parse_note_plaintext_without_memo_ovk(&pk_d, &esk, &ephemeral_key, &plaintext)?;