diff --git a/kernel-developer-pgp-guide.md b/kernel-developer-pgp-guide.md deleted file mode 100644 index 0441106..0000000 --- a/kernel-developer-pgp-guide.md +++ /dev/null @@ -1,984 +0,0 @@ -# Kernel developer PGP guide - -Updated: 2018-01-24 - -*Status: CURRENT, BETA* - -### Table of contents - -- [Kernel developer PGP guide](#kernel-developer-pgp-guide) - - [Table of contents](#table-of-contents) - - [Target audience](#target-audience) - - [Structure](#structure) - - [Checklist priority levels](#checklist-priority-levels) - - [The role of PGP in Linux Kernel development](#the-role-of-pgp-in-linux-kernel-development) - - [Trusting the developers, not infrastructure](#trusting-the-developers-not-infrastructure) - - [PGP tools](#pgp-tools) - - [Checklist](#checklist) - - [Considerations](#considerations) - - [Installing GnuPG](#installing-gnupg) - - [Making sure you always use GnuPG v.2](#making-sure-you-always-use-gnupg-v2) - - [Configure gpg-agent options](#configure-gpg-agent-options) - - [Set up a refresh cronjob](#set-up-a-refresh-cronjob) - - [Protecting your master PGP key](#protecting-your-master-pgp-key) - - [Checklist](#checklist-1) - - [Considerations](#considerations-1) - - [Understanding the "Master" (Certify) key](#understanding-the-%22master%22-certify-key) - - [Ensure your passphrase is strong](#ensure-your-passphrase-is-strong) - - [Create a separate Signing subkey](#create-a-separate-signing-subkey) - - [RSA vs. ECC subkeys](#rsa-vs-ecc-subkeys) - - [Back up your master key for disaster recovery](#back-up-your-master-key-for-disaster-recovery) - - [Back up your whole GnuPG directory](#back-up-your-whole-gnupg-directory) - - [Prepare detachable encrypted storage](#prepare-detachable-encrypted-storage) - - [Back up your GnuPG directory](#back-up-your-gnupg-directory) - - [Remove the master key from your homedir](#remove-the-master-key-from-your-homedir) - - [Removing your master key](#removing-your-master-key) - - [If you don't have the "private-keys-v1.d" directory](#if-you-dont-have-the-%22private-keys-v1d%22-directory) - - [Move the subkeys to a dedicated crypto device](#move-the-subkeys-to-a-dedicated-crypto-device) - - [Checklist](#checklist-2) - - [Considerations](#considerations-2) - - [The benefits of smartcards](#the-benefits-of-smartcards) - - [Available smartcard devices](#available-smartcard-devices) - - [Configuring your smartcard device](#configuring-your-smartcard-device) - - [Quick setup](#quick-setup) - - [PINs don't have to be numbers](#pins-dont-have-to-be-numbers) - - [Moving the subkeys to your smartcard](#moving-the-subkeys-to-your-smartcard) - - [Verifying that the keys were moved](#verifying-that-the-keys-were-moved) - - [Verifying that the smartcard is functioning](#verifying-that-the-smartcard-is-functioning) - - [Other common GnuPG operations](#other-common-gnupg-operations) - - [Mounting your master key offline storage](#mounting-your-master-key-offline-storage) - - [Updating your regular GnuPG working directory](#updating-your-regular-gnupg-working-directory) - - [Extending key expiration date](#extending-key-expiration-date) - - [Using PGP with Git](#using-pgp-with-git) - - [Checklist](#checklist-3) - - [Considerations](#considerations-3) - - [Configure git to use your PGP key](#configure-git-to-use-your-pgp-key) - - [How to work with signed tags](#how-to-work-with-signed-tags) - - [How to verify signed tags](#how-to-verify-signed-tags) - - [Verifying at pull time](#verifying-at-pull-time) - - [Configure git to always sign annotated tags](#configure-git-to-always-sign-annotated-tags) - - [How to work with signed commits](#how-to-work-with-signed-commits) - - [Creating signed commits](#creating-signed-commits) - - [Configure git to always sign commits](#configure-git-to-always-sign-commits) - - [How to verify kernel developer identities](#how-to-verify-kernel-developer-identities) - - [Checklist](#checklist-4) - - [Considerations](#considerations-4) - - [Configure auto-key-retrieval using WKD and DANE](#configure-auto-key-retrieval-using-wkd-and-dane) - - [Web of Trust (WOT) vs. Trust on First Use (TOFU)](#web-of-trust-wot-vs-trust-on-first-use-tofu) - - [Learn to use keyservers (more) safely](#learn-to-use-keyservers-more-safely) - -### Target audience - -This document is aimed at Linux kernel developers, and especially subsystem -maintainers. It contains a subset of information discussed in the more -general "Protecting Code Integrity" guide found in the same repository. If you -are not a Linux kernel developer, you should read the more general guide -instead. - -This document covers the following topics: - -1. How to improve your PGP key security -2. When and how to use PGP with git -3. How to verify fellow kernel developer identities - -### Structure - -Each section is split into two areas: - -- A checklist of actionable items -- Free-form list of considerations that explain what dictated these decisions, - together with configuration instructions - -#### Checklist priority levels - -The items in each checklist include the priority level, which we hope will -help guide your decision: - -- _(ESSENTIAL)_ items should definitely be high on the consideration list. -- _(NICE)_ to have items will improve the overall security, but will affect how - you interact with your work environment, and probably require learning new - habits or unlearning old ones. - -Remember, these are only guidelines. If you feel these priority levels do not -reflect your commitment to security, you should adjust them as you see fit. - -## The role of PGP in Linux Kernel development - -PGP helps ensure the integrity of the code that is produced by the Linux -Kernel development community and, to a lesser degree, establish trusted -communication channels between developers via PGP-signed email exchange. - -The Linux Kernel source code is available in two main formats: - -- Distributed source repositories (git) -- Periodic release snapshots (tarballs) - -Both git repositories and tarballs carry PGP signatures of the kernel -developers who create official kernel releases. These signatures offer a -cryptographic guarantee that downloadable versions made available via -kernel.org or any other mirrors are identical to what these developers have on -their workstations. To this end: - -- git repositories provide PGP signatures on all tags -- tarballs provide detached PGP signatures with all downloads - -### Trusting the developers, not infrastructure - -Ever since the 2011 compromise of core kernel.org systems, the main operating -principle of the Kernel Archives project has been to assume that any part of -the infrastructure can be compromised at any time. For this reason, the -administrators have taken deliberate steps to emphasize that trust must always -be placed with developers and never with the code hosting infrastructure, -regardless of how good the security practices for the latter may be. - -The above guiding principle is the reason why this guide is needed. We want to -make sure that by placing trust into developers we do not simply shift the -blame for potential future security incidents to someone else. The goal is to -provide a set of guidelines developers can use to create a secure working -environment and safeguard the PGP keys used to establish the integrity of the -Linux Kernel itself. - -## PGP tools - -### Checklist - -- [ ] Make sure you use GnuPG version 2 _(ESSENTIAL)_ -- [ ] Configure gpg-agent _(ESSENTIAL)_ -- [ ] Set up a refresh cronjob _(ESSENTIAL)_ - -### Considerations - -### Installing GnuPG - -Your distro should already have GnuPG installed by default, you just need to -verify that you are using version 2.x and not the legacy 1.4 release -- -many distributions still package both, with the default `gpg` command invoking -GnuPG v.1. To check, run: - - $ gpg --version | head -n1 - -If you see `gpg (GnuPG) 1.4.x`, then you are using GnuPG v.1. Try the `gpg2` -command (if you don't have it, you may need to install the gnupg2 package): - - $ gpg2 --version | head -n1 - -If you see `gpg (GnuPG) 2.x.x`, then you are good to go. This guide will -assume you have the version 2.2 of GnuPG (or later). If you are using version -2.0 of GnuPG, then some of the commands in this guide will not work, and you -should consider installing the latest 2.2 version of GnuPG. Versions of -gnupg-2.1.11 and later should be compatible for the purposes of this guide as -well. - -##### Making sure you always use GnuPG v.2 - -If you have both `gpg` and `gpg2` commands, you should make sure you are -always using GnuPG v2, not the legacy version. You can enforce this by setting -the appropriate alias: - - $ alias gpg=gpg2 - -You can put that in your `.bashrc` to make sure it's always the case. - -#### Configure gpg-agent options - -The GnuPG agent is a helper tool that will start automatically whenever you -use the `gpg` command and run in the background with the purpose of caching -the private key passphrase. It is no longer necessary to start it manually -at the beginning of your shell session. - -There are two options you should know in order to tweak when the passphrase -should be expired from cache: - -- `default-cache-ttl` (seconds): If you use the same key again before the - time-to-live expires, the countdown will reset for another period. - The default is 600 (10 minutes). -- `max-cache-ttl` (seconds): Regardless of how recently you've used the key - since initial passphrase entry, if the maximum time-to-live countdown - expires, you'll have to enter the passphrase again. The default is 30 - minutes. - -If you find either of these defaults too short (or too long), you can edit -your `~/.gnupg/gpg-agent.conf` file to set your own values: - - # set to 30 minutes for regular ttl, and 2 hours for max ttl - default-cache-ttl 1800 - max-cache-ttl 7200 - -#### Set up a refresh cronjob - -You will need to regularly refresh your keyring in order to get the latest -changes on other people's public keys, which is best done with a daily -cronjob: - - $ crontab -e - -Add the following on a new line: - - @daily /usr/bin/gpg2 --refresh >/dev/null 2>&1 - -**NOTE**: check the full path to your `gpg` or `gpg2` command and use the `gpg2` -command if regular `gpg` for you is the legacy GnuPG v.1. - -## Protecting your master PGP key - -### Checklist - -- [ ] Understand the "master" key vs. subkeys _(ESSENTIAL)_ -- [ ] Ensure your private key passphrase is strong _(ESSENTIAL)_ -- [ ] Create a separate **[S]** subkey _(ESSENTIAL)_ -- [ ] Back up the master key using paperkey _(ESSENTIAL)_ -- [ ] Back up your whole `.gnupg` directory to encrypted media _(ESSENTIAL)_ -- [ ] Remove the master key from your homedir _(ESSENTIAL)_ - -### Considerations - -This guide assumes that you already have a PGP key that you use for Linux -Kernel development purposes. If you do not yet have one, please see the -"Protecting Code Integrity" document in this repository for guidance on how to -create a new one. - -You should also make a new key if your current one is weaker than 2048 bits -(RSA). - -#### Understanding the "Master" (Certify) key - -In this and next section we'll talk about the "master key" and "subkeys". It -is important to understand the following: - -1. There are no technical differences between the "master key" and "subkeys." -2. At creation time, we assign functional limitations to each key by - giving it specific capabilities. -3. A PGP key can have 4 capabilities. - - **[S]** key can be used for signing - - **[E]** key can be used for encryption - - **[A]** key can be used for authentication - - **[C]** key can be used for certifying other keys -4. A single key may have multiple capabilities. - -The key carrying the **[C]** (certify) capability is considered the "master" -key because it is the only key that can be used to indicate relationship with -other keys. Only the **[C]** key can be used to: - -- add or revoke other keys (subkeys) with S/E/A capabilities -- add, change or revoke identities (uids) associated with the key -- add or change the expiration date on itself or any subkey -- sign other people's keys for the web of trust purposes - -By default, GnuPG creates the following when generating new keys: - -- A master key carrying both Certify and Sign capabilities (**[SC]**) -- A separate subkey with the Encryption capability (**[E]**) - -If you used the default parameters when generating your key, then that is what -you will have. You can verify by running `gpg --list-secret-keys`, for -example: - - sec rsa2048 2018-01-23 [SC] [expires: 2020-01-23] - 000000000000000000000000AAAABBBBCCCCDDDD - uid [ultimate] Alice Dev - ssb rsa2048 2018-01-23 [E] [expires: 2020-01-23] - -Any key carrying the **[C]** capability is your master key, regardless of any -other capabilities it may have assigned to it. - -The long line under the `sec` entry is your key fingerprint -- whenever you -see `[fpr]` in the examples below, that 40-character string is what it refers -to. - -#### Ensure your passphrase is strong - -GnuPG uses passphrases to encrypt your private keys before storing them on -disk. This way, even if your `.gnupg` directory is leaked or stolen in its -entirety, the attackers cannot use your private keys without first obtaining -the passphrase to decrypt them. - -It is absolutely essential that your private keys are protected by a -strong passphrase. To set it or change it, use: - - $ gpg --change-passphrase [fpr] - -#### Create a separate Signing subkey - -Our goal is to protect your master key by moving it to offline media, so -if you only have a combined **[SC]** key, then you should create a separate -signing subkey. - -##### RSA vs. ECC subkeys - -GnuPG 2.1 and later has full support for Elliptic Curve Cryptography, with -ability to combine ECC subkeys with traditional RSA master keys. The main -upside of ECC cryptography is that it is much faster computationally and -creates much smaller signatures when compared byte for byte with 2048+ bit RSA -keys. - -Unless you plan on using a smartcard device that does not support ECC -operations, we recommend that you create an ECC signing subkey for your kernel -work: - - $ gpg --quick-add-key [fpr] ed25519 sign - -If for some reason you prefer to stay with RSA subkeys, just replace "ed25519" -with "rsa2048" in the above command. - -Remember to tell the keyservers about this change, so others can pull down -your new subkey: - - $ gpg --send-key [fpr] - -#### Back up your master key for disaster recovery - -The more signatures you have on your PGP key from other developers, the more -reasons you have to create a backup version that lives on something other than -digital media, for disaster recovery reasons. - -The best way to create a printable hardcopy of your private key is by using -the `paperkey` software written for this very purpose. See `man paperkey` for -more details on the output format and its benefits over other solutions. -Paperkey should already be packaged for most distributions. - -Run the following command to create a hardcopy backup of your private key: - - $ gpg --export-secret-key [fpr] | paperkey -o /tmp/key-backup.txt - -Print out that file (or pipe the output straight to lpr), then take a pen and -write your passphrase on the margin of the paper. **This is strongly -recommended** because the key printout is still encrypted with that -passphrase, and if you ever change it you will not remember what it used to be -when you had created the backup -- *guaranteed*. - -Put the resulting printout and the hand-written passphrase into an envelope -and store in a secure and well-protected place, preferably away from your -home, such as your bank vault. - -**NOTE ON PRINTERS**: Your printer is probably no longer a simple dumb device -connected to your parallel port, but since the output is still encrypted with -your passphrase, printing out even to "cloud-integrated" modern printers -should remain a relatively safe operation. One option is to change the -passphrase on your master key immediately after you are done with paperkey. - -#### Back up your whole GnuPG directory - -**!!!Do not skip this step!!!** - -It is important to have a readily available backup of your PGP keys should you -need to recover them (this is different from the disaster-level preparedness -we did with `paperkey`). You will also rely on these external copies whenever -you need to use your Certify key -- such as when making changes to your own -key or signing other people's keys after conferences and meetups. - -##### Prepare detachable encrypted storage - -Start by getting a small USB "thumb" drive (preferably two!) that you will use -for backup purposes. You will need to encrypt them before using them for our -purposes: - -- [Ubuntu instructions](https://help.ubuntu.com/community/EncryptedFilesystemsOnRemovableStorage) - -For the encryption passphrase, you can use the same one as on your master key. - -##### Back up your GnuPG directory - -Once the encryption process is over, re-insert the USB drive and make sure it -gets properly mounted. Find out the full mount point of the device, for -example by running the `mount` command (under Linux, external media usually -gets mounted under `/media/disk`). - -Once you know the full mount path, copy your entire GnuPG directory there: - - $ cp -a ~/.gnupg [/media/disk/name]/gnupg-backup - -(Note: If you get any `Operation not supported on socket` errors, those are -benign and you can ignore them.) - -You should now test to make sure everything still works: - - $ gpg --homedir=[/media/disk/name]/gnupg-backup --list-key [fpr] - -If you don't get any errors, then you should be good to go. Unmount the USB -drive, distinctly label it so you don't blow it away next time you need to use -a random USB drive, and put in a safe place -- but not too far away, because -you'll need to use it every now and again for things like editing identities, -adding or revoking subkeys, or signing other people's keys. - -#### Remove the master key from your homedir - -The files in our home directory are not as well protected as we like to think. -They can be leaked or stolen via many different means: - -- by accident when making quick homedir copies to set up a new workstation -- by systems administrator negligence or malice -- via poorly secured backups -- via malware in desktop apps (browsers, pdf viewers, etc) -- via coercion when crossing international borders - -Protecting your key with a good passphrase greatly helps reduce the risk of -any of the above, but passphrases can be discovered via keyloggers, -shoulder-surfing, or any number of other means. For this reason, the -recommended setup is to remove your master key from your home directory and -store it on offline storage. - -##### Removing your master key - -Please see the previous section and make sure you have backed up your GnuPG -directory in its entirety. What we are about to do will render your key -useless if you do not have a usable backup! - -First, identify the keygrip of your master key: - - $ gpg --with-keygrip --list-key [fpr] - -The output will be something like this: - - pub rsa2048 2018-01-24 [SC] [expires: 2020-01-24] - 000000000000000000000000AAAABBBBCCCCDDDD - Keygrip = 1111000000000000000000000000000000000000 - uid [ultimate] Alice Dev - sub rsa2048 2018-01-24 [E] [expires: 2020-01-24] - Keygrip = 2222000000000000000000000000000000000000 - sub ed25519 2018-01-24 [S] - Keygrip = 3333000000000000000000000000000000000000 - -Find the keygrip entry that is beneath the `pub` line (right under the master -key fingerprint). This will correspond directly to a file in your `~/.gnupg` -directory: - - $ cd ~/.gnupg/private-keys-v1.d - $ ls - 1111000000000000000000000000000000000000.key - 2222000000000000000000000000000000000000.key - 3333000000000000000000000000000000000000.key - -All you have to do is simply remove the `.key` file that corresponds to the -master keygrip: - - $ cd ~/.gnupg/private-keys-v1.d - $ rm 1111000000000000000000000000000000000000.key - -Now, if you issue the `--list-secret-keys` command, it will show that the -master key is missing (the `#` indicates it is not available): - - $ gpg --list-secret-keys - sec# rsa2048 2018-01-24 [SC] [expires: 2020-01-24] - 000000000000000000000000AAAABBBBCCCCDDDD - uid [ultimate] Alice Dev - ssb rsa2048 2018-01-24 [E] [expires: 2020-01-24] - ssb ed25519 2018-01-24 [S] - -You should also remove any `secring.gpg` files in the `~/.gnupg` directory, -which are left over from earlier versions of GnuPG. - -##### If you don't have the "private-keys-v1.d" directory - -If you do not have a `~/.gnupg/private-keys-v1.d` directory, then your -secret keys are still stored in the legacy `secring.gpg` file used by GnuPG -v1. Making any changes to your key, such as changing the passphrase or adding -a subkey, should automatically convert the old `secring.gpg` format to use -`private-keys-v1.d` instead. - -Once you get that done, make sure to delete the obsolete `secring.gpg` file, -which still contains your private keys. - -## Move the subkeys to a dedicated crypto device - -### Checklist - -- [ ] Get a GnuPG-compatible hardware device _(NICE)_ -- [ ] Configure the device to work with GnuPG _(NICE)_ -- [ ] Set the user and admin PINs _(NICE)_ -- [ ] Move your subkeys to the device _(NICE)_ - -### Considerations - -Even though the master key is now safe from being leaked or stolen, the -subkeys are still in your home directory. Anyone who manages to get their -hands on those will be able to decrypt your communication or fake your -signatures (if they know the passphrase). Furthermore, each time a GnuPG -operation is performed, the keys are loaded into system memory and can be -stolen from there by sufficiently advanced malware (think Meltdown and -Spectre). - -The best way to completely protect your keys is to move them to a specialized -hardware device that is capable of smartcard operations. - -#### The benefits of smartcards - -A smartcard contains a cryptographic chip that is capable of storing private -keys and performing crypto operations directly on the card itself. Because the -key contents never leave the smartcard, the operating system of the computer -into which you plug in the hardware device is not able to retrieve the -private keys themselves. This is very different from the encrypted USB storage -device we used earlier for backup purposes -- while that USB device is plugged -in and mounted, the operating system is able to access the private key -contents. - -Using external encrypted USB media is not a substitute to having a -smartcard-capable device. - -#### Available smartcard devices - -Unless all your laptops and workstations have smartcard readers, the easiest -is to get a specialized USB device that implements smartcard functionality. -There are several options available: - -- [Nitrokey Start](https://shop.nitrokey.com/shop/product/nitrokey-start-6): - Open hardware and Free Software, based on FSI Japan's - [Gnuk](http://www.fsij.org/doc-gnuk/). Offers support for ECC keys, - but fewest security features (such as resistance to tampering or some - side-channel attacks). -- [Nitrokey Pro](https://shop.nitrokey.com/shop/product/nitrokey-pro-3): - Similar to the Nitrokey Start, but more tamper-resistant and offers more - security features, but no ECC support. -- [Yubikey 4](https://www.yubico.com/product/yubikey-4-series/): Proprietary - hardware and software, but cheaper than Nitrokey Pro and comes available in - the USB-C form that is more useful with newer laptops. Offers - additional security features such as FIDO U2F, but no ECC. - -[LWN has a good review](https://lwn.net/Articles/736231/) of some of the above -models, as well as several others. If you want to use ECC keys, your best bet -among commercially available devices is the Nitrokey Start. - -#### Configuring your smartcard device - -Your smartcard device should Just Work (TM) the moment you plug it into any -modern Linux workstation. You can verify it by running: - - $ gpg --card-status - -If you see full smartcard details, then you are good to go. Unfortunately, -troubleshooting all possible reasons why things may not be working for you is -way beyond the scope of this guide. If you are having trouble getting the card -to work with GnuPG, please seek help via usual support channels. - -##### Quick setup - -To configure your smartcard, you will need to use the GnuPG menu system, as -there are no convenient command-line switches: - - $ gpg --card-edit - [...omitted...] - gpg/card> admin - Admin commands are allowed - gpg/card> passwd - -You should set the user PIN (1), Admin PIN (3), and the Reset Code (4). Please -make sure to record and store these in a safe place -- especially the Admin -PIN and the Reset Code (which allows you to completely wipe the smartcard). -You so rarely need to use the Admin PIN, that you will inevitably forget what -it is if you do not record it. - -Getting back to the main card menu, you can also set other values (such as -name, sex, login data, etc), but it's not necessary and will additionally leak -information about your smartcard should you lose it. - -##### PINs don't have to be numbers - -Note, that despite having the name "PIN" (and implying that it must be a -"number"), neither the user PIN nor the admin PIN on the card need to be -numbers. - -#### Moving the subkeys to your smartcard - -Exit the card menu (using "q") and save all changes. Next, let's move your -subkeys onto the smartcard. You will need both your PGP key passphrase and the -admin PIN of the card for most operations. - - $ gpg --edit-key [fpr] - - Secret subkeys are available. - - pub rsa2048/AAAABBBBCCCCDDDD - created: 2018-01-23 expires: 2020-01-23 usage: SC - trust: ultimate validity: ultimate - ssb rsa2048/1111222233334444 - created: 2018-01-23 expires: never usage: E - ssb ed25519/5555666677778888 - created: 2017-12-07 expires: never usage: S - [ultimate] (1). Alice Dev - - gpg> - -Using `--edit-key` puts us into the menu mode again, and you will notice that -the key listing is a little different. From here on, all commands are done -from inside this menu mode, as indicated by `gpg>`. - -First, let's select the key we'll be putting onto the card -- you do this by -typing `key 1` (it's the first one in the listing, the **[E]** subkey): - - gpg> key 1 - -In the output, you should now see `ssb*` on the **[E]** key. The `*` indicates -which key is currently "selected." It works as a *toggle*, meaning that if you -type `key 1` again, the `*` will disappear and the key will not be selected -any more. - -Now, let's move that key onto the smartcard: - - gpg> keytocard - Please select where to store the key: - (2) Encryption key - Your selection? 2 - -Since it's our **[E]** key, it makes sense to put it into the Encryption slot. -When you submit your selection, you will be prompted first for your PGP key -passphrase, and then for the admin PIN. If the command returns without an -error, your key has been moved. - -**Important**: Now type `key 1` again to unselect the first key, and `key 2` -to select the **[S]** key: - - gpg> key 1 - gpg> key 2 - gpg> keytocard - Please select where to store the key: - (1) Signature key - (3) Authentication key - Your selection? 1 - -You can use the **[S]** key both for Signature and Authentication, but we want -to make sure it's in the Signature slot, so choose (1). Once again, if your -command returns without an error, then the operation was successful. - - gpg> q - Save changes? (y/N) y - -Saving the changes will delete the keys you moved to the card from your home -directory (but it's okay, because we have them in our backups should we need -to do this again for a replacement smartcard). - -##### Verifying that the keys were moved - -If you perform `--list-secret-keys` now, you will see a subtle difference in -the output: - - $ gpg --list-secret-keys - sec# rsa2048 2018-01-24 [SC] [expires: 2020-01-24] - 000000000000000000000000AAAABBBBCCCCDDDD - uid [ultimate] Alice Dev - ssb> rsa2048 2018-01-24 [E] [expires: 2020-01-24] - ssb> ed25519 2018-01-24 [S] - -The `>` in the `ssb>` output indicates that the subkey is only available on -the smartcard. If you go back into your secret keys directory and look at the -contents there, you will notice that the `.key` files there have been replaced -with stubs: - - $ cd ~/.gnupg/private-keys-v1.d - $ strings *.key | grep 'private-key' - -The output should contain `shadowed-private-key` to indicate that these files -are only stubs and the actual content is on the smartcard. - -#### Verifying that the smartcard is functioning - -To verify that the smartcard is working as intended, you can create a -signature: - - $ echo "Hello world" | gpg --clearsign > /tmp/test.asc - $ gpg --verify /tmp/test.asc - -This should ask for your smartcard PIN on your first command, and then show -"Good signature" after you run `gpg --verify`. - -Congratulations, you have successfully made it extremely difficult to steal -your digital developer identity! - -### Other common GnuPG operations - -Here is a quick reference for some common operations you'll need to do with -your PGP key. - -#### Mounting your master key offline storage - -You will need your master key for any of the operations below, so you will -first need to mount your backup offline storage and tell GnuPG to use it. - - $ export GNUPGHOME=/media/disk/name/gnupg-backup - $ gpg --list-secret-keys - -You want to make sure that you see `sec` and not `sec#` in the output (the `#` -means the key is not available and you're still using your regular home -directory location). - -##### Updating your regular GnuPG working directory - -After you make any changes to your key using the offline storage, you will -want to import these changes back into your regular working directory: - - $ gpg --export | gpg --homedir ~/.gnupg --import - $ unset GNUPGHOME - -#### Extending key expiration date - -The master key has the default expiration date of 2 years from the date of -creation. This is done both for security reasons and to make obsolete keys -eventually disappear from keyservers. - -To extend the expiration on your key by a year from current date, just run: - - $ gpg --quick-set-expire [fpr] 1y - -You can also use a specific date if that is easier to remember (e.g. your -birthday, January 1st, or Canada Day): - - $ gpg --quick-set-expire [fpr] 2020-07-01 - -Remember to send the updated key back to keyservers: - - $ gpg --send-key [fpr] - -## Using PGP with Git - -One of the core features of Git is its decentralized nature -- once a -repository is cloned to your system, you have full history of the project, -including all of its tags, commits and branches. However, with hundreds of -cloned repositories floating around, how does anyone verify that their copy of -linux.git has not been tampered with by a malicious third party? - -Or what happens if a backdoor is discovered in the code and the "Author" line -in the commit says it was done by you, while you're pretty sure you had -[nothing to do with it](https://github.com/jayphelps/git-blame-someone-else)? - -To address both of these issues, Git introduced PGP integration. Signed tags -prove the repository integrity by assuring that its contents are exactly the -same as on the workstation of the developer who created the tag, while signed -commits make it nearly impossible for someone to impersonate you without -having access to your PGP keys. - -### Checklist - -- [ ] Configure git to use your key _(ESSENTIAL)_ -- [ ] Configure git to always sign annotated tags _(NICE)_ -- [ ] Decide if you're going to use commit signing _(NICE)_ - -### Considerations - -#### Configure git to use your PGP key - -If you only have one secret key in your keyring, then you don't really need to -do anything extra, as it becomes your default key. - -However, if you happen to have multiple secret keys, you can tell git which -key should be used (`[fpr]` is the fingerprint of your key): - - $ git config --global user.signingKey [fpr] - -**IMPORTANT**: If you have a distinct `gpg2` command, then you should tell git -to always use it instead of the legacy `gpg` from version 1: - - $ git config --global gpg.program gpg2 - -#### How to work with signed tags - -To create a signed tag, simply pass the `-s` switch to the tag command: - - $ git tag -s [tagname] - -Our recommendation is to always sign git tags, as this allows other developers -to ensure that the git repository they are pulling from has not been -maliciously altered. - -##### How to verify signed tags - -To verify a signed tag, simply use the `verify-tag` command: - - $ git verify-tag [tagname] - -If you are verifying someone else's git tag, then you will need to import -their PGP key. Please refer to the "how to verify kernel developer identities" -section below. - -##### Verifying at pull time - -If you are pulling a tag from another fork of the project repository, git -should automatically verify the signature at the tip you're pulling and show -you the results during the merge operation: - - $ git pull [url] tags/sometag - -The merge message will contain something like this: - - Merge tag 'sometag' of [url] - - [Tag message] - - # gpg: Signature made [...] - # gpg: Good signature from [...] - -#### Configure git to always sign annotated tags - -Chances are, if you're creating an annotated tag, you'll want to sign it. To -force git to always sign annotated tags, you can set a global configuration -option: - - $ git config --global tag.forceSignAnnotated true - -Alternatively, you can just train your muscle memory to always pass the `-s` -switch: - - $ git tag -asm "Tag message" tagname - -#### How to work with signed commits - -It is easy to create signed commits, but it is much more difficult to -use them in Linux Kernel development, since it relies on patches sent to -the mailing list, and this workflow does not preserve PGP commit signatures. - -If you have your working git tree publicly available at some git hosting -service (kernel.org, infradead.org, ozlabs.org, or others), then the -recommendation is that you sign all your git commits even if upstream -developers do not directly benefit from this practice. Should there ever be a -need to perform code forensics or track code provenance, even externally -maintained trees carrying PGP commit signatures will be extremely valuable for -such purposes. - -##### Creating signed commits - -To create a signed commit, you just need to pass the `-S` flag to the `git -commit` command (it's capital `-S` due to collision with another flag): - - $ git commit -S - -#### Configure git to always sign commits - -You can tell git to always sign commits: - - git config --global commit.gpgSign true - -Or you can train your muscle memory to always pass the `-S` flag to all `git -commit` operations (this includes `--amend`). - -## How to verify kernel developer identities - -Signing tags and commits is easy, but how does one go about verifying that the -key used to sign something belongs to the actual kernel developer and not to -a malicious imposter? - -### Checklist - -- [ ] Configure auto-key-retrieval using WKD and DANE _(ESSENTIAL)_ -- [ ] Configure trust-model to `tofu+pgp` _(ESSENTIAL)_ -- [ ] Learn how to use keyservers (more) safely _(ESSENTIAL)_ - -### Considerations - -#### Configure auto-key-retrieval using WKD and DANE - -If you are not already someone with an extensive collection of other -developers' public keys, then you can jumpstart your keyring by relying -on key auto-discovery and auto-retrieval. GnuPG can piggyback on other -delegated trust technologies, namely DNSSEC and TLS, to get you going if the -prospect of starting your own Web of Trust from scratch is too daunting. - -Add the following to your `~/.gnupg/gpg.conf`: - - auto-key-locate wkd,dane,local - auto-key-retrieve - -DNS-Based Authentication of Named Entities ("DANE") is a method for publishing -public keys in DNS and securing them using DNSSEC signed zones. Web Key -Directory ("WKD") is the alternative method that uses https lookups for the -same purpose. When using either DANE or WKD for looking up public keys, GnuPG -will validate DNSSEC or TLS certificates, respectively, before adding -auto-retrieved public keys to your local keyring. - -Kernel.org publishes the WKD for all developers who have kernel.org accounts. -Once you have the above changes in your `gpg.conf`, you can auto-retrieve the -keys for Linus Torvalds and Greg Kroah-Hartman (if you don't already have -them): - - $ gpg --locate-keys torvalds@kernel.org gregkh@kernel.org - -If you have a kernel.org account, then you should make sure that you have -[added the kernel.org UID to your key](https://korg.wiki.kernel.org/userdoc/mail#adding_a_kernelorg_uid_to_your_pgp_key) -to make WKD more useful to other kernel developers. - -#### Web of Trust (WOT) vs. Trust on First Use (TOFU) - -PGP incorporates a trust delegation mechanism known as the "Web of Trust." At -its core, this is an attempt to replace the need for centralized Certification -Authorities of the HTTPS/TLS world. Instead of various software makers -dictating who should be your trusted certifying entity, PGP leaves this -responsibility to each user. - -Unfortunately, very few people understand how the Web of Trust works. While -it remains an important aspect of the OpenPGP specification, recent -versions of GnuPG (2.2 and above) have implemented an alternative mechanism -called "Trust on First Use" (TOFU). - -You can think of TOFU as "the SSH-like approach to trust." With SSH, the first -time you connect to a remote system, its key fingerprint is recorded and -remembered. If the key changes in the future, the SSH client will alert you -and refuse to connect, forcing you to make a decision on whether you choose to -trust the changed key or not. - -Similarly, the first time you import someone's PGP key, it is assumed to be -valid. If at any point in the future GnuPG comes across another key with the -same identity, both the previously imported key and the new key will be marked -as invalid and you will need to manually figure out which one to keep. - -We recommend that you use the combined TOFU+PGP trust model (which is the new -default in GnuPG v2). To set it, add (or modify) the `trust-model` setting in -`~/.gnupg/gpg.conf`: - - trust-model tofu+pgp - -#### Learn to use keyservers (more) safely - -If, despite setting `auto-key-retrieve`, you still get a "No public key" error -when trying to validate someone's tag, then you should attempt to lookup that -key using a keyserver. It is important to keep in mind that there is -absolutely no guarantee that the key you retrieve from a keyserver belongs to -the actual person -- that much is by design. You are supposed to use the Web -of Trust to establish key validity. - -How to properly maintain the Web of Trust is beyond the scope of this -document, simply because doing it properly requires both effort and dedication -that tends to be beyond the caring threshold of most human beings. Here are -some shortcuts that will help you reduce the risk of importing a malicious -key. - -First, let's say you've tried to run `git verify-tag` but it returned an error -saying the key is not found: - - $ git verify-tag sunxi-fixes-for-4.15-2 - gpg: Signature made Sun 07 Jan 2018 10:51:55 PM EST - gpg: using RSA key DA73759BF8619E484E5A3B47389A54219C0F2430 - gpg: issuer "wens@...org" - gpg: Can't check signature: No public key - -Let's query the keyserver for more info about that key fingerprint (the -fingerprint probably belongs to a subkey, so we can't use it directly without -finding out the ID of the master key it is associated with): - - $ gpg --search DA73759BF8619E484E5A3B47389A54219C0F2430 - gpg: data source: hkp://keys.gnupg.net - (1) Chen-Yu Tsai - 4096 bit RSA key C94035C21B4F2AEB, created: 2017-03-14, expires: 2019-03-15 - Keys 1-1 of 1 for "DA73759BF8619E484E5A3B47389A54219C0F2430". Enter number(s), N)ext, or Q)uit > q - -Locate the ID of the master key in the output, in our example -`C94035C21B4F2AEB`. Now say `q` and display the key of Linus Torvalds that you -have on your keyring: - - $ git --list-key torvalds@kernel.org - pub rsa2048 2011-09-20 [SC] - ABAF11C65A2970B130ABE3C479BE3E4300411886 - uid [ unknown] Linus Torvalds - sub rsa2048 2011-09-20 [E] - -Next, open the [PGP pathfinder](https://pgp.cs.uu.nl/). In the "From" field, -paste the key fingerprint of Linus Torvalds from the output above. In the "To" -field, paste they key-id you found via `gpg --search` of the unknown key, and -check the results: - -- [From Linus to Chen-Yu](https://pgp.cs.uu.nl/paths/79BE3E4300411886/to/C94035C21B4F2AEB.html) - -If you get a few decent trust paths, then it's a pretty good indication that -it is a valid key. You can add it to your keyring from the keyserver now: - - $ gpg --recv-key C94035C21B4F2AEB - -This process is not perfect, and you are obviously trusting the administrators -of the PGP Pathfinder service to not be malicious. However, if you do not -carefully maintain your own web of trust, then it is an improvement over -blindly trusting keyservers. diff --git a/protecting-code-integrity.md b/protecting-code-integrity.md index c3262a6..5607d77 100644 --- a/protecting-code-integrity.md +++ b/protecting-code-integrity.md @@ -1,6 +1,6 @@ # Protecting code integrity with PGP -Updated: 2018-01-22 +Updated: 2021-05-13 *Status: CURRENT* @@ -23,35 +23,31 @@ Updated: 2018-01-22 - [Web of Trust (WOT) vs. Trust on First Use (TOFU)](#web-of-trust-wot-vs-trust-on-first-use-tofu) - [Installing OpenPGP software](#installing-openpgp-software) - [Installing GnuPG](#installing-gnupg) - - [GnuPG 1 vs. 2](#gnupg-1-vs-2) - - [Making sure you always use GnuPG v.2](#making-sure-you-always-use-gnupg-v2) - - [Generating and protecting your master PGP key](#generating-and-protecting-your-master-pgp-key) + - [Generating and protecting your certification key](#generating-and-protecting-your-certification-key) - [Checklist](#checklist-1) - [Considerations](#considerations-1) - - [Understanding the "Master" (Certify) key](#understanding-the-%22master%22-certify-key) - - [Before you create the master key](#before-you-create-the-master-key) + - [Understanding the certification key](#understanding-the-certification-key) + - [Before you create the certification key](#before-you-create-the-certification-key) - [Primary identity](#primary-identity) - [Passphrase](#passphrase) - [Algorithm and key strength](#algorithm-and-key-strength) - - [Generate the master key](#generate-the-master-key) - - [Back up your master key](#back-up-your-master-key) + - [Generate the certification key](#generate-the-certification-key) + - [Back up your certification key](#back-up-your-certification-key) - [Add relevant identities](#add-relevant-identities) - [Pick the primary UID](#pick-the-primary-uid) - [Generating PGP subkeys](#generating-pgp-subkeys) - [Checklist](#checklist-2) - [Considerations](#considerations-2) - [Create the subkeys](#create-the-subkeys) - - [Upload your public keys to the keyserver](#upload-your-public-keys-to-the-keyserver) - - [Upload your public key to GitHub](#upload-your-public-key-to-github) - - [Set up a refresh cronjob](#set-up-a-refresh-cronjob) - - [Moving your master key to offline storage](#moving-your-master-key-to-offline-storage) + - [Upload your public key to GitHub](#upload-your-public-key-to-github) + - [Moving your certification key to offline storage](#moving-your-certification-key-to-offline-storage) - [Checklist](#checklist-3) - [Considerations](#considerations-3) - [Back up your GnuPG directory](#back-up-your-gnupg-directory) - [Prepare detachable encrypted storage](#prepare-detachable-encrypted-storage) - [Back up your GnuPG directory](#back-up-your-gnupg-directory-1) - - [Remove the master key](#remove-the-master-key) - - [Removing your master key](#removing-your-master-key) + - [Remove the certification key](#remove-the-certification-key) + - [Removing your certification key](#removing-your-certification-key) - [Remove the revocation certificate](#remove-the-revocation-certificate) - [Move the subkeys to a hardware device](#move-the-subkeys-to-a-hardware-device) - [Checklist](#checklist-4) @@ -65,7 +61,7 @@ Updated: 2018-01-22 - [Verifying that the keys were moved](#verifying-that-the-keys-were-moved) - [Verifying that the smartcard is functioning](#verifying-that-the-smartcard-is-functioning) - [Other common GnuPG operations](#other-common-gnupg-operations) - - [Mounting your master key offline storage](#mounting-your-master-key-offline-storage) + - [Mounting your offline storage](#mounting-your-offline-storage) - [Updating your regular GnuPG working directory](#updating-your-regular-gnupg-working-directory) - [Extending key expiration date](#extending-key-expiration-date) - [Revoking identities](#revoking-identities) @@ -78,7 +74,6 @@ Updated: 2018-01-22 - [Hashing function](#hashing-function) - [Annotated tags and tag signatures](#annotated-tags-and-tag-signatures) - [Signed commits](#signed-commits) - - [Signed pushes](#signed-pushes) - [Configure git to use your PGP key](#configure-git-to-use-your-pgp-key) - [How to work with signed tags](#how-to-work-with-signed-tags) - [How to verify signed tags](#how-to-verify-signed-tags) @@ -325,66 +320,39 @@ of the commands in the guide to work for you, unless you have a unix-like environment set up. For all other platforms, you'll need to do your own research to find the correct places to download and install GnuPG. -##### GnuPG 1 vs. 2 - -Both GnuPG v.1 and GnuPG v.2 implement the same standard, but they provide -incompatible libraries and command-line tools, so many distributions ship both -the legacy version 1 and the latest version 2. You need to make sure you are -always using GnuPG v.2. - -First, run: - - $ gpg --version | head -n1 - -If you see `gpg (GnuPG) 1.4.x`, then you are using GnuPG v.1. Try the `gpg2` -command: - - $ gpg2 --version | head -n1 - -If you see `gpg (GnuPG) 2.x.x`, then you are good to go. This guide will -assume you have the version 2.2 of GnuPG (or later). If you are using version -2.0 of GnuPG, some of the commands in this guide will not work, and you should -consider installing the latest 2.2 version of GnuPG. - -##### Making sure you always use GnuPG v.2 - -If you have both `gpg` and `gpg2` commands, you should make sure you are -always using GnuPG v2, not the legacy version. You can make sure of this by -setting the alias: - - $ alias gpg=gpg2 - -You can put that in your `.bashrc` to make sure it's always loaded whenever -you use the gpg commands. - -## Generating and protecting your master PGP key +## Generating and protecting your certification key ### Checklist -- [ ] Generate a 4096-bit RSA master key _(ESSENTIAL)_ -- [ ] Back up the master key using paperkey _(ESSENTIAL)_ +- [ ] Generate a 4096-bit RSA certification key _(ESSENTIAL)_ +- [ ] Back up the certification key using paperkey _(ESSENTIAL)_ - [ ] Add all relevant identities _(ESSENTIAL)_ ### Considerations -#### Understanding the "Master" (Certify) key +#### Understanding the certification key -In this and next section we'll talk about the "master key" and "subkeys". It -is important to understand the following: +In this and next section we'll talk about the certification key and subkeys. +The certification key is often called "the master key," but it is a poor +analogy, as it doesn't act in any way like a physical master key (in the sense +that it cannot decrypt content encrypted to any of the subkeys, as one +example). For this reason, we'll stick to calling it the "certification key." -1. There are no technical differences between the "master key" and "subkeys." +It is important to understand the following: + +1. There are no technical differences between the certify key and any of the + subkeys 2. At creation time, we assign functional limitations to each key by giving it specific capabilities. -3. A PGP key can have 4 capabilities. +3. A PGP key can have 4 capabilities: - **[S]** key can be used for signing - **[E]** key can be used for encryption - **[A]** key can be used for authentication - **[C]** key can be used for certifying other keys 4. A single key may have multiple capabilities. -The key carrying the **[C]** (certify) capability is considered the "master" -key because it is the only key that can be used to indicate relationship with -other keys. Only the **[C]** key can be used to: +The key carrying the **[C]** (certify) capability is used to indicate +relationship with other PGP keys. Only the **[C]** key can be used to: - add or revoke other keys (subkeys) with S/E/A capabilities - add, change or revoke identities (uids) associated with the key @@ -395,10 +363,10 @@ In the Free Software world, the **[C]** key is your digital identity. Once you create that key, you should take extra care to protect it and prevent it from falling into malicious hands. -#### Before you create the master key +#### Before you create the certify key -Before you create your master key you need to pick your primary identity and -your master passphrase. +Before you create your certify key you need to pick your primary identity and +your passphrase. ##### Primary identity @@ -428,23 +396,24 @@ to type and easy to remember. ##### Algorithm and key strength -Even though GnuPG has had support for Elliptic Curve crypto for a while now, -we'll be sticking to RSA keys, at least for a little while longer. While it is -possible to start using ED25519 keys right now, it is likely that you will -come across tools and hardware devices that will not be able to handle them -correctly. +GnuPG supports many algorithms, but we will only consider the below two: -You may also wonder why the master key is 4096-bit, if later in the guide we -state that 2048-bit keys should be good enough for the lifetime of RSA public -key cryptography. The reasons are mostly social and not technical: master keys -happen to be the most visible ones on the keychain, and some of the developers -you interact with will inevitably judge you negatively if your master key has -fewer bits than theirs. +- RSA for the certification key +- ECC (Elliptic Curve) for all other subkeys -#### Generate the master key +We use RSA for the certification key mainly for compatibility reasons -- there +is probably still some tooling that does not properly handle ECC keys, so +sticking with RSA for the certification key makes sense. We will use it only +very occasionally, so the slowness/size considerations are unimportant. -To generate your new master key, issue the following command, putting in the -right values instead of "Alice Engineer:" +All of the day-to-day work will be done using subkeys, so picking ECC makes +perfect sense there -- it will be faster and the resulting signatures will be +dramatically smaller. + +#### Generate the certification key + +To generate your new certification key, issue the following command, putting +in the right values instead of "Alice Engineer:" $ gpg --quick-generate-key 'Alice Engineer ' rsa4096 cert @@ -454,7 +423,7 @@ the command completes. Review the output of the command, it will be something like this: - pub rsa4096 2017-12-06 [C] [expires: 2019-12-06] + pub rsa4096 2021-05-01 [C] [expires: 2023-05-01] 111122223333444455556666AAAABBBBCCCCDDDD uid Alice Engineer @@ -472,7 +441,7 @@ At this point, I suggest you open a text editor, copy the fingerprint of your new key and paste it there. You'll need to use it for the next few steps, so having it close by will be handy. -#### Back up your master key +#### Back up your certification key For disaster recovery purposes -- and especially if you intend to use the Web of Trust and collect key signatures from other project developers -- you @@ -508,9 +477,9 @@ safe operation, but use your best paranoid judgement. #### Add relevant identities If you have multiple relevant email addresses (personal, work, open-source -project, etc), you should add them to your master key. You don't need to do -this for any addresses that you don't expect to use with PGP (e.g. probably -not your school alumni address). +project, etc), you should add them to your key. You don't need to do this for +any addresses that you don't expect to use with PGP (e.g. probably not your +school alumni address). The command is (put the full key fingerprint instead of `[fpr]`): @@ -531,78 +500,58 @@ different from what you want, you should fix it back: ### Checklist -- [ ] Generate a 2048-bit Encryption subkey _(ESSENTIAL)_ -- [ ] Generate a 2048-bit Signing subkey _(ESSENTIAL)_ -- [ ] Generate a 2048-bit Authentication subkey _(NICE)_ -- [ ] Upload your public keys to a PGP keyserver _(ESSENTIAL)_ -- [ ] Set up a refresh cronjob _(ESSENTIAL)_ +- [ ] Generate the Encryption subkey _(ESSENTIAL)_ +- [ ] Generate the Signing subkey _(ESSENTIAL)_ +- [ ] Generate the Authentication subkey _(NICE)_ +- [ ] Upload your public keys to a PGP keyserver _(NICE)_ +- [ ] Set up a refresh cronjob _(NICE)_ ### Considerations -Now that we've created the master key, let's create the keys you'll actually -be using for day-to-day work. We create 2048-bit keys because a lot of -specialized hardware (we'll discuss this further) does not handle larger keys, -but also for pragmatic reasons. If we ever find ourselves in a world where -2048-bit RSA keys are not considered good enough, it will be because of -fundamental breakthroughs in computing or mathematics and therefore longer -4096-bit keys will not make much difference. +Now that we've created the certification key, let's create the keys you'll +actually be using for day-to-day work. Before we do this, we need to pick the +ECC algorithm flavor. + +#### ED25519 or NIST? + +We won't go into the reasons behind why ECC is split into two camps. All you +need to know is that many people consider ed25519 "more pure" due to the way +its underlying curve primitives were selected and NIST "less pure" because +that selection process was not as public or thorough. + +Do you plan to use a hardware device like a Yubikey for storing your subkeys? +Then pick NIST (use "nistp256" instead of "cv25519" and "ed25519" below). If +you just plan to store your subkeys on your computer, then pick ED25519 (the +GnuPG default). + +Since you can revoke subkeys and create new ones at any time, this is not a +life or death kind of decision. If in doubt, pick ed25519. #### Create the subkeys To create the subkeys, run: - $ gpg --quick-add-key [fpr] rsa2048 encr - $ gpg --quick-add-key [fpr] rsa2048 sign + $ gpg --quick-add-key [fpr] cv25519 encr + $ gpg --quick-add-key [fpr] ed25519 sign You can also create the Authentication key, which will allow you to use your PGP key for ssh purposes: - $ gpg --quick-add-key [fpr] rsa2048 auth + $ gpg --quick-add-key [fpr] ed25519 auth You can review your key information using `gpg --list-key [fpr]`: - pub rsa4096 2017-12-06 [C] [expires: 2019-12-06] + pub rsa4096 2021-05-01 [C] [expires: 2023-05-01] 111122223333444455556666AAAABBBBCCCCDDDD uid [ultimate] Alice Engineer uid [ultimate] Alice Engineer - sub rsa2048 2017-12-06 [E] - sub rsa2048 2017-12-06 [S] + sub cv25519 2021-05-01 [E] + sub ed25519 2021-05-01 [S] -#### Upload your public keys to the keyserver +#### Upload your public key to GitHub -Your key creation is complete, so now you need to make it easier for others to -find it by uploading it to one of the public keyservers. (Do not do this step -if you're just messing around and aren't planning on actually using the key -you've created, as this just litters keyservers with useless data.) - - $ gpg --send-key [fpr] - -If this command does not succeed, you can try specifying the keyserver on a -port that is most likely to work: - - $ gpg --keyserver hkp://pgp.mit.edu:80 --send-key [fpr] - -Most keyservers communicate with each-other, so your key information will -eventually synchronize to all the others. - -**NOTE ON PRIVACY:** Keyservers are completely public and therefore, by -design, leak potentially sensitive information about you, such as your full -name, nicknames, and personal or work email addresses. If you sign other -people's keys or someone signs yours, keyservers will additionally become -leakers of your social connections. Once such personal information makes it to -the keyservers, it becomes impossible to edit or delete. Even if you revoke a -signature or identity, that does not delete them from your key record, just -marks them as revoked -- making them stand out even more. - -That said, if you participate in software development on a public project, all -of the above information is already public record, and therefore making it -additionally available via keyservers does not result in a net loss in -privacy. - -##### Upload your public key to GitHub - -If you use GitHub in your development (and who doesn't?), you should upload -your key following the instructions they have provided: +If you use GitHub in your development, you should upload your key following +the instructions they have provided: - [Adding a PGP key to your GitHub account](https://help.github.com/articles/adding-a-new-gpg-key-to-your-github-account/) @@ -610,39 +559,33 @@ To generate the public key output suitable to paste in, just run: $ gpg --export --armor [fpr] -#### Set up a refresh cronjob +#### Upload your public key to keys.openpgp.org -You will need to regularly refresh your keyring in order to get the latest -changes on other people's public keys. You can set up a cronjob to do that: +To make it easier for others to find your public key, you can upload it to the +keys.openpgp.org keyserver. Please follow the instructions provided here: - $ crontab -e +- [Upload to keys.openpgp.org](https://keys.openpgp.org/about/usage#gnupg-upload) -Add the following on a new line: - @daily /usr/bin/gpg2 --refresh >/dev/null 2>&1 - -**NOTE**: check the full path to your `gpg` or `gpg2` command and use the `gpg2` -command if regular `gpg` for you is the legacy GnuPG v.1. - -## Moving your master key to offline storage +## Moving your cerification key to offline storage ### Checklist - [ ] Prepare encrypted detachable storage _(ESSENTIAL)_ - [ ] Back up your GnuPG directory _(ESSENTIAL)_ -- [ ] Remove the master key from your home directory _(NICE)_ +- [ ] Remove the certification key from your home directory _(NICE)_ - [ ] Remove the revocation certificate from your home directory _(NICE)_ ### Considerations -Why would you want to remove your master **[C]** key from your home directory? -This is generally done to prevent your master key from being stolen or -accidentally leaked. Private keys are tasty targets for malicious actors -- we -know this from several successful malware attacks that scanned users' home +Why would you want to remove your certification (**[C]**) key from your home +directory? This is generally done to prevent it from being stolen or +accidentally leaked. Private keys are tasty targets for malicious actors -- +we know this from several successful malware attacks that scanned users' home directories and uploaded any private key content found there. It would be very damaging for any developer to have their PGP keys stolen -- -in the Free Software world this is often tantamount to identity theft. +in the Free Software world this is basically equal to identity theft. Removing private keys from your home directory helps protect you from such events. @@ -662,7 +605,8 @@ for backup purposes. You will first need to encrypt them: - [Apple instructions](https://support.apple.com/kb/PH25745) - [Linux instructions](https://help.ubuntu.com/community/EncryptedFilesystemsOnRemovableStorage) -For the encryption passphrase, you can use the same one as on your master key. +For the encryption passphrase, you can use the same one as on your private +key. #### Back up your GnuPG directory @@ -688,7 +632,7 @@ a random USB drive, and put in a safe place -- but not too far away, because you'll need to use it every now and again for things like editing identities, adding or revoking subkeys, or signing other people's keys. -#### Remove the master key +#### Remove the certification key The files in our home directory are not as well protected as we like to think. They can be leaked or stolen via many different means: @@ -702,32 +646,32 @@ They can be leaked or stolen via many different means: Protecting your key with a good passphrase greatly helps reduce the risk of any of the above, but passphrases can be discovered via keyloggers, shoulder-surfing, or any number of other means. For this reason, the -recommended setup is to remove your master key from your home directory and -store it on offline storage. +recommended setup is to remove your certification key from your home directory +and store it on offline storage. -##### Removing your master key +##### Removing your certification key Please see the previous section and make sure you have backed up your GnuPG directory in its entirety. What we are about to do will render your key useless if you do not have a usable backup! -First, identify the keygrip of your master key: +First, identify the "keygrip" of your certification key: $ gpg --with-keygrip --list-key [fpr] The output will be something like this: - pub rsa4096 2017-12-06 [C] [expires: 2019-12-06] + pub rsa4096 2021-05-01 [C] [expires: 2023-05-01] 111122223333444455556666AAAABBBBCCCCDDDD Keygrip = AAAA999988887777666655554444333322221111 uid [ultimate] Alice Engineer uid [ultimate] Alice Engineer - sub rsa2048 2017-12-06 [E] + sub cv25519 2021-05-01 [E] Keygrip = BBBB999988887777666655554444333322221111 - sub rsa2048 2017-12-06 [S] + sub ed25519 2021-05-01 [S] Keygrip = CCCC999988887777666655554444333322221111 -Find the keygrip entry that is beneath the `pub` line (right under the master +Find the keygrip entry that is beneath the `pub` line (right under the public key fingerprint). This will correspond directly to a file in your home `.gnupg` directory: @@ -738,34 +682,34 @@ key fingerprint). This will correspond directly to a file in your home CCCC999988887777666655554444333322221111.key All you have to do is simply remove the `.key` file that corresponds to the -master keygrip: +certification keygrip: $ cd ~/.gnupg/private-keys-v1.d $ rm AAAA999988887777666655554444333322221111.key Now, if you issue the `--list-secret-keys` command, it will show that the -master key is missing (the `#` indicates it is not available): +**[C]** key is not present (indicated by the `#` character): $ gpg --list-secret-keys - sec# rsa4096 2017-12-06 [C] [expires: 2019-12-06] + sec# rsa4096 2021-05-01 [C] [expires: 2023-05-01] 111122223333444455556666AAAABBBBCCCCDDDD uid [ultimate] Alice Engineer uid [ultimate] Alice Engineer - ssb rsa2048 2017-12-06 [E] - ssb rsa2048 2017-12-06 [S] + ssb cv25519 2021-05-01 [E] + ssb ed25519 2021-05-01 [S] #### Remove the revocation certificate Another file you should remove (but keep in backups) is the revocation -certificate that was automatically created with your master key. A revocation -certificate allows someone to permanently mark your key as revoked, meaning it -can no longer be used or trusted for any purpose. You would normally use it to -revoke a key that, for some reason, you can no longer control -- for example, -if you had lost the key passphrase. +certificate that was automatically created with your certification key. A +revocation certificate allows someone to permanently mark your key as revoked, +meaning it can no longer be used or trusted for any purpose. You would +normally use it to revoke a key that, for some reason, you can no longer +control -- for example, if you had lost the key passphrase. -Just as with the master key, if a revocation certificate leaks into malicious -hands, it can be used to destroy your developer digital identity, so it's -better to remove it from your home directory. +Just as with the certification key, if a revocation certificate leaks into +malicious hands, it can be used to destroy your developer digital identity, so +it's better to remove it from your home directory. cd ~/.gnupg/openpgp-revocs.d rm [fpr].rev @@ -781,7 +725,7 @@ better to remove it from your home directory. ### Considerations -Even though the master key is now safe from being leaked or stolen, the +Even though the certification key is now safe from being leaked or stolen, the subkeys are still in your home directory. Anyone who manages to get their hands on those will be able to decrypt your communication or fake your signatures (if they know the passphrase). Furthermore, each time a GnuPG @@ -826,17 +770,18 @@ features on the internal chip. Here are a few recommendations: - [Nitrokey Start](https://shop.nitrokey.com/shop/product/nitrokey-start-6): Open hardware and Free Software: one of the cheapest options for GnuPG use, - but with fewest extra security features + but with fewest extra security features. - [Nitrokey Pro](https://shop.nitrokey.com/shop/product/nitrokey-pro-3): Similar to the Nitrokey Start, but is tamper-resistant and offers more - security features (but not U2F, see the Fido U2F section of the guide) -- [Yubikey 4](https://www.yubico.com/product/yubikey-4-series/): Proprietary - hardware and software, but cheaper than Nitrokey Pro and comes available - in the USB-C form that is more useful with newer laptops; also offers - additional security features such as U2F + security features (but not U2F, see the Fido U2F section of the guide); only + supports NIST ECC cryptography. +- [Yubikey](https://www.yubico.com/): Proprietary hardware and software, but + cheaper than Nitrokey Pro and comes available in the USB-C form that is more + useful with newer laptops; also offers additional security features such as + U2F; only supports NIST ECC cryptography. -Our recommendation is to pick a device that is capable of both smartcard -functionality and U2F, which, at the time of writing, means a Yubikey 4. +If you want to use ED25519 subkeys, then your only choice is a Nitrokey Start, +though once Nitrokey 3 Pro is available, it should also be considered. #### Configuring your smartcard device @@ -894,12 +839,12 @@ the full 40-character fingerprint of your key. Secret subkeys are available. pub rsa4096/AAAABBBBCCCCDDDD - created: 2017-12-07 expires: 2019-12-07 usage: C + created: 2021-05-01 expires: 2023-05-01 usage: C trust: ultimate validity: ultimate - ssb rsa2048/1111222233334444 - created: 2017-12-07 expires: never usage: E - ssb rsa2048/5555666677778888 - created: 2017-12-07 expires: never usage: S + ssb cv25519/1111222233334444 + created: 2021-05-01 expires: never usage: E + ssb ed25519/5555666677778888 + created: 2021-05-01 expires: never usage: S [ultimate] (1). Alice Engineer [ultimate] (2) Alice Engineer @@ -917,12 +862,12 @@ typing `key 1` (it's the first one in the listing, our **[E]** subkey): The output should be subtly different: pub rsa4096/AAAABBBBCCCCDDDD - created: 2017-12-07 expires: 2019-12-07 usage: C + created: 2021-05-01 expires: 2023-05-01 usage: C trust: ultimate validity: ultimate - ssb* rsa2048/1111222233334444 - created: 2017-12-07 expires: never usage: E - ssb rsa2048/5555666677778888 - created: 2017-12-07 expires: never usage: S + ssb* cv25519/1111222233334444 + created: 2021-05-01 expires: never usage: E + ssb ed25519/5555666677778888 + created: 2021-05-01 expires: never usage: S [ultimate] (1). Alice Engineer [ultimate] (2) Alice Engineer @@ -974,12 +919,12 @@ If you perform `--list-secret-keys` now, you will see a subtle difference in the output: $ gpg --list-secret-keys - sec# rsa4096 2017-12-06 [C] [expires: 2019-12-06] + sec# rsa4096 2021-05-01 [C] [expires: 2023-05-01] 111122223333444455556666AAAABBBBCCCCDDDD uid [ultimate] Alice Engineer uid [ultimate] Alice Engineer - ssb> rsa2048 2017-12-06 [E] - ssb> rsa2048 2017-12-06 [S] + ssb> cv25519 2021-05-01 [E] + ssb> ed25519 2021-05-01 [S] The `>` in the `ssb>` output indicates that the subkey is only available on the smartcard. If you go back into your secret keys directory and look at the @@ -1013,10 +958,10 @@ your PGP key. In all of the below commands, the `[fpr]` is your key fingerprint. -#### Mounting your master key offline storage +#### Mounting your offline storage -You will need your master key for any of the operations below, so you will -first need to mount your backup offline storage and tell GnuPG to use it. +You will need your certification key for any of the operations below, so you +will first need to mount your backup offline storage and tell GnuPG to use it. First, find out where the media got mounted, e.g. by looking at the output of the `mount` command. Then, locate the directory with the backup of your GnuPG directory and tell GnuPG to use that as its home: @@ -1038,18 +983,18 @@ want to import these changes back into your regular working directory: #### Extending key expiration date -The master key we created has the default expiration date of 2 years from the -date of creation. This is done both for security reasons and to make obsolete -keys eventually disappear from keyservers. +The certification key we created has the default expiration date of 2 years +from the date of creation. This is done both for security reasons and to make +obsolete keys eventually disappear from keyservers. To extend the expiration on your key by a year from current date, just run: $ gpg --quick-set-expire [fpr] 1y You can also use a specific date if that is easier to remember (e.g. your -birthday, January 1st, or Canada Day): +birthday, January 1st, or Canada Day, 2030): - $ gpg --quick-set-expire [fpr] 2020-07-01 + $ gpg --quick-set-expire [fpr] 2030-07-01 Remember to send the updated key back to keyservers: @@ -1080,8 +1025,7 @@ location, but what if someone had managed to trick you? Or what happens if a backdoor is discovered in one of the projects you've worked on, and the "Author" line in the commit says it was done by you, while -you're pretty sure you had [nothing to do with -it](https://github.com/jayphelps/git-blame-someone-else)? +you're pretty sure you had [nothing to do with it](https://github.com/jayphelps/git-blame-someone-else)? To address both of these issues, Git introduced PGP integration. Signed tags prove the repository integrity by assuring that its contents are exactly the @@ -1091,7 +1035,7 @@ having access to your PGP keys. ### Checklist -- [ ] Understand signed tags, commits, and pushes _(ESSENTIAL)_ +- [ ] Understand signed tags, commits _(ESSENTIAL)_ - [ ] Configure git to use your key _(ESSENTIAL)_ - [ ] Learn how tag signing and verification works _(ESSENTIAL)_ - [ ] Configure git to always sign annotated tags _(NICE)_ @@ -1102,8 +1046,7 @@ having access to your PGP keys. ### Considerations Git implements multiple levels of integration with PGP, first starting with -signed tags, then introducing signed commits, and finally adding support for -signed pushes. +signed tags, and then introducing signed commits. #### Understanding Git Hashes @@ -1182,24 +1125,6 @@ developer's tree at the time the signature was made. Tag signatures and commit PGP signatures provide exact same security assurances about the repository and its entire history. -#### Signed pushes - -This is included here for completeness' sake, since this functionality needs -to be enabled on the server receiving the push before it does anything useful. -As we saw above, PGP-signing a git object gives verifiable information about -the developer's git tree, but not about their *intent* for that tree. - -For example, you can be working on an experimental branch in your own git fork -trying out a promising cool feature, but after you submit your work for -review, someone finds a nasty bug in your code. Since your commits are -properly signed, someone can take the branch containing your nasty bug and -push it into master, introducing a vulnerability that was never intended to go -into production. Since the commit is properly signed with your key, everything -looks legitimate and your reputation is questioned when the bug is discovered. - -Ability to require PGP-signatures during `git push` was added in order to -certify the *intent* of the commit, and not merely verify its contents. - #### Configure git to use your PGP key If you only have one secret key in your keyring, then you don't really need to @@ -1210,11 +1135,6 @@ key should be used (`[fpr]` is the fingerprint of your key): $ git config --global user.signingKey [fpr] -**NOTE**: If you have a distinct `gpg2` command, then you should tell git to -always use it instead of the legacy `gpg` from version 1: - - $ git config --global gpg.program gpg2 - #### How to work with signed tags To create a signed tag, simply pass the `-s` switch to the tag command: @@ -1360,18 +1280,12 @@ smartcard, you can use it with ssh for adding 2-factor authentication for your ssh sessions. You just need to tell your environment to use the correct socket file for talking to the agent. -First, add the following to your `~/.gnupg/gpg-agent.conf`: - - enable-ssh-support - -Then, add this to your `.bashrc`: +All you need is add this to your `.bashrc`: export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket) -You will need to kill the existing `gpg-agent` process and start a new login -session for the changes to take effect: +Then start a new login session for the changes to take effect: - $ killall gpg-agent $ bash $ ssh-add -L @@ -1500,7 +1414,8 @@ By this point you have accomplished the following important tasks: 1. Created your developer identity and protected it using PGP cryptography. 2. Configured your environment so your identity is not easily stolen by moving - your master key offline and your subkeys to an external hardware device. + your certification key offline and your subkeys to an external hardware + device. 3. Configured your git environment to ensure that anyone using your project is able to verify the integrity of the repository and its entire history. 4. Secured your online accounts using 2-factor authentication.