A collection of notes about generating and managing GPG keys.

Signing Key

Standard DSA keys are limited to 1024-bit. This isn't strong enough.

RSA keys of at least 2048 bits should be used.

Properties

  • RSA
  • 3072-bits
  • No expiry
  • Secure passphrase

Transcript

$ gpg --gen-key
gpg (GnuPG) 1.4.6; Copyright (C) 2006 Free Software Foundation, Inc.
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions. See the file COPYING for details.

Please select what kind of key you want:
   (1) DSA and Elgamal (default)
   (2) DSA (sign only)
   (5) RSA (sign only)
Your selection? 5
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 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) 0
Key does not expire at all
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: My Real Name
Email address: my.real@email.address
Comment: A Useful Comment
You selected this USER-ID:
    "My Real Name (A Useful Comment) <my.real@email.address>"

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

Enter passphrase: *********************************************
Repeat passphrase: *********************************************

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

gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, classic trust model
gpg: depth: 0  valid:   5  signed:   1  trust: 0-, 0q, 0n, 0m, 0f, 5u
gpg: depth: 1  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 1f, 0u
pub   2048R/FEEDBEEF 2008-11-17
      Key fingerprint = xxxx xxxx xxxx xxxx xxxx  xxxx xxxx xxxx xxxx xxxx
uid                  My Real Name (A Useful Comment) <my.real@email.address>

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.

Renewing an Expired Primary Key

$gpg --edit-key my.real@email.address
gpg> key 0
# selects primary key, deselects subkey
gpg> expire
# set new expiry
gpg> save

Encryption Subkey

Properties

  • RSA
  • 2048-bits
  • 5 year expiry

Transcript

$ gpg --edit-key FEEDBEEF
gpg (GnuPG) 1.4.6; Copyright (C) 2006 Free Software Foundation, Inc.
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions. See the file COPYING for details.

Secret key is available.

pub  2048R/FEEDBEEF  created: 2008-11-17  expires: never       usage: SC  
                     trust: ultimate      validity: ultimate
[ultimate] (1). My Real Name (A Useful Comment) <my.real@email.address>

Command> addkey
Key is protected.

You need a passphrase to unlock the secret key for
user: "My Real Name (A Useful Comment) <my.real@email.address>"
2048-bit RSA key, ID FEEDBEEF, created 2008-11-17

Enter passphrase: 

Please select what kind of key you want:
   (2) DSA (sign only)
   (4) Elgamal (encrypt only)
   (5) RSA (sign only)
   (6) RSA (encrypt only)
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) 5y
Key expires at Sat 16 Nov 2013 23:26:46 GMT
Is this correct? (y/N) y
Really create? (y/N) y
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.
..+++++
+++++

pub  2048R/FEEDBEEF  created: 2008-11-17  expires: never       usage: SC  
                     trust: ultimate      validity: ultimate
sub  2048R/FEEDBABE  created: 2008-11-17  expires: 2013-11-16  usage: E   
[ultimate] (1). My Real Name (A Useful Comment) <my.real@email.address>

Command> quit
Save changes? (y/N) y
$ 

Revocation Certificates

  • Extremely important when the private key has been compromised or lost
  • Revocation certs should be backed up securely and off-site

gpg --output revoke.asc --gen-revoke my.real@email.address

Replacing Expired Subkeys

  • Add new encryption subkey with 5-year expiry.

    gpg --edit FEEDBEEF
    gpg> list
    gpg> addkey
    
  • Expired subkeys must not be deleted otherwise you lose the ability to decrypt old messages

  • Do not revoke expired subkeys unless you have lost control of them

Removing Subkeys from the Public keyring

GPG always selects the newest valid subkey.

To remove the 2nd subkey:

```
gpg --edit DEADBEEF
gpg> key 2
gpg> delkey
```

Transcript

gpg> addkey
Key is protected.

You need a passphrase to unlock the secret key for
user: "My Real Name (A Useful Comment) <my.real@email.address>"
2048-bit RSA key, ID FEEDBEEF, created 2008-11-17

Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
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) 5y
Key expires at Tue 24 Oct 2017 02:29:50 BST
Is this correct? (y/N) y
Really create? (y/N) y
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, use the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
+++++
.+++++

pub  2048R/FEEDBEEF  created: 2008-11-17  expires: never       usage: SC  
                     trust: unknown       validity: unknown
sub  2048R/FEEDBABE  created: 2008-11-17  expired: 2012-10-19  usage: E   
sub  2048R/DEADBABE  created: 2012-10-25  expires: 2017-10-24  usage: E   
[ unknown] (1). My Real Name <my.real@email.address>

Hashing Algorithm

SHA1 is broken. SHA256 or SHA512 should be used.

echo "digest-algo SHA256" >> .gnupg/gpg.conf

Adding UIDs

  • TODO

    $ gpg --edit-key FEEDBEEF adduid uid 1 primary quit

  • After saving the new UID will be self-signed

  • Prior signatures on the key don't apply to the new UID

Exchanging Key Signatures

  • Signatures are collected on the Master (signing key)
  • You sign other keys with your Master key to indicate that you trust them
  • TODO: bits about signing trust level

Key Exchange Protocol

  1. Send contact details
    1. Alice sends a signed e-mail to Bob containing her telephone number and her public key.
    2. Bob sends a signed e-mail to Alice containing his public key.
  2. Bob calls Alice on the telephone
  3. Alice and Bob authenticate each other by voice verification
  4. Verify Alice's Key
    1. Bob reads the bibble-babble code of Alice's public key to Alice
    2. Alice confirms that Bob has received the key she sent
    3. Bob signs Alice's key
  5. Verify Bob's Key
    1. Alice reads the bibble-babble code of Bob's public key to Bob
    2. Bob confirms that Alice has received the key he sent
    3. Alice signs Bob's key
  6. Exchange updated keys
    1. Alice e-mails Bob's updated key to him
    2. Bob e-mails Alice's updated key to her

Signing a Key

  • Use key ID "FEEDBEEF" to sign key ID "DEADC0DE"

Transcript

$ gpg -u FEEDBEEF --edit-key DEADC0DE
gpg (GnuPG) 1.4.9; Copyright (C) 2008 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

pub  2048R/DEADC0DE  created: 2010-04-20  expires: never       usage: SC  
                     trust: ultimate      validity: ultimate
sub  2048R/DEADBABE  created: 2010-04-20  expires: 2015-04-19  usage: E   
[ultimate] (1). My Friends Name (Some info) <my.friends@email.address>

Command> sign

pub  2048R/DEADC0DE  created: 2010-04-20  expires: never       usage: SC  
                     trust: ultimate      validity: ultimate
 Primary key fingerprint: xxxx xxxx xxxx xxxx xxxx  xxxx xxxx xxxx xxxx xxxx

     My Friends Name (Some info) <my.friends@email.address>

Are you sure that you want to sign this key with your
key "My Real Name <my.real@email.address>" (FEEDBEEF)

Really sign? (y/N) y

You need a passphrase to unlock the secret key for
user: "My Real Name <my.real@email.address>"
2048-bit RSA key, ID FEEDBEEF, created 2007-08-21

Enter passphrase:


Command> quit
Save changes? (y/N) y

$ gpg --list-sigs my.friends@email.address
pub   2048R/DEADC0DE 2010-04-20
uid                  My Friends Name (Some info) <my.friends@email.address>
sig 3        DEADC0DE 2010-04-20  My Friends Name (Some info) <my.friends@email.address>
sig          FEEDBEEF 2010-04-20  My Real Name <my.real@email.address>
sub   2048R/DEADBABE 2010-04-20 [expires: 2015-04-19]
sig          DEADC0DE 2010-04-20  My Friends Name (Some info) <my.friends@email.address>

Advanced Signatures

tsign

  • Signs a key and sets trust level
  • Depth 1 is a normal signature
  • Depth 2 is "Trusted Introducer"
  • Depth 3 is "Meta Introducer"
  • Setting trust depth of Keymaster to "Trusted Introducer" lets Agent automatically trust keys signed by the keymaster.
  • Can limit trust transitivity to a domain

Organisation Key-management

  • Merges web-of-trust and hierarchical trust models

Master Signing Key

  • Also called a keymaster key or corporate signing key.
  • The master key for the organisation. (keymaster@organisation)
  • Signs all agent keys (at normal trust level)
  • Signed by principal agents (directors, CIO) at "Trusted Introducer" level
  • Trusted by Agents at "Trusted Introducer" level, not feasible for every

Agent Keys

  • Held by all members of the organisation
  • Signed by the master signing key

Role UIDs

  • TODO
  • UID for each role (and associated contact address) within the organisation
  • Can be moved between Agent Keys (?)

Changing Roles

Example: Agent A leaves role R, Agent B takes over role R

  • Agent A deletes UID for role R (role@organisation)
  • Agent B adds UID for role R (role@organisation)
  • Keymaster resigns Agent A and Agent B keys.
  • Keymaster updates both keys on public keyservers??

Transcript

gpg> adduid
@Real name: Janitor UID
@Email address: janitor@email.address
@Comment: role:janitor
You selected this USER-ID:
    "Janitor UID (role:janitor) <janitor@email.address>"

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

You need a passphrase to unlock the secret key for
...

Signing Process

Preliminaries

  • New Agent generates a new Agent Key
  • Agent adds UIDs for organizational roles

Principal signs Keymaster

  • tsign
  • trust full
  • depth 2
  • domain my.organisation

Keymaster signs Agent Key

  • sign or tsign
  • trust marginal or full
  • depth 1

Agent sets Keymaster as trusted

  • trust, or tsign
  • trust full
  • depth 2
  • domain my.organisation

Transcript

  • Keymaster signs Agent Key

    gpg -u keymaster@my.organisation --edit-key FEEDBEEF

    gpg (GnuPG) 1.4.9; Copyright (C) 2008 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.

    Secret key is available.

    pub 2048R/FEEDBEEF created: 2010-04-20 expires: never usage: SC
    trust: ultimate validity: ultimate sub 2048R/FEEDBABE created: 2010-04-20 expires: 2015-04-19 usage: E
    ultimate. My Real Name (A Useful Comment) my.real@email.address

    Command> tsign

    pub 2048R/FEEDBEEF created: 2010-04-20 expires: never usage: SC
    trust: ultimate validity: ultimate Primary key fingerprint: xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx

     My Real Name (A Useful Comment) <my.real@email.address>
    

    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 trust marginally 2 = I trust fully

    Your selection? 1

    Please enter the depth of this trust signature. A depth greater than 1 allows the key you are signing to make trust signatures on your behalf.

    Your selection? 1

    Please enter a domain to restrict this signature, or enter for none.

    Your selection?

    Are you sure that you want to sign this key with your key "Keymaster keymaster@my.organisation" (C0DED00D)

    Really sign? (y/N) y

    You need a passphrase to unlock the secret key for user: "Keymaster keymaster@my.organisation" 2048-bit RSA key, ID C0DED00D, created 2010-04-20

    Command> quit Save changes? (y/N) y

Subkeys for Untrusted Devices

  • Debian Subkey article
  • See GnuPG Cross Certification
  • Secondary signing key only for day-to-day use or on vulnerable systems. (e.g. mobile phones)
    • Secret subkey import not supported by BouncyCastle
  • Add signing subkey
  • cross-certify

    gpg --edit-key $MASTER_KEY_ID

Transcript

$ gpg --edit-key $MASTER_KEY_ID
pub  2048R/$MASTER_KEY_ID  created: 2011-02-18  expires: never       usage: SC  
sub  2048R/$SUB_ENC_KEY  created: 2011-02-18  expires: 2015-04-19  usage: E   
2048-bit RSA key, ID $MASTER_KEY_ID, created 2011-02-18
pub  2048R/$MASTER_KEY_ID  created: 2011-02-18  expires: never       usage: SC  
sub  2048R/$SUB_ENC_KEY  created: 2011-02-18  expires: 2015-04-19  usage: E   
sub  2048R/$SUB_SIGN_KEY  created: 2011-02-18  expires: never       usage: S   
gpg (GnuPG) 1.4.10; Copyright (C) 2008 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

pub  2048R/$MASTER_KEY_ID  created: 2011-02-18  expires: never       usage: SC  
                     trust: ultimate      validity: ultimate
sub  2048R/$SUB_ENC_KEY  created: 2011-02-18  expires: 2015-04-19  usage: E   
[ultimate] (1). My Real Name <my.real@email.address>
[ultimate] (2)  My Other Name (Some info) <my.other.real@email.address>

Command> addkey
Key is protected.

You need a passphrase to unlock the secret key for
user: "My Real Name <my.real@email.address>"
2048-bit RSA key, ID $MASTER_KEY_ID, created 2011-02-18

Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
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) 
Key does not expire at all
Is this correct? (y/N) y
Really create? (y/N) y
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, use the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
.+++++
...+++++

pub  2048R/$MASTER_KEY_ID  created: 2011-02-18  expires: never       usage: SC  
                     trust: ultimate      validity: ultimate
sub  2048R/$SUB_ENC_KEY  created: 2011-02-18  expires: 2015-04-19  usage: E   
sub  2048R/$SUB_SIGN_KEY  created: 2011-02-18  expires: never       usage: S   
[ultimate] (1). My Real Name <my.real@email.address>
[ultimate] (2)  My Other Name (Some info) <my.other.real@email.address>

Command> cross-certify
subkey $SUB_ENC_KEY does not sign and so does not need to be cross-certified
signing subkey $SUB_SIGN_KEY is already cross-certified

Command> save
$

Exporting stripped keys

Export only one subkey (e.g. to a mobile device).

  • export public key $MASTER_KEY
  • export-secret-subkeys $SIGNING_SUBKEY_ID
# export public key, secret sub encrypt as a file 
gpg -a --export $MASTER_KEY_ID > master.pub

# export subkeys as a file encrypted with an OTP
gpg -a --export-secret-subkeys $SIGNING_SUBKEY_ID $ENCRYPTION_SUBKEY_ID | gpg --armor --symmetric --output mobile-subkeys.asc
  • transfer to device
  • decrypt and import
    • OpenKeychain for Android supports this

Links