mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-07-30 20:11:23 +00:00
Switch to crypto_api_chachapoly crate
This crate exposes both the ChaCha20Poly1305 IETF construction, and the underlying ChaCha20 IETF primitive, removing the need for depending on our own fork of the previous chacha20-poly1305-aead crate.
This commit is contained in:
@@ -7,6 +7,7 @@ authors = [
|
||||
|
||||
[dependencies]
|
||||
byteorder = "1"
|
||||
crypto_api_chachapoly = "0.1"
|
||||
ff = { path = "../ff" }
|
||||
hex = "0.3"
|
||||
lazy_static = "1"
|
||||
@@ -18,7 +19,3 @@ sha2 = "0.8"
|
||||
[dependencies.blake2-rfc]
|
||||
git = "https://github.com/gtank/blake2-rfc"
|
||||
rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9"
|
||||
|
||||
[dependencies.chacha20-poly1305-aead]
|
||||
git = "https://github.com/gtank/chacha20-poly1305-aead"
|
||||
rev = "aefc71f95e8bc43f2070e3c5b08130d9c86bbf4f"
|
||||
|
@@ -3,7 +3,7 @@ extern crate lazy_static;
|
||||
|
||||
extern crate blake2_rfc;
|
||||
extern crate byteorder;
|
||||
extern crate chacha20_poly1305_aead;
|
||||
extern crate crypto_api_chachapoly;
|
||||
extern crate ff;
|
||||
extern crate hex;
|
||||
extern crate pairing;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
use blake2_rfc::blake2b::{Blake2b, Blake2bResult};
|
||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||
use chacha20_poly1305_aead::{self, as_bytes::AsBytes, chacha20::ChaCha20};
|
||||
use crypto_api_chachapoly::{ChaCha20Ietf, ChachaPolyIetf};
|
||||
use ff::{PrimeField, PrimeFieldRepr};
|
||||
use pairing::bls12_381::{Bls12, Fr};
|
||||
use rand::{OsRng, Rng};
|
||||
@@ -240,19 +240,14 @@ impl SaplingNoteEncryption {
|
||||
input.extend_from_slice(&self.memo.0);
|
||||
assert_eq!(input.len(), NOTE_PLAINTEXT_SIZE);
|
||||
|
||||
let mut ciphertext = Vec::with_capacity(NOTE_PLAINTEXT_SIZE);
|
||||
let tag = chacha20_poly1305_aead::encrypt(
|
||||
&key.as_bytes(),
|
||||
&[0u8; 12],
|
||||
&[],
|
||||
&input,
|
||||
&mut ciphertext,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut output = [0u8; ENC_CIPHERTEXT_SIZE];
|
||||
output[0..NOTE_PLAINTEXT_SIZE].copy_from_slice(&ciphertext);
|
||||
output[NOTE_PLAINTEXT_SIZE..ENC_CIPHERTEXT_SIZE].copy_from_slice(&tag);
|
||||
assert_eq!(
|
||||
ChachaPolyIetf::aead_cipher()
|
||||
.seal_to(&mut output, &input, &[], &key.as_bytes(), &[0u8; 12])
|
||||
.unwrap(),
|
||||
ENC_CIPHERTEXT_SIZE
|
||||
);
|
||||
|
||||
output
|
||||
}
|
||||
|
||||
@@ -263,23 +258,26 @@ impl SaplingNoteEncryption {
|
||||
) -> [u8; OUT_CIPHERTEXT_SIZE] {
|
||||
let key = prf_ock(&self.ovk, &cv, &cmu, &self.epk);
|
||||
|
||||
let mut input = [0u8; OUT_PLAINTEXT_SIZE];
|
||||
self.note.pk_d.write(&mut input[0..32]).unwrap();
|
||||
let mut buf = [0u8; OUT_CIPHERTEXT_SIZE];
|
||||
self.note.pk_d.write(&mut buf[0..32]).unwrap();
|
||||
self.esk
|
||||
.into_repr()
|
||||
.write_le(&mut input[32..OUT_PLAINTEXT_SIZE])
|
||||
.write_le(&mut buf[32..OUT_PLAINTEXT_SIZE])
|
||||
.unwrap();
|
||||
|
||||
let mut buffer = Vec::with_capacity(OUT_PLAINTEXT_SIZE);
|
||||
let tag =
|
||||
chacha20_poly1305_aead::encrypt(key.as_bytes(), &[0u8; 12], &[], &input, &mut buffer)
|
||||
.unwrap();
|
||||
|
||||
let mut output = [0u8; OUT_CIPHERTEXT_SIZE];
|
||||
output[0..OUT_PLAINTEXT_SIZE].copy_from_slice(&buffer);
|
||||
output[OUT_PLAINTEXT_SIZE..OUT_CIPHERTEXT_SIZE].copy_from_slice(&tag[..]);
|
||||
|
||||
output
|
||||
assert_eq!(
|
||||
ChachaPolyIetf::aead_cipher()
|
||||
.seal(
|
||||
&mut buf,
|
||||
OUT_PLAINTEXT_SIZE,
|
||||
&[],
|
||||
key.as_bytes(),
|
||||
&[0u8; 12]
|
||||
)
|
||||
.unwrap(),
|
||||
OUT_CIPHERTEXT_SIZE
|
||||
);
|
||||
buf
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,16 +327,19 @@ pub fn try_sapling_note_decryption(
|
||||
let shared_secret = sapling_ka_agree(ivk, epk);
|
||||
let key = kdf_sapling(&shared_secret, &epk);
|
||||
|
||||
let mut plaintext = Vec::with_capacity(NOTE_PLAINTEXT_SIZE);
|
||||
chacha20_poly1305_aead::decrypt(
|
||||
key.as_bytes(),
|
||||
&[0u8; 12],
|
||||
&[],
|
||||
&enc_ciphertext[..NOTE_PLAINTEXT_SIZE],
|
||||
&enc_ciphertext[NOTE_PLAINTEXT_SIZE..],
|
||||
&mut plaintext,
|
||||
)
|
||||
.ok()?;
|
||||
let mut plaintext = vec![0; ENC_CIPHERTEXT_SIZE];
|
||||
assert_eq!(
|
||||
ChachaPolyIetf::aead_cipher()
|
||||
.open_to(
|
||||
&mut plaintext,
|
||||
&enc_ciphertext,
|
||||
&[],
|
||||
key.as_bytes(),
|
||||
&[0u8; 12]
|
||||
)
|
||||
.ok()?,
|
||||
NOTE_PLAINTEXT_SIZE
|
||||
);
|
||||
|
||||
let (note, to) = parse_note_plaintext_minus_memo(ivk, cmu, &plaintext)?;
|
||||
|
||||
@@ -364,18 +365,24 @@ pub fn try_sapling_compact_note_decryption(
|
||||
let shared_secret = sapling_ka_agree(ivk, epk);
|
||||
let key = kdf_sapling(&shared_secret, &epk);
|
||||
|
||||
let mut chacha20 = ChaCha20::new(key.as_bytes(), &[0u8; 12]);
|
||||
// Skip over Poly1305 keying output
|
||||
chacha20.next();
|
||||
|
||||
let mut plaintext = Vec::with_capacity(COMPACT_NOTE_SIZE);
|
||||
// Prefix plaintext with 64 zero-bytes to skip over Poly1305 keying output
|
||||
const CHACHA20_BLOCK_SIZE: usize = 64;
|
||||
let mut plaintext = Vec::with_capacity(CHACHA20_BLOCK_SIZE + COMPACT_NOTE_SIZE);
|
||||
plaintext.extend_from_slice(&[0; CHACHA20_BLOCK_SIZE]);
|
||||
plaintext.extend_from_slice(&enc_ciphertext[0..COMPACT_NOTE_SIZE]);
|
||||
let keystream = chacha20.next();
|
||||
for i in 0..COMPACT_NOTE_SIZE {
|
||||
plaintext[i] ^= keystream.as_bytes()[i];
|
||||
}
|
||||
assert_eq!(
|
||||
ChaCha20Ietf::cipher()
|
||||
.decrypt(
|
||||
&mut plaintext,
|
||||
CHACHA20_BLOCK_SIZE + COMPACT_NOTE_SIZE,
|
||||
key.as_bytes(),
|
||||
&[0u8; 12],
|
||||
)
|
||||
.ok()?,
|
||||
CHACHA20_BLOCK_SIZE + COMPACT_NOTE_SIZE
|
||||
);
|
||||
|
||||
parse_note_plaintext_minus_memo(ivk, cmu, &plaintext)
|
||||
parse_note_plaintext_minus_memo(ivk, cmu, &plaintext[CHACHA20_BLOCK_SIZE..])
|
||||
}
|
||||
|
||||
/// Attempts to decrypt and validate the given `enc_ciphertext` using the given `ovk`.
|
||||
@@ -396,16 +403,13 @@ pub fn try_sapling_output_recovery(
|
||||
|
||||
let ock = prf_ock(&ovk, &cv, &cmu, &epk);
|
||||
|
||||
let mut op = Vec::with_capacity(OUT_PLAINTEXT_SIZE);
|
||||
chacha20_poly1305_aead::decrypt(
|
||||
ock.as_bytes(),
|
||||
&[0u8; 12],
|
||||
&[],
|
||||
&out_ciphertext[..OUT_PLAINTEXT_SIZE],
|
||||
&out_ciphertext[OUT_PLAINTEXT_SIZE..],
|
||||
&mut op,
|
||||
)
|
||||
.ok()?;
|
||||
let mut op = vec![0; OUT_CIPHERTEXT_SIZE];
|
||||
assert_eq!(
|
||||
ChachaPolyIetf::aead_cipher()
|
||||
.open_to(&mut op, &out_ciphertext, &[], ock.as_bytes(), &[0u8; 12])
|
||||
.ok()?,
|
||||
OUT_PLAINTEXT_SIZE
|
||||
);
|
||||
|
||||
let pk_d = edwards::Point::<Bls12, _>::read(&op[0..32], &JUBJUB)
|
||||
.ok()?
|
||||
@@ -418,16 +422,19 @@ pub fn try_sapling_output_recovery(
|
||||
let shared_secret = sapling_ka_agree(&esk, &pk_d);
|
||||
let key = kdf_sapling(&shared_secret, &epk);
|
||||
|
||||
let mut plaintext = Vec::with_capacity(NOTE_PLAINTEXT_SIZE);
|
||||
chacha20_poly1305_aead::decrypt(
|
||||
key.as_bytes(),
|
||||
&[0u8; 12],
|
||||
&[],
|
||||
&enc_ciphertext[..NOTE_PLAINTEXT_SIZE],
|
||||
&enc_ciphertext[NOTE_PLAINTEXT_SIZE..],
|
||||
&mut plaintext,
|
||||
)
|
||||
.ok()?;
|
||||
let mut plaintext = vec![0; ENC_CIPHERTEXT_SIZE];
|
||||
assert_eq!(
|
||||
ChachaPolyIetf::aead_cipher()
|
||||
.open_to(
|
||||
&mut plaintext,
|
||||
&enc_ciphertext,
|
||||
&[],
|
||||
key.as_bytes(),
|
||||
&[0u8; 12]
|
||||
)
|
||||
.ok()?,
|
||||
NOTE_PLAINTEXT_SIZE
|
||||
);
|
||||
|
||||
let mut d = [0u8; 11];
|
||||
d.copy_from_slice(&plaintext[1..12]);
|
||||
@@ -631,6 +638,13 @@ mod tests {
|
||||
let out_ciphertext = ne.encrypt_outgoing_plaintext(&cv, &cmu);
|
||||
|
||||
assert!(try_sapling_note_decryption(&ivk, epk, &cmu, &enc_ciphertext).is_some());
|
||||
assert!(try_sapling_compact_note_decryption(
|
||||
&ivk,
|
||||
epk,
|
||||
&cmu,
|
||||
&enc_ciphertext[..COMPACT_NOTE_SIZE]
|
||||
)
|
||||
.is_some());
|
||||
assert!(try_sapling_output_recovery(
|
||||
&ovk,
|
||||
&cv,
|
||||
|
Reference in New Issue
Block a user