use anyhow::Context as _;
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::io::{self, Write};
use std::time::SystemTime;
use sequoia_net::pks;
use sequoia_openpgp as openpgp;
use crate::openpgp::{
armor,
};
use crate::openpgp::types::{
CompressionAlgorithm,
};
use crate::openpgp::cert::prelude::*;
use crate::openpgp::crypto;
use crate::openpgp::{Cert, KeyID, Result};
use crate::openpgp::packet::prelude::*;
use crate::openpgp::parse::{
Parse,
PacketParserResult,
};
use crate::openpgp::parse::stream::*;
use crate::openpgp::serialize::stream::{
Message, Signer, LiteralWriter, Encryptor, Recipient,
Compressor,
padding::Padder,
};
use crate::openpgp::policy::Policy;
use crate::openpgp::types::KeyFlags;
use crate::openpgp::types::RevocationStatus;
use crate::{
Config,
parse_armor_kind,
};
#[cfg(feature = "autocrypt")]
pub mod autocrypt;
pub mod decrypt;
pub use self::decrypt::decrypt;
pub mod sign;
pub use self::sign::sign;
pub mod revoke;
pub mod dump;
pub use self::dump::dump;
mod inspect;
pub use self::inspect::inspect;
pub mod key;
pub mod merge_signatures;
pub use self::merge_signatures::merge_signatures;
pub mod keyring;
pub mod net;
pub mod certify;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum GetKeysOptions {
AllowNotAlive,
AllowRevoked,
}
/// Returns suitable signing keys from a given list of Certs.
fn get_keys<C>(certs: &[C], p: &dyn Policy,
private_key_store: Option<&str>,
timestamp: Option<SystemTime>,
flags: KeyFlags,
options: Option<&[GetKeysOptions]>)
-> Result<Vec<Box<dyn crypto::Signer + Send + Sync>>>
where C: Borrow<Cert>
{
let mut bad = Vec::new();
let options = options.unwrap_or(&[][..]);
let allow_not_alive = options.contains(&GetKeysOptions::AllowNotAlive);
let allow_revoked = options.contains(&GetKeysOptions::AllowRevoked);
let mut keys: Vec<Box<dyn crypto::Signer + Send + Sync>> = Vec::new();
'next_cert: for tsk in certs {
let tsk = tsk.borrow();
let vc = match tsk.with_policy(p, timestamp) {
Ok(vc) => vc,
Err(err) => {
return Err(
err.context(format!("Found no suitable key on {}", tsk)));
}
};
for ka in vc.keys().key_flags(flags.clone()) {
let bad_ = [
! allow_not_alive && matches!(ka.alive(), Err(_)),
! allow_revoked && matches!(ka.revocation_status(),
RevocationStatus::Revoked(_)),
! ka.pk_algo().is_supported(),
];
if bad_.iter().any(|x| *x) {
bad.push((ka.fingerprint(), bad_));
continue;
}
let key = ka.key();
if let Some(secret) = key.optional_secret() {
let unencrypted = match secret {
SecretKeyMaterial::Encrypted(ref e) => {
let password = rpassword::read_password_from_tty(Some(
&format!("Please enter password to decrypt {}/{}: ",
tsk, key