Skip to content

Instantly share code, notes, and snippets.

@jonasfj
Created December 12, 2017 14:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonasfj/d0c0cbb63bf2eee74f229c4959bb0b88 to your computer and use it in GitHub Desktop.
Save jonasfj/d0c0cbb63bf2eee74f229c4959bb0b88 to your computer and use it in GitHub Desktop.
Decent links:
* https://github.com/drduh/YubiKey-Guide
* https://blog.josefsson.org/2014/06/23/offline-gnupg-master-key-and-subkeys-on-yubikey-neo-smartcard/
* http://stafwag.github.io/blog/blog/2015/06/16/using-yubikey-neo-as-gpg-smartcard-for-ssh-authentication/
* Or just google for gpg, yubikey, ssh, there is a lot of guides.
## The GPG setup
A gpg key is:
* (C) Master key , can certify/sign other keys.
* 3 sub-keys:
* (A) Authentication key , can authenticate you (example SSH)
* (S) Signing key , can sign messages
* (E) Encryption key , can decrypt messages
In theory you can have sub-keys per device, but multiple encryption keys (E) is a mess.
Limitations of this guide:
* We do 3 sub-keys, not a set of sub-keys per device, this is hard with:
* (E) encryption key
* (A) authentication key, as you would need to add all (serverside on SSH)
* We don't set expiration, you can if you want, but this is likely to cause pain.
(as you'll forget to renew the expiration, before it expires)
* I haven't found a way to moved a master key to a smartcard (yubikey), I'm not
sure it's supported by GPG. Maybe some other apps supports it.
---
Terminology:
* stripped key: means the secret key have been removed, but a reference indicating
that it exists remains. Example, you backup your master key and then delete it
from your installation, now it's stripped.
* stubbed key: means the secret key have been moved to a smartcard device (yubikey).
Instead of the secret RSA key there is now a stub referencing the serial number
of the yubikey holding it. Only the yubikey with matching serial number can be used.
We create:
* master key (C) + 3 sub-keys (A), (S), (E)
* `all-keys.txt` , containing all secret keys
* `master-key.txt` , containing the secret master key
* `sub-keys.txt` , containing stripped master key, and all secret sub-keys
* `key-stubs.txt` , containing stripped master key, and stub sub-keys
* `public-key.txt` , containing the public keys and identities
Note:
When GPG moves a key to your yubikey it keeps a stub key with a reference the
yubikey serial number. Hence, two yubikeys with the same private keys, can't
be used with the same machine without importing the other stubs (sad).
## Configure Yubikey
First enable CCID mode (this is often the case by default):
ykman mode 'OTP+U2F+CCID'
Edit the card to change PINs using:
gpg --card-edit
Use `admin` command to change "PIN" and "Admin PIN".
Default PIN: 12345678
Default Admin PIN: 123456 (Also called PUK code)
Typically, PIN will be required to use the card, often the card will remain
unlock for long time. Type PIN wrong 3 times and card will require Admin PIN.
Similarly, Admin PIN will be require to change preferences, keys and other things.
You can also play with setting a time out for when to require the PIN again,
or require touch, you can set it so that touch requirement can't be changed.
You can also change number of times PIN can be typed wrong, and what to do when
it happens, but these things are beyond this guide.
## How to build This Setup
Generate master key:
gpg --expert --gen-key
Choose (8) for RSA with custom capabilities
Remove capabilities for (S) signing, (E) encryption and (A) authentication if set
Keep (or set) capability for (C) certify
Make the key...
Export the master key:
gpg --export-secret-keys -a > master-key.txt
Add sub-keys:
gpg --expert --edit-key jopsen@gmail.com
Also add any additional identities like jonasfj@mozilla.com.
Now do `addkey` for (S) signing, (E) encryption and (A) authentication.
Then use the `save` command.
Export all-keys, sub-keys and public keys:
gpg --export-secret-subkeys -a > sub-keys.txt
gpg --export-secret-keys -a > all-key.txt
gpg --export -a > public-key.txt
Remove master key:
rm -rf .gnupg/
mkdir .gnupg
gpg-connect-agent /bye
gpgconf --reload scdaemon
Import sub-keys:
gpg --import sub-keys.txt
Move to card:
gpg --expert --edit-key jopsen@gmail.com
Use `key 1` to select the first subkey using `toggle` followed by `key 1`,
then use `keytocard`, repeat for all subkeys.
Once all subkeys are moved to the card export the key stubs:
gpg --export-secret-keys -a > key-stubs.txt
If you have multiple yubikeys, you can remove .gnupg and start over by importing
`sub-keys.txt` for each card. If you don't, you're done.
## Using GPG as SSH agent
**Background**, when you type `ssh <host>` into your terminal, your SSH client
connects to an ssh-agent over a unix domain socket. It is this ssh-agent that
reads your `~/.ssh` folder, unlocks your key and holds it in memory. This way:
* If your SSH client has a memory bug that leaks random memory, an attacker
can't steal your private key material, because it's in a different process.
* You can forward your ssh-agent to another machine (say a jump host), that way
you can using an SSH client on the other machines without copying your secret
key to a foreign machine (like a jump host).
* You can use a different ssh-agent than the default one, this is what we'll do.
When GPG is running on your system it also uses a gpg-agent, which holds your
private key material, similarly, the gpg client talks to the gpg-agent when it
wants to do an operation using the secret key material.
To **use gpg-agent as ssh-agent** you need to add:
echo 'enable-ssh-support' >> ~/.gnupg/gpg-agent.conf
Then restart your gpg-agent with `gpg-connect-agent reloadagent /bye`.
Or similar trick, `killall` should also do fine.
Note, you may have to logout and login again, or restart to get the correct
environment variables set. Or maybe even set them manually, notably you need to
see:
SSH_AUTH_SOCK=/home/<username>/.gnupg/S.gpg-agent.ssh
In your environment. On linux the system configuration is typically smart enough
to detect that you've enabled ssh support. But if not adding it to your `.profile`
might do the trick (you'll want it available to graphical applications too).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment