yubikey-cli v0.4.0 (#284)

This commit is contained in:
Tony Arcieri (iqlusion)
2021-07-12 14:33:51 -07:00
committed by GitHub
parent 01e5bba33f
commit 224d346f09
6 changed files with 99 additions and 96 deletions
Generated
+1 -1
View File
@@ -998,7 +998,7 @@ dependencies = [
[[package]] [[package]]
name = "yubikey-cli" name = "yubikey-cli"
version = "0.4.0-pre" version = "0.4.0"
dependencies = [ dependencies = [
"env_logger", "env_logger",
"gumdrop", "gumdrop",
+10 -3
View File
@@ -4,16 +4,23 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 0.4.0 (2021-07-12)
### Changed
- Switch to renamed `yubikey` crate ([#283])
- Bump MSRV to 1.51+ ([#283])
[#283]: https://github.com/iqlusioninc/yubikey.rs/pull/283
## 0.3.0 (2021-03-22) ## 0.3.0 (2021-03-22)
### Changed ### Changed
- Bump `yubikey` dependency to v0.3 ([#240]) - Bump `yubikey-piv` dependency to v0.3 ([#240])
[#240]: https://github.com/iqlusioninc/yubikey.rs/pull/240 [#240]: https://github.com/iqlusioninc/yubikey.rs/pull/240
## 0.2.0 (2021-01-30) ## 0.2.0 (2021-01-30)
### Changed ### Changed
- Bump MSRV to 1.46+ ([#208]) - Bump MSRV to 1.46+ ([#208])
- Bump `yubikey` dependency to v0.2 ([#220]) - Bump `yubikey-piv` dependency to v0.2 ([#220])
[#208]: https://github.com/iqlusioninc/yubikey.rs/pull/208 [#208]: https://github.com/iqlusioninc/yubikey.rs/pull/208
[#220]: https://github.com/iqlusioninc/yubikey.rs/pull/220 [#220]: https://github.com/iqlusioninc/yubikey.rs/pull/220
@@ -23,7 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `status` command ([#72], [#74]) - `status` command ([#72], [#74])
### Changed ### Changed
- Bump `yubikey` to v0.1.0 ([#180]) - Bump `yubikey-piv` to v0.1.0 ([#180])
- Bump `x509-parser` to v0.8 ([#181]) - Bump `x509-parser` to v0.8 ([#181])
- Bump `sha2` to v0.9 ([#182]) - Bump `sha2` to v0.9 ([#182])
- Rename `list` command to `readers`; improve usage ([#71]) - Rename `list` command to `readers`; improve usage ([#71])
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "yubikey-cli" name = "yubikey-cli"
version = "0.4.0-pre" version = "0.4.0"
description = """ description = """
Command-line interface for performing encryption and signing using RSA/ECC keys Command-line interface for performing encryption and signing using RSA/ECC keys
stored on YubiKey devices. stored on YubiKey devices.
+1 -3
View File
@@ -1,13 +1,11 @@
//! Print device status //! Print device status
use crate::terminal::STDOUT; use crate::terminal::{print_cert_info, STDOUT};
use gumdrop::Options; use gumdrop::Options;
use std::io::{self, Write}; use std::io::{self, Write};
use termcolor::{ColorSpec, StandardStreamLock, WriteColor}; use termcolor::{ColorSpec, StandardStreamLock, WriteColor};
use yubikey::{piv::*, YubiKey}; use yubikey::{piv::*, YubiKey};
use crate::print_cert_info;
// String to use for `None` // String to use for `None`
const NONE_STR: &str = "<none>"; const NONE_STR: &str = "<none>";
+6 -85
View File
@@ -1,92 +1,13 @@
//! `yubikey` command-line utility. //! `yubikey` command-line utility.
//!
//! The goal of this tool is to provide functionality similar to `yubico-piv-tool`
//! but implemented in pure Rust.
//!
//! It also serves as a demonstration/example of how to use the `yubikey` crate.
#![forbid(unsafe_code)] #![forbid(unsafe_code)]
#![warn( #![warn(missing_docs, rust_2018_idioms, unused_qualifications)]
missing_docs,
rust_2018_idioms,
unused_lifetimes,
unused_qualifications
)]
#[macro_use] #[macro_use]
pub mod terminal; pub mod terminal;
pub mod commands; pub mod commands;
use log::debug;
use sha2::{Digest, Sha256};
use std::io::{self, Write};
use std::str;
use subtle_encoding::hex;
use termcolor::{ColorSpec, StandardStreamLock, WriteColor};
use x509_parser::parse_x509_certificate;
use yubikey::{certificate::Certificate, piv::*, YubiKey};
/// Write information about certificate found in slot a la yubico-piv-tool output.
pub fn print_cert_info(
yubikey: &mut YubiKey,
slot: SlotId,
stream: &mut StandardStreamLock<'_>,
) -> io::Result<()> {
let cert = match Certificate::read(yubikey, slot) {
Ok(c) => c,
Err(e) => {
debug!("error reading certificate in slot {:?}: {}", slot, e);
return Ok(());
}
};
let buf = cert.into_buffer();
if !buf.is_empty() {
let fingerprint = Sha256::digest(&buf);
let slot_id: u8 = slot.into();
print_cert_attr(stream, "Slot", format!("{:x}", slot_id))?;
match parse_x509_certificate(&buf) {
Ok((_rem, cert)) => {
print_cert_attr(
stream,
"Algorithm",
cert.tbs_certificate.subject_pki.algorithm.algorithm,
)?;
print_cert_attr(stream, "Subject", cert.tbs_certificate.subject)?;
print_cert_attr(stream, "Issuer", cert.tbs_certificate.issuer)?;
print_cert_attr(
stream,
"Fingerprint",
str::from_utf8(hex::encode(fingerprint).as_slice()).unwrap(),
)?;
print_cert_attr(
stream,
"Not Before",
cert.tbs_certificate.validity.not_before.to_rfc2822(),
)?;
print_cert_attr(
stream,
"Not After",
cert.tbs_certificate.validity.not_after.to_rfc2822(),
)?;
}
_ => {
println!("Failed to parse certificate");
return Ok(());
}
};
}
Ok(())
}
/// Print a status attribute
fn print_cert_attr(
stream: &mut StandardStreamLock<'_>,
name: &str,
value: impl ToString,
) -> io::Result<()> {
stream.set_color(ColorSpec::new().set_bold(true))?;
write!(stream, "{:>12}:", name)?;
stream.reset()?;
writeln!(stream, " {}", value.to_string())?;
stream.flush()?;
Ok(())
}
+80 -3
View File
@@ -1,9 +1,17 @@
//! Status messages //! Status messages
use lazy_static::lazy_static; use lazy_static::lazy_static;
use std::io::{self, Write}; use log::debug;
use std::sync::Mutex; use sha2::{Digest, Sha256};
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; use std::{
io::{self, Write},
str,
sync::Mutex,
};
use subtle_encoding::hex;
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, StandardStreamLock, WriteColor};
use x509_parser::parse_x509_certificate;
use yubikey::{certificate::Certificate, piv::*, YubiKey};
/// Print a success status message (in green if colors are enabled) /// Print a success status message (in green if colors are enabled)
#[macro_export] #[macro_export]
@@ -163,3 +171,72 @@ impl Status {
Ok(()) Ok(())
} }
} }
/// Write information about certificate found in slot a la yubico-piv-tool output.
pub fn print_cert_info(
yubikey: &mut YubiKey,
slot: SlotId,
stream: &mut StandardStreamLock<'_>,
) -> io::Result<()> {
let cert = match Certificate::read(yubikey, slot) {
Ok(c) => c,
Err(e) => {
debug!("error reading certificate in slot {:?}: {}", slot, e);
return Ok(());
}
};
let buf = cert.into_buffer();
if !buf.is_empty() {
let fingerprint = Sha256::digest(&buf);
let slot_id: u8 = slot.into();
print_cert_attr(stream, "Slot", format!("{:x}", slot_id))?;
match parse_x509_certificate(&buf) {
Ok((_rem, cert)) => {
print_cert_attr(
stream,
"Algorithm",
cert.tbs_certificate.subject_pki.algorithm.algorithm,
)?;
print_cert_attr(stream, "Subject", cert.tbs_certificate.subject)?;
print_cert_attr(stream, "Issuer", cert.tbs_certificate.issuer)?;
print_cert_attr(
stream,
"Fingerprint",
str::from_utf8(hex::encode(fingerprint).as_slice()).unwrap(),
)?;
print_cert_attr(
stream,
"Not Before",
cert.tbs_certificate.validity.not_before.to_rfc2822(),
)?;
print_cert_attr(
stream,
"Not After",
cert.tbs_certificate.validity.not_after.to_rfc2822(),
)?;
}
_ => {
println!("Failed to parse certificate");
return Ok(());
}
};
}
Ok(())
}
/// Print a status attribute
fn print_cert_attr(
stream: &mut StandardStreamLock<'_>,
name: &str,
value: impl ToString,
) -> io::Result<()> {
stream.set_color(ColorSpec::new().set_bold(true))?;
write!(stream, "{:>12}:", name)?;
stream.reset()?;
writeln!(stream, " {}", value.to_string())?;
stream.flush()?;
Ok(())
}