Typo and wording fixes

Signed-off-by: Konstantin Ryabitsev <konstantin@linuxfoundation.org>
This commit is contained in:
Konstantin Ryabitsev 2017-12-14 15:08:16 -05:00
parent e44163234d
commit 790759787e
No known key found for this signature in database
GPG Key ID: 34BAB80AF9F247B8
1 changed files with 66 additions and 61 deletions

View File

@ -1,6 +1,6 @@
# Protecting code integrity with PGP
Updated: 2017-12-15
Updated: 2017-12-14
*Status: CURRENT, BETA*
@ -9,8 +9,9 @@ Updated: 2017-12-15
This document is aimed at developers working on free software projects. It
covers the following topics:
1. PGP key best practices
2. Introduction to PGP and Git
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
developing non-free or source-available ("Open Source") software. If you write
@ -98,7 +99,8 @@ 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 the 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
@ -162,10 +164,10 @@ 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: uknown** -- means there is no assurance at all that this key
- **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)
#### 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
@ -406,7 +408,7 @@ 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 IDs you've already added using:
You can review the UIDs you've already added using:
$ gpg --list-key [fpr] | grep ^uid
@ -434,8 +436,8 @@ be using for day-to-day work. We create 2048-bit keys because a lot of
specialized hardware (we'll discuss this further) does not handle larger keys,
but also for pragmatic reasons. If we ever find ourselves in a world where
2048-bit RSA keys are not considered good enough, it will be because of
fundamental problems with the RSA protocol and longer 4096-bit keys will not
make much difference.
fundamental breakthroughs in computing or mathematics and therefore longer
4096-bit keys will not make much difference.
#### Create the subkeys
@ -445,7 +447,7 @@ To create the subkeys, run:
$ gpg --quick-add-key [fpr] rsa2048 sign
You can also create the Authentication key, which will allow you to use your
PGP key for ssh purposes (covered in other guides):
PGP key for ssh purposes:
$ gpg --quick-add-key [fpr] rsa2048 auth
@ -467,8 +469,8 @@ 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 a keyserver on a port
that is most likely to work:
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]
@ -486,7 +488,7 @@ 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 a keyserver record does not result in net loss in
additionally available via keyservers does not result in a net loss in
privacy.
##### Upload your public key to GitHub
@ -496,14 +498,15 @@ 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 file to paste in, just run:
To generate the public key output suitable to paste in, just run:
$ gpg --export --armor [fpr]
#### Set up a refresh cronjob
You will need to regularly refresh the public keys on your keyring in order to
get the latest changes on other people's keys.
get the latest changes on other people's keys. You can set up a cronjob to do
that:
$ crontab -e
@ -531,9 +534,10 @@ 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 to a developer to have their PGP keys stolen -- in
the Free Software world this is often tantamount to identity theft. Removing
private keys from your home directory helps protect you from such events.
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.
Removing private keys from your home directory helps protect you from such
events.
#### Back up your GnuPG directory
@ -571,8 +575,8 @@ You should now test to make sure it still works:
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 adding identities,
extra subkeys, or adding signatures to other people's keys.
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
@ -734,7 +738,7 @@ 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
@ -752,7 +756,7 @@ 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 key passphrase and the
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.
@ -794,7 +798,7 @@ The output should be subtly different:
[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
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.
@ -806,7 +810,7 @@ Now, let's move that key onto the smartcard:
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 key
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.
@ -831,7 +835,7 @@ making sure first to unselect `key 2`. Once you're done, choose "q":
gpg> q
Save changes? (y/N) y
Saving the changes will remove the keys you moved to the card from your home
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).
@ -848,8 +852,8 @@ the output:
ssb> rsa2048 2017-12-06 [E]
ssb> rsa2048 2017-12-06 [S]
The `>` in the `ssb>` output indicates that the subkey is only available on a
smartcard. If you go back into your secret keys directory and look at the
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:
@ -875,7 +879,7 @@ your digital developer identity!
### Other common GnuPG operations
Here is a quick reference for various common operations you'll need to do with
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.
@ -892,7 +896,8 @@ directory and tell GnuPG to use that as its home:
$ 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).
means the key is not available and you're still using your regular home
directory location).
##### Updating your regular GnuPG working directory
@ -908,12 +913,12 @@ The master key we created has the default expiration date of 2 years from the
date of creation. This is done both for security reasons and to make obsolete
keys eventually disappear from keyservers.
To extend the expiry date on your key by another year, just run:
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, Cinco de Mayo, or Canada Day):
birthday, January 1st, or Canada Day):
$ gpg --quick-set-expire [fpr] 2020-07-01
@ -967,13 +972,13 @@ 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 directory, which
will inevitably be different if any part of the repository has changed.
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 list the following information about the repository and the change being
will include the following information about the repository and the change being
made:
- the checksum hash of the tree
@ -1011,13 +1016,13 @@ effectively assure you of the following:
- 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 and subtrees
- 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
assurances that _all contents in the repository, including all of its
history, are exactly the same as the contents of the repository on the
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
@ -1036,7 +1041,7 @@ 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 repository
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
@ -1045,15 +1050,15 @@ in 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 enforce PGP-signatures during `git push` was added in order to
enforce the *intent* of the commit, and not merely certify what the commit is.
enforce the *intent* of the commit, and not merely certify its contents.
#### Configure git to use your PGP key
If you only have one secret key in your keyring, then you don't really need to
do anything extra, as it becomes your default key.
However, if you happen to have multiple keys, you can tell git which key
should be used (`[fpr]` is the fingerprint of your 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]
@ -1070,13 +1075,13 @@ To create a signed tag, simply pass the `-s` switch to the tag command:
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. to introduce backdoors).
maliciously altered (e.g. in order to introduce backdoors).
##### How to verify signed tags
To verify a signed tag, simply pass the `-v` switch to the tag command:
To verify a signed tag, simply use the `verify-tag` command:
$ git tag -v [tagname]
$ 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
@ -1119,7 +1124,7 @@ 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 repository.
"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):
@ -1139,7 +1144,7 @@ To verify a single commit you can use `verify-commit`:
You can also look at repository logs and request that all commit signatures
are verified and shown:
$ git log --pretty=short --show-signatures
$ git log --pretty=short --show-signature
##### Verifying commits during git merge
@ -1152,7 +1157,7 @@ the `-S` flag):
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 difficult.
signing for your project difficult.
##### If your project uses mailing lists for patch management
@ -1171,13 +1176,13 @@ 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.
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 on the background with the purpose of caching
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).
@ -1215,23 +1220,23 @@ Then, add this to your `.bashrc`:
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
You will need to kill existing `gpg-agent` sessions and start a new login
session:
You will need to kill the existing `gpg-agent` process and start a new login
session for the changes to take effect:
$ killall gpg-agent
$ bash
$ ssh-add -L
The last command should list the SSH representation of your PGP Auth key (the
comment should say `cardno:XXXXXXX` at the end to indicate it's coming from
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 above output to
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-based access to anything:
keyservers, should you need to grant them ssh access to anything:
$ gpg --export-ssh-key [keyid]
@ -1277,19 +1282,19 @@ The most widely known mechanisms for 2-factor authentication are:
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.
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 a hurdle). Plus,
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 obtain both your account password and
the 2-factor token, they can replay them on the legitimate site and gain
access to your account.
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
@ -1331,7 +1336,7 @@ where this functionality should be enabled are:
#### Configure TOTP failover, if possible
Many sites will allow you to configure multiple 2-factor mechanisms, and the
recommended option is:
recommended setup is:
- U2F token as the primary mechanism
- TOTP phone app as the secondary mechanism