summaryrefslogtreecommitdiffstats
path: root/sq
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2021-01-28 17:55:41 +0100
committerJustus Winter <justus@sequoia-pgp.org>2021-01-28 17:55:41 +0100
commiteab0f433a0847918ac9d9549cdde3a010e35ceac (patch)
tree156493bec77a72225204f724a9918153e4722c40 /sq
parentba10ed512b11684877f011d67d63431ee6926979 (diff)
sq: Add key extract-cert.
- Fixes #383.
Diffstat (limited to 'sq')
-rw-r--r--sq/src/commands/key.rs14
-rw-r--r--sq/src/sq-usage.rs56
-rw-r--r--sq/src/sq_cli.rs42
3 files changed, 108 insertions, 4 deletions
diff --git a/sq/src/commands/key.rs b/sq/src/commands/key.rs
index b4c51e65..86891954 100644
--- a/sq/src/commands/key.rs
+++ b/sq/src/commands/key.rs
@@ -28,6 +28,7 @@ use crate::decrypt_key;
pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> {
match m.subcommand() {
("generate", Some(m)) => generate(m, config.force)?,
+ ("extract-cert", Some(m)) => extract_cert(config, m)?,
("adopt", Some(m)) => adopt(config, m)?,
("attest-certifications", Some(m)) =>
attest_certifications(config, m)?,
@@ -205,6 +206,19 @@ fn generate(m: &ArgMatches, force: bool) -> Result<()> {
Ok(())
}
+fn extract_cert(config: Config, m: &ArgMatches) -> Result<()> {
+ let input = open_or_stdin(m.value_of("input"))?;
+ let mut output = create_or_stdout(m.value_of("output"), config.force)?;
+
+ let cert = Cert::from_reader(input)?;
+ if m.is_present("binary") {
+ cert.serialize(&mut output)?;
+ } else {
+ cert.armored().serialize(&mut output)?;
+ }
+ Ok(())
+}
+
fn adopt(config: Config, m: &ArgMatches) -> Result<()> {
let input = open_or_stdin(m.value_of("certificate"))?;
let cert = Cert::from_reader(input)?;
diff --git a/sq/src/sq-usage.rs b/sq/src/sq-usage.rs
index 46561f6f..04aea10c 100644
--- a/sq/src/sq-usage.rs
+++ b/sq/src/sq-usage.rs
@@ -324,6 +324,7 @@
//!
//! SUBCOMMANDS:
//! generate Generates a new key
+//! extract-cert Converts a key to a cert
//! attest-certifications Attests to third-party certifications
//! adopt Binds keys from one certificate to another
//! help
@@ -343,6 +344,11 @@
//! This can be used in case the key is superseded, lost, or compromised.
//! It is a good idea to keep a copy of this in a safe place.
//!
+//! After generating a key, use "sq key extract-cert" to get the
+//! certificate corresponding to the key. The key must be kept secure,
+//! while the certificate should be handed out to correspondents, e.g. by
+//! uploading it to a keyserver.
+//!
//! USAGE:
//! sq key generate [FLAGS] [OPTIONS] --export <OUTFILE>
//!
@@ -393,8 +399,11 @@
//!
//! EXAMPLES:
//!
-//! # Generates a key
-//! $ sq key generate --userid "<juliet@example.org>"
+//! # First, this generates a key
+//! $ sq key generate --userid "<juliet@example.org>" --export juliet.key.pgp
+//!
+//! # Then, this extracts the certificate for distribution
+//! $ sq key extract-cert --output juliet.cert.pgp juliet.key.pgp
//!
//! # Generates a key protecting it with a password
//! $ sq key generate --userid "<juliet@example.org>" --with-password
@@ -403,6 +412,49 @@
//! $ sq key generate --userid "<juliet@example.org>" --userid "Juliet Capulet"
//! ```
//!
+//! ### Subcommand key extract-cert
+//!
+//! ```text
+//! Converts a key to a cert
+//!
+//! After generating a key, use this command to get the certificate
+//! corresponding to the key. The key must be kept secure, while the
+//! certificate should be handed out to correspondents, e.g. by uploading
+//! it to a keyserver.
+//!
+//! USAGE:
+//! sq key extract-cert [FLAGS] [OPTIONS] [FILE]
+//!
+//! FLAGS:
+//! -B, --binary
+//! Emits binary data
+//!
+//! -h, --help
+//! Prints help information
+//!
+//! -V, --version
+//! Prints version information
+//!
+//!
+//! OPTIONS:
+//! -o, --output <FILE>
+//! Writes to FILE or stdout if omitted
+//!
+//!
+//! ARGS:
+//! <FILE>
+//! Reads from FILE or stdin if omitted
+//!
+//!
+//! EXAMPLES:
+//!
+//! # First, this generates a key
+//! $ sq key generate --userid "<juliet@example.org>" --export juliet.key.pgp
+//!
+//! # Then, this extracts the certificate for distribution
+//! $ sq key extract-cert --output juliet.cert.pgp juliet.key.pgp
+//! ```
+//!
//! ### Subcommand key attest-certifications
//!
//! ```text
diff --git a/sq/src/sq_cli.rs b/sq/src/sq_cli.rs
index cfa5e366..642418c1 100644
--- a/sq/src/sq_cli.rs
+++ b/sq/src/sq_cli.rs
@@ -462,12 +462,20 @@ but we provide reasonable defaults for most users.
When generating a key, we also generate a revocation certificate.
This can be used in case the key is superseded, lost, or compromised.
It is a good idea to keep a copy of this in a safe place.
+
+After generating a key, use \"sq key extract-cert\" to get the
+certificate corresponding to the key. The key must be kept secure,
+while the certificate should be handed out to correspondents, e.g. by
+uploading it to a keyserver.
")
.after_help(
"EXAMPLES:
-# Generates a key
-$ sq key generate --userid \"<juliet@example.org>\"
+# First, this generates a key
+$ sq key generate --userid \"<juliet@example.org>\" --export juliet.key.pgp
+
+# Then, this extracts the certificate for distribution
+$ sq key extract-cert --output juliet.cert.pgp juliet.key.pgp
# Generates a key protecting it with a password
$ sq key generate --userid \"<juliet@example.org>\" --with-password
@@ -550,6 +558,36 @@ $ sq key generate --userid \"<juliet@example.org>\" --userid \"Juliet Capulet\"
mandatory if OUTFILE is \"-\". \
[default: <OUTFILE>.rev]"))
)
+ .subcommand(SubCommand::with_name("extract-cert")
+ .display_order(110)
+ .about("Converts a key to a cert")
+ .long_about(
+"Converts a key to a cert
+
+After generating a key, use this command to get the certificate
+corresponding to the key. The key must be kept secure, while the
+certificate should be handed out to correspondents, e.g. by uploading
+it to a keyserver.
+")
+ .after_help(
+ "EXAMPLES:
+
+# First, this generates a key
+$ sq key generate --userid \"<juliet@example.org>\" --export juliet.key.pgp
+
+# Then, this extracts the certificate for distribution
+$ sq key extract-cert --output juliet.cert.pgp juliet.key.pgp
+")
+ .arg(Arg::with_name("input")
+ .value_name("FILE")
+ .help("Reads from FILE or stdin if omitted"))
+ .arg(Arg::with_name("output")
+ .short("o").long("output").value_name("FILE")
+ .help("Writes to FILE or stdout if omitted"))
+ .arg(Arg::with_name("binary")
+ .short("B").long("binary")
+ .help("Emits binary data"))
+ )
.subcommand(
SubCommand::with_name("adopt")
.display_order(800)