Merge branch 'master' of https://github.com/mricon/itpol into mricon-master

Signed-off-by: Konstantin Ryabitsev <konstantin@linuxfoundation.org>
This commit is contained in:
Konstantin Ryabitsev 2021-05-13 15:12:38 -04:00
commit e536c34df0
No known key found for this signature in database
GPG Key ID: B6C41CE35664996C
2 changed files with 155 additions and 1224 deletions

View File

@ -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 <adev@kernel.org>
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 <adev@kernel.org>
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 <adev@kernel.org>
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 <adev@kernel.org>
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 <adev@kernel.org>
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 <wens@...org>
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 <torvalds@kernel.org>
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.

View File

@ -1,6 +1,6 @@
# Protecting code integrity with PGP # Protecting code integrity with PGP
Updated: 2018-01-22 Updated: 2021-05-13
*Status: CURRENT* *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) - [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 OpenPGP software](#installing-openpgp-software)
- [Installing GnuPG](#installing-gnupg) - [Installing GnuPG](#installing-gnupg)
- [GnuPG 1 vs. 2](#gnupg-1-vs-2) - [Generating and protecting your certification key](#generating-and-protecting-your-certification-key)
- [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)
- [Checklist](#checklist-1) - [Checklist](#checklist-1)
- [Considerations](#considerations-1) - [Considerations](#considerations-1)
- [Understanding the "Master" (Certify) key](#understanding-the-%22master%22-certify-key) - [Understanding the certification key](#understanding-the-certification-key)
- [Before you create the master key](#before-you-create-the-master-key) - [Before you create the certification key](#before-you-create-the-certification-key)
- [Primary identity](#primary-identity) - [Primary identity](#primary-identity)
- [Passphrase](#passphrase) - [Passphrase](#passphrase)
- [Algorithm and key strength](#algorithm-and-key-strength) - [Algorithm and key strength](#algorithm-and-key-strength)
- [Generate the master key](#generate-the-master-key) - [Generate the certification key](#generate-the-certification-key)
- [Back up your master key](#back-up-your-master-key) - [Back up your certification key](#back-up-your-certification-key)
- [Add relevant identities](#add-relevant-identities) - [Add relevant identities](#add-relevant-identities)
- [Pick the primary UID](#pick-the-primary-uid) - [Pick the primary UID](#pick-the-primary-uid)
- [Generating PGP subkeys](#generating-pgp-subkeys) - [Generating PGP subkeys](#generating-pgp-subkeys)
- [Checklist](#checklist-2) - [Checklist](#checklist-2)
- [Considerations](#considerations-2) - [Considerations](#considerations-2)
- [Create the subkeys](#create-the-subkeys) - [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)
- [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)
- [Set up a refresh cronjob](#set-up-a-refresh-cronjob)
- [Moving your master key to offline storage](#moving-your-master-key-to-offline-storage)
- [Checklist](#checklist-3) - [Checklist](#checklist-3)
- [Considerations](#considerations-3) - [Considerations](#considerations-3)
- [Back up your GnuPG directory](#back-up-your-gnupg-directory) - [Back up your GnuPG directory](#back-up-your-gnupg-directory)
- [Prepare detachable encrypted storage](#prepare-detachable-encrypted-storage) - [Prepare detachable encrypted storage](#prepare-detachable-encrypted-storage)
- [Back up your GnuPG directory](#back-up-your-gnupg-directory-1) - [Back up your GnuPG directory](#back-up-your-gnupg-directory-1)
- [Remove the master key](#remove-the-master-key) - [Remove the certification key](#remove-the-certification-key)
- [Removing your master key](#removing-your-master-key) - [Removing your certification key](#removing-your-certification-key)
- [Remove the revocation certificate](#remove-the-revocation-certificate) - [Remove the revocation certificate](#remove-the-revocation-certificate)
- [Move the subkeys to a hardware device](#move-the-subkeys-to-a-hardware-device) - [Move the subkeys to a hardware device](#move-the-subkeys-to-a-hardware-device)
- [Checklist](#checklist-4) - [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 keys were moved](#verifying-that-the-keys-were-moved)
- [Verifying that the smartcard is functioning](#verifying-that-the-smartcard-is-functioning) - [Verifying that the smartcard is functioning](#verifying-that-the-smartcard-is-functioning)
- [Other common GnuPG operations](#other-common-gnupg-operations) - [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) - [Updating your regular GnuPG working directory](#updating-your-regular-gnupg-working-directory)
- [Extending key expiration date](#extending-key-expiration-date) - [Extending key expiration date](#extending-key-expiration-date)
- [Revoking identities](#revoking-identities) - [Revoking identities](#revoking-identities)
@ -78,7 +74,6 @@ Updated: 2018-01-22
- [Hashing function](#hashing-function) - [Hashing function](#hashing-function)
- [Annotated tags and tag signatures](#annotated-tags-and-tag-signatures) - [Annotated tags and tag signatures](#annotated-tags-and-tag-signatures)
- [Signed commits](#signed-commits) - [Signed commits](#signed-commits)
- [Signed pushes](#signed-pushes)
- [Configure git to use your PGP key](#configure-git-to-use-your-pgp-key) - [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 work with signed tags](#how-to-work-with-signed-tags)
- [How to verify signed tags](#how-to-verify-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 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. research to find the correct places to download and install GnuPG.
##### GnuPG 1 vs. 2 ## Generating and protecting your certification key
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
### Checklist ### Checklist
- [ ] Generate a 4096-bit RSA master key _(ESSENTIAL)_ - [ ] Generate a 4096-bit RSA certification key _(ESSENTIAL)_
- [ ] Back up the master key using paperkey _(ESSENTIAL)_ - [ ] Back up the certification key using paperkey _(ESSENTIAL)_
- [ ] Add all relevant identities _(ESSENTIAL)_ - [ ] Add all relevant identities _(ESSENTIAL)_
### Considerations ### 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 In this and next section we'll talk about the certification key and subkeys.
is important to understand the following: 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 2. At creation time, we assign functional limitations to each key by
giving it specific capabilities. 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 - **[S]** key can be used for signing
- **[E]** key can be used for encryption - **[E]** key can be used for encryption
- **[A]** key can be used for authentication - **[A]** key can be used for authentication
- **[C]** key can be used for certifying other keys - **[C]** key can be used for certifying other keys
4. A single key may have multiple capabilities. 4. A single key may have multiple capabilities.
The key carrying the **[C]** (certify) capability is considered the "master" The key carrying the **[C]** (certify) capability is used to indicate
key because it is the only key that can be used to indicate relationship with relationship with other PGP keys. Only the **[C]** key can be used to:
other keys. Only the **[C]** key can be used to:
- add or revoke other keys (subkeys) with S/E/A capabilities - add or revoke other keys (subkeys) with S/E/A capabilities
- add, change or revoke identities (uids) associated with the key - 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 create that key, you should take extra care to protect it and prevent it from
falling into malicious hands. 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 Before you create your certify key you need to pick your primary identity and
your master passphrase. your passphrase.
##### Primary identity ##### Primary identity
@ -428,23 +396,24 @@ to type and easy to remember.
##### Algorithm and key strength ##### Algorithm and key strength
Even though GnuPG has had support for Elliptic Curve crypto for a while now, GnuPG supports many algorithms, but we will only consider the below two:
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.
You may also wonder why the master key is 4096-bit, if later in the guide we - RSA for the certification key
state that 2048-bit keys should be good enough for the lifetime of RSA public - ECC (Elliptic Curve) for all other subkeys
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.
#### 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 All of the day-to-day work will be done using subkeys, so picking ECC makes
right values instead of "Alice Engineer:" 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 <alice@example.org>' rsa4096 cert $ gpg --quick-generate-key 'Alice Engineer <alice@example.org>' rsa4096 cert
@ -454,7 +423,7 @@ the command completes.
Review the output of the command, it will be something like this: 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 111122223333444455556666AAAABBBBCCCCDDDD
uid Alice Engineer <alice@example.org> uid Alice Engineer <alice@example.org>
@ -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 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. 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 For disaster recovery purposes -- and especially if you intend to use the Web
of Trust and collect key signatures from other project developers -- you 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 #### Add relevant identities
If you have multiple relevant email addresses (personal, work, open-source 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 project, etc), you should add them to your key. You don't need to do this for
this for any addresses that you don't expect to use with PGP (e.g. probably any addresses that you don't expect to use with PGP (e.g. probably not your
not your school alumni address). school alumni address).
The command is (put the full key fingerprint instead of `[fpr]`): 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 ### Checklist
- [ ] Generate a 2048-bit Encryption subkey _(ESSENTIAL)_ - [ ] Generate the Encryption subkey _(ESSENTIAL)_
- [ ] Generate a 2048-bit Signing subkey _(ESSENTIAL)_ - [ ] Generate the Signing subkey _(ESSENTIAL)_
- [ ] Generate a 2048-bit Authentication subkey _(NICE)_ - [ ] Generate the Authentication subkey _(NICE)_
- [ ] Upload your public keys to a PGP keyserver _(ESSENTIAL)_ - [ ] Upload your public keys to a PGP keyserver _(NICE)_
- [ ] Set up a refresh cronjob _(ESSENTIAL)_ - [ ] Set up a refresh cronjob _(NICE)_
### Considerations ### Considerations
Now that we've created the master key, let's create the keys you'll actually Now that we've created the certification key, let's create the keys you'll
be using for day-to-day work. We create 2048-bit keys because a lot of actually be using for day-to-day work. Before we do this, we need to pick the
specialized hardware (we'll discuss this further) does not handle larger keys, ECC algorithm flavor.
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 #### ED25519 or NIST?
fundamental breakthroughs in computing or mathematics and therefore longer
4096-bit keys will not make much difference. 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 #### Create the subkeys
To create the subkeys, run: To create the subkeys, run:
$ gpg --quick-add-key [fpr] rsa2048 encr $ gpg --quick-add-key [fpr] cv25519 encr
$ gpg --quick-add-key [fpr] rsa2048 sign $ gpg --quick-add-key [fpr] ed25519 sign
You can also create the Authentication key, which will allow you to use your You can also create the Authentication key, which will allow you to use your
PGP key for ssh purposes: 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]`: 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 111122223333444455556666AAAABBBBCCCCDDDD
uid [ultimate] Alice Engineer <alice@example.org> uid [ultimate] Alice Engineer <alice@example.org>
uid [ultimate] Alice Engineer <allie@example.net> uid [ultimate] Alice Engineer <allie@example.net>
sub rsa2048 2017-12-06 [E] sub cv25519 2021-05-01 [E]
sub rsa2048 2017-12-06 [S] 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 If you use GitHub in your development, you should upload your key following
find it by uploading it to one of the public keyservers. (Do not do this step the instructions they have provided:
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:
- [Adding a PGP key to your GitHub account](https://help.github.com/articles/adding-a-new-gpg-key-to-your-github-account/) - [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] $ 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 To make it easier for others to find your public key, you can upload it to the
changes on other people's public keys. You can set up a cronjob to do that: 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 ## Moving your cerification key to offline storage
**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
### Checklist ### Checklist
- [ ] Prepare encrypted detachable storage _(ESSENTIAL)_ - [ ] Prepare encrypted detachable storage _(ESSENTIAL)_
- [ ] Back up your GnuPG directory _(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)_ - [ ] Remove the revocation certificate from your home directory _(NICE)_
### Considerations ### Considerations
Why would you want to remove your master **[C]** key from your home directory? Why would you want to remove your certification (**[C]**) key from your home
This is generally done to prevent your master key from being stolen or directory? This is generally done to prevent it from being stolen or
accidentally leaked. Private keys are tasty targets for malicious actors -- we accidentally leaked. Private keys are tasty targets for malicious actors --
know this from several successful malware attacks that scanned users' home we know this from several successful malware attacks that scanned users' home
directories and uploaded any private key content found there. directories and uploaded any private key content found there.
It would be very damaging for any developer to have their PGP keys stolen -- 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 Removing private keys from your home directory helps protect you from such
events. events.
@ -662,7 +605,8 @@ for backup purposes. You will first need to encrypt them:
- [Apple instructions](https://support.apple.com/kb/PH25745) - [Apple instructions](https://support.apple.com/kb/PH25745)
- [Linux instructions](https://help.ubuntu.com/community/EncryptedFilesystemsOnRemovableStorage) - [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 #### 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, 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. 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. 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: 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 Protecting your key with a good passphrase greatly helps reduce the risk of
any of the above, but passphrases can be discovered via keyloggers, any of the above, but passphrases can be discovered via keyloggers,
shoulder-surfing, or any number of other means. For this reason, the 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 recommended setup is to remove your certification key from your home directory
store it on offline storage. 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 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 directory in its entirety. What we are about to do will render your key
useless if you do not have a usable backup! 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] $ gpg --with-keygrip --list-key [fpr]
The output will be something like this: 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 111122223333444455556666AAAABBBBCCCCDDDD
Keygrip = AAAA999988887777666655554444333322221111 Keygrip = AAAA999988887777666655554444333322221111
uid [ultimate] Alice Engineer <alice@example.org> uid [ultimate] Alice Engineer <alice@example.org>
uid [ultimate] Alice Engineer <allie@example.net> uid [ultimate] Alice Engineer <allie@example.net>
sub rsa2048 2017-12-06 [E] sub cv25519 2021-05-01 [E]
Keygrip = BBBB999988887777666655554444333322221111 Keygrip = BBBB999988887777666655554444333322221111
sub rsa2048 2017-12-06 [S] sub ed25519 2021-05-01 [S]
Keygrip = CCCC999988887777666655554444333322221111 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 key fingerprint). This will correspond directly to a file in your home
`.gnupg` directory: `.gnupg` directory:
@ -738,34 +682,34 @@ key fingerprint). This will correspond directly to a file in your home
CCCC999988887777666655554444333322221111.key CCCC999988887777666655554444333322221111.key
All you have to do is simply remove the `.key` file that corresponds to the 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 $ cd ~/.gnupg/private-keys-v1.d
$ rm AAAA999988887777666655554444333322221111.key $ rm AAAA999988887777666655554444333322221111.key
Now, if you issue the `--list-secret-keys` command, it will show that the 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 $ 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 111122223333444455556666AAAABBBBCCCCDDDD
uid [ultimate] Alice Engineer <alice@example.org> uid [ultimate] Alice Engineer <alice@example.org>
uid [ultimate] Alice Engineer <allie@example.net> uid [ultimate] Alice Engineer <allie@example.net>
ssb rsa2048 2017-12-06 [E] ssb cv25519 2021-05-01 [E]
ssb rsa2048 2017-12-06 [S] ssb ed25519 2021-05-01 [S]
#### Remove the revocation certificate #### Remove the revocation certificate
Another file you should remove (but keep in backups) is the revocation Another file you should remove (but keep in backups) is the revocation
certificate that was automatically created with your master key. A revocation certificate that was automatically created with your certification key. A
certificate allows someone to permanently mark your key as revoked, meaning it revocation certificate allows someone to permanently mark your key as revoked,
can no longer be used or trusted for any purpose. You would normally use it to meaning it can no longer be used or trusted for any purpose. You would
revoke a key that, for some reason, you can no longer control -- for example, normally use it to revoke a key that, for some reason, you can no longer
if you had lost the key passphrase. control -- for example, if you had lost the key passphrase.
Just as with the master key, if a revocation certificate leaks into malicious Just as with the certification key, if a revocation certificate leaks into
hands, it can be used to destroy your developer digital identity, so it's malicious hands, it can be used to destroy your developer digital identity, so
better to remove it from your home directory. it's better to remove it from your home directory.
cd ~/.gnupg/openpgp-revocs.d cd ~/.gnupg/openpgp-revocs.d
rm [fpr].rev rm [fpr].rev
@ -781,7 +725,7 @@ better to remove it from your home directory.
### Considerations ### 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 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 hands on those will be able to decrypt your communication or fake your
signatures (if they know the passphrase). Furthermore, each time a GnuPG 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): - [Nitrokey Start](https://shop.nitrokey.com/shop/product/nitrokey-start-6):
Open hardware and Free Software: one of the cheapest options for GnuPG use, 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): - [Nitrokey Pro](https://shop.nitrokey.com/shop/product/nitrokey-pro-3):
Similar to the Nitrokey Start, but is tamper-resistant and offers more 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) security features (but not U2F, see the Fido U2F section of the guide); only
- [Yubikey 4](https://www.yubico.com/product/yubikey-4-series/): Proprietary supports NIST ECC cryptography.
hardware and software, but cheaper than Nitrokey Pro and comes available - [Yubikey](https://www.yubico.com/): Proprietary hardware and software, but
in the USB-C form that is more useful with newer laptops; also offers cheaper than Nitrokey Pro and comes available in the USB-C form that is more
additional security features such as U2F 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 If you want to use ED25519 subkeys, then your only choice is a Nitrokey Start,
functionality and U2F, which, at the time of writing, means a Yubikey 4. though once Nitrokey 3 Pro is available, it should also be considered.
#### Configuring your smartcard device #### Configuring your smartcard device
@ -894,12 +839,12 @@ the full 40-character fingerprint of your key.
Secret subkeys are available. Secret subkeys are available.
pub rsa4096/AAAABBBBCCCCDDDD 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 trust: ultimate validity: ultimate
ssb rsa2048/1111222233334444 ssb cv25519/1111222233334444
created: 2017-12-07 expires: never usage: E created: 2021-05-01 expires: never usage: E
ssb rsa2048/5555666677778888 ssb ed25519/5555666677778888
created: 2017-12-07 expires: never usage: S created: 2021-05-01 expires: never usage: S
[ultimate] (1). Alice Engineer <alice@example.org> [ultimate] (1). Alice Engineer <alice@example.org>
[ultimate] (2) Alice Engineer <allie@example.net> [ultimate] (2) Alice Engineer <allie@example.net>
@ -917,12 +862,12 @@ typing `key 1` (it's the first one in the listing, our **[E]** subkey):
The output should be subtly different: The output should be subtly different:
pub rsa4096/AAAABBBBCCCCDDDD 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 trust: ultimate validity: ultimate
ssb* rsa2048/1111222233334444 ssb* cv25519/1111222233334444
created: 2017-12-07 expires: never usage: E created: 2021-05-01 expires: never usage: E
ssb rsa2048/5555666677778888 ssb ed25519/5555666677778888
created: 2017-12-07 expires: never usage: S created: 2021-05-01 expires: never usage: S
[ultimate] (1). Alice Engineer <alice@example.org> [ultimate] (1). Alice Engineer <alice@example.org>
[ultimate] (2) Alice Engineer <allie@example.net> [ultimate] (2) Alice Engineer <allie@example.net>
@ -974,12 +919,12 @@ If you perform `--list-secret-keys` now, you will see a subtle difference in
the output: the output:
$ gpg --list-secret-keys $ 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 111122223333444455556666AAAABBBBCCCCDDDD
uid [ultimate] Alice Engineer <alice@example.org> uid [ultimate] Alice Engineer <alice@example.org>
uid [ultimate] Alice Engineer <allie@example.net> uid [ultimate] Alice Engineer <allie@example.net>
ssb> rsa2048 2017-12-06 [E] ssb> cv25519 2021-05-01 [E]
ssb> rsa2048 2017-12-06 [S] ssb> ed25519 2021-05-01 [S]
The `>` in the `ssb>` output indicates that the subkey is only available on 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 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. 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 You will need your certification key for any of the operations below, so you
first need to mount your backup offline storage and tell GnuPG to use it. 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 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 the `mount` command. Then, locate the directory with the backup of your GnuPG
directory and tell GnuPG to use that as its home: 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 #### Extending key expiration date
The master key we created has the default expiration date of 2 years from the The certification key we created has the default expiration date of 2 years
date of creation. This is done both for security reasons and to make obsolete from the date of creation. This is done both for security reasons and to make
keys eventually disappear from keyservers. obsolete keys eventually disappear from keyservers.
To extend the expiration on your key by a year from current date, just run: To extend the expiration on your key by a year from current date, just run:
$ gpg --quick-set-expire [fpr] 1y $ gpg --quick-set-expire [fpr] 1y
You can also use a specific date if that is easier to remember (e.g. your 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: 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 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 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 you're pretty sure you had [nothing to do with it](https://github.com/jayphelps/git-blame-someone-else)?
it](https://github.com/jayphelps/git-blame-someone-else)?
To address both of these issues, Git introduced PGP integration. Signed tags To address both of these issues, Git introduced PGP integration. Signed tags
prove the repository integrity by assuring that its contents are exactly the prove the repository integrity by assuring that its contents are exactly the
@ -1091,7 +1035,7 @@ having access to your PGP keys.
### Checklist ### Checklist
- [ ] Understand signed tags, commits, and pushes _(ESSENTIAL)_ - [ ] Understand signed tags, commits _(ESSENTIAL)_
- [ ] Configure git to use your key _(ESSENTIAL)_ - [ ] Configure git to use your key _(ESSENTIAL)_
- [ ] Learn how tag signing and verification works _(ESSENTIAL)_ - [ ] Learn how tag signing and verification works _(ESSENTIAL)_
- [ ] Configure git to always sign annotated tags _(NICE)_ - [ ] Configure git to always sign annotated tags _(NICE)_
@ -1102,8 +1046,7 @@ having access to your PGP keys.
### Considerations ### Considerations
Git implements multiple levels of integration with PGP, first starting with Git implements multiple levels of integration with PGP, first starting with
signed tags, then introducing signed commits, and finally adding support for signed tags, and then introducing signed commits.
signed pushes.
#### Understanding Git Hashes #### 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 PGP signatures provide exact same security assurances about the repository and
its entire history. 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 #### Configure git to use your PGP key
If you only have one secret key in your keyring, then you don't really need to 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] $ 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 #### How to work with signed tags
To create a signed tag, simply pass the `-s` switch to the tag command: 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 ssh sessions. You just need to tell your environment to use the correct socket
file for talking to the agent. file for talking to the agent.
First, add the following to your `~/.gnupg/gpg-agent.conf`: All you need is add this to your `.bashrc`:
enable-ssh-support
Then, add this to your `.bashrc`:
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket) 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 Then start a new login session for the changes to take effect:
session for the changes to take effect:
$ killall gpg-agent
$ bash $ bash
$ ssh-add -L $ 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. 1. Created your developer identity and protected it using PGP cryptography.
2. Configured your environment so your identity is not easily stolen by moving 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 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. able to verify the integrity of the repository and its entire history.
4. Secured your online accounts using 2-factor authentication. 4. Secured your online accounts using 2-factor authentication.