diff options
| -rw-r--r-- | docs/protecting-code-integrity.md | 1437 |
1 files changed, 1437 insertions, 0 deletions
diff --git a/docs/protecting-code-integrity.md b/docs/protecting-code-integrity.md new file mode 100644 index 0000000..147694b --- /dev/null +++ b/docs/protecting-code-integrity.md @@ -0,0 +1,1437 @@ +# Protecting code integrity with PGP + +Updated: 2021-05-13 + +*Status: CURRENT* + +### Table of contents + +- [Protecting code integrity with PGP](#protecting-code-integrity-with-pgp) + - [Table of contents](#table-of-contents) + - [Target audience](#target-audience) + - [Structure](#structure) + - [Checklist priority levels](#checklist-priority-levels) + - [Basic PGP concepts and tools](#basic-pgp-concepts-and-tools) + - [Checklist](#checklist) + - [Considerations](#considerations) + - [Extremely Basic Overview of PGP operations](#extremely-basic-overview-of-pgp-operations) + - [Encryption](#encryption) + - [Signatures](#signatures) + - [Combined usage](#combined-usage) + - [Understanding Key Identities](#understanding-key-identities) + - [Understanding Key Validity](#understanding-key-validity) + - [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) + - [Generating and protecting your certification key](#generating-and-protecting-your-certification-key) + - [Checklist](#checklist-1) + - [Considerations](#considerations-1) + - [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 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 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 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) + - [Considerations](#considerations-4) + - [The benefits of smartcards](#the-benefits-of-smartcards) + - [Available smartcard devices](#available-smartcard-devices) + - [Configuring your smartcard device](#configuring-your-smartcard-device) + - [PINs don't have to be numbers](#pins-dont-have-to-be-numbers) + - [Quick setup](#quick-setup) + - [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 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) + - [Using PGP with Git](#using-pgp-with-git) + - [Checklist](#checklist-5) + - [Considerations](#considerations-5) + - [Understanding Git Hashes](#understanding-git-hashes) + - [Tree hashes](#tree-hashes) + - [Commit hashes](#commit-hashes) + - [Hashing function](#hashing-function) + - [Annotated tags and tag signatures](#annotated-tags-and-tag-signatures) + - [Signed commits](#signed-commits) + - [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) + - [How to verify signed commits](#how-to-verify-signed-commits) + - [Verifying commits during git merge](#verifying-commits-during-git-merge) + - [If your project uses mailing lists for patch management](#if-your-project-uses-mailing-lists-for-patch-management) + - [Configure git to always sign commits](#configure-git-to-always-sign-commits) + - [Configure gpg-agent options](#configure-gpg-agent-options) + - [Bonus: Using gpg-agent with ssh](#bonus-using-gpg-agent-with-ssh) + - [Protecting online accounts](#protecting-online-accounts) + - [Checklist](#checklist-6) + - [Considerations](#considerations-6) + - [Two-factor authentication with Fido U2F](#two-factor-authentication-with-fido-u2f) + - [Get a token capable of Fido U2F](#get-a-token-capable-of-fido-u2f) + - [Enable 2-factor authentication on your online accounts](#enable-2-factor-authentication-on-your-online-accounts) + - [Configure TOTP failover, if possible](#configure-totp-failover-if-possible) + - [Further reading](#further-reading) + +### Target audience + +This document is aimed at developers working on free software projects. It +covers the following topics: + +1. PGP basics and best practices +2. How to use PGP with Git +3. How to protect your developer accounts + +We use the term "Free" as in "Freedom," but this guide can also be used for +any other kind of software that relies on contributions from a distributed +team of developers. If you write code that goes into public source +repositories, you can benefit from getting acquainted with and following this +guide. + +### Structure + +Each section is split into two areas: + +- The checklist that can be adapted to your project's needs +- 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. + If not implemented, they will introduce high risks to the code that gets + committed to the open-source project. +- _(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 project's commitment to security, you should adjust them as you +see fit. + +## Basic PGP concepts and tools + +### Checklist + +- [ ] Understand the role of PGP in Free Software Development _(ESSENTIAL)_ +- [ ] Understand the basics of Public Key Cryptography _(ESSENTIAL)_ +- [ ] Understand PGP Encryption vs. Signatures _(ESSENTIAL)_ +- [ ] Understand PGP key identities _(ESSENTIAL)_ +- [ ] Understand PGP key validity _(ESSENTIAL)_ +- [ ] Install GnuPG utilities (version 2.x) _(ESSENTIAL)_ + +### Considerations + +The Free Software community has long relied on PGP for assuring the +authenticity and integrity of software products it produced. You may not be +aware of it, but whether you are a Linux, Mac or Windows user, you have +previously relied on PGP to ensure the integrity of your computing +environment: + +- Linux distributions rely on PGP to ensure that binary or source packages have + not been altered between when they have been produced and when they are + installed by the end-user. +- Free Software projects usually provide detached PGP signatures to accompany + released software archives, so that downstream projects can verify the + integrity of downloaded releases before integrating them into their own + distributed downloads. +- Free Software projects routinely rely on PGP signatures within the code + itself in order to track provenance and verify integrity of code committed + by project developers. + +This is very similar to developer certificates/code signing mechanisms used by +programmers working on proprietary platforms. In fact, the core concepts +behind these two technologies are very much the same -- they differ mostly in +the technical aspects of the implementation and the way they delegate trust. +PGP does not rely on centralized Certification Authorities, but instead lets +each user assign their own trust to each certificate. + +Our goal is to get your project on board using PGP for code provenance and +integrity tracking, following best practices and observing basic security +precautions. + +### Extremely Basic Overview of PGP operations + +You do not need to know the exact details of how PGP works -- understanding +the core concepts is enough to be able to use it successfully for our +purposes. PGP relies on Public Key Cryptography to convert plain text into +encrypted text. This process requires two distinct keys: + +- A public key that is _known to everyone_ +- A private key that is _only known to the owner_ + +#### Encryption + +For encryption, PGP uses the public key of the owner to create a message that +is only decryptable using the owner's private key: + +1. the sender generates a random encryption key ("session key") +2. the sender encrypts the contents using that session key (using a symmetric + cipher) +3. the sender encrypts the session key using the recipient's _public_ PGP key +4. the sender sends both the encrypted contents and the encrypted session key + to the recipient + +To decrypt: + +1. the recipient decrypts the session key using their _private_ PGP key +2. the recipient uses the session key to decrypt the contents of the message + +#### Signatures + +For creating signatures, the private/public PGP keys are used the opposite way: + +1. the signer generates the checksum hash of the contents +2. the signer uses their own _private_ PGP key to encrypt that checksum +3. the signer provides the encrypted checksum alongside the contents + +To verify the signature: + +1. the verifier generates their own checksum hash of the contents +2. the verifier uses the signer's _public_ PGP key to decrypt the provided + checksum +3. if the checksums match, the integrity of the contents is verified + +#### Combined usage + +Frequently, encrypted messages are also signed with the sender's own PGP key. +This should be the default whenever using encrypted messaging, as encryption +without authentication is not very meaningful (unless you are a whistleblower +or a secret agent and need plausible deniability). + +### Understanding Key Identities + +Each PGP key must have one or multiple Identities associated with it. Usually, +an "Identity" is the person's full name and email address in the following +format: + + Alice Engineer <alice.engineer@example.com> + +Sometimes it will also contain a comment in brackets, to tell the end-user +more about that particular key: + + Bob Designer (obsolete 1024-bit key) <bob.designer@example.com> + +Since people can be associated with multiple professional and personal +entities, they can have multiple identities on the same key: + + Alice Engineer <alice.engineer@example.com> + Alice Engineer <aengineer@personalmail.example.org> + Alice Engineer <webmaster@girlswhocode.example.net> + +When multiple identities are used, one of them would be marked as the "primary +identity" to make searching easier. + +### Understanding Key Validity + +To be able to use someone else's public key for encryption or verification, +you need to be sure that it actually belongs to the right person (Alice) and +not to an impostor (Eve). In PGP, this certainty is called "key validity:" + +- **Validity: full** -- means we are pretty sure this key belongs to Alice +- **Validity: marginal** -- means we are *somewhat* sure this key belongs to + Alice +- **Validity: unknown** -- means there is no assurance at all that this key + belongs to Alice + +#### 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, and even +fewer bother to keep it going. It remains an important aspect of the OpenPGP +specification, but 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 +trusted. 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. + +In this guide, we will be using the TOFU trust model. + +### Installing OpenPGP software + +First, it is important to understand the distinction between PGP, OpenPGP, +GnuPG and gpg: + +- **PGP** ("Pretty Good Privacy") is the name of the original commercial + software +- **OpenPGP** is the IETF standard compatible with the original PGP tool +- **GnuPG** ("Gnu Privacy Guard") is free software that implements the OpenPGP + standard +- The command-line tool for GnuPG is called "**gpg**" + +Today, the term "PGP" is almost universally used to mean "the OpenPGP +standard," not the original commercial software, and therefore "PGP" and +"OpenPGP" are interchangeable. The terms "GnuPG" and "gpg" should only be used +when referring to the tools, not to the output they produce or OpenPGP +features they implement. For example: + +- PGP (not GnuPG or GPG) key +- PGP (not GnuPG or GPG) signature +- PGP (not GnuPG or GPG) keyserver + +Understanding this should protect you from an inevitable pedantic "actually" +from other PGP users you come across. + +#### Installing GnuPG + +If you are using Linux, you should already have GnuPG installed. On a Mac, +you should install [GPG-Suite](https://gpgtools.org) or you can use `brew +install gnupg2`. On a Windows PC, you should install +[GPG4Win](https://www.gpg4win.org), and you will probably need to adjust some +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. + +## Generating and protecting your certification key + +### Checklist + +- [ ] Generate a 4096-bit RSA certification key _(ESSENTIAL)_ +- [ ] Back up the certification key using paperkey _(ESSENTIAL)_ +- [ ] Add all relevant identities _(ESSENTIAL)_ + +### Considerations + +#### Understanding the certification key + +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." + +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: + - **[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 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 +- add or change the expiration date on itself or any subkey +- sign other people's keys for the web of trust purposes + +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 certify key + +Before you create your certify key you need to pick your primary identity and +your passphrase. + +##### Primary identity + +Identities are strings using the same format as the "From" field in emails: + + Alice Engineer <alice.engineer@example.org> + +You can create new identities, revoke old ones, and change which identity is +your "primary" one at any time. Since the primary identity is shown in all +GnuPG operations, you should pick a name and address that are both +professional and the most likely ones to be used for PGP-protected +communication, such as your work address or the address you use for signing +off on project commits. + +##### Passphrase + +The passphrase is used exclusively for encrypting the private key with a +symmetric algorithm while it is stored on disk. If the contents of your +`.gnupg` directory ever get leaked, a good passphrase is the last line of +defense between the thief and them being able to impersonate you online, which +is why it is important to set up a good passphrase. + +A good guideline for a strong passphrase is 3-4 words from a rich or mixed +dictionary that are not quotes from popular sources (songs, books, slogans). +You'll be using this passphrase fairly frequently, so it should be both easy +to type and easy to remember. + +##### Algorithm and key strength + +GnuPG supports many algorithms, but we will only consider the below two: + +- RSA for the certification key +- ECC (Elliptic Curve) for all other subkeys + +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. + +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 <alice@example.org>' rsa4096 cert + +A dialog will pop up asking to enter the passphrase. Then, you may need to +move your mouse around or type on some keys to generate enough entropy until +the command completes. + +Review the output of the command, it will be something like this: + + pub rsa4096 2021-05-01 [C] [expires: 2023-05-01] + 111122223333444455556666AAAABBBBCCCCDDDD + uid Alice Engineer <alice@example.org> + +Note the long string on the 2nd line -- that is the full fingerprint of your +newly generated key. Key IDs can be represented in three different forms: + +- **fingerprint**, a full 40-character key identifier +- **long**, last 16-characters of the fingerprint (`AAAABBBBCCCCDDDD`) +- **short**, last 8 characters of the fingerprint (`CCCCDDDD`) + +You should avoid using 8-character "short key IDs" as they are not +sufficiently unique. + +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 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 +should create a hardcopy backup of your private key. This is supposed to be +the "last resort" measure in case all other backup mechanisms have failed. + +The best way to create a printable hardcopy of your private key is using the +`paperkey` software written for this very purpose. Paperkey is available on +all Linux distros, as well as installable via `brew install paperkey` on Macs. + +Run the following command, replacing `[fpr]` with the full fingerprint of your +key: + + $ gpg --export-secret-key [fpr] | paperkey -o /tmp/key-backup.txt + +The output will be in a format that is easy to OCR or input by hand, should +you ever need to recover it. Print out that file, then take a pen and write +the key passphrase on the margin of the paper. **This is a required step** +because the key printout is still encrypted with the passphrase, and if you +ever change the passphrase on your key, you will not remember what it used to +be when you had first created it -- *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**: Long gone are days when printers were dumb devices +connected to your computer's parallel port. These days they have full +operating systems, hard drives, and cloud integration. Since the key content +we send to the printer will be encrypted with the passphrase, this is a fairly +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 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]`): + + $ gpg --quick-add-uid [fpr] 'Alice Engineer <allie@example.net>' + +You can review the UIDs you've already added using: + + $ gpg --list-key [fpr] | grep ^uid + +##### Pick the primary UID + +GnuPG will make the latest UID you add as your primary UID, so if that is +different from what you want, you should fix it back: + + $ gpg --quick-set-primary-uid [fpr] 'Alice Engineer <alice@example.org>' + +## Generating PGP subkeys + +### Checklist + +- [ ] 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 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] 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] ed25519 auth + +You can review your key information using `gpg --list-key [fpr]`: + + pub rsa4096 2021-05-01 [C] [expires: 2023-05-01] + 111122223333444455556666AAAABBBBCCCCDDDD + uid [ultimate] Alice Engineer <alice@example.org> + uid [ultimate] Alice Engineer <allie@example.net> + sub cv25519 2021-05-01 [E] + sub ed25519 2021-05-01 [S] + +#### Upload your public key to GitHub + +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/) + +To generate the public key output suitable to paste in, just run: + + $ gpg --export --armor [fpr] + +#### Upload your public key to keys.openpgp.org + +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: + +- [Upload to keys.openpgp.org](https://keys.openpgp.org/about/usage#gnupg-upload) + + +## Moving your certification key to offline storage + +### Checklist + +- [ ] Prepare encrypted detachable storage _(ESSENTIAL)_ +- [ ] Back up your GnuPG directory _(ESSENTIAL)_ +- [ ] 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 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 basically equal to identity theft. +Removing private keys from your home directory helps protect you from such +events. + +#### Back up your 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`). + +#### Prepare detachable encrypted storage + +Start by getting a small USB "thumb" drive (preferably two!) that you will use +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 private +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`, under Mac it's `/Volumes`). + +Once you know the full mount path, copy your entire GnuPG directory there: + + $ cp -rp ~/.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 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: + +- 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 certification key from your home directory +and store it on offline storage. + +##### 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 certification key: + + $ gpg --with-keygrip --list-key [fpr] + +The output will be something like this: + + pub rsa4096 2021-05-01 [C] [expires: 2023-05-01] + 111122223333444455556666AAAABBBBCCCCDDDD + Keygrip = AAAA999988887777666655554444333322221111 + uid [ultimate] Alice Engineer <alice@example.org> + uid [ultimate] Alice Engineer <allie@example.net> + sub cv25519 2021-05-01 [E] + Keygrip = BBBB999988887777666655554444333322221111 + sub ed25519 2021-05-01 [S] + Keygrip = CCCC999988887777666655554444333322221111 + +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: + + $ cd ~/.gnupg/private-keys-v1.d + $ ls + AAAA999988887777666655554444333322221111.key + BBBB999988887777666655554444333322221111.key + CCCC999988887777666655554444333322221111.key + +All you have to do is simply remove the `.key` file that corresponds to the +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 +**[C]** key is not present (indicated by the `#` character): + + $ gpg --list-secret-keys + sec# rsa4096 2021-05-01 [C] [expires: 2023-05-01] + 111122223333444455556666AAAABBBBCCCCDDDD + uid [ultimate] Alice Engineer <alice@example.org> + uid [ultimate] Alice Engineer <allie@example.net> + 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 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 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 + +## Move the subkeys to a hardware 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 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 +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 decrypted, the operating system is still able to access the private key +contents. Using external encrypted USB media is not a substitute to having a +smartcard-capable device. + +Some other benefits of smartcards: + +- they are relatively cheap and easy to obtain +- they are small and easy to carry with you +- they can be used with multiple devices +- many of them are tamper-resistant (depends on manufacturer) + +#### Available smartcard devices + +Smartcards started out embedded into actual wallet-sized cards, which earned +them their name. You can still buy and use GnuPG-capable smartcards, and they +remain one of the cheapest available devices you can get. However, actual +smartcards have one important downside: they require a smartcard reader, and +very few laptops come with one. + +For this reason, manufacturers have started providing small USB devices, the +size of a USB thumb drive or smaller, that either have the microsim-sized +smartcard pre-inserted, or that simply implement the smartcard protocol +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. +- [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); 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. + +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 + +Your smartcard device should Just Work (TM) the moment you plug it into any +modern Linux or Mac workstation. You can verify it by running: + + $ gpg --card-status + +If you didn't get an error, but a full listing of the card 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 support via +your operating system's usual support channels. + +##### 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. + +Your device will probably have default user and admin PINs set up when it +arrives. For Yubikeys, these are `123456` and `12345678` respectively. If +those don't work for you, please check any accompanying documentation +that came with your device. + +##### 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) and Admin PIN (3). Please make sure to record +and store these in a safe place -- especially the Admin PIN. 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. + +#### 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. Remember, that `[fpr]` stands for +the full 40-character fingerprint of your key. + + $ gpg --edit-key [fpr] + + Secret subkeys are available. + + pub rsa4096/AAAABBBBCCCCDDDD + created: 2021-05-01 expires: 2023-05-01 usage: C + trust: ultimate validity: ultimate + 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 <alice@example.org> + [ultimate] (2) Alice Engineer <allie@example.net> + + 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, our **[E]** subkey): + + gpg> key 1 + +The output should be subtly different: + + pub rsa4096/AAAABBBBCCCCDDDD + created: 2021-05-01 expires: 2023-05-01 usage: C + trust: ultimate validity: ultimate + 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 <alice@example.org> + [ultimate] (2) Alice Engineer <allie@example.net> + +Notice the `*` that is next to the `ssb` line corresponding to the key -- it +indicates that the 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. + +Finally, if you created an **[A]** key, you can move it to the card as well, +making sure first to unselect `key 2`. Once you're done, choose "q": + + 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# rsa4096 2021-05-01 [C] [expires: 2023-05-01] + 111122223333444455556666AAAABBBBCCCCDDDD + uid [ultimate] Alice Engineer <alice@example.org> + uid [ultimate] Alice Engineer <allie@example.net> + 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 +contents there, you will notice that the `.key` files there have been replaced +with stubs: + + $ cd ~/.gnupg/private-keys-v1.d + $ strings *.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. + +In all of the below commands, the `[fpr]` is your key fingerprint. + +#### Mounting your offline storage + +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: + + $ 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 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, 2030): + + $ gpg --quick-set-expire [fpr] 2030-07-01 + +Remember to send the updated key back to keyservers: + + $ gpg --send-key [fpr] + +#### Revoking identities + +If you need to revoke an identity (e.g. you changed employers and your old +email address is no longer valid), you can use a one-liner: + + $ gpg --quick-revoke-uid [fpr] 'Alice Engineer <aengineer@example.net>' + +You can also do the same with the menu mode using `gpg --edit-key [fpr]`. + +Once you are done, 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 the +repository you downloaded has not been tampered with by a malicious third +party? You may have cloned it from GitHub or some other official-looking +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)? + +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 + +- [ ] 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)_ +- [ ] Learn how commit signing and verification works _(ESSENTIAL)_ +- [ ] Configure git to always sign commits _(NICE)_ +- [ ] Configure gpg-agent options _(ESSENTIAL)_ + +### Considerations + +Git implements multiple levels of integration with PGP, first starting with +signed tags, and then introducing signed commits. + +#### Understanding Git Hashes + +Git is a complicated beast, but you need to know what a "hash" is in order to +have a good grasp on how PGP integrates with it. We'll narrow it down to two +kinds of hashes: tree hashes and commit hashes. + +##### Tree hashes + +Every time you commit a change to a repository, git records checksum hashes +of all objects in it -- contents (blobs), directories (trees), file names and +permissions, etc, for each subdirectory in the repository. It only does this +for trees and blobs that have changed with each commit, so as not to +re-checksum the entire tree unnecessarily if only a small part of it was +touched. + +Then it calculates and stores the checksum of the toplevel tree, which will +inevitably be different if any part of the repository has changed. + +##### Commit hashes + +Once the tree hash has been created, git will calculate the commit hash, which +will include the following information about the repository and the change being +made: + +- the checksum hash of the tree +- the checksum hash of the tree before the change (parent) +- information about the author (name, email, time of authorship) +- information about the committer (name, email, time of commit) +- the commit message + +##### Hashing function + +At the time of writing, git still uses the SHA1 hashing mechanism to calculate +checksums, though work is under way to transition to a stronger algorithm that +is more resistant to collisions. Note, that git already includes collision +avoidance routines, so it is believed that a successful collision attack +against git remains impractical. + +#### Annotated tags and tag signatures + +Git tags allow developers to mark specific commits in the history of each git +repository. Tags can be "lightweight" -- more or less just a pointer at a +specific commit, or they can be "annotated," which becomes its own object in +the git tree. An annotated tag object contains all of the following +information: + +- the checksum hash of the commit being tagged +- the tag name +- information about the tagger (name, email, time of tagging) +- the tag message + +A PGP-signed tag is simply an annotated tag with all these entries wrapped +around in a PGP signature. When a developer signs their git tag, they +effectively assure you of the following: + +- who they are (and why you should trust them) +- what the state of their repository was at the time of signing: + - the tag includes the hash of the commit + - the commit hash includes the hash of the toplevel tree + - which includes hashes of all files, contents, and subtrees + - it also includes all information about authorship + - including exact times when changes were made + +When you clone a git repository and verify a signed tag, that gives you +cryptographic assurance that _all contents in the repository, including all of +its history, are exactly the same as the contents of the repository on the +developer's computer at the time of signing_. + +#### Signed commits + +Signed commits are very similar to signed tags -- the contents of the commit +object are PGP-signed instead of the contents of the tag object. A commit +signature also gives you full verifiable information about the state of the +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. + +#### 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] + +#### 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 working with has not been +maliciously altered (e.g. in order to introduce backdoors). + +##### 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 "Trusted Team communication" document in +the same repository for guidance on this topic. + +##### 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 +incorporate them into your workflow. Many projects use signed commits as a +sort of "Committed-by:" line equivalent that records code provenance -- the +signatures are rarely verified by others except when tracking down project +history. In a sense, signed commits are used for "tamper evidence," and not to +"tamper-proof" the git workflow. + +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 + +Our recommendation is to always sign commits and to require them of all +project members, regardless of whether anyone is verifying them (that can +always come at a later time). + +##### How to verify signed commits + +To verify a single commit you can use `verify-commit`: + + $ git verify-commit [hash] + +You can also look at repository logs and request that all commit signatures +are verified and shown: + + $ git log --pretty=short --show-signature + +##### Verifying commits during git merge + +If all members of your project sign their commits, you can enforce signature +checking at merge time (and then sign the resulting merge commit itself using +the `-S` flag): + + $ git merge --verify-signatures -S merged-branch + +Note, that the merge will fail if there is even one commit that is not signed +or does not pass verification. As it is often the case, technology is the easy +part -- the human side of the equation is what makes adopting strict commit +signing for your project difficult. + +##### If your project uses mailing lists for patch management + +If your project uses a mailing list for submitting and processing patches, +then there is little use in signing commits, because all signature information +will be lost when sent through that medium. It is still useful to sign your +commits, just so others can refer to your publicly hosted git trees for +reference, but the upstream project receiving your patches will not be able to +verify them directly with git. + +You can still sign the emails containing the patches, though. + +#### 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`). + +#### 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. This way you only have to unlock your key once to +use it repeatedly (very handy if you need to sign a bunch of git operations in +an automated script without having to continuously retype your passphrase). + +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 + +##### Bonus: Using gpg-agent with ssh + +If you've created an **[A]** (Authentication) key and moved it to the +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. + +All you need is add this to your `.bashrc`: + + export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket) + +Then start a new login session for the changes to take effect: + + $ bash + $ ssh-add -L + +The last command should list the SSH representation of your PGP Auth key (the +comment should say `cardno:XXXXXXXX` at the end to indicate it's coming from +the smartcard). + +To enable key-based logins with ssh, just add the `ssh-add -L` output to +`~/.ssh/authorized_keys` on remote systems you log in to. Congratulations, +you've just made your ssh credentials extremely difficult to steal. + +As a bonus, you can get other people's PGP-based ssh keys from public +keyservers, should you need to grant them ssh access to anything: + + $ gpg --export-ssh-key [keyid] + +This can come in super handy if you need to allow developers access to git +repositories over ssh. + +## Protecting online accounts + +### Checklist + +- [ ] Get a U2F-capable device _(ESSENTIAL)_ +- [ ] Enable 2-factor authentication for your online accounts _(ESSENTIAL)_ + - [ ] GitHub/GitLab + - [ ] Google + - [ ] Social Media +- [ ] Use U2F as primary mechanism, with TOTP as fallback _(ESSENTIAL)_ + +### Considerations + +You may have noticed how a lot of your online developer identity is tied to +your email address. If someone can gain access to your mailbox, they would be +able to do a lot of damage to you personally, and to your reputation as a free +software developer. Protecting your email accounts is just as important as +protecting your PGP keys. + +#### Two-factor authentication with Fido U2F + +[Two-factor authentication](https://en.wikipedia.org/wiki/Multi-factor_authentication) +is a mechanism to improve account security by requiring a physical token in +addition to a username and password. The goal is to make sure that even if +someone steals your password (via keylogging, shoulder surfing, or other +means), they still wouldn't be able to gain access to your account without +having in their possession a specific physical device ("something you have" +factor). + +The most widely known mechanisms for 2-factor authentication are: + +- SMS-based verification +- Time-based One-Time Passwords (TOTP) via a smartphone app, such as + the "Google Authenticator" or similar solutions +- Hardware tokens supporting Fido U2F + +SMS-based verification is easiest to configure, but has the following +important downsides: it is useless in areas without signal (e.g. most building +basements), and can be defeated if the attacker is able to intercept or divert +SMS messages, for example by cloning your SIM card. + +TOTP-based multi-factor authentication offers more protection than SMS, but +has important scaling downsides (there are only so many tokens you can add to +your smartphone app before finding the correct one becomes unwieldy). Plus, +there's no avoiding the fact that your secret key ends up stored on the +smartphone itself -- which is a complex, globally connected device that may or +may not have been receiving timely security patches from the manufacturer. + +Most importantly, neither TOTP nor SMS methods protect you from phishing +attacks -- if the phisher is able to steal both your account password and the +2-factor token, they can replay them on the legitimate site and gain access to +your account. + +[Fido U2F](https://en.wikipedia.org/wiki/Universal_2nd_Factor) is a standard +developed specifically to provide a mechanism for 2-factor authentication +*and* to combat credential phishing. The U2F protocol will store each site's +unique key on the USB token and will prevent you from accidentally giving the +attacker both your password and your one-time token if you try to use it on +anything other than the legitimate website. + +Both Chrome and Firefox support U2F 2-factor authentication, and hopefully +other browsers will soon follow. + +#### Get a token capable of Fido U2F + +There are [many options available](http://www.dongleauth.info/dongles/) for +hardware tokens with Fido U2F support, but if you're already ordering a +smartcard-capable physical device, then your best option is a Yubikey 4, which +supports both. + +#### Enable 2-factor authentication on your online accounts + +You definitely want to enable this option on the email provider you are using +(especially if it is Google, which has excellent support for U2F). Other sites +where this functionality should be enabled are: + +- **GitHub**: it probably occurred to you when you uploaded your PGP public key + that if anyone else is able to gain access to your account, they can replace + your key with their own. If you publish code on GitHub, you should take care + of your account security by protecting it with U2F-backed authentication. +- **GitLab**: for the same reasons as above. +- **Google**: if you have a google account, you will be surprised how many + sites allow logging in with Google authentication instead of site-specific + credentials. +- **Facebook**: same as above, a lot of online sites offer the option to + authenticate using a Facebook account. You should 2-factor protect your + Facebook account even if you do not use it. +- Other sites, as you deem necessary. See + [dongleauth.info](http://www.dongleauth.info) for inspiration. + +#### Configure TOTP failover, if possible + +Many sites will allow you to configure multiple 2-factor mechanisms, and the +recommended setup is: + +- U2F token as the primary mechanism +- TOTP phone app as the secondary mechanism + +This way, even if you lose your U2F token, you should be able to re-gain +access to your account. Alternatively, you can enroll multiple U2F tokens +(e.g. you can get another cheap token that only does U2F and use it for +backup reasons). + +## Further reading + +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 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. + +You are already in a good place, but you should also read up on the following +topics: + +- How to secure your team communication (see the document in this repository). + Decisions regarding your project development and governance require just as + much careful protection as any committed code, if not so. Make sure that + your team communication is trusted and the integrity of all decisions is + verified. +- How to secure your workstation (see the document in this repository). Your + goal is to minimize risky behaviour that would cause your project code to be + contaminated, or your developer identity to be stolen. +- How to write secure code (see various documentation related to the + programming languages and libraries used by your project). Bad, insecure + code is still bad, insecure code even if there is a PGP signature on the + commit that introduced it. |
