feat: pgp card make

This commit is contained in:
2022-04-06 00:33:40 +08:00
parent 02a9e72a8a
commit e841ba3331
2 changed files with 111 additions and 7 deletions

View File

@@ -1,3 +1,5 @@
use std::time::SystemTime;
use clap::{App, Arg, ArgMatches, SubCommand};
use openpgp::crypto::mpi::ProtectedMPI;
use openpgp::crypto::mpi::PublicKey as MpiPublicKey;
@@ -11,7 +13,9 @@ use openpgp::packet::key::SubordinateRole;
use openpgp::packet::Signature;
use openpgp::packet::signature::subpacket::{SubpacketTag, SubpacketValue};
use openpgp::parse::{PacketParser, PacketParserResult, Parse};
use openpgp_card::OpenPgp;
use openpgp_card::{Error, KeyType, OpenPgp};
use openpgp_card::card_do::KeyGenerationTime;
use openpgp_card::crypto_data::{CardUploadableKey, PrivateKeyMaterial, RSAKey};
use openssl::bn::BigNum;
use rust_util::util_clap::{Command, CommandError};
use rust_util::XResult;
@@ -38,11 +42,85 @@ impl PgpRsaPrivateKeySet {
#[derive(Debug)]
struct PgpRsaPrivateKey {
creation_time_secs: u32,
key_id: KeyID,
fingerprint: Fingerprint,
rsa_private_key: RsaCrt,
}
#[derive(Debug)]
struct RsaKeyCrt {
e: Vec<u8>,
p: Vec<u8>,
q: Vec<u8>,
pq: Vec<u8>,
dp1: Vec<u8>,
dq1: Vec<u8>,
n: Vec<u8>,
}
impl RsaKeyCrt {
fn from(rsa_crt: &RsaCrt) -> Self {
Self {
e: rsa_crt.public_exponent.to_vec(),
p: rsa_crt.prime1.to_vec(),
q: rsa_crt.prime2.to_vec(),
pq: rsa_crt.coefficient.to_vec(),
dp1: rsa_crt.exponent1.to_vec(),
dq1: rsa_crt.exponent2.to_vec(),
n: rsa_crt.modulus.to_vec(),
}
}
}
impl RSAKey for RsaKeyCrt {
fn e(&self) -> &[u8] {
self.e.as_slice()
}
fn p(&self) -> &[u8] {
self.p.as_slice()
}
fn q(&self) -> &[u8] {
self.q.as_slice()
}
fn pq(&self) -> Box<[u8]> {
self.pq.clone().into()
}
fn dp1(&self) -> Box<[u8]> {
self.dp1.clone().into()
}
fn dq1(&self) -> Box<[u8]> {
self.dq1.clone().into()
}
fn n(&self) -> &[u8] {
self.n.as_slice()
}
}
impl CardUploadableKey for PgpRsaPrivateKey {
fn private_key(&self) -> Result<PrivateKeyMaterial, Error> {
Ok(PrivateKeyMaterial::R(Box::new(RsaKeyCrt::from(&self.rsa_private_key))))
}
fn timestamp(&self) -> KeyGenerationTime {
KeyGenerationTime::from(self.creation_time_secs)
}
fn fingerprint(&self) -> Result<openpgp_card::card_do::Fingerprint, Error> {
if let Fingerprint::V4(fingerprint_v4) = self.fingerprint {
Ok(openpgp_card::card_do::Fingerprint::from(fingerprint_v4))
} else {
Err(Error::InternalError("Not supported fingerprint version".to_string()))
}
}
}
pub struct CommandImpl;
impl Command for CommandImpl {
@@ -50,7 +128,7 @@ impl Command for CommandImpl {
fn subcommand<'a>(&self) -> App<'a, 'a> {
SubCommand::with_name(self.name()).about("OpenPGP Card Make subcommand")
// .arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).default_value("12345678").help("OpenPGP card admin pin"))
.arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).default_value("12345678").help("OpenPGP card admin pin"))
.arg(Arg::with_name("pass").long("pass").takes_value(true).required(false).help("Password for PGP secret key"))
.arg(Arg::with_name("in").long("in").takes_value(true).required(false).help("PGP file in"))
.arg(Arg::with_name("force-make").long("force-make").help("Force make OpenPGP card"))
@@ -103,10 +181,14 @@ impl Command for CommandImpl {
}
debugging!("Found PGP RSA private key set: {:?}", pgp_rsa_private_key_set);
success!("Found PGP RSA private keys, signing: {}, encryption: {}, authentication: {}",
pgp_rsa_private_key_set.signing.is_some(),
pgp_rsa_private_key_set.encryption.is_some(),
pgp_rsa_private_key_set.authentication.is_some());
// TODO success logging
if pgp_rsa_private_key_set.signing.is_none() || pgp_rsa_private_key_set.encryption.is_none() || pgp_rsa_private_key_set.authentication.is_none() {
warning!("");// TODO ...
warning!("PGP RSA private keys is not complete!");
return Ok(None);
}
let force_make = sub_arg_matches.is_present("force-make");
@@ -123,7 +205,23 @@ impl Command for CommandImpl {
opt_result!(trans.verify_pw3(pin.as_ref()), "Admin pin verify failed: {}");
success!("Admin pin verify success!");
// trans.key_import()
let signing_key = pgp_rsa_private_key_set.signing.unwrap();
let signing_key_id = signing_key.key_id.clone();
information!("Prepare write PGP signing key, key id: {}", signing_key_id);
opt_result!(trans.key_import(Box::new(signing_key), KeyType::Signing), "Write PGP signing key failed: {}");
success!("Write PGP signing key success, key id: {}", signing_key_id);
let encryption_key = pgp_rsa_private_key_set.encryption.unwrap();
let encryption_key_id = encryption_key.key_id.clone();
information!("Prepare write PGP encryption key, key id: {}", signing_key_id);
opt_result!(trans.key_import(Box::new(encryption_key), KeyType::Decryption), "Write PGP encryption key failed: {}");
success!("Write PGP encryption key success, key id: {}", encryption_key_id);
let authentication_key = pgp_rsa_private_key_set.authentication.unwrap();
let authentication_key_id = authentication_key.key_id.clone();
information!("Prepare write PGP authentication key, key id: {}", signing_key_id);
opt_result!(trans.key_import(Box::new(authentication_key), KeyType::Authentication), "Write PGP authentication key failed: {}");
success!("Write PGP authentication key success, key id: {}", authentication_key_id);
Ok(None)
}
@@ -137,7 +235,12 @@ fn parse_security_sub_key_to_pgp_rsa_private_key(key: &Key<SecretParts, Subordin
return simple_error!("Not RSA public key");
};
// default PGP implementation SHOULD encrypt private keys
let private_key = opt_result!(key.clone().decrypt_secret(&password), "Decrypt private key failed: {}");
// TODO information!("{:?}", key.secret());
let private_key = if key.has_unencrypted_secret() {
key.clone()
} else {
opt_result!(key.clone().decrypt_secret(&password), "Decrypt private key failed: {}")
};
let (p, q) = if let Key::V4(private_key4) = private_key {
if let SecretKeyMaterial::Unencrypted(unencrypted) = private_key4.secret() {
unencrypted.map(|f| {
@@ -158,7 +261,9 @@ fn parse_security_sub_key_to_pgp_rsa_private_key(key: &Key<SecretParts, Subordin
let q = BigNum::from_slice(q.value()).unwrap();
let e = BigNum::from_slice(e.value()).unwrap();
let rsa_crt = opt_result!(RsaCrt::from(p, q, e), "Parse RSA crt failed: {}");
let creation_time_secs = key.creation_time().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs() as u32;
Ok(PgpRsaPrivateKey {
creation_time_secs,
key_id: key.keyid(),
fingerprint: key.fingerprint(),
rsa_private_key: rsa_crt,

View File

@@ -6,7 +6,6 @@ use rust_util::util_clap::{Command, CommandError};
mod fido;
mod digest;
#[allow(unused)] // pending use in pgpcardimport
mod rsautil;
mod pkiutil;
mod pgpcardutil;