From 9057ad516fff2730b6151ae5cb2b34e682c9e6dd Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Thu, 21 Apr 2022 18:02:22 +0200 Subject: [PATCH] First part of end-user guide. --- .gitlab-ci.yml | 17 +++ guide/book.toml | 16 +++ guide/src/SUMMARY.md | 12 ++ guide/src/context.md | 29 +++++ guide/src/opgpcard.md | 251 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 325 insertions(+) create mode 100644 guide/book.toml create mode 100644 guide/src/SUMMARY.md create mode 100644 guide/src/context.md create mode 100644 guide/src/opgpcard.md diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 83ec76f..c6ef6b8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,6 +3,7 @@ # SPDX-License-Identifier: CC0-1.0 stages: + - pages - lint - test - virtual-test @@ -21,6 +22,21 @@ cache: &general_cache_config - target/ - $CARGO_HOME +pages: + stage: pages + cache: [ ] + image: debian:stable-slim + before_script: + - apt update -y -qq + - apt install -y -qq --no-install-recommends wget ca-certificates + - wget https://github.com/rust-lang/mdBook/releases/download/v0.4.15/mdbook-v0.4.15-x86_64-unknown-linux-gnu.tar.gz + - tar xvzf mdbook-v0.4.15-x86_64-unknown-linux-gnu.tar.gz + script: + - ./mdbook build guide/ + artifacts: + paths: + - public + reuse: stage: lint cache: [ ] @@ -29,6 +45,7 @@ reuse: entrypoint: [ "" ] script: - reuse lint + dependencies: [] cargo-fmt: stage: lint diff --git a/guide/book.toml b/guide/book.toml new file mode 100644 index 0000000..64d4653 --- /dev/null +++ b/guide/book.toml @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2022 Heiko Schaefer +# SPDX-License-Identifier: MIT OR Apache-2.0 + +[book] +authors = ["hkos"] +language = "en" +multilingual = false +src = "src" +title = "OpenPGP card user guide" + +[output.html] +git-repository-url = "https://gitlab.com/hkos/openpgp-card" +git-repository-icon = "fa-gitlab" + +[build] +build-dir = "../public" diff --git a/guide/src/SUMMARY.md b/guide/src/SUMMARY.md new file mode 100644 index 0000000..8dad764 --- /dev/null +++ b/guide/src/SUMMARY.md @@ -0,0 +1,12 @@ + + +# Summary + +- [Context](context.md) +- [Initializing cards with `opgpcard`](opgpcard.md) +- [SSH authentication](ssh.md) +- [git commit signing](git.md) +- [Thunderbird](thunderbird.md) diff --git a/guide/src/context.md b/guide/src/context.md new file mode 100644 index 0000000..838f5d1 --- /dev/null +++ b/guide/src/context.md @@ -0,0 +1,29 @@ + + +# OpenPGP card "hardware tokens" + +This series of articles describes how to use [OpenPGP card](https://en.wikipedia.org/wiki/OpenPGP_card) devices +(e.g. [YubiKey](https://www.yubico.com/products/), [Nitrokey](https://www.nitrokey.com/) +or [Gnuk](https://www.fsij.org/doc-gnuk/)) with new - and still experimental - Sequoia PGP-based tools. + +OpenPGP cards are hardware tokens that can store private key material and perform cryptographic operations. +The point of using such a device is that private cryptographic key material is never directly accessible to the +user's computer. + +This way, even if the user's computer is compromised, their private OpenPGP key material is protected from being +exfiltrated by an attacker. + + +## New tools + +Until now, most users have interacted with OpenPGP cards using one or both of: + +1. [GnuPG](https://www.gnupg.org) (which internally uses a subsystem called [scdaemon](https://www.gnupg.org/documentation/manuals/gnupg/Invoking-SCDAEMON.html)), or + +2. [OpenKeychain](https://www.openkeychain.org/) (OpenKeychain can be used via the K9 email software), or the related [TermBot](https://github.com/cotechde/termbot) SSH client, on Android devices. + +This project works towards a new set of tools, using a library-first approach, written in Rust. +These tools are based on a set of [OpenPGP card libraries](https://gitlab.com/hkos/openpgp-card) and [Sequoia PGP](https://sequoia-pgp.org/). diff --git a/guide/src/opgpcard.md b/guide/src/opgpcard.md new file mode 100644 index 0000000..3450b78 --- /dev/null +++ b/guide/src/opgpcard.md @@ -0,0 +1,251 @@ + + +# The opgpcard tool + +To set up (or inspect) an OpenPGP card, we'll use the `opgpcard` tool. +So first, we install that tool. + +In short: + +1. install the build dependencies, then +2. `cargo install openpgp-card-tools` + +Longer form [installation instructions](https://gitlab.com/hkos/openpgp-card/-/tree/main/tools#install). + + +# Exploring the state of an OpenPGP card + +Using the `opgpcard` tool (installed above), you can easily check the status of a card that is plugged in: + +`$ opgpcard status` + +The output will start like this: + +``` +OpenPGP card FFFE:12345678 (card version 2.0) +[...] +``` + +In this case, the card identifier is `FFFE:12345678` (you'll need to use the identifier for your card, in some of the following steps). + + +# Specifying which card to operate on + +For read operations, when exactly one card is plugged in, `opgpcard` will automatically use that card. + +In all other cases (when multiple cards are plugged in, or for any write operations), you need to specify which card +you want to interact with, via the `-c` parameter. + +For example: + +`$ opgpcard status -c FFFE:12345678` + +## Enumerating all available cards + +You can use `opgpcard list` to enumerate all cards that are connected to the system. + + +# PINs + +For some operations, OpenPGP cards require the user to provide a 'PIN', to show that the user is authorized to perform the operation. + +Most OpenPGP cards distinguish two different PINs: + +1. a *User PIN* and +2. an *Admin PIN*. + +The User PIN is needed for cryptographic operations (such as decryption or signing with the card). +The Admin PIN is needed to configure the card itself (for example to import a key onto a card). + +On new (or factory reset) cards, the default User PIN is typically `123456`, the default Admin PIN is `12345678`. + +## Modes of PIN entry + +`opgpcard` supports three different modes of PIN entry: + +1. When the OpenPGP card is inserted in a Smartcard reader with a pinpad (that is, when the OpenPGP card is inserted into a hardware reader device that has a numerical keypad), PINs can be entered directly via that pinpad. + +2. If no pinpad reader is available, PINs can be entered directly on the host computer. + +3. Alternatively it's possible to supply PINs via a file (or a file descriptor), which can be convenient in non-interactive settings. + +## Changing your User and Admin PIN from the default values + +To change the User PIN from its default of `123456` to a value that third parties can't easily guess, run: + +`$ opgpcard pin -c FFFE:12345678 set-user` + +This command will ask you to enter the current User PIN (so `123456`, if your card is new), and then a new PIN, +twice (to avoid inadvertently setting the PIN to an unintended value). + +And analogously for the Admin PIN, to change it from its default of `12345678`: + +`$ opgpcard pin -c FFFE:12345678 set-admin` + +Typically, the minimum length is 6 digits for the User PIN and 8 digits for the Admin PIN. + +(Note that if you lose your Admin PIN, there is no way to recover it! In that case you can start over by blanking the +card with the `factory-reset` command. This resets the PINs to their defaults and removes all keys from the card.) + + +# Setting metadata on a card + +## Set name + +You can set a "Cardholder Name" on an OpenPGP card. That name field is informational. + +`opgpcard admin -c FFFE:12345678 name "Alice Adams"` + +## Set URL + +You can set a URL on an OpenPGP card. + +The URL "should contain a Link to a set of public keys in OpenPGP format, related to the card". +Some software may use this URL to obtain a copy of the corresponding public key for a card. + +`$ opgpcard admin -c FFFE:12345678 url ` + +If you do use the URL field, the URL should serve a copy of your public key. +For most use cases, you don't need to set the URL. + +### Using `keys.openpgp.org` for the URL + +If you have uploaded (or plan to upload) your certificate to the `keys.openpgp.org` keyserver, you can set the URL +field on your card to point to that server: + +If the fingerprint of your certificate is `0123456789ABCDEF0123456789ABCDEF01234567`, then you can set the URL +as follows: + +`$ opgpcard admin -c FFFE:12345678 url "https://keys.openpgp.org/vks/v1/by-fingerprint/0123456789ABCDEF0123456789ABCDEF01234567"` + +### Other URLs + +You can use any URL that serves your public key, including a link to your certificate on: + +- gitlab (`https://gitlab.com/.gpg`) or github (`https://github.com/.gpg`) +- any other keyserver, such as https://keyserver.ubuntu.com/, +- a WKD server, +- a copy of your certificate on your personal website, ... + +# Importing a key to a card + +*(This operation will delete keys that currently exist on your card. +Make sure your card doesn't contain irreplaceable keys before you import keys!)* + +If you have a key that you want to use, you can use that key. + +If you don't (or if you want to first experiment with a test-key) you can generate a new key with the `sq` utility +(available as `sequoia-sq` in a number of distributions, or installable with the `cargo` Rust package manager). + +``` +$ sq key generate --export key.pgp +``` + +We can inspect this newly generated key (or your pre-existing key) by running: + +``` +$ sq inspect key.pgp +key.pgp: Transferable Secret Key. + + Fingerprint: 17F2509AB619C8D78B598E54567817AC43A7F7AE +Public-key algo: EdDSA Edwards-curve Digital Signature Algorithm +Public-key size: 256 bits + Secret key: Unencrypted + Creation time: 2022-04-20 09:46:27 UTC +Expiration time: 2025-04-20 03:12:48 UTC (creation time + P1095DT62781S) + Key flags: certification + + Subkey: E7A3D0E45991BE6445668CFD348634FD4CC638CA +Public-key algo: EdDSA Edwards-curve Digital Signature Algorithm +Public-key size: 256 bits + Secret key: Unencrypted + Creation time: 2022-04-20 09:46:27 UTC +Expiration time: 2025-04-20 03:12:48 UTC (creation time + P1095DT62781S) + Key flags: signing + + Subkey: 593970CE20BFE3D58AA4EF12EA988C77EEC05B0A +Public-key algo: ECDH public key algorithm +Public-key size: 256 bits + Secret key: Unencrypted + Creation time: 2022-04-20 09:46:27 UTC +Expiration time: 2025-04-20 03:12:48 UTC (creation time + P1095DT62781S) + Key flags: transport encryption, data-at-rest encryption +``` + +In this case, we see (in the `Key flags` field) that the primary key `17F2509AB619C8D78B598E54567817AC43A7F7AE` +can be used for certification only. +In addition, there is a signing subkey `E7A3D0E45991BE6445668CFD348634FD4CC638CA` +and an encryption subkey `593970CE20BFE3D58AA4EF12EA988C77EEC05B0A`: + +To explicitly import the two subkeys onto our card, we run: + +``` +$ opgpcard admin -c FFFE:12345678 import --sig-fp E7A3D0E45991BE6445668CFD348634FD4CC638CA --dec-fp 593970CE20BFE3D58AA4EF12EA988C77EEC05B0A key.pgp +Enter Admin PIN: +Uploading E7A3D0E45991BE6445668CFD348634FD4CC638CA as signing key +Uploading 593970CE20BFE3D58AA4EF12EA988C77EEC05B0A as decryption key +``` + +Checking the card's status now shows: + +``` +$ opgpcard status +OpenPGP card FFFE:12345678 (card version 2.0) + +Signature key + fingerprint: E7A3 D0E4 5991 BE64 4566 8CFD 3486 34FD 4CC6 38CA + created: 2022-04-20 09:46:27 + algorithm: Ed25519 (EdDSA) + +Decryption key + fingerprint: 5939 70CE 20BF E3D5 8AA4 EF12 EA98 8C77 EEC0 5B0A + created: 2022-04-20 09:46:27 + algorithm: Cv25519 (ECDH) + +Authentication key + algorithm: RSA 2048 [e 32] + +Signature counter: 0 +Signature pin only valid once: true +Password validation retry count: + user pw: 3, reset: 3, admin pw: 3 +``` + +The two subkeys have been loaded into the suitable slots on the card. + +In fact, for this key, we don't need to explicitly specify the fingerprints. `opgpcard admin import` automatically +imports keys that contain exactly one signing (sub)key, and zero or one decryption and authentication subkeys, respectively: + +``` +opgpcard admin -c FFFE:12345678 import key.pgp +Enter Admin PIN: +Uploading E7A3D0E45991BE6445668CFD348634FD4CC638CA as signing key +Uploading 593970CE20BFE3D58AA4EF12EA988C77EEC05B0A as decryption key +``` + + +# Key generation on a card + +*(This operation will delete keys that currently exist on your card. +Make sure your card doesn't contain irreplaceable keys before you generate keys on your card!)* + +This step will generate a new set of ECC Curve25519 keys on your OpenPGP card: + +`opgpcard admin -c FFFE:12345678 generate -o output-cert.pub 25519` + +The file `output-cert.pub` will contain the OpenPGP public key that corresponds to the newly generated keys on the card. +We won't need this public key for ssh use (but you might need it if you want to use the key on this card for other purposes). + +## Pros and cons of generating keys on a card + +When you generate keys on your card, your computer never has access to the private key material. +This is nice if you want to be sure that the private key material can not possibly get exfiltrated from your computer, +even if it is fully compromised. + +On the other hand, this means that you can - by design - not make a backup (or second copy) of these private keys. +If the card is lost (or breaks) these keys are gone forever. + +Depending on your use case, these tradeoffs may or may not be a good fit for your goals.