From c9ab9820a8afa271754397e7ce8ff344955e0c62 Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Mon, 4 Apr 2022 15:42:55 +0800 Subject: [PATCH] feat: v1.1.5, piv display public key pem --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/cmd_piv.rs | 38 +++++++++++++++++++++++++++----------- src/cmd_pivsign.rs | 1 + 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 20de577..3704e59 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -384,7 +384,7 @@ dependencies = [ [[package]] name = "card-cli" -version = "1.1.4" +version = "1.1.5" dependencies = [ "authenticator", "base64 0.13.0", diff --git a/Cargo.toml b/Cargo.toml index 60848d6..8799201 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "card-cli" -version = "1.1.4" +version = "1.1.5" authors = ["Hatter Jiang "] edition = "2018" diff --git a/src/cmd_piv.rs b/src/cmd_piv.rs index bd15414..7acf7a5 100644 --- a/src/cmd_piv.rs +++ b/src/cmd_piv.rs @@ -26,6 +26,8 @@ impl Command for CommandImpl { fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError { let detail_output = sub_arg_matches.is_present("detail"); + let show_config = sub_arg_matches.is_present("show-config"); + let mut yk = opt_result!(YubiKey::open(), "YubiKey not found: {}"); success!("Name: {}", yk.name()); information!("Version: {}", yk.version()); @@ -42,7 +44,7 @@ impl Command for CommandImpl { Ok(pin_retries) => information!("PIN retries: {}",pin_retries), Err(e) => warning!("PIN retries: {}", e), } - if sub_arg_matches.is_present("show-config") { + if show_config { let config = yk.config(); information!("Config: {:#?}", config); } @@ -51,7 +53,7 @@ impl Command for CommandImpl { Ok(keys) => { information!("Found {} PIV keys", keys.len()); if detail_output { - keys.iter().for_each(|k| information!("Found key: {:?}", k)); + keys.iter().for_each(|k| debugging!("Found key: {:?}", k)); } } Err(e) => failure!("Get PIV keys failed: {}", e) @@ -73,14 +75,14 @@ fn print_cert_info(yubikey: &mut YubiKey, slot: SlotId, detail_output: bool) -> return simple_error!("error reading certificate in slot {:?}: {}", slot, e); } }; - let buf = cert.into_buffer(); + let buf = cert.as_ref().clone(); if !buf.is_empty() { information!("{}", "-".repeat(88)); - let fingerprint_sha256 = Sha256::digest(&*buf); + let certificate_fingerprint_sha256 = Sha256::digest(buf); let slot_id: u8 = slot.into(); - success!("Slot: {:?}, id: {:x}", slot, slot_id); + success!("Slot: {:?}, id: {:x}, algorithm: {:?}", slot, slot_id, cert.subject_pki().algorithm()); let cert_pem_obj = Pem { tag: String::from("CERTIFICATE"), @@ -96,12 +98,26 @@ fn print_cert_info(yubikey: &mut YubiKey, slot: SlotId, detail_output: bool) -> match parse_x509_certificate(&buf) { Ok((_rem, cert)) => { - success!("Algorithm: {}", cert.tbs_certificate.subject_pki.algorithm.algorithm); + information!("Algorithm: {}", cert.tbs_certificate.subject_pki.algorithm.algorithm); - success!("Subject: {}", cert.tbs_certificate.subject); - success!("Issuer: {}", cert.tbs_certificate.issuer); - success!("Fingerprint(SHA256): {}", hex::encode(fingerprint_sha256)); - success!("Not Before: {}", cert.tbs_certificate.validity.not_before.to_rfc2822()); + let public_key_fingerprint_sha256 = Sha256::digest(cert.tbs_certificate.subject_pki.raw); + let cert_public_key_pem_obj = Pem { + tag: String::from("PUBLIC KEY"), + contents: cert.tbs_certificate.subject_pki.raw.to_vec(), + }; + if detail_output { + information!("{}", pem::encode(&cert_public_key_pem_obj).trim()); + } else { + rust_util::util_msg::when(MessageType::DEBUG, || { + debugging!("{}", pem::encode(&cert_pem_obj).trim()); + }); + } + + information!("Subject: {}", cert.tbs_certificate.subject); + information!("Issuer: {}", cert.tbs_certificate.issuer); + information!("Certificate fingerprint(SHA256): {}", hex::encode(certificate_fingerprint_sha256)); + information!("Public key fingerprint(SHA256): {}", hex::encode(public_key_fingerprint_sha256)); + information!("Not Before: {}", cert.tbs_certificate.validity.not_before.to_rfc2822()); let mut not_after_desc = String::new(); let not_after_timestamp = cert.tbs_certificate.validity.not_after.timestamp(); @@ -113,7 +129,7 @@ fn print_cert_info(yubikey: &mut YubiKey, slot: SlotId, detail_output: bool) -> let valid_time = simpledateformat::format_human(Duration::from_secs((not_after_timestamp - now_timestamp) as u64)); not_after_desc.push_str(&format!("(left {})", valid_time)); } - success!("Not After: {} {}", cert.tbs_certificate.validity.not_after.to_rfc2822(), not_after_desc); + information!("Not After: {} {}", cert.tbs_certificate.validity.not_after.to_rfc2822(), not_after_desc); } _ => { warning!("Failed to parse certificate"); diff --git a/src/cmd_pivsign.rs b/src/cmd_pivsign.rs index 276e2e6..d89f8ea 100644 --- a/src/cmd_pivsign.rs +++ b/src/cmd_pivsign.rs @@ -28,6 +28,7 @@ impl Command for CommandImpl { let mut yk = opt_result!(YubiKey::open(), "YubiKey not found: {}"); opt_result!(yk.verify_pin(pin.as_bytes()), "YubiKey verify pin failed: {}"); + // TODO make PKCS#1_5 padding signature let raw_in = [1_u8; 256]; let sign_result = yubikey::piv::sign_data(&mut yk, &raw_in, AlgorithmId::Rsa2048, SlotId::Signature); let sign = opt_result!(sign_result, "Sign data failed: {}");