From e81809d39fa60d36def8889bba576f3f34885d03 Mon Sep 17 00:00:00 2001 From: narodnik Date: Mon, 15 Aug 2022 13:26:13 +0200 Subject: [PATCH] forgot to add note.rs in last commit --- bin/daod/src/note.rs | 96 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 bin/daod/src/note.rs diff --git a/bin/daod/src/note.rs b/bin/daod/src/note.rs new file mode 100644 index 000000000..e30420430 --- /dev/null +++ b/bin/daod/src/note.rs @@ -0,0 +1,96 @@ +use crypto_api_chachapoly::ChachaPolyIetf; +use rand::rngs::OsRng; + +use darkfi::{ + crypto::{ + diffie_hellman::{kdf_sapling, sapling_ka_agree}, + keypair::{PublicKey, SecretKey}, + types::{DrkCoinBlind, DrkSerial, DrkTokenId, DrkValueBlind}, + }, + util::serial::{Decodable, Encodable, SerialDecodable, SerialEncodable}, + Error, Result, +}; + +pub const AEAD_TAG_SIZE: usize = 16; + +pub fn encrypt(note: &T, public: &PublicKey) -> Result { + let ephem_secret = SecretKey::random(&mut OsRng); + let ephem_public = PublicKey::from_secret(ephem_secret); + let shared_secret = sapling_ka_agree(&ephem_secret, public); + let key = kdf_sapling(&shared_secret, &ephem_public); + + let mut input = Vec::new(); + note.encode(&mut input)?; + + let mut ciphertext = vec![0; input.len() + AEAD_TAG_SIZE]; + assert_eq!( + ChachaPolyIetf::aead_cipher() + .seal_to(&mut ciphertext, &input, &[], key.as_ref(), &[0u8; 12]) + .unwrap(), + input.len() + AEAD_TAG_SIZE + ); + + Ok(EncryptedNote2 { ciphertext, ephem_public }) +} + +#[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)] +pub struct EncryptedNote2 { + ciphertext: Vec, + ephem_public: PublicKey, +} + +impl EncryptedNote2 { + pub fn decrypt(&self, secret: &SecretKey) -> Result { + let shared_secret = sapling_ka_agree(secret, &self.ephem_public); + let key = kdf_sapling(&shared_secret, &self.ephem_public); + + let mut plaintext = vec![0; self.ciphertext.len()]; + assert_eq!( + ChachaPolyIetf::aead_cipher() + .open_to(&mut plaintext, &self.ciphertext, &[], key.as_ref(), &[0u8; 12]) + .map_err(|_| Error::NoteDecryptionFailed)?, + self.ciphertext.len() - AEAD_TAG_SIZE + ); + + T::decode(&plaintext[..]) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use darkfi::crypto::keypair::Keypair; + use group::ff::Field; + + #[test] + fn test_note_encdec() { + #[derive(SerialEncodable, SerialDecodable)] + struct MyNote { + serial: DrkSerial, + value: u64, + token_id: DrkTokenId, + coin_blind: DrkCoinBlind, + value_blind: DrkValueBlind, + token_blind: DrkValueBlind, + memo: Vec, + } + let note = MyNote { + serial: DrkSerial::random(&mut OsRng), + value: 110, + token_id: DrkTokenId::random(&mut OsRng), + coin_blind: DrkCoinBlind::random(&mut OsRng), + value_blind: DrkValueBlind::random(&mut OsRng), + token_blind: DrkValueBlind::random(&mut OsRng), + memo: vec![32, 223, 231, 3, 1, 1], + }; + + let keypair = Keypair::random(&mut OsRng); + + let encrypted_note = encrypt(¬e, &keypair.public).unwrap(); + let note2: MyNote = encrypted_note.decrypt(&keypair.secret).unwrap(); + assert_eq!(note.value, note2.value); + assert_eq!(note.token_id, note2.token_id); + assert_eq!(note.token_blind, note2.token_blind); + assert_eq!(note.memo, note2.memo); + } +}