extern crate sequoia_openpgp as openpgp;
use std::io::{self, Write};
use openpgp::cert::prelude::*;
use openpgp::crypto::SessionKey;
use openpgp::parse::{stream::*, Parse};
use openpgp::policy::Policy;
use openpgp::policy::StandardPolicy as P;
use openpgp::serialize::stream::*;
use openpgp::types::SymmetricAlgorithm;
pub fn generate(email: &str) -> openpgp::Result<openpgp::Cert> {
let (cert, _revocation) = CertBuilder::new()
.add_userid(email)
.add_transport_encryption_subkey()
.generate()?;
Ok(cert)
}
pub fn sign(
signed_message: &mut (dyn Write + Send + Sync),
plaintext: &str,
tsk: &openpgp::Cert,
) -> openpgp::Result<()> {
let policy = &P::new();
let keypair = tsk
.keys()
.unencrypted_secret()
.with_policy(policy, None)
.alive()
.revoked(false)
.for_signing()
.next()
.unwrap()
.key()
.clone()
.into_keypair()?;
let message = Message::new(signed_message);
let message = Signer::new(message, keypair)?.build()?;
let mut message = LiteralWriter::new(message).build()?;
message.write_all(plaintext.as_bytes())?;
message.finalize()?;
Ok(())
}
pub fn encrypt(
ciphertext: &mut (dyn Write + Send + Sync),
plaintext: &str,
recipient: &openpgp::Cert,
) -> openpgp::Result<()> {
let policy = &P::new();
let recipients = recipient
.keys()
.with_policy(policy, None)
.supported()
.alive()
.revoked(false)
.for_transport_encryption();
let message = Message::new(ciphertext);
let message = Encryptor::for_recipients(message, recipients).build()?;
let mut message = LiteralWriter::new(message).build()?;
message.write_all(plaintext.as_bytes())?;
message.finalize()?;
Ok(())
}
pub fn decrypt(
plaintext: &mut dyn Write,
ciphertext: &[u8],
recipient: &openpgp::Cert,
) -> openpgp::Result<()> {
let policy = &P::new();
let helper = Helper {
policy,
secret: recipient,
};
let mut decryptor =
DecryptorBuilder::from_bytes(ciphertext)?.with_policy(policy, None, helper)?;
io::copy(&mut decryptor, plaintext)?;
Ok(())
}
struct Helper<'a> {
policy: &'a dyn Policy,
secret: &'a openpgp::Cert,
}
impl VerificationHelper for Helper<'_> {
fn get_certs(&mut self, _ids: &[openpgp::KeyHandle]) -> openpgp::Result<Vec<openpgp::Cert>> {
Ok(Vec::new())
}
fn check(&mut self, _structure: MessageStructure) -> openpgp::Result<()> {
Ok(())
}
}
impl DecryptionHelper for Helper<'_> {
fn decrypt(
&mut self,
pkesks: &[openpgp::packet::PKESK],
_skesks: &[openpgp::packet::SKESK],
sym_algo: Option<SymmetricAlgorithm>,
decrypt: &mut dyn FnMut(Option<SymmetricAlgorithm>, &SessionKey) -> bool,
) -> openpgp::Result<Option<Cert>> {
let key = self
.secret
.keys()
.unencrypted_secret()
.with_policy(self.policy, None)
.for_transport_encryption()
.nth(0)
.unwrap()
.key()
.clone();
let mut pair = key.into_keypair().unwrap();
pkesks[0]
.decrypt(&mut pair, sym_algo)
.map(|(algo, session_key)| decrypt(algo, &session_key));
Ok(None)
}
}