diff --git a/Cargo.lock b/Cargo.lock index 3747dde..5d69ec2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -384,7 +384,7 @@ dependencies = [ [[package]] name = "card-cli" -version = "1.2.0" +version = "1.2.1" dependencies = [ "authenticator", "base64 0.13.0", diff --git a/Cargo.toml b/Cargo.toml index d87e1b5..34000d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "card-cli" -version = "1.2.0" +version = "1.2.1" authors = ["Hatter Jiang "] edition = "2018" diff --git a/src/cmd_pgpcardmake.rs b/src/cmd_pgpcardmake.rs index 59a77b0..11d51d9 100644 --- a/src/cmd_pgpcardmake.rs +++ b/src/cmd_pgpcardmake.rs @@ -132,6 +132,8 @@ impl Command for CommandImpl { .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")) + .arg(Arg::with_name("print-public-keys").long("print-public-keys").help("Print public keys")) + .arg(Arg::with_name("print-private-keys").long("print-private-keys").help("Print private keys")) } fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError { @@ -192,6 +194,39 @@ impl Command for CommandImpl { pgp_rsa_private_key_set.encryption.is_some(), pgp_rsa_private_key_set.authentication.is_some()); + let print_private_keys = sub_arg_matches.is_present("print-private-keys"); + let print_public_keys = sub_arg_matches.is_present("print-public-keys"); + if let Some(signing_key) = &pgp_rsa_private_key_set.signing { + if print_private_keys { + let signing_key_pem = opt_result!(signing_key.rsa_private_key.to_pem(), "Signing private key to pem failed: {}"); + information!("Signing key: {}", signing_key_pem); + } + if print_public_keys { + let signing_public_key_pem = opt_result!(signing_key.rsa_private_key.to_public_key_pem(), "Signing public key to pem failed: {}"); + information!("Signing public key: {}", signing_public_key_pem); + } + } + if let Some(encryption_key) = &pgp_rsa_private_key_set.encryption { + if print_private_keys { + let encryption_key_pem = opt_result!(encryption_key.rsa_private_key.to_pem(), "Encryption private key to pem failed: {}"); + information!("Encryption key: {}", encryption_key_pem); + } + if print_public_keys { + let encryption_public_key_pem = opt_result!(encryption_key.rsa_private_key.to_public_key_pem(), "Encryption public key to pem failed: {}"); + information!("Encryption public key: {}", encryption_public_key_pem); + } + } + if let Some(authentication_key) = &pgp_rsa_private_key_set.authentication { + if print_private_keys { + let authentication_key_pem = opt_result!(authentication_key.rsa_private_key.to_pem(), "Authentication private key to pem failed: {}"); + information!("Authentication key: {}", authentication_key_pem); + } + if print_public_keys { + let authentication_public_key_pem = opt_result!(authentication_key.rsa_private_key.to_public_key_pem(), "Authentication public key to pem failed: {}"); + information!("Authentication public key: {}", authentication_public_key_pem); + } + } + let force_make = sub_arg_matches.is_present("force-make"); if !force_make { warning!("Force make is OFF, add argument --force-make to open, skip write private keys to card!"); diff --git a/src/pkiutil.rs b/src/pkiutil.rs index a6b688d..1ac99b4 100644 --- a/src/pkiutil.rs +++ b/src/pkiutil.rs @@ -17,7 +17,7 @@ pub fn bytes_to_pem(tag: &str, contents: T) -> String where T: Into> pub fn sequoia_openpgp_public_key_pem(public_key: &PublicKey) -> Option<(Vec, String)> { match public_key { PublicKey::RSA { e, n } => { - Some(internal_rsa_public_key_pem(n.value(), e.value())) + Some(rsa_public_key_pem(n.value(), e.value())) } _ => { warning!("Not RSA public key: {:?}", public_key); @@ -29,7 +29,7 @@ pub fn sequoia_openpgp_public_key_pem(public_key: &PublicKey) -> Option<(Vec pub fn openpgp_card_public_key_pem(public_key: &PublicKeyMaterial) -> Option<(Vec, String)> { match public_key { PublicKeyMaterial::R(rsa_pub) => { - Some(internal_rsa_public_key_pem(rsa_pub.n(), rsa_pub.v())) + Some(rsa_public_key_pem(rsa_pub.n(), rsa_pub.v())) } _ => { warning!("Not RSA public key: {:?}", public_key); @@ -38,7 +38,7 @@ pub fn openpgp_card_public_key_pem(public_key: &PublicKeyMaterial) -> Option<(Ve } } -fn internal_rsa_public_key_pem(n: &[u8], e: &[u8]) -> (Vec, String) { +pub fn rsa_public_key_pem(n: &[u8], e: &[u8]) -> (Vec, String) { let rsa_pub_key = Rsa::from_public_components( BigNum::from_slice(n).unwrap(), BigNum::from_slice(e).unwrap(), @@ -47,3 +47,4 @@ fn internal_rsa_public_key_pem(n: &[u8], e: &[u8]) -> (Vec, String) { let rsa_pub_key_bytes_sha256 = sha256_bytes(&rsa_pub_key_bytes); (rsa_pub_key_bytes_sha256, bytes_to_pem("PUBLIC KEY", rsa_pub_key_bytes)) } + diff --git a/src/rsautil.rs b/src/rsautil.rs index 119cae4..ad70f2a 100644 --- a/src/rsautil.rs +++ b/src/rsautil.rs @@ -1,5 +1,6 @@ use openssl::bn::{BigNum, BigNumContext}; -use openssl::rsa::Padding; +use openssl::pkey::PKey; +use openssl::rsa::{Padding, Rsa}; use rust_util::XResult; #[derive(Debug)] @@ -26,6 +27,31 @@ impl RsaCrt { pub fn from(p: BigNum, q: BigNum, e: BigNum) -> XResult { Ok(opt_result!( inner_from(p, q, e), "Calc RsaCrt failed: {}")) } + + pub fn to_public_key_pem(&self) -> XResult { + Ok(crate::pkiutil::rsa_public_key_pem( + clone_big_num(&self.modulus)?.to_vec().as_slice(), + clone_big_num(&self.public_exponent)?.to_vec().as_slice(), + ).1) + } + + pub fn to_pem(&self) -> XResult { + let private_key = opt_result!(Rsa::from_private_components( + clone_big_num(&self.modulus)?, + clone_big_num(&self.public_exponent)?, + clone_big_num(&self.private_exponent)?, + clone_big_num(&self.prime1)?, + clone_big_num(&self.prime2)?, + clone_big_num(&self.exponent1)?, + clone_big_num(&self.exponent2)?, + clone_big_num(&self.coefficient)?, + ), "From private components failed: {}"); + let private_pkey = opt_result!(PKey::from_rsa(private_key), "From rsa to pkey failed: {}"); + // let k = private_key.private_key_to_pem_passphrase(Cipher::aes_128_gcm(), passphrase); + let private_key_pem = opt_result!(private_pkey.private_key_to_pem_pkcs8(), "Private key to pem failed: {}"); + + Ok(opt_result!(String::from_utf8(private_key_pem), "Pem to string failed: {}").trim().to_string()) + } } pub fn clone_big_num(n: &BigNum) -> XResult {