Add esk check in parse_note_plaintext_without_memo() and try_sapling_output_recovery()
This commit is contained in:
parent
5480a376df
commit
d54fd09c5f
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
jubjub::{
|
jubjub::{
|
||||||
edwards,
|
edwards,
|
||||||
fs::{Fs, FsRepr},
|
fs::{Fs, FsRepr},
|
||||||
PrimeOrder, ToUniform, Unknown,
|
PrimeOrder, Unknown,
|
||||||
},
|
},
|
||||||
primitives::{Diversifier, Note, PaymentAddress, Rseed},
|
primitives::{Diversifier, Note, PaymentAddress, Rseed},
|
||||||
};
|
};
|
||||||
|
@ -20,10 +20,7 @@ use std::convert::TryInto;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
use crate::{
|
use crate::{keys::OutgoingViewingKey, JUBJUB};
|
||||||
keys::{prf_expand, OutgoingViewingKey},
|
|
||||||
JUBJUB,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const KDF_SAPLING_PERSONALIZATION: &[u8; 16] = b"Zcash_SaplingKDF";
|
pub const KDF_SAPLING_PERSONALIZATION: &[u8; 16] = b"Zcash_SaplingKDF";
|
||||||
pub const PRF_OCK_PERSONALIZATION: &[u8; 16] = b"Zcash_Derive_ock";
|
pub const PRF_OCK_PERSONALIZATION: &[u8; 16] = b"Zcash_Derive_ock";
|
||||||
|
@ -346,6 +343,7 @@ impl SaplingNoteEncryption {
|
||||||
fn parse_note_plaintext_without_memo<P: consensus::Parameters>(
|
fn parse_note_plaintext_without_memo<P: consensus::Parameters>(
|
||||||
height: u32,
|
height: u32,
|
||||||
ivk: &Fs,
|
ivk: &Fs,
|
||||||
|
epk: &edwards::Point<Bls12, PrimeOrder>,
|
||||||
cmu: &Fr,
|
cmu: &Fr,
|
||||||
plaintext: &[u8],
|
plaintext: &[u8],
|
||||||
) -> Option<(Note<Bls12>, PaymentAddress<Bls12>)> {
|
) -> Option<(Note<Bls12>, PaymentAddress<Bls12>)> {
|
||||||
|
@ -383,6 +381,13 @@ fn parse_note_plaintext_without_memo<P: consensus::Parameters>(
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Rseed::AfterZip212(_) = note.rseed {
|
||||||
|
let derived_esk = note.derive_esk().unwrap();
|
||||||
|
if note.g_d.mul(derived_esk, &JUBJUB) != *epk {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Some((note, to))
|
Some((note, to))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,15 +445,7 @@ pub fn try_sapling_note_decryption<P: consensus::Parameters>(
|
||||||
NOTE_PLAINTEXT_SIZE
|
NOTE_PLAINTEXT_SIZE
|
||||||
);
|
);
|
||||||
|
|
||||||
let (note, to) = parse_note_plaintext_without_memo::<P>(height, ivk, cmu, &plaintext)?;
|
let (note, to) = parse_note_plaintext_without_memo::<P>(height, ivk, epk, cmu, &plaintext)?;
|
||||||
|
|
||||||
match note.rseed {
|
|
||||||
Rseed::AfterZip212(rseed) => {
|
|
||||||
let derived_esk = Fs::to_uniform(prf_expand(&rseed, &[0x05]).as_bytes());
|
|
||||||
assert_eq!(note.g_d.mul(derived_esk, &JUBJUB), *epk);
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut memo = [0u8; 512];
|
let mut memo = [0u8; 512];
|
||||||
memo.copy_from_slice(&plaintext[COMPACT_NOTE_SIZE..NOTE_PLAINTEXT_SIZE]);
|
memo.copy_from_slice(&plaintext[COMPACT_NOTE_SIZE..NOTE_PLAINTEXT_SIZE]);
|
||||||
|
@ -482,7 +479,7 @@ pub fn try_sapling_compact_note_decryption<P: consensus::Parameters>(
|
||||||
plaintext.copy_from_slice(&enc_ciphertext);
|
plaintext.copy_from_slice(&enc_ciphertext);
|
||||||
ChaCha20Ietf::xor(key.as_bytes(), &[0u8; 12], 1, &mut plaintext);
|
ChaCha20Ietf::xor(key.as_bytes(), &[0u8; 12], 1, &mut plaintext);
|
||||||
|
|
||||||
parse_note_plaintext_without_memo::<P>(height, ivk, cmu, &plaintext)
|
parse_note_plaintext_without_memo::<P>(height, ivk, epk, cmu, &plaintext)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recovery of the full note plaintext by the sender.
|
/// Recovery of the full note plaintext by the sender.
|
||||||
|
@ -583,6 +580,12 @@ pub fn try_sapling_output_recovery<P: consensus::Parameters>(
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Rseed::AfterZip212(_) = note.rseed {
|
||||||
|
if note.derive_esk().unwrap() != esk {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Some((note, to, Memo(memo)))
|
Some((note, to, Memo(memo)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue