use anyhow::{Context, Result};
use sequoia_openpgp::packet::Signature;
use sequoia_openpgp::Cert;
use sequoia_openpgp::KeyHandle;
use crate::db::models;
use crate::pgp;
pub(crate) fn check_for_equivalent_revocation(
revocations: Vec<models::Revocation>,
revocation: &Signature,
) -> Result<bool> {
for db_rev in revocations {
let r = pgp::to_signature(db_rev.revocation.as_bytes())
.context("Couldn't re-armor revocation cert from CA db")?;
if revocation.normalized_eq(&r) {
return Ok(true);
}
}
Ok(false)
}
pub(crate) fn validate_revocation(cert: &Cert, revocation: &mut Signature) -> Result<bool> {
let before = cert.primary_key().self_revocations().count();
let revoked = cert.to_owned().insert_packets(revocation.to_owned())?;
let after = revoked.primary_key().self_revocations().count();
if before + 1 != after {
return Ok(false);
}
let key = revoked.primary_key().key();
Ok(revocation.verify_primary_key_revocation(key, key).is_ok())
}
pub(crate) fn search_revocable_cert_by_keyid(
certs: Vec<models::Cert>,
revoc: &mut Signature,
) -> Result<Option<models::Cert>> {
let revoc_keyhandles = revoc.get_issuers();
if revoc_keyhandles.is_empty() {
return Err(anyhow::anyhow!("Signature has no issuer KeyID"));
}
for db_cert in certs {
let c = pgp::to_cert(db_cert.pub_cert.as_bytes())?;
let c_keyid = c.keyid();
if !revoc_keyhandles.contains(&KeyHandle::KeyID(c_keyid)) {
continue;
}
if validate_revocation(&c, revoc)? {
return Ok(Some(db_cert));
}
}
Ok(None)
}