Browse Source

Return edwards::Point from sapling_ka_agree

This matches how sapling_ka_agree and kdf_sapling are defined in the
protocol spec. kdf_sapling also now takes ownership of dhsecret to
discourage use of the sapling_ka_agree output elsewhere.
hush
Jack Grigg 5 years ago
parent
commit
060977fe54
No known key found for this signature in database GPG Key ID: 9E8255172BBF9898
  1. 2
      librustzcash/src/rustzcash.rs
  2. 34
      zcash_primitives/src/note_encryption.rs

2
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
}

34
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<Bls12, PrimeOrder>
where
edwards::Point<Bls12, Unknown>: 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<Bls12, PrimeOrder>) -> Blake2bResult {
fn kdf_sapling(
dhsecret: edwards::Point<Bls12, PrimeOrder>,
epk: &edwards::Point<Bls12, PrimeOrder>,
) -> 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);

Loading…
Cancel
Save