use std::io::stdout;
use minipgp6::{keygen::generate_tsk, locking::try_unlock_with_passwords};
use minipgp6_armor::{DataType, write::Armorer};
use minipgp6_packet::{
Serialize,
transferable::{Tpk, Tsk},
types::{algorithm::PublicKeyAlgorithm, time::Timestamp},
};
use minipgp6_sign::{data, data::DetachedSignature};
use minipgp6_validity::Checked;
use rand::thread_rng;
fn sign(tsk: &Tsk, data: &[u8]) -> Result<DetachedSignature, Box<dyn std::error::Error>> {
let checked = Checked::from(tsk);
let signers = checked.valid_for_data_signing();
let unlocked_signers: Vec<_> = signers
.into_iter()
.flat_map(|s| try_unlock_with_passwords(s, &[]))
.collect();
let signatures = DetachedSignature::sign_data(thread_rng(), data, &unlocked_signers)?;
assert_eq!(signatures.len(), 1);
if let Some(sig) = signatures.into_iter().next() {
Ok(sig)
} else {
Err("No signature found".into())
}
}
fn verify(
cert: &Tpk,
signature: DetachedSignature,
data: &[u8],
) -> Result<(), Box<dyn std::error::Error>> {
let checked = Checked::from(cert);
let verifiers = checked.valid_for_data_verification_at(Timestamp::now());
let digests = DetachedSignature::digests(&[signature], data)?;
let valid = data::check_digests(&digests, &verifiers)?;
for (_signature, signer) in valid {
eprintln!("- valid signature by {}", signer.fingerprint())
}
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
const PAYLOAD: &str = "hello world";
let mut rng = thread_rng();
let tsk = generate_tsk(
&mut rng,
PublicKeyAlgorithm::Ed25519,
Some(PublicKeyAlgorithm::X25519),
&["alice"],
None,
)?;
eprintln!("Signing the payload {:?}", PAYLOAD);
eprintln!();
let signature = sign(&tsk, PAYLOAD.as_bytes())?;
eprintln!("Signature:");
let mut out = Armorer::new(stdout(), DataType::Signature)?;
signature.to_writer(&mut out)?;
out.finalize()?;
eprintln!();
let cert = Tpk::from(tsk.clone());
eprintln!("OpenPGP certificate:");
let mut out = Armorer::new(stdout(), DataType::Public)?;
cert.to_writer(&mut out)?;
out.finalize()?;
eprintln!();
eprintln!("Verification result:");
verify(&cert, signature, PAYLOAD.as_bytes())?;
Ok(())
}