---
title: PGP and You
teaser: |
  Learn not only how to use PGP, but why each step is important and how to make
  decisions when interacting with PGP.
tags: git,open source,unix
author: Caleb Hearth
published_on: 2014-10-31
---

Pretty Good Privacy (OpenPGP) is [a standard]
that enables encrypted communication
between individuals.

[a standard]: http://datatracker.ietf.org/doc/rfc4880/?include\_text=1

You may have received an email
with a "NONAME" or "signature.asc" attachment
and wondered what it was,
or you might have seen an ["armored" email]
wrapped in something like:

["armored" email]: http://xkcd.com/1181/

    -----BEGIN PGP SIGNED MESSAGE-----
    [Plaintext message]
    -----BEGIN PGP SIGNATURE-----
    [Jumble of confusing characters]
    -----END PGP SIGNATURE-----

By the end of this article,
you'll understand what these
attachments and gibberish mean,
why they're important,
and how you can have your very own.

You'll also have the superpowers
to strongly encrypt messages,
verify the source of tagged Git releases,
and sign your emails with something
stronger than your name in ASCII.

I put off using PGP
for a long time,
because it struck me as needlessly complex.
My goal is to get more people using PGP
as a matter of course
and as a way to increase privacy.
This article is organized
such that you can find a goal,
have _how_ to complete it explained,
and also understand why each step is neccesary.

It is also ordered chronologically,
so that if you are just getting started
you can follow along in order.

### Note on GPG output

All of the GPG output
for my own email address
has been modified in two ways:

1. I am using a preexisting key, so the generation and most of the modification
   output has been changed to swap in my actual key (to avoid confusion).
1. The first UID on my key is actually my personal email address, so I've
   changed that to be my thoughtbot address.

The sample output
should be reasonably close
to actual output,
despite my changes.

The actual public key
is available on [a keyserver near you].

[a keyserver near you]: https://pgp.mit.edu/pks/lookup?op=vindex&search=0x1621ADC2A0ACE70A

## Getting Started

To begin,
install GNU Privacy Guard—or `gpg`—which is a free-as-in-speech implementation
of the OpenPGP standard.

<kbd>brew install gpg2</kbd>

If you're on another \*NIX system,
it's likely that you already have
`gpg`/`gnupg` installed.
If not,
it should be easy to find -
you're looking for at least version 2.

Note:
Because of variances
in how systems refer to the binary,
I will always refer to `gpg`.
On OS X via Homebrew,
the actual binary is `gpg2`.

I've found that it is
simpler to interact with shorter commands,
so I've aliased it as `gpg`.

### Generating a public/private key pair

To get anywhere with PGP,
you'll need to have
a keypair.

A keypair is composed of two parts:

* A public key,
  which you'll publish,
  allows others to
  encrypt messages to you
  and verify messages from you.
* A private key,
  which you'll keep secret and safe,
  allows you to decrypt the messages
  encrypted to your public key
  and to sign messages
  so that others can verify
  they are from you.

Algorithms which separate keys into public/private pairs
are more secure for several reasons,
including that the private key should never
be on the Internet.

    $ gpg --gen-key
    Please select what kind of key you want:
       (1) RSA and RSA (default)
       (2) DSA and Elgamal
       (3) DSA (sign only)
       (4) RSA (sign only)
    Your selection?

Most of the defaults are good choices
for this process,
so let's start by accepting `(1) RSA and RSA (default)`,
pressing <kbd>Enter</kbd>
to accept the default.

    RSA keys may be between 1024 and 8192 bits long.
    What keysize do you want? (2048)

Again, 2048 isn't a bad option here.
The size of the key determines how
long it takes to brute-force a key
as well as how long it takes to use
the public key to encrypt messages
and the private key to decrypt them.

Longer is stronger,
but you'll also slow down
anything using your key.

2048 is a good lower bound,
but feel free to go higher.
I'd personally recommend 8192
as the largest currently available.

It is worth noting
that 2048 keys will likely
be unsafe against
"very highly funded and knowledgable adversaries"
([The comp.security.pgp FAQ Chapter 4.  Keys](http://www.pgp.net/pgpnet/pgp-faq/pgp-faq-keys.html#key-size))
by the year 2020.

    Requested keysize is 2048 bits
    Please specify how long the key should be valid.
             0 = key does not expire
          <n>  = key expires in n days
          <n>w = key expires in n weeks
          <n>m = key expires in n months
          <n>y = key expires in n years
    Key is valid for? (0)

This step allows you to
limit the length of time your keys
will be valid for.

It's possible to refresh the key
before it expires
so you're not completely losing a key
if it runs out of time.

I didn't want to bother
with refreshing my key regularly,
so mine never expires.
Several others at thoughtbot have
an expiration for 1 year
after the key was generated.

Any choice here is fine,
just remember to refresh your key
at whatever interval you define.

    GnuPG needs to construct a user ID to identify your key.

    Real name: Caleb Hearth
    Email address: caleb@thoughtbot.com
    Comment:
    You selected this USER-ID:
        "Caleb Hearth <caleb@thoughtbot.com>"

    Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?

This step is fairly self-explanatory.
Comments are optional,
and as you can see
I don't usually add them.

    You need a Passphrase to protect your secret key.

    Enter passphrase:

This step is pretty important,
which is why the prompt is phrased the way it is.
It's possible,
but highly discouraged,
not to have a passphrase.

Remember that a passphrase
is inherently longer than a password
which makes it harder,
but still possible,
to brute-force.

Use standard password best practices
to build out a memorable and strong phrase.

See "[Choosing Secure Passwords][choosing-secure]", "[Passwords Are Not Broken,
but How We Choose them Sure Is][way-choose]", and of course "[Entirety Of Man’s
Personal Data Protected By Reference To Third Season Of ‘The West
Wing’][onion-data]".

[choosing-secure]: https://www.schneier.com/blog/archives/2014/03/choosing_secure_1.html
[way-choose]: https://www.schneier.com/essays/archives/2008/11/passwords_are_not_br.html
[onion-data]: http://www.theonion.com/articles/entirety-of-mans-personal-data-protected-by-refere,36632/

    We need to generate a lot of random bytes. It is a good idea to perform
    some other action (type on the keyboard, move the mouse, utilize the
    disks) during the prime generation; this gives the random number
    generator a better chance to gain enough entropy.
    […]
    gpg: key A0ACE70A marked as ultimately trusted
    public and secret key created and signed.

    pub   2048R/A0ACE70A 2013-08-12
          Key fingerprint = B432 C068 2FD1 C2D0 6A8B  3951 1621 ADC2 A0AC E70A
    uid                  Caleb Hearth <caleb@thoughtbot.com>
    sub   2048R/545CA4DF 2013-08-12

Great, we're set up locally with a keypair!

### Adding identities

You needn't go through
this whole process
for every email address you have.

I can edit my key
to add another user id:

    $ gpg --edit-key caleb@thoughtbot.com
    Secret key is available.

    pub  2048R/A0ACE70A  created: 2013-08-12  expires: never       usage: SC
                         trust: ultimate      validity: ultimate
    sub  2048R/545CA4DF  created: 2013-08-12  expires: never       usage: E
    [ultimate] (1). Caleb Hearth <caleb@thoughtbot.com>

    gpg>

Typing `help` from this prompt
informs us that the `adduid` command
lets us "add a user ID".
That sounds right.

    gpg> adduid
    Real name: Caleb Hearth
    Email address: caleb@calebhearth.com
    Comment:
    You selected this USER-ID:
        "Caleb Hearth <caleb@calebhearth.com>"

    Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o

    You need a passphrase to unlock the secret key for
    user: "Caleb Hearth <caleb@thoughtbot.com>"
    2048-bit RSA key, ID A0ACE70A, created 2013-08-12


    pub  2048R/A0ACE70A  created: 2013-08-12  expires: never       usage: SC
                         trust: ultimate      validity: ultimate
    sub  2048R/545CA4DF  created: 2013-08-12  expires: never       usage: E
    [ultimate] (1)  Caleb Hearth <caleb@thoughtbot.com>
    [ unknown] (2). Caleb Hearth <caleb@calebhearth.com>

    gpg> save

After saving,
my key has two UIDs attached,
representing my work and personal email addresses.

    $ gpg --list-keys A0ACE70A
    pub   2048R/A0ACE70A 2013-08-12
    uid                  Caleb Hearth <caleb@thoughtbot.com>
    uid                  Caleb Hearth <caleb@calebhearth.com>
    sub   2048R/545CA4DF 2013-08-12

### Generating a revocation certificate

It might be seem strange to revoke your key
as soon as you've created it,
but what you're really doing here
is creating an insurance policy
in case I lose access to my key.

There are some who would suggest writing down the (relatively short)
revocation certificate and storing it in a safety deposit box,
but I would say that a flash drive
or a known location on multiple computers
are more pragmatic options,
if ultimately less secure.
Storing this on the Internet is not a good idea
as you can't control the security of others' servers.

Generate a revocation certificate:

    $ gpg --output revoke.asc --gen-revoke caleb@thoughtbot.com

    sec  2048R/A0ACE70A 2013-08-12 Caleb Hearth <caleb@thoughtbot.com>

    Create a revocation certificate for this key? (y/N) y
    Please select the reason for the revocation:
      0 = No reason specified
      1 = Key has been compromised
      2 = Key is superseded
      3 = Key is no longer used
      Q = Cancel
    (Probably you want to select 1 here)
    Your decision?

Since you're making this revocation in advance,
you can't really specify the reason,
so select <kbd>0</kbd>.

For the same reason,
skip the description.

    Your decision? 0
    Enter an optional description; end it with an empty line:
    >
    Reason for revocation: No reason specified
    (No description given)
    Is this okay? (y/N) y

    You need a passphrase to unlock the secret key for
    user: "Caleb Hearth <caleb@thoughtbot.com>"
    2048-bit RSA key, ID A0ACE70A, created 2013-08-12

    ASCII armored output forced.
    Revocation certificate created.

    Please move it to a medium which you can hide away; if Mallory gets
    access to this certificate he can use it to make your key unusable.
    It is smart to print this certificate and store it away, just in case
    your media become unreadable.  But have some caution:  The print system of
    your machine might store the data and make it available to others!

It's a good idea to store this
in a separate place from your private key.
That "the print system of your machine might store the data"
is probably more paranoid than you need to be --
printing is a good way to handle this.

### Sharing your public key to keyservers

By their nature,
public keys are meant
to be easily available.

The primary method of sharing keys
is to publish them to a keyserver.
The `gpg` program includes
functionality to push keys.
From [`gpg2(1)`]:

[`gpg2(1)`]: http://linux.die.net/man/1/gpg2

    --send-keys key IDs
        Similar  to --export but sends the keys to a keyserver.
        [...] If no key IDs are given, gpg does nothing.

To publish to a keyserver,
pass the key id
from the output above
to `--send-keys`:

    $ gpg --send-keys A0ACE70A
    gpg: sending key A0ACE70A to hkp server keys.gnupg.net

The `gpg` program comes
preconfigured with
the `keys.gnupg.net` keyserver.
Keyservers propagate keys
to each other,
so this is a fine default
unless you have
a reason to use another server.

You can also publish your key
in other places,
e.g., my key is hosted on my server
at [calebhearth.com/pubkey.asc.txt](http://calebhearth.com/pubkey.asc.txt)
and thoughtbot's is on [pgp.thoughtbot.com](http://pgp.thoughtbot.com).

The more places your key is,
the easier it will be for others to find.

### Protecting your private key

There are many extremes you could go to
to keep your private key safe.

A good, pragmatic, option is to store it
(possibly along with the revocation certificate and public key)
on a flash drive which you keep in a safe,
secure place that only you have access to.
Storing secret keys on the Internet is a very bad idea,
since you have no way of knowing when someone else's server
has been compromised unless they fess up to it.

## Exchanging public keys

The first step to exchanging keys is to
actually get the key somehow.

The simplest way
to add a key to your keyring
is `--search-keys` for
an email address or name
which gives you
an interactive program
to select keys.

The search is pretty smart,
so if you searched for me as
"Caleb Hearth thoughtbot",
you'd get:

    $ gpg --search-keys "Caleb Hearth thoughtbot"
    gpg: searching for "Caleb Hearth thoughtbot" from hkp server keys.gnupg.net
    (1)     Caleb Hearth <caleb@thoughtbot.com>
            Caleb Hearth <caleb@calebhearth.com>
              2048 bit RSA key A0ACE70A, created: 2013-08-12
    Keys 1-1 of 1 for "Caleb Hearth thoughtbot".
      Enter number(s), N)ext, or Q)uit > 1
    gpg: requesting key A0ACE70A from hkp server keys.gnupg.net
    gpg: key A0ACE70A : public key "Caleb Hearth <caleb@thoughtbot.com>" imported
    gpg: Total number processed: 1
    gpg:               imported: 1  (RSA: 1)

Alternatively,
if you were sent an email
with a public key attachment
or otherwise acquired a file
containing a signature,
you can import the file with `gpg`:

    $ gpg --import pubkey.asc
    gpg: key A0ACE70A: "Caleb Hearth <caleb@thoughtbot.com>" not changed
    gpg: Total number processed: 1
    gpg:              unchanged: 1

Finding a public key
for another person
isn't all you need to do
to trust their identity
and share with others that you do.

Now that my public key is in your keyring
you can encrypt and sign messages to that key
and verify that messages signed or encrypted
with that key are valid.
You can't,
however,
actually trust that the person
who controls that key is me.

The reasons the key
might not belong to me vary,
and include [Man-in-the-middle (MITM)] attacks
or even [someone else deciding to
make a key] that appears to belong to me.

[Man-in-the-middle (MITM)]: http://en.wikipedia.org/wiki/Man-in-the-middle\_attack
[someone else deciding to make a key]: https://pgp.mit.edu/pks/lookup?search=president%40whitehouse.gov&op=index

To do that,
you'd need to verify
the key's fingerprint
by somehow having me tell it to you
in a venue where you can be sure
that you are talking to me.

Ideally
this would be in person
with me reading my fingerprint
to you aloud
while you verify
the fingerprint
on your own computer.
This isn't always practical
but you definitely want
to be absolutely sure
the person telling you
that the key is mine
is me.
A phone or video call
(if you would recognize my face or voice),
verifying on social media,
instant messaging,
checking the signatures of others
who have signed my key
(and who you trust),
or preferably some combination of these
are all potential avenues
for verification.

To display a key's fingerprint:

    $ gpg --fingerprint "Caleb Hearth" # or A0ACE70A
    pub   2048R/A0ACE70A 2013-08-12
          Key fingerprint = B432 C068 2FD1 C2D0 6A8B  3951 1621 ADC2 A0AC E70A
    uid                  Caleb Hearth <caleb@thoughtbot.com>
    uid                  Caleb Hearth <caleb@calebhearth.com>
    sub   2048R/545CA4DF 2013-08-12

### Signing a key

Signing a key marks an implicit trust.
This means that you have done
some amount of work to verify
the identity of the keyholder.

The level of trust can be specified,
and ranges from
"I didn't actually check anything"
to
"I have verified this key's fingerprint
and this person's identity
in person using legal documents".

The default level,
which GnuPG will assume if you don't specify that it should ask,
is `I will not answer.`
This is a reasonable default,
but I prefer to be prompted
and to specify how well I have verified a signature.

A conceptual similarity to signing a key at the highest level
(`I have done very careful checking.`)
would be to vouch in court that
the person the key represents
is the person you met
and that they are the person they claim to be.

Ideally,
this would mean that you had
personally met the person
and verified their fingerprint.

Signing a key is useful
because it informs others
that they can trust the signature
to the extent
that they trust you to verify signatures.

If you do not personally
know the person you are exchanging keys with,
actual verification of legal identity (photo id)
and of the ownership of the email address
are important steps.
[PGP Key Signing](http://phildev.net/pgp/gpgsigning.html) has a good overview
of how these verifications
could be accomplished.

Let's look at two scenarios:
Mike Burns has been my coworker
as long as I've been at thoughtbot.
I'm completely confident in his identity.

I met Mike in person at thoughtbot's annual gathering
and we exchanged key signatures at a "key signing party".
At this party,
I searched for his key on a public keyserver
and he verified his fingerprint by reading it out loud
from his computer
while I read the fingerprint of the downloaded key
on my computer.

Since the whole key matched,
and I know Mike personally,
I signed his key at level 3
(described as "I have done very careful checking.")

George is also a longtime coworker.
Although he lives in Stockholm,
I've met him before and am confident in his identity.
However,
I can't verify his key's fingerprint in person.

There's still a way I can sign George's key.
I'll start by retrieving it based on the key id he told me in Slack:

    $ gpg --recv-keys B51FFCFB
    gpg: requesting key B51FFCFB from hkp server keys.gnupg.net
    gpg: key B51FFCFB: public key "George Richard John Brocklehurst (thoughtbot)
      <george@thoughtbot.com>" imported
    […]
    gpg: Total number processed: 1
    gpg:               imported: 1  (RSA: 1)

I can open the key
to inspect and edit it:

    $ gpg --ask-cert-level --edit-key george@thoughtbot.com

    pub  2048R/B51FFCFB  created: 2013-11-04  expires: never       usage: SC
                         trust: unknown       validity: full
    sub  2048R/E666A729  created: 2013-11-04  expires: never       usage: E
    [  full  ] (1). George Richard John Brocklehurst (thoughtbot) <george@thoughtbot.com>
    [  full  ] (2)  George Richard John Brocklehurst <george@georgebrock.com>
    [  full  ] (3)  [jpeg image of size 8985]

    gpg>

I'm shown the key with all identities
(user ids)
as well as the trust level I have
for each of them.

I have "full" trust in
George's keys,
thanks to the Web of Trust,
because someone I've trusted
has signed George's key:

    gpg> check
    uid  George Richard John Brocklehurst (thoughtbot) <george@thoughtbot.com>
    sig!         AFEB61EC 2013-11-04  Michael John Burns (Mike) <mike@mike-burns.com
    sig!3        B51FFCFB 2013-11-04  [self-signature]
    sig!         2846B014 2014-01-13  Michael John Burns <mike@mike-burns.com>
    uid  George Richard John Brocklehurst <george@georgebrock.com>
    sig!         AFEB61EC 2013-11-04  Michael John Burns (Mike) <mike@mike-burns.com
    sig!3        B51FFCFB 2013-11-04  [self-signature]
    sig!         2846B014 2014-01-13  Michael John Burns <mike@mike-burns.com>
    uid  [jpeg image of size 8985]
    sig!         AFEB61EC 2013-11-06  Michael John Burns (Mike) <mike@mike-burns.com
    sig!3        B51FFCFB 2013-11-05  [self-signature]
    sig!         2846B014 2014-01-13  Michael John Burns <mike@mike-burns.com>
    21 signatures not checked due to missing keys

Since I don't have George here
to tell me his fingerprint in person,
I'll go through a few extra steps.
I've already confirmed that
my trusted introducer,
Mike Burns,
has signed George's key.
Next,
I'll ask George to give me his fingerprint
in a couple of different locations:
an email from George's thoughtbot address,
our company's Slack room,
and his [Twitter account](https://twitter.com/calebthompson/status/507196135271063552).
Once it's been confirmed in those locations,
and given that I know George personally
and he gave me the key id to download in the first place,
I'm willing to sign his key
and confirm that I believe it to be controlled by George.

    gpg> sign
    Really sign all user IDs? (y/N)

This prompt,
and the default "N" choice,
attempt to point me in the right direction about signing.

While I'm sure that George has a thoughtbot.com email address,
I'm less positive that he owns the georgebrock.com email address.
George also attached a photo,
which I can open in a default photo viewer with:

    gpg> showphoto

That's a picture of George,
so I'll sign photo user attribute as well:

    gpg> sign
    Really sign all user IDs? (y/N) n
    Hint: Select the user IDs to sign

    gpg> 1

    pub  2048R/B51FFCFB  created: 2013-11-04  expires: never       usage: SC
                         trust: unknown       validity: full
    sub  2048R/E666A729  created: 2013-11-04  expires: never       usage: E
    [  full  ] (1)* George Richard John Brocklehurst (thoughtbot) <george@thoughtbot.com>
    [  full  ] (2)  George Richard John Brocklehurst <george@georgebrock.com>
    [  full  ] (3)  [jpeg image of size 8985]

    gpg> 3

    pub  2048R/B51FFCFB  created: 2013-11-04  expires: never       usage: SC
                         trust: unknown       validity: full
    sub  2048R/E666A729  created: 2013-11-04  expires: never       usage: E
    [  full  ] (1)* George Richard John Brocklehurst (thoughtbot) <george@thoughtbot.com>
    [  full  ] (2)  George Richard John Brocklehurst <george@georgebrock.com>
    [  full  ] (3)* [jpeg image of size 8985]

    gpg>

Now when I issue `sign`,
the program knows to only sign identities 1 and 3.

    gpg> sign

    pub  2048R/B51FFCFB  created: 2013-11-04  expires: never       usage: SC
                         trust: unknown       validity: full
     Primary key fingerprint: 0750 F6BF 8064 E22C 68D2  3D90 0C64 3A97 B51F FCFB

         George Richard John Brocklehurst (thoughtbot) <george@thoughtbot.com>
         [jpeg image of size 8985]

    How carefully have you verified the key you are about to sign actually belongs
    to the person named above?  If you don't know what to answer, enter "0".

       (0) I will not answer. (default)
       (1) I have not checked at all.
       (2) I have done casual checking.
       (3) I have done very careful checking.

    Your selection? (enter '?' for more information):

Unlike the situation with Mike
where we were together in person,
I haven't been able to fully validate
George's key.

I've gone through what I'll consider "casual" checking:
his email address,
his Twitter account,
his Slack account,
and a signature from a trusted introducer (Mike).

    Your selection? (enter '?' for more information): 2
    Are you sure that you want to sign this key with your
    key "Caleb Hearth <caleb@thoughtbot.com>" (A0ACE70A)

    I have checked this key casually.

    Really sign? (y/N) y

    You need a passphrase to unlock the secret key for
    user: "Caleb Hearth <caleb@thoughtbot.com>"
    2048-bit RSA key, ID A0ACE70A, created 2013-08-12

    gpg> save

Great,
now I've signed my local copy of George's key,
marking that I trust his identity
and verified it casually.

As a final validation step,
rather than sending the signature myself as described later
I will export and encrypt it to the key,
and email it to George so that he can import it and publish,
provided that he has access to the key.

    $ gpg --armor --export george@thoughtbot.com > george_at_thoughtbot.asc
    $ gpg --armor --encrypt \
      --recipient george@thoughtbot.com \
      --output george_at_thoughtbot_ENCRYPTED.asc \
      george_at_thoughtbot.asc

I'll send the encrypted file to George with instructions:

    gpg --decrypt george_at_thoughtbot_ENCRYPTED.asc > george_at_thoughtbot.asc
    gpg --import george_at_thoughtbot.asc
    gpg --send-keys george@thoughtbot.com

Before I forget,
I'll delete the files
`george_at_thoughtbot_ENCRYPTED.asc` and
`george_at_thoughtbot.asc`.

Sending the key to George this way
provides an additional layer of trust,
that he has access to unlock and use
the secret key to decrypt the signature.

I'll delete the key from my local keyring,
and redownload it using `--recv-keys` or `import`
so that I don't accidentally push up
the signature myself.

    $ gpg --delete-key B51FFCFB

    pub  2048R/B51FFCFB 2013-11-04 George Richard John Brocklehurst (thoughtbot) <george@thoughtbot.com>

    Delete this key from the keyring? (y/N) y

    $ gpg --recv-keys B51FFCFB

Now that you know I'd sign a key in this way,
you may want to take that into account
when assigning a level of trust to me.
For example,
if a person I knew went through a process like this
I wouldn't trust beyond "marginal",
because I'd not want to trust this process by another person "fully".

A simpler,
and more likely method,
would be to have George confirm his fingerprint for me
on a video chat,
so that I could confirm it was him telling me.

At least at this point,
I deem it highly unlikely that anyone
could intercept and fake a video call,
so that could give allow me
to mark a higher level of confirmation
of his identity.

### Trusting a key

Much of PGP's strength
comes from its Web of Trust concept.

To paraphrase [Phil Zimmermann],
PGP's inventor,
as you import keys from people you interact with
and build your network
you may find that you trust some people
to verify others' identities.

[Phil Zimmermann]: https://www.philzimmermann.com/EN/background/index.html

PGP allows you to note
the extent to which you trust someone's veracity
at verifying the identity of keyholders.

First of all,
this isn't something you would do
for every key.
Trust is personal
and will never be shared.
You can feel free
to be truthful about your trust
that this person is properly verifying keys -
they won't ever know what level you give
unless you tell them.
You can also feel free
not to trust a signature at all.

Additionally,
trust levels can be changed
as you learn more about a person.

Unfortunately,
the `gpg` user interface
does not make either of these concepts
very clear.

Just like signing,
I need to edit the key
(these steps can actually
be combined if I want
to do both of them at once).

Since Mike taught me how to verify a key
in the first place,
I trust that he will verify someone's identity
with reasonable veracity.

Assuming I already have Mike's key
and know its id:

    $ gpg --edit-key 2846B014

    pub  4096R/2846B014  created: 2013-11-27  expires: 2018-11-26  usage: SC
                         trust: unknown       validity: unknown
    sub  2048R/14A5A932  created: 2013-11-27  expires: 2018-11-26  usage: S
    [ unknown] (1). Michael John Burns <mike@mike-burns.com>
    [ unknown] (2)  Michael John Burns <mburns@thoughtbot.com>
    gpg> fpr
    pub   4096R/2846B014 2013-11-27 Michael John Burns <mike@mike-burns.com>
     Primary key fingerprint: 5FD8 2CE6 A646 3285 538F  C3A5 3E67 61F7 2846 B014

Once I've verified the fingerprint
as discussed above,
I can assign trust.

    gpg> trust
    pub  4096R/2846B014  created: 2013-11-27  expires: 2018-11-26  usage: SC
                         trust: unknown       validity: unknown
    sub  2048R/14A5A932  created: 2013-11-27  expires: 2018-11-26  usage: S
    [ unknown] (1). Michael John Burns <mike@mike-burns.com>
    [ unknown] (2)  Michael John Burns <mburns@thoughtbot.com>

    Please decide how far you trust this user to correctly verify other users' keys
    (by looking at passports, checking fingerprints from different sources, etc.)

      1 = I don't know or won't say
      2 = I do NOT trust
      3 = I trust marginally
      4 = I trust fully
      5 = I trust ultimately
      m = back to the main menu

    Your decision?

You should never trust anyone
other than yourself
ultimately.

When you've answered,
you'll be back at the prompt.

    Your decision? 4

    pub  4096R/2846B014  created: 2013-11-27  expires: 2018-11-26  usage: SC
                         trust: full          validity: unknown
    [ unknown] (1). Michael John Burns <mike@mike-burns.com>
    [ unknown] (2)  Michael John Burns <mburns@thoughtbot.com>
    Please note that the shown key validity is not necessarily correct
    unless you restart the program.

    gpg> save

You need to save the key
for the trust change to persist,
and then you can quit.

### Revoking a key signature

A major part of why I'd be willing to sign George's key "casually"
is that key signatures can be revoked.

There are various reasons for doing this,
including that a person lost access to their key
(hopefully they'd also have revoked it),
you made a mistake signing it,
the person no longer controls an email address
(possibly they left a job),
or you realize that the person wasn't actually who you thought.

    $ gpg --edit-key george@thoughtbot.com

    pub  2048R/B51FFCFB  created: 2013-11-04  expires: never       usage: SC
                         trust: unknown       validity: full
    sub  2048R/E666A729  created: 2013-11-04  expires: never       usage: E
    [  full  ] (1). George Richard John Brocklehurst (thoughtbot) <george@thoughtbot.com>
    [  full  ] (2)  George Richard John Brocklehurst <george@georgebrock.com>
    [  full  ] (3)  [jpeg image of size 8985]

The `revsig` command allows us to
create a revocation certificate for the signature.

    gpg> revsig
    You have signed these user IDs on key B51FFCFB:
         George Richard John Brocklehurst (thoughtbot) <george@thoughtbot.com>
       signed by your key A0ACE70A on 2014-09-03
         George Richard John Brocklehurst <george@georgebrock.com>
         [jpeg image of size 8985]
       signed by your key A0ACE70A on 2014-09-03

I am prompted to revoke each signed user id,
and I'll answer yes to both:

    user ID: "George Richard John Brocklehurst (thoughtbot) <george@thoughtbot.com>"
    signed by your key A0ACE70A on 2014-09-03
    Create a revocation certificate for this signature? (y/N) y
    user ID: "[jpeg image of size 8985]"
    signed by your key A0ACE70A on 2014-09-03
    Create a revocation certificate for this signature? (y/N) y

I get a prompt asking why I am revoking:

    You are about to revoke these signatures:
         George Richard John Brocklehurst (thoughtbot) <george@thoughtbot.com>
       signed by your key A0ACE70A on 2014-09-03
         [jpeg image of size 8985]
       signed by your key A0ACE70A on 2014-09-03
    Really create the revocation certificates? (y/N) y
    Please select the reason for the revocation:
      0 = No reason specified
      4 = User ID is no longer valid
      Q = Cancel

Entering 4 will let us leave a description.

    Your decision? 4

I enter a description,
owning up to the reason your signature isn't valid anymore.

    Enter an optional description; end it with an empty line:
    > Incorrectly verified. This is not George's key.
    >
    Reason for revocation: User ID is no longer valid
    Incorrectly verified. This is not George's key.
    Is this okay? (y/N) y

    You need a passphrase to unlock the secret key for
    user: "Caleb Hearth <caleb@thoughtbot.com>"
    2048-bit RSA key, ID A0ACE70A, created 2013-08-12


    pub  2048R/B51FFCFB  created: 2013-11-04  expires: never       usage: SC
                         trust: unknown       validity: full
    sub  2048R/E666A729  created: 2013-11-04  expires: never       usage: E
    [  full  ] (1). George Richard John Brocklehurst (thoughtbot) <george@thoughtbot.com>
    [  full  ] (2)  George Richard John Brocklehurst <george@georgebrock.com>
    [  full  ] (3)  [jpeg image of size 8985]

    gpg> save

You can now publish the revocation certificate,
and the key signature would no longer be valid.

Of course,
I didn't actually revoke this key signature.

### Publishing your changes

Just like when I created my original key,
I can push up changes such as signing
with the `--send-keys` command and key ids:

    gpg --send-keys B51FFCFB 2846B014

## For Fun and Profit

So you've followed this guide,
have a key
and have potentially signed or trusted other keys.

There are some interesting things
you can do with your new setup.

### Signing Git commits and tags

A major benefit of using PGP
is that you're able to sign your commits and tags,
allowing others to verify that they have versions of software
from a trusted source.

#### Why Sign Commits

Just like emails and other messages,
a commit signed by someone in your Web of Trust (WoT)
can be confirmed to be from a trusted source.
Even if the signer is not in your WoT,
you can still fairly simply verify their signature is valid.

A strict policy of signing all commits,
therefore,
could prevent someone committing as you
(perhaps with `GIT_COMMITTER_NAME` and `GIT_COMMITTER_EMAIL`)
from fully blaming you for a change.

An even stricter policy of only allowing
commits signed by those in a maintainer's Web of Trust
could help to ensure that a codebase's
quality, security, etc. were maintained.

Git knows how to verify commit and tag signatures,
so it's simple to do so.

    $ git log --show-signature

    commit 8499951498cac1be0e7db1cf7d7e01d443be2916
    gpg: Signature made Tue Oct 28 18:41:31 2014 CDT using RSA key ID A0ACE70A
    gpg: Good signature from "Caleb Hearth <caleb@thoughtbot.com>"
    gpg:                 aka "Caleb Hearth <caleb@calebhearth.com>"
    Author: Caleb Hearth <caleb@calebhearth.com>
    Date:   Tue Oct 28 18:41:22 2014 -0500

#### Why Sign Tags

Simpler than signing commits,
signing a tag states that
you have looked over the commits
leading up to the tagged commit
and that you made a commit.

This is particularly useful
for verifying the source of
released versions of software libraries.

Since it is just as easy to forge
a tag identity as a commit identity,
PGP-signing tags is still a good idea.
It is also less obtrusive than with commits,
since tags happen less often.

To verify a tag:

    $ git tag --verify v1.1.0
    object 239fc554285c4d21fee71d9de79d88c4ebe4936e
    type commit
    tag v1.1.0
    tagger Caleb Hearth <caleb@calebhearth.com> 1412371030 -0500

    griddler 1.1.0
    gpg: Signature made Fri Oct  3 16:17:10 2014 CDT using RSA key ID A0ACE70A
    gpg: Good signature from "Caleb Hearth <caleb@thoughtbot.com>"
    gpg:                 aka "Caleb Hearth <caleb@calebhearth.com>"

#### Signing commits

You can tell `git-commit` to sign a commit
by passing the `-S` or `--gpg-sign` argument
with a key id (hex or name/email).

    git commit --gpg-sign A0ACE70A

The argument is optional if you've configured a signing key.

#### Signing tags

You can tell `git-tag` to sign a commit
by passing `-s` or `--sign` to use the default Git `user.email`
or by passing `-u` or `--local-user` and a key ID.

Naturally,
those couldn't be the same argument
as `git-commit` uses.

##### git-bump

Tim Pope wrote a great tool
for managing Git tags and GitHub Releases,
[`git-bump`].

I use this myself for managing releases
of [Griddler], [Formulaic], and [Scenic]
and it makes it quite easy to create
not only signed tags,
but also meaningfully annotated tags.

[`git-bump`]: https://github.com/tpope/git-bump
[Griddler]: https://github.com/thoughtbot/griddler/releases
[Formulaic]: https://github.com/thoughtbot/formulaic/releases
[Scenic]: https://github.com/thoughtbot/scenic/releases

Unfortunately GitHub do not (yet)
display any sort of PGP signature.

#### Configure signing key

Configuring your signing key is fairly simple.

<kbd>git config --global user.signingkey "Caleb Hearth <caleb@thoughtbot.com>"</kbd>

#### Configure Git to always sign commits

If you choose,
you can also configure `git`
to default to signing all commits:

<kbd>git config --global commit.gpgsign true</kbd>

It's worth noting that
without using an agent to manage your key,
this can result in needing to type your passphrase a lot
during operations such as
rebasing, interactive commits, or stashes.

### Signing and encrypting emails

First, a word on etiquette:

It's important when you receive
an encrypted message
that you not respond in plaintext
with the original encrypted message quoted.

Ideally,
when you receive an encrypted message
you should respond with an encrypted message.

Whenever messaging someone whose key I have
or who sends me a message with a signature attached
I send further emails encrypted.

Basically,
this means that I use encryption
whenever possible.

This isn't any more difficult for me
than signing,
and assuming the message recipient also has a reasonable setup,
they'll only need to enter their passphrase
to read the message.

#### Setting up Mutt for PGP

My [mutt configuration]
represents a fairly normal mutt/PGP setup.

[mutt configuration]: https://gist.github.com/calebthompson/8451a25b10d9fae666c3

It includes signing emails by default
as attachments,
which to most people looks like "NONAME" or "signature.asc",
but for others with a PGP setup
is a lot more useful than your name at the end.

[`muttrc(5)`] and [`gpg2(1)`] have extensive documentation
on these settings,
and I'll leave that research as an exercise for the reader.

[`muttrc(5)`]: http://linux.die.net/man/5/muttrc

##### Encrypting emails

From the email compose view,
press <kbd>p</kbd> to open the PGP menu:

    PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, (i)nline format, or (c)lear?

By default,
the configuration I linked earlier will `(s)ign`
as the default configured key,
and this menu allows you to change that behavior
for a specific email.

Generally when encrypting,
it makes sense to select `(b)oth`
so that you have a signature added as well.

`(i)nline format` provides the ASCII-armored
format I made fun of at the beginning of this article.
There are one or two mail clients,
such as [K-9 mail],
which only understand this format.

[K-9 mail]: https://code.google.com/p/k9mail/issues/detail?id=13

#### Setting up Mail.app for PGP

If you're planning to use PGP with Mail.app,
[GPGTools](https://gpgtools.org/) provide GPGMail
for integration with your PGP key,
as well as some other GPG tools that provide a GUI
interface to OpenPGP.

### Using an agent for managing your passphrase

Agents are programs which remember
your GPG passphrase for a limited time,
allowing you to enter it once
and not need to re-enter it for some set amount of time,
which is really nice during rebases or stashes in Git
or when sending several emails in a short amount of time.

I use the `gpg-agent` program,
which should be available
in your favorite package manager.

## Revoking a key

Revoking a key
is something you want to do when
you've lost access to a secret key,
or someone else has gained control of it.

If you've already
generated a key using the method
in the [Generating a revocation certificate] section,
you can import it and send it to keyservers with:

[Generating a revocation certificate]: #generating-a-revocation-certificate

I don't have output for this
because I don't want to revoke
my key.

If you haven't generated a revocation certificate,
you still can if you have access to the secret key.
Use the instructions
from the [Generating a revocation certificate] section
to do so.

Otherwise,
in the words of Phil Zimmermann,
"I'm sorry, you're hosed."

Either way,
it's a good idea to sign
your old public key with your new key
so that there is a link between the two.

Doing so will also connect your
old and new webs of trust,
which should help in re-confirming people.

## Bibliography and Further Reading

* [The GNU Privacy Handbook](https://www.gnupg.org/gph/en/manual.html)
* [Exchanging Keys](https://www.gnupg.org/gph/en/manual/x56.html)
* [PGP Setup](http://www.phildev.net/pgp/gpgkeygen.html)
* [PGP Trust](http://www.phildev.net/pgp/gpgtrust.html)
* [Is it okay to sign a PGP key without an IRL meeting?](http://security.stackexchange.com/questions/35666/is-it-okay-to-sign-a-pgp-key-without-an-irl-meeting)
* [How to revoke a GnuPG/PGP signature on a key](https://security.ias.edu/how-revoke-gnupgpgp-signature-key)
* [MuttGuide / UseGPG](http://dev.mutt.org/trac/wiki/MuttGuide/UseGPG) is a
  great reference on setting up Mutt to use PGP.
* [A Git Horror Story](http://mikegerwitz.com/papers/git-horror-story) details
  why you might want to sign commits and tags using PGP.

Special thanks to Mike Burns and Pat Brisbin,
who have been instrumental in my own PGP education,
and to George Brocklehurst and Mike Burns for
kindly allowing the use of their keys in my examples.
