From 2965dcd8cd83016a071feef4dad0e49d300eaf89 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Mon, 17 Oct 2022 23:57:46 +0200 Subject: sq: Add sq keystore list - Implement `sq keystore list` to list all of the keys on the keystore. --- sq/sq-usage.md | 44 +++++++++++++++++++++++++++ sq/src/commands/keystore.rs | 72 +++++++++++++++++++++++++++++++++++++++++++++ sq/src/commands/mod.rs | 1 + sq/src/sq.rs | 4 +++ sq/src/sq_cli/keystore.rs | 42 ++++++++++++++++++++++++++ sq/src/sq_cli/mod.rs | 3 ++ 6 files changed, 166 insertions(+) create mode 100644 sq/src/commands/keystore.rs create mode 100644 sq/src/sq_cli/keystore.rs diff --git a/sq/sq-usage.md b/sq/sq-usage.md index 8eb0fe80..d4b22d77 100644 --- a/sq/sq-usage.md +++ b/sq/sq-usage.md @@ -65,6 +65,8 @@ SUBCOMMANDS: Manages collections of keys or certs certify Certifies a User ID for a Certificate + keystore + Interact with the keystore autocrypt Communicates certificates using Autocrypt keyserver @@ -1190,6 +1192,48 @@ EXAMPLES: $ sq certify juliet.pgp romeo.pgp "" ``` +## Subcommand sq keystore + +```text +Interact with the keystore + +USAGE: + sq keystore + +OPTIONS: + -h, --help + Print help information + +SUBCOMMANDS: + help + Print this message or the help of the given subcommand(s) + list + Lists resources on the keystore + +EXAMPLES: + +# List the keys. +$ sq keystore list +``` + +### Subcommand sq keystore list + +```text +Lists resources on the keystore + +USAGE: + sq keystore list + +OPTIONS: + -h, --help + Print help information + +EXAMPLES: + +# List the keys on the keystore +$ sq keystore list +``` + ## Subcommand sq autocrypt ```text diff --git a/sq/src/commands/keystore.rs b/sq/src/commands/keystore.rs new file mode 100644 index 00000000..e44453db --- /dev/null +++ b/sq/src/commands/keystore.rs @@ -0,0 +1,72 @@ +use sequoia_openpgp as openpgp; +use openpgp::Result; + +use sequoia_keystore as keystore; +use keystore::Keystore; + +use crate::sq_cli; +use crate::Config; + +fn list(_config: Config, _c: sq_cli::keystore::ListCommand) -> Result<()> { + let context = keystore::Context::new()?; + let mut ks = Keystore::connect(&context)?; + + let mut backends = ks.backends()?; + for (b, backend) in backends.iter_mut().enumerate() { + if b > 0 { + eprintln!(""); + } + eprintln!("Backend: {}", backend.id()?); + let devices = backend.list()?; + for mut device in devices { + eprintln!(" Device: {}", device.id()?); + let keys = device.list()?; + for (k, mut key) in keys.into_iter().enumerate() { + let pk = key.public_key().clone(); + let ct = pk.creation_time(); + let ct: chrono::DateTime = ct.into(); + + use openpgp::types::PublicKeyAlgorithm::*; + #[allow(deprecated)] + let bits = match pk.pk_algo() { + RSAEncryptSign + | RSAEncrypt + | RSASign + | ElGamalEncrypt + | DSA + | ElGamalEncryptSign => + pk.mpis().bits().unwrap_or(0).to_string(), + _ => "".to_string(), + }; + + let id = if let Ok(id) = key.id() { + if id != pk.fingerprint().to_string() { + format!(" ({})", id) + } else { + "".into() + } + } else { + "".into() + }; + + eprintln!(" {}. {}{} {} {}{}", + k + 1, + pk.pk_algo(), bits, + pk.fingerprint(), + ct.format("%Y-%m-%d"), + id); + } + } + } + + Ok(()) +} + +pub fn dispatch(config: Config, c: sq_cli::keystore::Command) -> Result<()> { + use sq_cli::keystore::Subcommands::*; + match c.subcommand { + List(sc) => { + list(config, sc) + }, + } +} diff --git a/sq/src/commands/mod.rs b/sq/src/commands/mod.rs index c9219324..ecb37dcd 100644 --- a/sq/src/commands/mod.rs +++ b/sq/src/commands/mod.rs @@ -57,6 +57,7 @@ pub use self::merge_signatures::merge_signatures; pub mod keyring; pub mod net; pub mod certify; +pub mod keystore; #[derive(Debug, Clone, PartialEq, Eq)] pub enum GetKeysOptions { diff --git a/sq/src/sq.rs b/sq/src/sq.rs index 1c4f7016..ff5756e9 100644 --- a/sq/src/sq.rs +++ b/sq/src/sq.rs @@ -745,6 +745,10 @@ fn main() -> Result<()> { SqSubcommands::Certify(command) => { commands::certify::certify(config, command)? } + + SqSubcommands::Keystore(command) => { + commands::keystore::dispatch(config, command)? + } } Ok(()) diff --git a/sq/src/sq_cli/keystore.rs b/sq/src/sq_cli/keystore.rs new file mode 100644 index 00000000..46082471 --- /dev/null +++ b/sq/src/sq_cli/keystore.rs @@ -0,0 +1,42 @@ +use clap::{Args, Parser, Subcommand}; + +#[derive(Parser, Debug)] +#[clap( + name = "keystore", + about = "Interact with the keystore", + long_about = +"Interact with the keystore +", + after_help = +"EXAMPLES: + +# List the keys. +$ sq keystore list +", + subcommand_required = true, + arg_required_else_help = true +)] +pub struct Command { + #[clap(subcommand)] + pub subcommand: Subcommands, +} + + +#[derive(Debug, Subcommand)] +pub enum Subcommands { + List(ListCommand), +} + +#[derive(Debug, Args)] +#[clap( + about = "Lists resources on the keystore", + long_about = "Lists resources on the keystore +", + after_help = "EXAMPLES: + +# List the keys on the keystore +$ sq keystore list +" +)] +pub struct ListCommand { +} diff --git a/sq/src/sq_cli/mod.rs b/sq/src/sq_cli/mod.rs index 5221a2ec..9ff6fcc1 100644 --- a/sq/src/sq_cli/mod.rs +++ b/sq/src/sq_cli/mod.rs @@ -20,6 +20,7 @@ pub mod revoke; mod sign; mod verify; pub mod wkd; +pub mod keystore; pub mod types; @@ -126,6 +127,8 @@ pub enum SqSubcommands { Keyring(keyring::Command), Certify(certify::Command), + Keystore(keystore::Command), + #[cfg(feature = "autocrypt")] Autocrypt(autocrypt::Command), Keyserver(keyserver::Command), -- cgit v1.2.3