use anyhow::Result; use rs_merkle::{algorithms::Sha256, MerkleProof}; use sp_client::silentpayments::{ bitcoin_hashes::{sha256t_hash_newtype, Hash, HashEngine}, secp256k1::PublicKey, }; use aes_gcm::aead::{Aead, Payload}; pub use aes_gcm::{AeadCore, Aes256Gcm, KeyInit}; use rand::{thread_rng, CryptoRng, RngCore}; pub const AAD: &[u8] = "4nk".as_bytes(); sha256t_hash_newtype! { pub struct AnkSharedSecretTag = hash_str("4nk/AnkSharedSecret"); #[hash_newtype(forward)] pub struct AnkSharedSecretHash(_); } impl AnkSharedSecretHash { pub fn from_shared_point(shared_point: PublicKey) -> Self { let mut eng = AnkSharedSecretHash::engine(); eng.input(&shared_point.serialize_uncompressed()[1..]); AnkSharedSecretHash::from_engine(eng) } } pub fn generate_key(rng: &mut (impl CryptoRng + RngCore)) -> [u8; 32] { let key = Aes256Gcm::generate_key(rng); key.into() } pub fn encrypt_with_key(key: &[u8; 32], plaintext: &[u8]) -> Result> { let encryption_eng = Aes256Gcm::new(key.into()); let nonce = Aes256Gcm::generate_nonce(&mut thread_rng()); let payload = Payload { msg: plaintext, aad: AAD, }; let ciphertext = encryption_eng .encrypt(&nonce, payload) .map_err(|e| anyhow::anyhow!(e))?; let mut res: Vec = Vec::with_capacity(nonce.len() + ciphertext.len()); res.extend_from_slice(&nonce); res.extend_from_slice(&ciphertext); Ok(res) } pub fn decrypt_with_key(key: &[u8; 32], ciphertext: &[u8]) -> Result> { let decryption_eng = Aes256Gcm::new(key.into()); let nonce = &ciphertext[..12]; let payload = Payload { msg: &ciphertext[12..], aad: AAD, }; let plaintext = decryption_eng .decrypt(nonce.into(), payload) .map_err(|e| anyhow::anyhow!(e))?; Ok(plaintext) } pub fn verify_merkle_proof(proof: &[u8], root: &[u8; 32], index: usize, hash: &[u8; 32], total_leaves_count: usize) -> Result { let proof = MerkleProof::::from_bytes(proof)?; Ok(proof.verify(*root, &[index], &[*hash], total_leaves_count)) }