feat: parse pgp file works

This commit is contained in:
2021-07-10 15:42:38 +08:00
parent a8ca665ce9
commit a7fd036328
4 changed files with 290 additions and 85 deletions

View File

@@ -2,6 +2,13 @@ use clap::{ArgMatches, SubCommand, App, Arg};
use crate::cmd::{Command, CommandError};
use sequoia_openpgp::parse::Parse;
use sequoia_openpgp::parse::{PacketParser, PacketParserResult};
use sequoia_openpgp::Packet;
use sequoia_openpgp::packet::Key;
use chrono::{DateTime, Local};
use openssl::rsa::Rsa;
use sequoia_openpgp::crypto::mpi::PublicKey;
use openssl::bn::BigNum;
use pem::Pem;
pub struct CommandImpl;
@@ -10,107 +17,159 @@ impl Command for CommandImpl {
fn subcommand<'a>(&self) -> App<'a, 'a> {
SubCommand::with_name(self.name()).about("OpenPGP Card List subcommand")
// .arg(Arg::with_name("app-id").long("app-id").default_value("https://example.com").help("App id"))
// .arg(Arg::with_name("timeout").long("timeout").default_value("10").help("Timeout in seconds"))
.arg(Arg::with_name("in").long("in").takes_value(true).help("File input"))
.arg(Arg::with_name("detail").long("detail").help("Detail output"))
.arg(Arg::with_name("json").long("json").help("JSON output"))
}
fn run(&self, _arg_matches: &ArgMatches, _sub_arg_matches: &ArgMatches) -> CommandError {
let p = PacketParser::from_bytes(b"-----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: GPGTools - https://gpgtools.org
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
let in_file = sub_arg_matches.value_of("in");
let show_detail = sub_arg_matches.is_present("detail");
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
=HzsD
-----END PGP PUBLIC KEY BLOCK-----");
// TODO ...
let mut ppr = p.unwrap();
let in_file = match in_file {
Some(i) => i,
None => return simple_error!("Input file must assined"),
};
let in_file_bytes = opt_result!(std::fs::read(in_file), "Read file: {}, failed: {}", in_file);
let p = PacketParser::from_bytes(&in_file_bytes);
let mut ppr = opt_result!(p, "Parse file: {}, failed: {}", in_file);
while let PacketParserResult::Some(pp) = ppr {
success!(">> >> {:?}", &pp.packet);
// Start parsing the next packet, recursing.
match &pp.packet {
Packet::Signature(signature) => {
debugging!("Found signature: {:?}", signature);
information!("Found signature: {:?} - {:?} [{:?}]", signature.get_issuers(), signature.hash_algo(), signature.features());
}
Packet::OnePassSig(one_pass_sig) => {
information!("Found one pass sig: {:?}", one_pass_sig);
}
Packet::PublicKey(public_key) => {
debugging!("Found public key: {:?}", public_key);
match public_key {
Key::V4(key4) => {
let mut public_key4 = String::with_capacity(512);
public_key4.push_str(&format!("\n\tKey ID: {:?}", key4.keyid()));
public_key4.push_str(&format!("\n\tFinger print {:?}", key4.fingerprint()));
public_key4.push_str(&format!("\n\tHash algo security: {:?}", key4.hash_algo_security()));
// public_key4.push_str(&format!("\n\tKey handle {:?}", key4.key_handle()));
let creation_time: DateTime<Local> = DateTime::from(key4.creation_time());
let creation_time_str = simpledateformat::fmt("yyyy-MM-dd HH:mm:ss").unwrap().format(&creation_time);
public_key4.push_str(&format!("\n\tCreation time {}", creation_time_str));
public_key4.push_str(&format!("\n\tPublic algo: {:?}", key4.pk_algo()));
if show_detail {
if let Some(pubkey_pem) = public_key_pem(key4.mpis()) {
public_key4.push_str(&format!("\n\tPublic key PEM: {}", pubkey_pem));
}
}
information!("Found public key: {}", public_key4);
}
unknown => warning!("Unknown key: {:?}", unknown),
}
}
Packet::PublicSubkey(public_sub_key) => {
debugging!("Found public sub key: {:?}", public_sub_key);
match public_sub_key {
Key::V4(key4) => {
let mut public_key4 = String::with_capacity(512);
public_key4.push_str(&format!("\n\tKey ID: {:?}", key4.keyid()));
public_key4.push_str(&format!("\n\tFinger print {:?}", key4.fingerprint()));
public_key4.push_str(&format!("\n\tHash algo security: {:?}", key4.hash_algo_security()));
let creation_time: DateTime<Local> = DateTime::from(key4.creation_time());
let creation_time_str = simpledateformat::fmt("yyyy-MM-dd HH:mm:ss").unwrap().format(&creation_time);
public_key4.push_str(&format!("\n\tCreation time {}", creation_time_str));
public_key4.push_str(&format!("\n\tPublic algo: {:?}", key4.pk_algo()));
if show_detail {
if let Some(pubkey_pem) = public_key_pem(key4.mpis()) {
public_key4.push_str(&format!("\n\tPublic key PEM: {}", pubkey_pem));
}
}
information!("Found public key: {}", public_key4);
}
unknown => warning!("Unknown key: {:?}", unknown),
}
}
Packet::SecretKey(secret_key) => {
information!("Found secret key: {:?}", secret_key);
}
Packet::SecretSubkey(secret_sub_key) => {
information!("Found secret sub key: {:?}", secret_sub_key);
}
Packet::Marker(marker) => {
information!("Found marker: {:?}", marker);
}
Packet::Trust(trust) => {
information!("Found trust: {:?}", trust);
}
Packet::UserID(user_id) => {
information!("Found user ID: {}", String::from_utf8_lossy(user_id.value()));
}
Packet::UserAttribute(user_attribute) => {
information!("Found user attribute: {:?}", user_attribute);
}
Packet::Literal(literal) => {
information!("Found literal: {:?}", literal);
}
Packet::CompressedData(compressed_data) => {
information!("Found compressed data: {:?}", compressed_data);
}
Packet::PKESK(pkesk) => {
information!("Found PKESK: {:?}", pkesk);
}
Packet::SKESK(skesk) => {
information!("Found SKESK: {:?}", skesk);
}
Packet::SEIP(seip) => {
information!("Found SEIP: {:?}", seip);
}
Packet::MDC(mdc) => {
information!("Found MDC: {:?}", mdc);
}
Packet::AED(aed) => {
information!("Found AED: {:?}", aed);
}
Packet::Unknown(unknown) => {
warning!("Found unknown: {:?}", unknown);
}
unknown => {
warning!("Found UNKNOWN: {:?}", unknown);
}
}
ppr = pp.recurse()?.1;
}
if let PacketParserResult::EOF(eof) = ppr {
// information!("{:?}", eof);
debugging!("{:?}", eof);
if eof.is_message().is_ok() {
information!("IS MESSAGE");
information!("FILE IS MESSAGE");
} else if eof.is_cert().is_ok() {
information!("IS CERT");
information!("FILE IS CERT");
} else if eof.is_keyring().is_ok() {
information!("IS KEYRING");
information!("FILE IS KEYRING");
} else {
information!("IS OTHER");
information!("FILE IS OTHER");
}
}
Ok(())
}
}
fn public_key_pem(public_key: &PublicKey) -> Option<String> {
match public_key {
PublicKey::RSA { e, n } => {
let rr = Rsa::from_public_components(
BigNum::from_slice(n.value()).unwrap(),
BigNum::from_slice(e.value()).unwrap(),
);
let pubkey_pem_obj = Pem {
tag: String::from("RSA PUBLIC KEY"),
contents: rr.unwrap().public_key_to_der().unwrap(),
};
Some(pem::encode(&pubkey_pem_obj))
}
_ => {
warning!("Not rsa public key: {:?}", public_key);
None
}
}
}