zcash_note_encryption: Switch to chacha20poly1305 crate
Extracted from: f03f05f251
This commit is contained in:
parent
6770db186b
commit
b0ff1f9914
|
@ -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"
|
||||||
|
|
112
src/lib.rs
112
src/lib.rs
|
@ -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)?;
|
||||||
|
|
Loading…
Reference in New Issue