Last active
January 27, 2016 05:23
-
-
Save arrjay/646d9b32d7f44566588b to your computer and use it in GitHub Desktop.
my dual-card gpg setup
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
My two-card, multiple encryption key GPG setup | |
============================================== | |
This document walks through setting up a GPG keyring that uses two smartcards to hold | |
two *different* authentication and encryption keys, linked to a single identity. This | |
keeps a master identity separate from either smart card, so if you need to revoke one | |
later, it is fairly easy to do. This document assumes you are working with an offline | |
computer, preferably one with it's own disk encryption setup. | |
First Steps | |
----------- | |
- Set up GPG - see included gpg.conf | |
- (Preference) I create a private git repo on the gpg-keying box to checkpoint operations | |
in case I need to revert one. | |
$ gpg -k | |
(should produce no keys output) | |
$ cd ~/.gnupg | |
$ cp [gpg.conf] gpg.conf | |
$ git init . | |
$ git add pubring.gpg secring.gpg trustdb.gpg | |
$ git commit -m "initial (blank keyrings)" | |
$ cd ~ | |
Generate a GPG identity key | |
--------------------------- | |
$ gpg --expert --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) | |
(7) DSA (set your own capabilities) | |
(8) RSA (set your own capabilities) | |
Your selection? | |
> Enter 8 | |
Possible actions for a RSA key: Sign Certify Encrypt Authenticate | |
Current allowed actions: Sign Certify Encrypt | |
(S) Toggle the sign capability | |
(E) Toggle the encrypt capability | |
(A) Toggle the authenticate capability | |
(Q) Finished | |
Your selection? | |
> Enter S, E, Q (we only want the certify flag) | |
RSA keys may be between 1024 and 4096 bits long. | |
What keysize do you want? (2048) | |
> Enter 4096 | |
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) | |
> Enter 3y | |
Key expires at [DATE] [TZ] | |
Is this correct? (y/N) | |
> Enter y | |
GnuPG needs to construct a user ID to identify your key. | |
Real name: | |
> Enter (Your Name) | |
Email address: | |
> Enter (an email address you use. you can add more later.) | |
Comment: | |
> Enter (LEAVE BLANK!) | |
You will now enter and verify a passphrase. You should probably write this down and store it | |
offline. | |
(Wait for gpg to gather entropy) | |
gpg: key 0xFF8383600C7C8D79 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 NNNN-NN-NN | |
pub 4096R/0xHHHHHHHHHHHHHHHH NNNN-NN-NN [expires: NNNN-NN-NN] | |
Key fingerprint = HHHH HHHH HHHH HHHH HHHH HHHH HHHH HHHH HHHH HHHH | |
uid [ultimate] (Your Name) <(Email)> | |
$ cd ~/.gnupg | |
$ git commit -a -m "created initial key" | |
Add additional email addresses | |
------------------------------ | |
I prefer adding any additional emails before mucking with | |
$ gpg --edit-key (your email) | |
gpg> adduid | |
Real name: | |
> Enter (Your Name) | |
Email address: | |
> Enter (the email address you are adding) | |
Comment: | |
> Enter (LEAVE BLANK!) | |
You will now enter your passphrase to update the key. | |
gpg> save | |
$ cd ~/.gnupg | |
$ git commit -a -m "added identities" | |
A note about smartcards | |
----------------------- | |
Some of my smartcards can hold 4096-bit keys, and some can only hold 2048-bit keys. You can | |
only load a key of equal or lesser size into a smartcard - keep this in mind when generating | |
new subkeys! | |
Here's an easy way to check: | |
$ gpg --card-status|grep "Key attributes" | |
Key attributes ...: 2048R 2048R 2048R | |
$ | |
The above card can only hold 2048-bit keys. A card which can hold 4096-bit keys will say 4096 | |
in the attribute line. There are also some cards that hold 3072-bit keys, but I don't have one. | |
Generate Subkeys | |
---------------- | |
I made 5 subkeys, but you can make as many as you want at this point. The tricky part is | |
only having one type flag per-key, for loading on to smart cards. | |
$ gpg --expert --edit-key (your email) | |
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? | |
> E, Q (for a Signing key) | |
> S, Q (for an Encryption key) | |
> S, E, A, Q (for an Authtication key) | |
RSA keys may be between 1024 and 4096 bits long. | |
What keysize do you want? (2048) | |
> (this answer is dependent on your car capabilities, see above!) | |
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) | |
> (if you set an expiry on your main key, you will probably want this to expire sooner) | |
gpg> | |
[at this point, you can addkey until you have all your subkeys] | |
gpg> save | |
$ cd ~/.gnupg | |
$ git commit -a -m "added subkeys" | |
Generate master revocation | |
-------------------------- | |
$ gpg --gen-revoke (your email) > master-key-revocation.asc | |
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? | |
> (I actually use reason 2 here, since your master key should continue to be offline!) | |
Enter an optional description; end it with an empty line: | |
> (left it blank) | |
$ | |
(Leave the file on the offline box - you only need it if you want to stop using your key) | |
Moving keys to multiple cards | |
----------------------------- | |
The easiest way to do this is export all your private keys, populate the first card, then | |
reimport all your private keys and populate the second card. Finally, remove all the | |
private keys and reintroduce the key stubs using gpg --card-status. | |
Initializing a Card | |
------------------- | |
$ gpg --card-edit | |
gpg/card> admin | |
gpg/card> lang | |
Language preferences: en | |
gpg/card> passwd | |
gpg: OpenPGP card no. NNNNNNNNNNN detected | |
1 - change PIN | |
2 - unblock PIN | |
3 - change Admin PIN | |
4 - set the Reset Code | |
Q - quit | |
Your selection? 3 | |
(first enter the existing admin pin, then the new one + verify) | |
PIN changed. | |
Your selection? 1 | |
(first enter the existing pin, then the new one + verify) | |
PIN changed. | |
Your selection? Q | |
gpg/card> quit | |
Moving a key to a card | |
---------------------- | |
$ gpg --edit-key (your email) | |
gpg> toggle | |
gpg> key (key number to move, pick one at a time) | |
gpg> keytocard | |
(you are then asked for the card slot to store the key in. match the appropriate key type.) | |
(then enter the admin pin...) | |
gpg> key | |
gpg> key (some other slot) | |
gpg> keytocard | |
[...] | |
Generating a multi-card private keyring | |
--------------------------------------- | |
After deleting all the private keys, import just the public key, then run gpg --card-status | |
with the first card inserted. | |
$ mkdir gpg-card1 gpg-card2 gpg-allcards | |
$ cd gpg-card1 | |
$ gpg --card-status | |
$ gpg --export-secret-keys (your email) | gpgsplit -v | |
$ gpg --delete-secret-keys (your email) | |
(swap cards) | |
$ cd ../gpg-card2 | |
$ gpg --card-status | |
$ gpg --export-secret-keys (your email) | gpgsplit -v | |
$ gpg --delete-secret-keys (your email) | |
$ cd ../gpg-allcards | |
Now, I don't have a great way of determining which subkeys you need for the keygrips. | |
I was able to work it out from the output of gpg -K while a card was loaded and pull in the | |
appropriate .secret_subkey files... | |
$ cp ../gpg-card1/* . | |
$ cp ../gpg-card2/000016*.secret_subkey . | |
$ cp ../gpg-card2/000014*.secret_subkey . | |
$ cat * | gpg --import | |
If you did this right, you should have ssb> for all your subkeys! If you're feeling bold, | |
you can export this private keyring to github! All it contains is the grips for smartcards. | |
Problems | |
-------- | |
I replaced a card, and ssh consistently asked for the old card unlocking the auth key - easiest fix is to drop all your private keys (your entire .gnupg dir, really) and reimport the new stubs. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# This is an implementation of the Riseup OpenPGP Best Practices | |
# https://help.riseup.net/en/security/message-security/openpgp/best-practices | |
# | |
#----------------------------- | |
# behavior | |
#----------------------------- | |
# Disable inclusion of the version string in ASCII armored output | |
no-emit-version | |
# Disable comment string in clear text signatures and ASCII armored messages | |
no-comments | |
# Display long key IDs | |
keyid-format 0xlong | |
# List all keys (or the specified ones) along with their fingerprints | |
with-fingerprint | |
# Display the calculated validity of user IDs during key listings | |
list-options show-uid-validity | |
verify-options show-uid-validity | |
# Try to use the GnuPG-Agent. With this option, GnuPG first tries to connect to | |
# the agent before it asks for a passphrase. | |
use-agent | |
#----------------------------- | |
# keyserver | |
#----------------------------- | |
# This is the server that --recv-keys, --send-keys, and --search-keys will | |
# communicate with to receive keys from, send keys to, and search for keys on | |
keyserver hkps://hkps.pool.sks-keyservers.net | |
# Provide a certificate store to override the system default | |
# Get this from https://sks-keyservers.net/sks-keyservers.netCA.pem | |
keyserver-options ca-cert-file=/usr/local/etc/ssl/certs/hkps.pool.sks-keyservers.net.pem | |
# Set the proxy to use for HTTP and HKP keyservers - default to the standard | |
# local Tor socks proxy | |
# It is encouraged to use Tor for improved anonymity. Preferrably use either a | |
# dedicated SOCKSPort for GnuPG and/or enable IsolateDestPort and | |
# IsolateDestAddr | |
#keyserver-options http-proxy=socks5-hostname://127.0.0.1:9050 | |
# Don't leak DNS, see https://trac.torproject.org/projects/tor/ticket/2846 | |
keyserver-options no-try-dns-srv | |
# When using --refresh-keys, if the key in question has a preferred keyserver | |
# URL, then disable use of that preferred keyserver to refresh the key from | |
keyserver-options no-honor-keyserver-url | |
# When searching for a key with --search-keys, include keys that are marked on | |
# the keyserver as revoked | |
keyserver-options include-revoked | |
#----------------------------- | |
# algorithm and ciphers | |
#----------------------------- | |
# list of personal digest preferences. When multiple digests are supported by | |
# all recipients, choose the strongest one | |
personal-cipher-preferences AES256 AES192 AES CAST5 | |
# list of personal digest preferences. When multiple ciphers are supported by | |
# all recipients, choose the strongest one | |
personal-digest-preferences SHA512 SHA384 SHA256 SHA224 | |
# message digest algorithm used when signing a key | |
cert-digest-algo SHA512 | |
# This preference list is used for new keys and becomes the default for | |
# "setpref" in the edit menu | |
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment