Improvements for the sq commandline utility

By David | July 5, 2023

With recent work on Sequoia sq I have focused on improving the user experience (UX) of the commandline interface (CLI) and adding new features for increased feature parity with gpg. These changes are available starting with version 0.31.0.

The effort has been accompanied by a few code refactorings which touch on the subject of making the CLI more composable and safe to use in the future.

This article provides an overview of the new features and improvements.

Adding subkeys

It is now possible to add new subkeys to a certificate using sq key subkey add (!22).

There are three different types of subkeys which may be added:

  • signing: used for signing data
  • authentication: used for authentication (e.g., as an SSH key)
  • encryption: used for storage and/or transport encryption

A subkey may be used for both signing and authentication, but if the subkey is supposed to be used for encryption, it can only be of that type.

Let’s assume Alice has created a certificate as follows:

$ sq key generate --userid "Alice <alice@example.org>" --output alice.key.pgp

She can now add a new authentication subkey:

$ sq key subkey add \
    --output alice-new.key.pgp \
    --can-authenticate \
  alice.key.pgp

Or a new signing subkey:

$ sq key subkey add \
    --output alice-new.key.pgp \
    --can-sign \
  alice.key.pgp

Or a subkey used for both authentication and signing:

$ sq key subkey add \
    --output alice-new.key.pgp \
    --can-authenticate \
    --can-sign \
  alice.key.pgp

Or one used for both storage and transport encryption:

$ sq key subkey add \
    --output alice-new.key.pgp \
    --can-encrypt=universal \
  alice.key.pgp

Setting expiry

To simplify providing expiration dates for new keys and subkeys, the --expires and --expires-in parameters have been unified as --expiry (!22). The new parameter takes either an ISO 8601 timestamp or a custom duration, replacing the previous parameters (respectively).

Let’s assume Alice wants to generate a certificate that is only valid for the next five days. She can use the following:

$ sq key generate \
    --expiry 5d \
    --userid "Alice <alice@example.org>" \
    --output alice.pgp.key

If she wants to create a certificate that expires at a specific point in time, the following will do:

$ sq key generate \
    --expiry "2038‐05‐01T13:37:42Z" \
    --userid "Alice <alice@example.org>" \
    --output alice.pgp.key

Usability improvements

To more closely match the style of the rest of the interface, the revocation commands sq revoke certificate, sq revoke subkey and sq revoke userid have been renamed to sq key revoke, sq key subkey revoke and sq key userid revoke, respectively (!38).

From a usability perspective this bundles actions on certain facilities as commands below a given topic, which lowers cognitive load when using sq. Users can now for example refer to subcommands below sq key subkey for all available commands towards subkeys.

Working with input and output

Over the years sq has gained many features, some of which had first been incubated in other repositories and then added as a whole. As time went by (and CLI tooling in Rust improved along the way), different styles of input and output handling manifested and found their way into the code base. Most of them were based on the String type, which is not the best choice for a cross-platform approach, as platform-aware path handling goes a long way in circumventing file handling issues.

Making use of a more recent clap, I have been able to create a custom type which allows either using stdin/ stdout or a file, by facilitating PathBuf instead of String (!32).

This type (or PathBuf directly) is now used throughout the CLI when handling input and output, which increases robustness and code sharing.

Additionally, the default parameter name for defining output has been consolidated towards --output/ -o (e.g., sq key generate now uses it instead of --export) to streamline the interface.

Output for revocation certificates

Revocations have historically been written to stdout. With sq version 0.31.0 it is now possible to alternatively write them to a file using the --output option.

Let’s assume Alice has created a certificate as follows:

$ sq key generate --userid "Alice <alice@example.org>" --output alice.key.pgp

She can now write a revocation certificate to file if e.g. the certificate has been compromised:

$ sq key revoke \
    --certificate-file alice.key.pgp \
    --output alice.rev \
  compromised \
  "oh no"

Linting keyrings

Thanks to the work of Jan Christian Grünhage, the previously separate tool sq-keyring-linter is now available as sq keyring lint (!29).

To lint a keyring using sq one can now run:

$ sq keyring lint keyring.pgp

Funding

This work is supported by a grant from the NLnet Foundation from the NGI Assure fund, which is financially supported by the European Council.

Financial Support

Since the start of the project over five years ago, the p≡p foundation financially supports the people who work on Sequoia. In 2021, the NLnet foundation awarded us six grants as part of the NGI Assure program.

We are actively looking for additional financial support to diversify our funding.

You don’t need to directly use Sequoia to be positively impacted by it. We’re focused on creating tools for activists, lawyers, and journalists who can’t rely on centralized authentication solutions. So, consider donating. Of course, if your company is using Sequoia, consider sponsoring a developer (or two). Note: if you want to use Sequoia under a license other than the LGPLv2+, please contact the foundation.