diff --git a/librustzcash/src/rustzcash.rs b/librustzcash/src/rustzcash.rs index 1c84c8d..da448b0 100644 --- a/librustzcash/src/rustzcash.rs +++ b/librustzcash/src/rustzcash.rs @@ -541,7 +541,7 @@ pub extern "system" fn librustzcash_sapling_ka_agree( // Produce result let result = unsafe { &mut *result }; - result.copy_from_slice(&ka); + ka.write(&mut result[..]).expect("length is not 32 bytes"); true } diff --git a/zcash_primitives/src/note_encryption.rs b/zcash_primitives/src/note_encryption.rs index e4886b3..cffb93f 100644 --- a/zcash_primitives/src/note_encryption.rs +++ b/zcash_primitives/src/note_encryption.rs @@ -149,7 +149,7 @@ fn generate_esk() -> Fs { /// Sapling key agreement for note encryption. /// /// Implements section 5.4.4.3 of the Zcash Protocol Specification. -pub fn sapling_ka_agree<'a, P>(esk: &Fs, pk_d: &'a P) -> [u8; 32] +pub fn sapling_ka_agree<'a, P>(esk: &Fs, pk_d: &'a P) -> edwards::Point where edwards::Point: From<&'a P>, { @@ -159,20 +159,18 @@ where let p = p.mul_by_cofactor(&JUBJUB); // Multiply by esk - let p = p.mul(*esk, &JUBJUB); - - // Produce result - let mut result = [0; 32]; - p.write(&mut result[..]).expect("length is not 32 bytes"); - result + p.mul(*esk, &JUBJUB) } /// Sapling KDF for note encryption. /// /// Implements section 5.4.4.4 of the Zcash Protocol Specification. -fn kdf_sapling(dhsecret: &[u8], epk: &edwards::Point) -> Blake2bResult { +fn kdf_sapling( + dhsecret: edwards::Point, + epk: &edwards::Point, +) -> Blake2bResult { let mut input = [0u8; 64]; - input[0..32].copy_from_slice(&dhsecret); + dhsecret.write(&mut input[0..32]).unwrap(); epk.write(&mut input[32..64]).unwrap(); let mut h = Blake2b::with_params(32, &[], &[], KDF_SAPLING_PERSONALIZATION); @@ -293,7 +291,7 @@ impl SaplingNoteEncryption { /// Generates `encCiphertext` for this note. pub fn encrypt_note_plaintext(&self) -> [u8; ENC_CIPHERTEXT_SIZE] { let shared_secret = sapling_ka_agree(&self.esk, &self.to.pk_d); - let key = kdf_sapling(&shared_secret, &self.epk); + let key = kdf_sapling(shared_secret, &self.epk); // Note plaintext encoding is defined in section 5.5 of the Zcash Protocol // Specification. @@ -394,7 +392,7 @@ pub fn try_sapling_note_decryption( assert_eq!(enc_ciphertext.len(), ENC_CIPHERTEXT_SIZE); let shared_secret = sapling_ka_agree(ivk, epk); - let key = kdf_sapling(&shared_secret, &epk); + let key = kdf_sapling(shared_secret, &epk); let mut plaintext = [0; ENC_CIPHERTEXT_SIZE]; assert_eq!( @@ -436,7 +434,7 @@ pub fn try_sapling_compact_note_decryption( assert_eq!(enc_ciphertext.len(), COMPACT_NOTE_SIZE); let shared_secret = sapling_ka_agree(ivk, epk); - let key = kdf_sapling(&shared_secret, &epk); + let key = kdf_sapling(shared_secret, &epk); // Prefix plaintext with 64 zero-bytes to skip over Poly1305 keying output const CHACHA20_BLOCK_SIZE: usize = 64; @@ -494,7 +492,7 @@ pub fn try_sapling_output_recovery( let esk = Fs::from_repr(esk).ok()?; let shared_secret = sapling_ka_agree(&esk, &pk_d); - let key = kdf_sapling(&shared_secret, &epk); + let key = kdf_sapling(shared_secret, &epk); let mut plaintext = [0; ENC_CIPHERTEXT_SIZE]; assert_eq!( @@ -1009,9 +1007,15 @@ mod tests { // let shared_secret = sapling_ka_agree(&esk, &pk_d); - assert_eq!(shared_secret, tv.shared_secret); + { + let mut encoded = [0; 32]; + shared_secret + .write(&mut encoded[..]) + .expect("length is not 32 bytes"); + assert_eq!(encoded, tv.shared_secret); + } - let k_enc = kdf_sapling(&shared_secret, &epk); + let k_enc = kdf_sapling(shared_secret, &epk); assert_eq!(k_enc.as_bytes(), tv.k_enc); let ovk = OutgoingViewingKey(tv.ovk);