use anyhow::{Result, Error}; use crate::aes_gcm::aead::{Aead, Payload}; use crate::aes_gcm::Nonce; use crate::sp_client::bitcoin::hashes::Hash; use crate::sp_client::silentpayments::utils::SilentPaymentAddress; use crate::crypto::{Aes256Gcm, AnkSharedSecretHash, KeyInit, AAD}; use crate::log; use serde::ser::SerializeStruct; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::collections::HashMap; use std::str::FromStr; #[derive(Debug, Clone, Default, PartialEq)] pub struct SecretsStore{ shared_secrets: HashMap, unconfirmed_secrets: Vec } impl Serialize for SecretsStore { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let mut temp_map = HashMap::with_capacity(self.shared_secrets.len()); for (key, value) in &self.shared_secrets { let key_str = key.to_string(); let value_str = value.to_string(); temp_map.insert(key_str, value_str); } let mut state = serializer.serialize_struct("SecretsStore", 2)?; state.serialize_field("shared_secrets", &temp_map)?; let unconfirmed_secrets_hex: Vec = self .unconfirmed_secrets .iter() .map(|secret| secret.to_string()) .collect(); state.serialize_field("unconfirmed_secrets", &unconfirmed_secrets_hex)?; state.end() } } impl<'de> Deserialize<'de> for SecretsStore { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { // Deserialize the structure as a map #[derive(Deserialize)] struct SecretsStoreHelper { shared_secrets: HashMap, unconfirmed_secrets: Vec, } let helper = SecretsStoreHelper::deserialize(deserializer)?; let mut shared_secrets = HashMap::with_capacity(helper.shared_secrets.len()); for (key_str, value_str) in helper.shared_secrets { let key = SilentPaymentAddress::try_from(key_str).map_err(serde::de::Error::custom)?; // Convert String to SilentPaymentAddress let value = AnkSharedSecretHash::from_str(&value_str).map_err(serde::de::Error::custom)?; // Convert hex string back to Vec shared_secrets.insert(key, value); } let mut unconfirmed_secrets = Vec::with_capacity(helper.unconfirmed_secrets.len()); for secret_str in helper.unconfirmed_secrets { let secret_bytes = AnkSharedSecretHash::from_str(&secret_str).map_err(serde::de::Error::custom)?; unconfirmed_secrets.push(secret_bytes); } Ok(SecretsStore { shared_secrets, unconfirmed_secrets, }) } } impl SecretsStore { pub fn new() -> Self { Self { shared_secrets: HashMap::new(), unconfirmed_secrets: Vec::new() } } pub fn add_unconfirmed_secret(&mut self, new_secret: AnkSharedSecretHash) { self.unconfirmed_secrets.push(new_secret); } pub fn confirm_secret_for_address(&mut self, secret: AnkSharedSecretHash, address: SilentPaymentAddress) { if let Some(pos) = self.unconfirmed_secrets.iter() .position(|s| *s == secret) { self.shared_secrets.insert(address, self.unconfirmed_secrets.swap_remove(pos)); } else { // We didn't know about that secret, just add it // TODO if we already had a secret for this address we just replace it for now self.shared_secrets.insert(address, secret); } } pub fn get_secret_for_address(&self, address: SilentPaymentAddress) -> Option<&AnkSharedSecretHash> { self.shared_secrets.get(&address) } pub fn try_decrypt(&self, cipher: &[u8]) -> Result<(AnkSharedSecretHash, Vec)> { let nonce = Nonce::from_slice(&cipher[..12]); for (address, secret) in self.shared_secrets.iter() { log::debug!("Attempting decryption with key {} for {}", secret, address); let engine = Aes256Gcm::new(secret.as_byte_array().into()); if let Ok(plain) = engine.decrypt( &nonce, Payload { msg: &cipher[12..], aad: AAD, }, ) { return Ok((*secret, plain)); } } // We try unconfirmed secrets for secret in self.unconfirmed_secrets.iter() { log::debug!("Attempting decryption with unconfirmed key {}", secret); let engine = Aes256Gcm::new(secret.as_byte_array().into()); if let Ok(plain) = engine.decrypt( &nonce, Payload { msg: &cipher[12..], aad: AAD, }, ) { return Ok((*secret, plain)); } } Err(Error::msg("Failed to decrypt message")) } }