Use the decryption helper to decrypt when dumping packets.
This commit is contained in:
parent
0a7a75a102
commit
65bc02e089
@ -92,7 +92,15 @@ pub struct DumpCommand {
|
|||||||
value_name = "SESSION-KEY",
|
value_name = "SESSION-KEY",
|
||||||
help = "Decrypts an encrypted message using SESSION-KEY",
|
help = "Decrypts an encrypted message using SESSION-KEY",
|
||||||
)]
|
)]
|
||||||
pub session_key: Option<SessionKey>,
|
pub session_key: Vec<SessionKey>,
|
||||||
|
|
||||||
|
#[clap(
|
||||||
|
long = "recipient-file",
|
||||||
|
value_name = "KEY_FILE",
|
||||||
|
help = "Decrypts the message using the key in KEY_FILE",
|
||||||
|
)]
|
||||||
|
pub recipient_file: Vec<PathBuf>,
|
||||||
|
|
||||||
#[clap(
|
#[clap(
|
||||||
long = "mpis",
|
long = "mpis",
|
||||||
help = "Prints cryptographic artifacts",
|
help = "Prints cryptographic artifacts",
|
||||||
|
@ -48,15 +48,18 @@ pub fn dispatch(config: Config, command: Command)
|
|||||||
let output_type = command.output;
|
let output_type = command.output;
|
||||||
let mut output = output_type.create_unsafe(config.force)?;
|
let mut output = output_type.create_unsafe(config.force)?;
|
||||||
|
|
||||||
let session_key = command.session_key;
|
|
||||||
let width = if let Some((width, _)) = terminal_size() {
|
let width = if let Some((width, _)) = terminal_size() {
|
||||||
Some(width.0.into())
|
Some(width.0.into())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
dump::dump(&mut input, &mut output,
|
let secrets =
|
||||||
|
load_keys(command.recipient_file.iter().map(|s| s.as_ref()))?;
|
||||||
|
dump::dump(&config,
|
||||||
|
secrets,
|
||||||
|
&mut input, &mut output,
|
||||||
command.mpis, command.hex,
|
command.mpis, command.hex,
|
||||||
session_key.as_ref(), width)?;
|
command.session_key, width)?;
|
||||||
},
|
},
|
||||||
|
|
||||||
Subcommands::Decrypt(command) => {
|
Subcommands::Decrypt(command) => {
|
||||||
|
@ -2,10 +2,9 @@ use std::io::{self, Read};
|
|||||||
|
|
||||||
use sequoia_openpgp as openpgp;
|
use sequoia_openpgp as openpgp;
|
||||||
use openpgp::armor::ReaderMode;
|
use openpgp::armor::ReaderMode;
|
||||||
use self::openpgp::types::SymmetricAlgorithm;
|
|
||||||
use self::openpgp::fmt::hex;
|
use self::openpgp::fmt::hex;
|
||||||
use self::openpgp::crypto::mpi;
|
use self::openpgp::crypto::mpi;
|
||||||
use self::openpgp::{Packet, Result};
|
use self::openpgp::{Cert, Packet, Result};
|
||||||
use self::openpgp::packet::prelude::*;
|
use self::openpgp::packet::prelude::*;
|
||||||
use self::openpgp::packet::header::CTB;
|
use self::openpgp::packet::header::CTB;
|
||||||
use self::openpgp::packet::{Header, header::BodyLength, Signature};
|
use self::openpgp::packet::{Header, header::BodyLength, Signature};
|
||||||
@ -17,6 +16,7 @@ use self::openpgp::parse::{
|
|||||||
PacketParserBuilder,
|
PacketParserBuilder,
|
||||||
PacketParserResult,
|
PacketParserResult,
|
||||||
map::Map,
|
map::Map,
|
||||||
|
stream::DecryptionHelper,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::Convert;
|
use crate::Convert;
|
||||||
@ -33,10 +33,12 @@ pub enum Kind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::redundant_pattern_matching)]
|
#[allow(clippy::redundant_pattern_matching)]
|
||||||
pub fn dump<W>(input: &mut (dyn io::Read + Sync + Send),
|
pub fn dump<W>(config: &crate::Config,
|
||||||
|
secrets: Vec<Cert>,
|
||||||
|
input: &mut (dyn io::Read + Sync + Send),
|
||||||
output: &mut dyn io::Write,
|
output: &mut dyn io::Write,
|
||||||
mpis: bool, hex: bool,
|
mpis: bool, hex: bool,
|
||||||
sk: Option<&SessionKey>,
|
session_keys: Vec<SessionKey>,
|
||||||
width: W)
|
width: W)
|
||||||
-> Result<Kind>
|
-> Result<Kind>
|
||||||
where W: Into<Option<usize>>
|
where W: Into<Option<usize>>
|
||||||
@ -49,10 +51,23 @@ pub fn dump<W>(input: &mut (dyn io::Read + Sync + Send),
|
|||||||
let mut dumper = PacketDumper::new(width, mpis);
|
let mut dumper = PacketDumper::new(width, mpis);
|
||||||
let mut first_armor_block = true;
|
let mut first_armor_block = true;
|
||||||
let mut is_keyring = true;
|
let mut is_keyring = true;
|
||||||
|
let mut helper = crate::commands::decrypt::Helper::new(
|
||||||
|
&config, None, 0, Vec::new(), secrets, session_keys.clone(), false);
|
||||||
|
|
||||||
|
let mut pkesks = vec![];
|
||||||
|
let mut skesks = vec![];
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
while let PacketParserResult::Some(mut pp) = ppr {
|
while let PacketParserResult::Some(mut pp) = ppr {
|
||||||
let additional_fields = match pp.packet {
|
let additional_fields = match pp.packet {
|
||||||
|
Packet::PKESK(ref p) => {
|
||||||
|
pkesks.push(p.clone());
|
||||||
|
vec![]
|
||||||
|
},
|
||||||
|
Packet::SKESK(ref p) => {
|
||||||
|
skesks.push(p.clone());
|
||||||
|
vec![]
|
||||||
|
},
|
||||||
Packet::Literal(_) => {
|
Packet::Literal(_) => {
|
||||||
let mut prefix = vec![0; 40];
|
let mut prefix = vec![0; 40];
|
||||||
let n = pp.read(&mut prefix)?;
|
let n = pp.read(&mut prefix)?;
|
||||||
@ -62,61 +77,44 @@ pub fn dump<W>(input: &mut (dyn io::Read + Sync + Send),
|
|||||||
if n == prefix.len() { "..." } else { "" }),
|
if n == prefix.len() { "..." } else { "" }),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
Packet::SEIP(_) if sk.is_none() => {
|
Packet::SEIP(_) | Packet::AED(_) => {
|
||||||
|
dumper.flush(output)?;
|
||||||
message_encrypted = true;
|
message_encrypted = true;
|
||||||
vec!["No session key supplied".into()]
|
|
||||||
}
|
|
||||||
Packet::SEIP(_) if sk.is_some() => {
|
|
||||||
message_encrypted = true;
|
|
||||||
let sk = sk.unwrap();
|
|
||||||
let decrypted_with = if let Some(algo) = sk.symmetric_algo {
|
|
||||||
// We know which algorithm to use, so only try decrypting
|
|
||||||
// with that one.
|
|
||||||
pp.decrypt(algo, &sk.session_key).is_ok().then(|| algo)
|
|
||||||
} else {
|
|
||||||
// We don't know which algorithm to use,
|
|
||||||
// try to find one that decrypts the message.
|
|
||||||
(1u8..=19)
|
|
||||||
.map(SymmetricAlgorithm::from)
|
|
||||||
.find(|algo| pp.decrypt(*algo, &sk.session_key).is_ok())
|
|
||||||
};
|
|
||||||
|
|
||||||
|
let mut success = false;
|
||||||
let mut fields = Vec::new();
|
let mut fields = Vec::new();
|
||||||
fields.push(format!("Session key: {}", &sk.display_sensitive()));
|
let sym_algo_hint = if let Packet::AED(ref aed) = pp.packet {
|
||||||
if let Some(algo) = decrypted_with {
|
Some(aed.symmetric_algo())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let decryption_proxy = |algo, secret: &_| {
|
||||||
|
// Take the algo from the AED packet over
|
||||||
|
// the dummy one from the SKESK5 packet.
|
||||||
|
let algo = sym_algo_hint.unwrap_or(algo);
|
||||||
|
let result = pp.decrypt(algo, secret);
|
||||||
|
if let Ok(_) = result {
|
||||||
|
fields.push(
|
||||||
|
format!("Session key: {}", &hex::encode(secret)));
|
||||||
fields.push(format!("Symmetric algo: {}", algo));
|
fields.push(format!("Symmetric algo: {}", algo));
|
||||||
fields.push("Decryption successful".into());
|
fields.push("Decryption successful".into());
|
||||||
|
success = true;
|
||||||
|
true
|
||||||
} else {
|
} else {
|
||||||
if let Some(algo) = sk.symmetric_algo {
|
false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(e) = helper.decrypt(&pkesks[..], &skesks[..],
|
||||||
|
sym_algo_hint, decryption_proxy)
|
||||||
|
{
|
||||||
|
for algo in session_keys.iter()
|
||||||
|
.filter_map(|sk| sk.symmetric_algo)
|
||||||
|
{
|
||||||
fields.push(format!(
|
fields.push(format!(
|
||||||
"Indicated Symmetric algo: {}", algo
|
"Indicated Symmetric algo: {}", algo));
|
||||||
));
|
|
||||||
};
|
|
||||||
fields.push("Decryption failed".into());
|
|
||||||
}
|
}
|
||||||
fields
|
fields.push(format!("Decryption failed: {}", e));
|
||||||
},
|
|
||||||
Packet::AED(_) if sk.is_none() => {
|
|
||||||
message_encrypted = true;
|
|
||||||
vec!["No session key supplied".into()]
|
|
||||||
}
|
|
||||||
Packet::AED(_) if sk.is_some() => {
|
|
||||||
message_encrypted = true;
|
|
||||||
let sk = sk.as_ref().unwrap();
|
|
||||||
let algo = if let Packet::AED(ref aed) = pp.packet {
|
|
||||||
aed.symmetric_algo()
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
|
|
||||||
let _ = pp.decrypt(algo, &sk.session_key);
|
|
||||||
|
|
||||||
let mut fields = Vec::new();
|
|
||||||
fields.push(format!("Session key: {}", sk.display_sensitive()));
|
|
||||||
if pp.processed() {
|
|
||||||
fields.push("Decryption successful".into());
|
|
||||||
} else {
|
|
||||||
fields.push("Decryption failed".into());
|
|
||||||
}
|
}
|
||||||
fields
|
fields
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user