#openpgp-card #git #signing #user #pin #verification #oct-git

bin+lib openpgp-card-tool-git

A simple tool for Git signing and verification with a focus on OpenPGP cards

3 unstable releases

0.1.0 May 6, 2024
0.0.2 Apr 30, 2024
0.0.1 Apr 29, 2024

#5 in #openpgp-card

Download history 273/week @ 2024-04-28 147/week @ 2024-05-05 2/week @ 2024-05-12 15/week @ 2024-05-19

172 downloads per month

MIT/Apache

210KB
687 lines

OpenPGP card tool for Git signing and verification

This project provides the oct-git "OpenPGP card tool for Git".

oct-git generates (and verifies) OpenPGP signatures in the context of the Git distributed version control system. It serves as a replacement to the gpg program, for use with Git.

Why

The oct-git tool is a stand-alone, "no-moving-parts" solution, written in pure Rust, based on the rPGP OpenPGP library and Rust Crypto. It aims for simplicity, requires no long-running processes[^pcsc], and doesn't keep a permanent connection to OpenPGP card hardware devices.

[^pcsc]: On Linux, the pcscd system service is required, while on Windows and Mac, a PC/SC subsystem doesn't need to be installed (it is a part of the core system and available by default).

oct-git works natively on Linux, Mac and Windows. It is a new standalone solution and doesn't require (or use) any part of GnuPG.

By contrast, other tools that deal with OpenPGP tend to be complex, have many moving parts (including multiple processes, some of them long-running).

Setup

oct-git is designed specifically for use with the Git version control system, as a helper to perform OpenPGP signing and verification. Users will typically not interact directly with oct-git, after an initial one-time setup.

If you call oct-git without parameters, you'll see a very brief setup help text.

Configuring Git to use oct-git

To use oct-git, Git must be configured appropriately.

Most importantly, the binary that git calls for OpenPGP functionality must be configured:

git config --global gpg.program <path to oct-git>

Additionally, the OpenPGP key that git should use for signing must be configured. This value can be set to the OpenPGP fingerprint of the signing component key, or the primary fingerprint of the key:

git config --global user.signingkey <fingerprint>

Once this basic setup is done, git can be instructed to sign every commit by default:

git config --global commit.gpgsign true

And/or to sign every Git tag by default:

git config --global tag.gpgsign true

Switching Git's OpenPGP subsystem between oct-git and GnuPG

If you'd like to try oct-git, but are undecided between using it or GnuPG, once you have set up Git's OpenPGP configuration, you can always easily switch between OpenPGP Git subsystems:

You can simply call:

git config --global gpg.program <path to GnuPG>

or

git config --global gpg.program <path to oct-git>

Switching between the two alternative OpenPGP subsystems should be quick and a mostly unexciting experience. We encourage unhesitant switching between the implementations if you want to compare them, or just play.

Architecture and subsystems

The oct-git tool consists of one standalone binary, which is called by git, both for the creation of signatures and for the verification of signatures.

Logically, oct-git consists of a set of subsystems:

graph TB
    Git --> OG["oct-git <br/> (commit/tag signing and verification)"]
    OG --> CARD["OpenPGP card <br/> (produces signatures, accessed via PC/SC)"]
    OG --> STATE["openpgp-card-state library <br/> (config and PIN storage backend access)"]
    STATE --> PINS["PIN storage backend <br/> (makes User PINs available to applications)"]
    OG --> NOTIFY["Desktop notifications <br/> (e.g.: touch confirmation required)"]
    OG --> RCS["rpgpie-certificate-store"]
    RCS --> CERTD["openpgp-cert-d <br/> (shared public key storage)"]
    RCS --> PKI["OpenPGP PKI <br/> (retrieve certificates from keyservers etc)"]

Most of these subsystems consist of Rust libraries that are linked into the oct-git program.

The following subsystems are not libraries:

  • "OpenPGP card" is a physical hardware security device (often a USB device) that contains your private signing key material, to issue Git signatures with.
  • An "openpgp-cert-d" instance consists of a set of files in a shared location in your local filesystem that contains OpenPGP certificates (public keys).
  • "OpenPGP PKI" means public keyservers that serve OpenPGP certificates (public keys). This subsystem queries keyservers over the internet, to acquire copies of certificates.

User PINs: Configuring access to OpenPGP card devices

OpenPGP card devices require a User PIN to authorize private key operations (in the case of this tool: creating cryptographic signatures for git commits).

Access to OpenPGP card User PINs is handled indirectly, using the shared openpgp-card-state infrastructure.

If you have already stored the User PIN for your card in openpgp-card-state, it can be used from oct-git immediately. Otherwise, you can store the User PIN using oct-git, like this:

$ oct-git --store-card-pin
Found OpenPGP card 0000:01234567
  No User PIN is stored in openpgp-card-state
  Enter User PIN to store (or <Enter> to skip):
  User PIN has been stored in openpgp-card-state

The User PIN storage process in oct-git is interactive. For each connected OpenPGP card device, it checks if a valid PIN is already available in openpgp-card-state. If not, the user is prompted for the User PIN of that card.

Signing

oct-git can be used by Git to sign commits or tags.

Signing with oct-git requires that an OpenPGP card with the data signing key material is plugged into your system. Additionally, the User PIN for any OpenPGP card device must be accessible via openpgp-card-state (see above).

Verification

Verification of signatures automatically uses OpenPGP certificates from the local openpgp-cert-d "shared OpenPGP Certificate Directory".

If a certificate is not present in the local openpgp-cert-d store, oct-git attempts to automatically download it [^lookup] from a number of well-known public online directories (currently,oct-git queries keyserver.ubuntu.com and keys.openpgp.org).

[^lookup]: PKI queries to acquire certificates perform a lookup by signing key fingerprint or key id.

Manually importing certificates to the store

You can manually import certificates into the "shared OpenPGP Certificate Directory" using oct-git:

$ oct-git --import <certificate file>

This can be useful if you want to verify commits by a certificate that oct-git can't obtain from the public OpenPGP PKI.

Limitation: Updating certificates in the store

oct-git currently isn't able to update certificates in the openpgp-cert-d store. There is a tracking issue for this feature.

Limitation: Verification "trust level"

oct-git currently doesn't display a "trust level" for signature verification. The "trust" concept in question is based on the Web of Trust, and requires configuration of "trust roots", as well as signature chains on which to perform "Web of Trust" evaluations.

This functionality will be added in the future.

Until then, oct-git displays signatures with the "Unverified" trust level, since we don't currently have a basis for emitting more specific information.

This output means that the signature is cryptographically correct, and the fingerprint of the issuer is shown. However, no chain of trust to the signer is known.

Internals

Technically, oct-git implements a lookalike for a very small subset of GnuPG's CLI interface.

Specifically, we implement just enough functionality so that Git is able to do signing and verification operations using oct-git instead of gpg.

Having a separate binary for use with Git enables oct-git to be a lot more specific in its user interactions. For example, when touch confirmation is required, oct-git will show a notification that informs the user that a touch input on a card is required, and shows that the request originates from oct-git.

The two following sections show how oct-git is called internally - usually such calls to oct-git are issued by the git program.

Basic detached signing

oct-git -u SIGNING_KEY_FPR --detach-sign < Cargo.toml > Cargo.toml.sig

The SIGNING_KEY_FPR parameter must be set to the fingerprint of the signing subkey (not the certificate) in a hex-encoded format with no spaces (0x prefix is optional and removed during comparisons).

The fingerprint may be retrieved using oct status command.

Signature verification

oct-git --verify Cargo.toml.sig - < Cargo.toml

Future directions

The coupling of Git with the OpenPGP signing and verification subsystem is currently based on GnuPG's CLI interface.

This is not ideal, and it limits the design space for alternative OpenPGP subsystems for Git, such as oct-git. In the longer term, it would be great if Git supported a more simple, generic and well-defined interface between itself and signing/verification subsystems.

This goal is currently out of scope for this project, but we'd love to hear from you, if you are working on it!

Funding

This project has been funded in part through NGI Assure, a fund established by NLnet with financial support from the European Commission's Next Generation Internet program.

NGI Assure Logo


🐒️🥯️

Dependencies

~49–83MB
~1.5M SLoC