extern crate sequoia_openpgp as openpgp;
use std::io::{self, Write};
use openpgp::parse::{stream::*, Parse};
use openpgp::policy::StandardPolicy as P;
pub fn verify(
plaintext: &mut dyn Write,
signed_message: &[u8],
sender: &openpgp::Cert,
) -> openpgp::Result<()> {
let policy = &P::new();
let helper = Helper { cert: sender };
let mut verifier =
VerifierBuilder::from_bytes(signed_message)?.with_policy(policy, None, helper)?;
io::copy(&mut verifier, plaintext)?;
Ok(())
}
struct Helper<'a> {
cert: &'a openpgp::Cert,
}
impl VerificationHelper for Helper<'_> {
fn get_certs(&mut self, _ids: &[openpgp::KeyHandle]) -> openpgp::Result<Vec<openpgp::Cert>> {
Ok(vec![self.cert.clone()])
}
fn check(&mut self, structure: MessageStructure) -> openpgp::Result<()> {
let mut good = false;
for (i, layer) in structure.into_iter().enumerate() {
match (i, layer) {
(0, MessageLayer::SignatureGroup { results }) => {
match results.into_iter().next() {
Some(Ok(_)) => good = true,
Some(Err(e)) => return Err(openpgp::Error::from(e).into()),
None => return Err(anyhow::anyhow!("No signature")),
}
}
_ => return Err(anyhow::anyhow!("Unexpected message structure")),
}
}
if good {
Ok(()) } else {
Err(anyhow::anyhow!("Signature verification failed"))
}
}
}