Skip to content

Instantly share code, notes, and snippets.

@Jc2k
Last active March 24, 2024 14:42
Show Gist options
  • Save Jc2k/de5ea2f2dc7904f077c1 to your computer and use it in GitHub Desktop.
Save Jc2k/de5ea2f2dc7904f077c1 to your computer and use it in GitHub Desktop.
GPG Cheat Sheet
if [ -f "${HOME}/.gpg-agent-info" ]; then
. "${HOME}/.gpg-agent-info"
export GPG_AGENT_INFO
export SSH_AUTH_SOCK
export SSH_AGENT_PID
fi

Config

See files attached to this gist:

  • gpg.conf -> ~/.gnupg/gpg.conf
  • gpg-agent.conf -> ~/.gnupg/gpg-agent.conf
  • .bash_profile -> ~/.bash_profile

## Generating a new set of keys

We want to generate a master key. This will be 4096 bits. It will be stored offline (and never on a machine wither internet access). We won't set an expiration on this key.

We'll then generate 3 subkeys:

  • A signing key
  • An encryption key
  • An authentication key

These will have an expiration date.

Generate the base key

 $ gpg --gen-key

 gpg: keyring `/home/user/.gnupg/secring.gpg' created
 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? 4
 RSA keys may be between 1024 and 4096 bits long.
 What keysize do you want? (2048) 4096
 Requested keysize is 4096 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) 1y
 Key expires at Thu 14 Apr 2016 11:49:51 AM UTC
 Is this correct? (y/N) y

 You need a user ID to identify your key; the software constructs the user ID
 from the Real Name, Comment and Email Address in this form:
     "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"

 Real name: Test User
 Email address: test@test.com
 Comment: 
 You selected this USER-ID:
     "Test User <test@test.com>"

 Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
 You need a Passphrase to protect your secret key.

 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 0x2896DB4A0E427716 marked as ultimately trusted
 public and secret key created and signed.

 gpg: checking the trustdb
 gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
 gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
 gpg: next trustdb check due at 2016-04-14
 pub   4096R/0x2896DB4A0E427716 2015-04-15 [expires: 2016-04-14]
       Key fingerprint = E397 DF19 074B 0A37 FC4F  B4E5 2896 DB4A 0E42 7716
 uid                            Test User <test@test.com>

 Note that this key cannot be used for encryption.  You may want to use
 the command "--edit-key" to generate a subkey for this purpose.

Add a key for signing

$ gpg --expert --edit-key 0x2896DB4A0E427716
Secret key is available.
gpg> addkey

(Enter your password if prompted).

Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
Your selection? 4
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 
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) 6m
Key expires at Mon 12 Oct 2015 12:05:23 PM UTC
Is this correct? (y/N) y
Really create? (y/N) y
gpg> save

Add an encryption key

$ gpg --expert --edit-key 0x2896DB4A0E427716
Secret key is available.
gpg> addkey
Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
Your selection? 6
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 
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) 6m
Key expires at Mon 12 Oct 2015 12:05:50 PM UTC
Is this correct? (y/N) y
Really create? (y/N) y
gpg> save

Add an authentication key

$ gpg --expert --edit-key 0x2896DB4A0E427716
Secret key is available.
gpg> addkey
Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
Your selection? 8

Possible actions for a RSA key: Sign Encrypt Authenticate 
Current allowed actions: Sign Encrypt 

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

 Your selection? (S ENTER E ENTER A ENTER Q ENTER to make an authentication only key)

RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 
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) 6m
Key expires at Mon 12 Oct 2015 12:06:18 PM UTC

Is this correct? (y/N) y Really create? (y/N) y

gpg> save

Generate a revocation certificate in case this key is lost or compromised. It’s probably worth actually printing this and sticking it somewhere safe in addition to storing a electronic version.

$ gpg --gen-revoke 0x2896DB4A0E427716
sec  4096R/0x2896DB4A0E427716 2015-04-15 Test User <test@test.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? 1
Enter an optional description; end it with an empty line:
> 
Reason for revocation: Key has been compromised
(No description given)
Is this okay? (y/N) y

You need a passphrase to unlock the secret key for
user: "Test User <test@test.com>"
4096-bit RSA key, ID 0x2896DB4A0E427716, created 2015-04-15

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!
-----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: A revocation certificate should follow

iQIfBCABCgAJBQJVLlD8Ah0CAAoJECiW20oOQncWQk0QAKofL48WIppMMbu9YLWS
aEIqg0AEVxBsVY6jk5+1IFByTulfkrf5ew4tbIJOuIjp0sIjfy4VXjWOqyw4peWS
OV9/N1JNxaQ8SjsmeiDycxEhLT3F6IUBiJ377NIgiAQ9BrYnqBdOekVxv0mjYEda
tLv0/vjfmum45q1ZLiQnOB3r8mK5nIqoky0Y/UhYZDtrM6b+Csk5+HEl0HZx7cKM
0lwF3ccEbsUcLIngyqj5J+5AUaePkszOwZuvrqdd+AslekC4f3LbKXfKa7K42H4h
9cVxBLxv320Bizo+0iBhCetraXmkv8A+f9AK6e26QLziKj16RrOf22d1MrYan4CX
+6JE+6l6ScgmhwX+UpeYwX8zAsr7f/jILKTVlbNb0jYUFFLw+pMZcohDOx+RS0ed
esWjXVBm/0+mFJLZoJLQj4AgraSBVXa8x8SD+TX7RKEKxhmJfaLC0WiAg4SSA9Kv
h93wgaP4z2/s2AJarZk81XyzILVGIh3tjfww93/myce+PxXHDVc+YTD1D4kEcJL2
KUZCcnennpnRVS3M+PqKryF6ZXMVgG79N4ia50owUeDzwxJOW2MokL0TRB0A1OEo
1CuNivzQkyvx+ywQa3nLeTrd7fJu9+tmYOTwuRk1m9gZ3IEeUJkK8bfntsOKK9XT
gY2OYVpEhMQ4Kblpx03YX25U
=j75h
-----END PGP PUBLIC KEY BLOCK-----

Setting up a yubikey

Enter card edit mode:

$ gpg --card-edit

Application ID ...: D2760001240102000006030189290000
Version ..........: 2.0
Manufacturer .....: Yubico
Serial number ....: 03018929
Name of cardholder: 
Language prefs ...: en
Sex ..............: 
URL of public key : 
Login data .......: NA
Signature PIN ....: forced
Key attributes ...: 2048R 2048R 2048R
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 0
Signature key ....: 
Encryption key....: 
Authentication key: 
General key info..: [none]

Turn on admin mode:

gpg/card> admin
Admin commands are allowed

Enter the passwd menu and change the user and admin pin:

gpg/card> passwd
gpg: OpenPGP card no. D2760001240102000006030189290000 detected

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? 1
PIN changed.

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? 3
PIN changed.

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? q

Set smart card settings like the url of your public key:

gpg/card> url
URL to retrieve public key: https://keybase.io/user/key.asc

gpg/card> name
Cardholder's surname: User
Cardholder's given name: Test

gpg/card> login
Login data (account name): test

gpg/card> sex
Sex ((M)ale, (F)emale or space): M

gpg/card> lang
Language preferences: en

And we are done:

gpg/card> quit

Transferring subkeys onto a yubikey

Enter key edit mode

$ gpg --edit-key 0x2896DB4A0E427716

Secret key is available.

pub  4096R/0x2896DB4A0E427716  created: 2015-04-15  expires: 2016-04-14  usage: SC
                               trust: ultimate      validity: ultimate
sub  2048R/0x770A210849C9CBD7  created: 2015-04-15  expires: 2015-10-12  usage: S
sub  2048R/0x6BF07F7DA7D84FFD  created: 2015-04-15  expires: 2015-10-12  usage: E
sub  2048R/0x7B13B2E1879F1ED3  created: 2015-04-15  expires: 2015-10-12  usage: A
[ultimate] (1). Test User <test@test.com>
[ultimate] (2)  Test User <test@megatestcorp.ca>
[ultimate] (3)  Test User <test@keybase.io>

'Toggle' to see the secret keys:

gpg> toggle

sec  4096R/0x2896DB4A0E427716  created: 2015-04-15  expires: 2016-04-14
ssb  2048R/0x770A210849C9CBD7  created: 2015-04-15  expires: never
ssb  2048R/0x6BF07F7DA7D84FFD  created: 2015-04-15  expires: never
ssb  2048R/0x7B13B2E1879F1ED3  created: 2015-04-15  expires: never
(1)  Test User <test@test.com>
(2)  Test User <test@megatestcorp.ca>
(3)  Test User <test@keybase.io>

Select the first secret key:

gpg> key 1

sec  4096R/0x2896DB4A0E427716  created: 2015-04-15  expires: 2016-04-14
ssb* 2048R/0x770A210849C9CBD7  created: 2015-04-15  expires: never
ssb  2048R/0x6BF07F7DA7D84FFD  created: 2015-04-15  expires: never
ssb  2048R/0x7B13B2E1879F1ED3  created: 2015-04-15  expires: never
(1)  Test User <test@test.com>
(2)  Test User <test@megatestcorp.ca>
(3)  Test User <test@keybase.io>

gpg> keytocard
Signature key ....: FE6C F0EA CBCC 7EE7 4093  31FC 770A 2108 49C9 CBD7
Encryption key....: 61D4 690A B2FF DD1E BA20  7236 3F4C 28B7 720F 4E92
Authentication key: CB86 2306 2D78 9F11 3F40  BD12 7B13 B2E1 879F 1ED3

Please select where to store the key:
   (1) Signature key
   (3) Authentication key
Your selection? 1

You need a passphrase to unlock the secret key for
user: "Test User <test@test.com>"
2048-bit RSA key, ID 0x770A210849C9CBD7, created 2015-04-15


sec  4096R/0x2896DB4A0E427716  created: 2015-04-15  expires: 2016-04-14
ssb* 2048R/0x770A210849C9CBD7  created: 2015-04-15  expires: never
                     card-no: 0006 03018929
ssb  2048R/0x6BF07F7DA7D84FFD  created: 2015-04-15  expires: never
ssb  2048R/0x7B13B2E1879F1ED3  created: 2015-04-15  expires: never
(1)  Test User <test@test.com>
(2)  Test User <test@megatestcorp.ca>
(3)  Test User <test@keybase.io>

You need to key 1 again to deselect that key:

gpg> key 1

Repeat for key 2 and 3:

gpg> key 2
<snip>
gpg> keytocard
Signature key ....: FE6C F0EA CBCC 7EE7 4093  31FC 770A 2108 49C9 CBD7
Encryption key....: 61D4 690A B2FF DD1E BA20  7236 3F4C 28B7 720F 4E92
Authentication key: CB86 2306 2D78 9F11 3F40  BD12 7B13 B2E1 879F 1ED3

Please select where to store the key:
   (2) Encryption key
Your selection? 2

You need a passphrase to unlock the secret key for
user: "Test User <test@test.com>"
2048-bit RSA key, ID 0x6BF07F7DA7D84FFD, created 2015-04-15

gpg> key 2
<snip>
gpg> key 3
<snip>

gpg> keytocard
Signature key ....: FE6C F0EA CBCC 7EE7 4093  31FC 770A 2108 49C9 CBD7
Encryption key....: 61D4 690A B2FF DD1E BA20  7236 3F4C 28B7 720F 4E92
Authentication key: CB86 2306 2D78 9F11 3F40  BD12 7B13 B2E1 879F 1ED3

Please select where to store the key:
   (3) Authentication key
Your selection? 3

You need a passphrase to unlock the secret key for
user: "Test User <test@test.com>"
2048-bit RSA key, ID 0x7B13B2E1879F1ED3, created 2015-04-15


sec  4096R/0x2896DB4A0E427716  created: 2015-04-15  expires: 2016-04-14
ssb  2048R/0x770A210849C9CBD7  created: 2015-04-15  expires: never
                     card-no: 0006 03018929
ssb  2048R/0x6BF07F7DA7D84FFD  created: 2015-04-15  expires: never
                     card-no: 0006 03018929
ssb* 2048R/0x7B13B2E1879F1ED3  created: 2015-04-15  expires: never
                     card-no: 0006 03018929
(1)  Test User <test@test.com>
(2)  Test User <test@megatestcorp.ca>
(3)  Test User <test@keybase.io>

And save:

gpg> save

New computer (without yubikey)

gpg --import publickey.gpg
gpg --import secretsubkeys.gpg

New computer (yubikey)

Plug in yubikey and:

gpg --card-edit
> fetch
> Ctrl+c
gpg --card-status

You can now sign, encrypt and authenticate with the subkeys stored on the yubikey, and your master key is safely stored offline.

## Offline Actions

Backing up your keys

Export your subkeys seperately from your master key:

gpg -a --export 0x5CA1AB1E > publickey.asc
gpg -a --export-secret-keys 0x5CA1AB1E > secretkeys.asc
gpg -a --export-secret-subkeys 0x5CA1AB1E > secretsubkeys.asc

Replacing a lost subkey

Generate a new subkey:

gpg --edit-key 0x5CA1AB1E
> addkey
choose 5 (RSA, sign only)

Expire your old key:

gpg --edit-key 0x5CA1AB1E
> key 2
> expire

Signing keys

With your offline keypair:

gpg --recv-key 0x5CA1AB1E
gpg --sign-key --ask-cert-level 0x5CA1AB1E
gpg --edit-key 0x5CA1AB1E trust
gpg --send-key 0x5CA1AB1E

From your online keypair:

gpg --recv-key 0x5CA1AB1E

Things have gone wrong

I've imported the secret key on the wrong machine

You should only be using your master key from an offline environment, but if you slipped up and need to undo it:

gpg --delete-secret-key 0x5CA1AB1E

See "New PC" to reimport your subkeys and public key.

Links

pinentry-program /usr/local/MacGPG2/libexec/pinentry-mac.app/Contents/MacOS/pinentry-mac
default-cache-ttl 600
max-cache-ttl 7200
enable-ssh-support
write-env-file
# when outputting certificates, view user IDs distinctly from keys:
fixed-list-mode
# long keyids are more collision-resistant than short keyids (it's trivial to make a key with any desired short keyid)
keyid-format 0xlong
# when multiple digests are supported by all recipients, choose the strongest one:
personal-digest-preferences SHA512 SHA384 SHA256 SHA224
# preferences chosen for new keys should prioritize stronger algorithms:
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 BZIP2 ZLIB ZIP Uncompressed
# If you use a graphical environment (and even if you don't) you should be using an agent:
# (similar arguments as https://www.debian-administration.org/users/dkg/weblog/64)
use-agent
# You should always know at a glance which User IDs gpg thinks are legitimately bound to the keys in your keyring:
verify-options show-uid-validity
list-options show-uid-validity
# when making an OpenPGP certification, use a stronger digest than the default SHA1:
cert-digest-algo SHA256
# prevent version string from appearing in your signatures/public keys
no-emit-version
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment