use std::collections::HashMap;
use std::ops::Deref;
use crate::auth::certificates::certificate::AuthCertificate;
use crate::auth::error::AuthError;
use crate::wallet::interfaces::{Certificate, WalletInterface};
#[derive(Clone, Debug)]
#[cfg_attr(feature = "network", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "network", serde(rename_all = "camelCase"))]
pub struct VerifiableCertificate {
#[cfg_attr(feature = "network", serde(flatten))]
pub certificate: Certificate,
pub keyring: HashMap<String, String>,
#[cfg_attr(feature = "network", serde(skip_serializing_if = "Option::is_none"))]
pub decrypted_fields: Option<HashMap<String, String>>,
}
impl Deref for VerifiableCertificate {
type Target = Certificate;
fn deref(&self) -> &Self::Target {
&self.certificate
}
}
impl VerifiableCertificate {
pub fn new(certificate: Certificate, keyring: HashMap<String, String>) -> Self {
VerifiableCertificate {
certificate,
keyring,
decrypted_fields: None,
}
}
pub async fn decrypt_fields<W: WalletInterface + ?Sized>(
&mut self,
verifier_wallet: &W,
) -> Result<HashMap<String, String>, AuthError> {
if self.keyring.is_empty() {
return Err(AuthError::CertificateValidation(
"a keyring is required to decrypt certificate fields for the verifier".to_string(),
));
}
let encrypted_fields = self.certificate.fields.clone().unwrap_or_default();
let serial_number = crate::auth::certificates::certificate::base64_encode(
&self.certificate.serial_number.0,
);
let result = AuthCertificate::decrypt_fields(
&encrypted_fields,
&self.keyring,
&serial_number,
&self.certificate.subject,
verifier_wallet,
)
.await
.map_err(|e| {
AuthError::CertificateValidation(format!(
"failed to decrypt selectively revealed certificate fields using keyring: {}",
e
))
})?;
self.decrypted_fields = Some(result.clone());
Ok(result)
}
}