Created
December 12, 2017 14:36
-
-
Save jonasfj/d0c0cbb63bf2eee74f229c4959bb0b88 to your computer and use it in GitHub Desktop.
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
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 [email protected] | |
Also add any additional identities like [email protected]. | |
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 [email protected] | |
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