summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@pep.foundation>2022-10-17 23:57:46 +0200
committerNeal H. Walfield <neal@pep.foundation>2022-10-17 23:58:33 +0200
commit2965dcd8cd83016a071feef4dad0e49d300eaf89 (patch)
treec2b161a24e2818def1b64c6f68082568e526c653
parentb7149f0ecb129a57c864f4a3e461796d5181045d (diff)
sq: Add sq keystore listneal/secret-keystore
- Implement `sq keystore list` to list all of the keys on the keystore.
-rw-r--r--sq/sq-usage.md44
-rw-r--r--sq/src/commands/keystore.rs72
-rw-r--r--sq/src/commands/mod.rs1
-rw-r--r--sq/src/sq.rs4
-rw-r--r--sq/src/sq_cli/keystore.rs42
-rw-r--r--sq/src/sq_cli/mod.rs3
6 files changed, 166 insertions, 0 deletions
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 "<romeo@example.org>"
```
+## Subcommand sq keystore
+
+```text
+Interact with the keystore
+
+USAGE:
+ sq keystore <SUBCOMMAND>
+
+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<chrono::Utc> = 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),