diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7fe6f0c..5606ed2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,7 +3,6 @@ # SPDX-License-Identifier: CC0-1.0 stages: - - pages - lint - test - virtual-test @@ -22,21 +21,6 @@ cache: &general_cache_config - target/ - $CARGO_HOME -pages: - stage: pages - 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 - cache: [ ] - reuse: stage: lint image: diff --git a/guide/book.toml b/guide/book.toml deleted file mode 100644 index 1bb6d26..0000000 --- a/guide/book.toml +++ /dev/null @@ -1,16 +0,0 @@ -# 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/openpgp-card/openpgp-card" -git-repository-icon = "fa-gitlab" - -[build] -build-dir = "../public" diff --git a/guide/src/SUMMARY.md b/guide/src/SUMMARY.md deleted file mode 100644 index fe4bac7..0000000 --- a/guide/src/SUMMARY.md +++ /dev/null @@ -1,12 +0,0 @@ - - -# Summary - -- [OpenPGP cards](context.md) -- [Setting up 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 deleted file mode 100644 index dac7dda..0000000 --- a/guide/src/context.md +++ /dev/null @@ -1,36 +0,0 @@ - - -# OpenPGP card "hardware tokens" - -This series of guides describes how to use [OpenPGP card](https://en.wikipedia.org/wiki/OpenPGP_card) "hardware tokens" -(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. - -## What are OpenPGP cards? - -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. - -## Tool support, so far - -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. - -## New OpenPGP card tools - -This series of guides introduces a new set of tools that leverage OpenPGP cards, written in Rust. -These tools are built on a set of [OpenPGP card libraries](https://gitlab.com/openpgp-card/openpgp-card) -and [Sequoia PGP](https://sequoia-pgp.org/). - -The ultimate goal of this series is to document a complete suite of easy-to-use tools for all use cases around -OpenPGP cards. diff --git a/guide/src/opgpcard.md b/guide/src/opgpcard.md deleted file mode 100644 index afdc363..0000000 --- a/guide/src/opgpcard.md +++ /dev/null @@ -1,286 +0,0 @@ - - -# The opgpcard tool - -To set up and inspect OpenPGP cards, we'll use the [`opgpcard`](https://crates.io/crates/openpgp-card-tools) tool, -which is based on [Sequoia PGP](https://sequoia-pgp.org/) -and [new Rust OpenPGP card libraries](https://gitlab.com/openpgp-card/openpgp-card). - -## Install - -To install the `opgpcard` tool, we - -- install the required build dependencies (a Rust toolchain, pcsc-lite, nettle), then -- `cargo install openpgp-card-tools` - -[Detailed installation instructions](https://gitlab.com/openpgp-card/openpgp-card/-/tree/main/tools#install). - -## Running opgpcard - -### Make sure PC/SC is available - -`opgpcard` uses the PC/SC framework. So on Linux-based systems, you need to make sure the `pcscd` -service is running to be able to access your OpenPGP cards. - -### Troubleshooting "Error: No cards found" - -If `opgpcard` unexpectedly prints `Error: No cards found`, your OpenPGP card might be locked by GnuPG. - -When you use GnuPG with an OpenPGP card, its `scdaemon` service typically opens your card with exclusive access -privileges, for an indefinite duration. This prevents other software from accessing the card. - -To re-gain access to your card, you can: -- mechanically unplug and replug the card, or you can -- tell GnuPG to temporarily shut down its `scdaemon` subsystem (the recommended way to do this is: `gpgconf --kill scdaemon`). - -After this, `opgpcard` should be able to access your OpenPGP card. - -(Note: With recent versions of GnuPG, you can configure `scdaemon` to -[use PC/SC in shared access mode](https://www.gnupg.org/documentation/manuals/gnupg/Scdaemon-Options.html#index-pcsc_002dshared)) - -# Exploring the state of an OpenPGP card - -Using the `opgpcard` tool, you can easily check the status of a card: - -`$ opgpcard status` - -The output will start like this: - -``` -OpenPGP card FFFE:12345678 (card version 2.0) -[...] -``` - -... and then show information about the keys on the card (if any). - -In this case, the card's identifier is `FFFE:12345678` -(you'll need this identifier for your card, in some of the following steps). - - -# Specifying which card to operate on - -`opgpcard` is designed to work just as reliably and easily in environments where many OpenPGP card devices exist, -and are plugged in at the same time. Therefore, you will need to explicitly specify which card you want to operate on, -in many cases. - -For read operations `opgpcard` will automatically use that card, when exactly one card is plugged in. - -In all other cases: -- when multiple cards are plugged in, and -- for any write operations, - -you need to specify which card you want to interact with, via the `--card` (`-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 your 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 use two different PINs (for different types of operations): - -- *User PIN*, -- *Admin PIN*. - -The User PIN is required 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 the card. - -On new cards (or after a factory reset), the default User PIN is `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, PINs can be entered directly via that pinpad. - -2. If no pinpad reader is available, PINs can be entered on the host computer. - -3. Alternatively, it's possible to supply PINs via a file (or a file descriptor). This can be convenient in non-interactive settings, like shell scripts. - -## Changing your User and Admin PIN from the default values - -To change the User PIN from its default of `123456` to a different value (one 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 (`123456`, if your card is new), and then a new PIN, -twice (to avoid inadvertently setting the PIN to an unintended value). - -Analogously for the Admin PIN, to change it from its default of `12345678`: - -`$ opgpcard pin -c FFFE:12345678 set-admin` - -The minimum length for User PINs is 6 digits. For the Admin PIN, 8 digits. - -(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. A `factory-reset` reverts 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 the key material on your 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 this URL. - -# Importing a key to a card - -*(This operation deletes keys that currently exist on your card. -Make sure your card doesn't contain irreplaceable keys before you import keys!)* - -If you have an existing key that you want to import onto your card, you need a file that contains the key -(if you want to use a private key from a GnuPG store, you can export it with `gpg --export-secret-key -a > key.pgp`). - -If you don't have a key yet (or if you prefer to experiment with a test-key, for now), you can generate a new key with -the `sq` utility (available as `sequoia-sq` -in [a number of distributions](https://repology.org/project/sequoia-sq/versions), or you can -[build it as a container, or with the Cargo package manager](https://gitlab.com/sequoia-pgp/sequoia#building-sequoia)). - -To generate a basic OpenPGP key, we run: - -``` -$ sq key generate --export key.pgp -``` - -We can inspect this newly generated key (or your pre-existing key) by looking at the structure of the OpenPGP key data -in the file: - -``` -$ 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 -``` - -Here, we see (by looking at the `Key flags` fields) that the primary key `17F2509AB619C8D78B598E54567817AC43A7F7AE` -can be used for certification only. In addition, there is a signing subkey `E7A3D0E45991BE6445668CFD348634FD4CC638CA` -and an encryption subkey `593970CE20BFE3D58AA4EF12EA988C77EEC05B0A`. - -## Automatically importing subkeys for simple OpenPGP keys - -Because this key has only one (sub)key for signing and encrypting, respectively, we can import it onto our card easily: - -``` -$ opgpcard admin -c FFFE:12345678 import key.pgp -Enter Admin PIN: -Uploading E7A3D0E45991BE6445668CFD348634FD4CC638CA as signing key -Uploading 593970CE20BFE3D58AA4EF12EA988C77EEC05B0A as decryption key -``` - -We see that the two subkeys have been loaded into the suitable slots on the card. - -For this key, we don't need to explicitly specify the fingerprints of the keys we want to import: -`opgpcard admin import` can automatically import keys that contain exactly one signing (sub)key, and zero or one -decryption and authentication subkeys, respectively. - -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] - -Retry counters: User PIN: 3, Admin PIN: 3, Resetting Code: 3 -Signature counter: 0 -Signature PIN only valid once: true -``` - - -## Explicitly picking (sub)keys to import, for more complex OpenPGP keys - -If our key contains multiple (sub)keys for signing, encrypting, or authentication, respectively, -we need to explicitly specify which subkeys we want imported onto our card. - -With the OpenPGP key from above, that would look like: - -``` -$ 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 -``` - - -# Key generation on a card - -*(This operation deletes keys that currently exist on your card. -Make sure your card doesn't contain irreplaceable keys before you generate keys on your card!)* - -To generate a new set of ECC Curve 25519 keys on your OpenPGP card, we can run: - -`$ opgpcard admin -c FFFE:12345678 generate -o cert.pub 25519` - -The output file `cert.pub` will contain the OpenPGP public key that corresponds to the newly generated keys on the card. - -## 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. - -(Also, when generating private key material on a card, you rely on the hard- and software of that card not to have -flaws that may compromise your key's security.) - -Depending on your use case, these tradeoffs may or may not be a good fit for your goals. diff --git a/guide/src/ssh.md b/guide/src/ssh.md deleted file mode 100644 index 1d0275c..0000000 --- a/guide/src/ssh.md +++ /dev/null @@ -1,141 +0,0 @@ - - -# SSH login using an OpenPGP card - -In this guide, we'll set up OpenPGP card-based SSH logins to a remote machine. - -We assume that you have an OpenPGP card plugged into your client machine, and that an authentication key is available -on that card. - -We also assume that the `opgpcard` tool [is installed](https://openpgp-card.gitlab.io/openpgp-card/opgpcard.html#install). - -## Optional: generate throwaway keys on your card, for this guide - -If you have a blank OpenPGP card, and want to generate throwaway keys to try this guide, you can generate keys on the -card by running: - -``` -$ opgpcard admin -c FFFE:12345678 generate -o /tmp/cert.pub 25519 -``` - -Replace `FFFE:12345678` with the identifier of your own card (as shown by `opgpcard list`). - -This command instructs your card to generate a set of ECC Curve 25519 keys. Not all cards support this algorithm. -If yours doesn't, you can generate RSA 2048 keys instead: - -``` -$ opgpcard admin -c FFFE:12345678 generate -o /tmp/cert.pub rsa2048 -``` - -Key generation will ask for both the Admin PIN (`12345678` by default) and the User PIN (`123456` by default). -You can ignore the public key output in `/tmp/cert.pub`, if you don't want to use these keys outside this guide. - -If you only generate keys to try this guide, you'll probably want to run `opgpcard factory-reset -c ` at -the end. This will revert your card back into a blank state (and remove our throwaway keys). - -# Allowing access to the remote server - -Now we'll add our "SSH public key" to the remote machine's list of authorized keys. - -More specifically, we'll add the SSH public key that corresponds to the authentication key on our OpenPGP card. -This tells the remote machine that we want our OpenPGP card to be considered a valid means of authorization to log in. - -## Adding the public key to `authorized_keys` on a remote machine - -To see the SSH public key representation of the authentication key on our OpenPGP card, we run `opgpcard ssh`: - -``` -$ opgpcard ssh -OpenPGP card FFFE:12345678 - -Authentication key fingerprint: -7A21F955A14C1C134D9EAE90E8B3EFD2581F3113 - -SSH public key: -ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP3GtBCzGAUjg8iN9JOo5f+cFCYLaWE8titbIbimtKwe opgpcard:FFFE:12345678 -``` - -In this output, the last line shows our SSH public key, which is: - -`ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP3GtBCzGAUjg8iN9JOo5f+cFCYLaWE8titbIbimtKwe opgpcard:FFFE:12345678` - -We add this line to the `~/.ssh/authorized_keys` file in an account on a remote server. - -Now the SSH daemon on that machine will consider the authentication key on our OpenPGP card as proof that we're allowed -to log in. - -(Note that the public key line doesn't need to be kept secret. Only its counterpart, the secret key on our card, is -sensitive.) - -# Setting up the client side - -Next we install two pieces of software on our client machine, to communicate with the remote machine using -the [SSH authentication protocol](https://datatracker.ietf.org/doc/html/rfc4252) protocol: - -1) an OpenPGP card-based private key store daemon, and -2) an ssh-agent implementation. - -Each of these will listen to a Unix domain socket (we'll define an environment variable for each). - -In this guide, for demonstration purposes, we'll run these services in a terminal, as Rust debug builds, with rather -chatty debug output (in production systems, you'll probably want to run release builds as system services). - -NOTE: These services are in an early experimental stage. Read the documentation for caveats, and don't use them -in sensitive contexts, just yet. - -## Card-based Private Key Store - -This is an experimental Private Key Store that enables use of cryptographic keys stored on OpenPGP cards. - -We'll build and run it in place, for this guide: - -``` -$ git clone https://gitlab.com/sequoia-pgp/pks-openpgp-card -$ cd pks-openpgp-card -$ cargo run -- -H unix://$XDG_RUNTIME_DIR/pks-openpgp-card.sock -``` - -## Private Key Store-based SSH Agent - -An SSH Agent implementation that can use keys on OpenPGP cards, via the Private Key Store from the previous step. - -``` -$ git clone https://gitlab.com/sequoia-pgp/ssh-agent-pks -$ cd ssh-agent-pks -$ cargo run -- -H unix://$XDG_RUNTIME_DIR/ssh-agent-pks.sock --endpoint $XDG_RUNTIME_DIR/pks-openpgp-card.sock -``` - -## Using the SSH Agent - -To use `ssh-agent-pks` with your system's SSH client, the variable `SSH_AUTH_SOCK` must point to it: - -`export SSH_AUTH_SOCK=$XDG_RUNTIME_DIR/ssh-agent-pks.sock` - -### Register a card with the agent - -Once the two services are running, you can register an OpenPGP card with the `ssh-agent-pks` OpenSSH agent, by telling -it to add the authentication key from the card: - -`ssh-add -s /7A21F955A14C1C134D9EAE90E8B3EFD2581F3113` - -`7A21F955A14C1C134D9EAE90E8B3EFD2581F3113` is the fingerprint of our authentication key, as shown from -`opgpcard ssh`, above. You need to add the fingerprint of your OpenPGP card's authentication key. -Don't forget to add a slash before the fingerprint! - -You will be prompted to "Enter passphrase for PKCS#11" (don't let this message confuse you: you actually need to enter the User PIN for your OpenPGP card, but the SSH software doesn't know this). - -Remember that the User PIN is `123456` by default, on most cards (and remember to change the PIN for cards that -you'll use productively). - -This operation is not persisting anything on disk, for now. You always need to add keys to `ssh-agent-pks` after -starting it. - -## Log into remote machines - -When `SSH_AUTH_SOCK` is set, you should now be able to `ssh `. -This will use the authentication key on your OpenPGP card to authorize your login. - -Yay!