use crate::traits::{EnvelopeEncryptedData, KeyStore, LabelResolver};
use anyhow::{anyhow, Result};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct EncryptedLabelGroup {
pub label: String,
pub envelope: Option<EnvelopeEncryptedData>,
}
impl EncryptedLabelGroup {
pub fn is_empty(&self) -> bool {
match &self.envelope {
Some(env) => env.encrypted_data.is_empty(),
None => true,
}
}
}
pub fn encrypt_label_group<T: Serialize>(
label: &str,
fields_struct: &T,
keystore: &KeyStore,
resolver: &dyn LabelResolver,
) -> Result<EncryptedLabelGroup> {
let plain_bytes = serde_cbor::to_vec(fields_struct)?;
let info = resolver
.resolve_label_info(label)?
.ok_or_else(|| anyhow!("Label '{label}' not available in current context"))?;
let envelope = keystore.encrypt_with_envelope(
&plain_bytes,
info.network_id.as_deref(),
info.profile_public_keys,
)?;
Ok(EncryptedLabelGroup {
label: label.to_string(),
envelope: Some(envelope),
})
}
pub fn decrypt_label_group<T: for<'de> Deserialize<'de> + Default>(
encrypted_group: &EncryptedLabelGroup,
keystore: &KeyStore,
) -> Result<T> {
if encrypted_group.is_empty() {
return Err(anyhow!("Empty encrypted group"));
}
let env = encrypted_group
.envelope
.as_ref()
.ok_or_else(|| anyhow!("Empty encrypted group"))?;
let plaintext = keystore.decrypt_envelope_data(env)?;
let fields_struct: T = serde_cbor::from_slice(&plaintext)?;
Ok(fields_struct)
}
pub fn decrypt_bytes(bytes: &[u8], keystore: &Arc<KeyStore>) -> anyhow::Result<Vec<u8>> {
let env: EnvelopeEncryptedData = serde_cbor::from_slice(bytes).map_err(|e| anyhow!(e))?;
keystore.decrypt_envelope_data(&env).map_err(|e| anyhow!(e))
}