The Yubikey Neo is a very interesting piece of kit. It can generate secure passwords on the press of a button via a USB connection or by swiping over a NFC sensor. This allows it to be used as a second factor authentication for a variety of websites and services like Lastpass. I've previously blogged about getting a Yubikey working to authenticate a VPN tunnel with Netscreen SSG Firewalls linked to Active Directory and use it to secure my Lastpass account. However it can also be used as a CCID virtual smartcard for encrypting files with GPG and authenticating SSH connections in a very secure manner. Because your private key is stored on the Yubikey Neo and can not be removed this means that you can use it in less secure environments without the risk of your private key itself being compromised.
There are already lots of good guides on the net regarding how to do this if you are happy to generate your private keys on the Neo itself however this has one big drawback (which is also one of the big security features). A private key cannot be removed from the Neo. This means that if you generate the key on the Neo itself and then lose the Neo you have lost your only copy of that private key. In many cases this is good - you do not want anyone to "borrow" your Neo and copy your private keys. Generating new Keys can be done relatively easily. However if you already have a private key that you use in secure environments but also want the ability to access it elsewhere (maybe you have a private key you use personally which you want to also use at work but all the system administrators at your work can access your work file system for example) then I have not seen many guides for importing existing keys to the Neo. Partly this is because the firmware that comes with the Neo only supports generating keys on the device not importing. Once you hit software that needs compiling a lot of assumed knowledge can get in the way. So for a full walk-through of adding an existing key to a Neo read on:
Initial Linux Setup
The first thing you will need to do is get a Yubikey Neo (Sorry, it has to be the Neo for now - other Yubikeys do not include the ccid/GPG abilities).
For this guide I started with a fresh install of Debian 7.3.0 64 bit from the netinstall image and then upgraded to testing (from Wheezy to Jessie). I did not install the Desktop or Print Server components during install but if you do this with a desktop installation then it should not make much difference. Any recent Linux distro should work but writing this guide from a fresh install means you can reproduce my steps exactly if required. I had multiple issues with Gnupg 2.0.19 which is the version in Debian Stable which is why I upgraded to Testing which has version 2.0.22 (improved support for card readers).
The first step is therefore to install Debian Stable and check internet access is working. To upgrade to Debian Testing edit /etc/apt/sources.list and change every instance of the word wheezy to jessie. Then start the upgrade - this step will take a while.
To compile the new applet for installing on your Yubikey you will need:The first step is therefore to install Debian Stable and check internet access is working. To upgrade to Debian Testing edit /etc/apt/sources.list and change every instance of the word wheezy to jessie. Then start the upgrade - this step will take a while.
# apt-get updateAfter upgrading I always prefer to reboot to ensure there are no unexpected issues that will appear next time I turn the machine on. There are then a few packages that you need to install from the repositories so you might as well get them all now:
# apt-get dist-upgrade
- Accept warning about needing to uninstall a few packages that are blocking the upgrade, then later press q to close the screen of upgrade notices about various packages.
# aptitude install openjdk-6-jdk antTo compile the Yubikey Personalisation Tool you also need:
# aptitude install junit4
# aptitude install libyubikey-dev pkg-config libusb-1.0-0-dev libjson0-dev makeAnd to compile gpshell (for installing the new applet on the Neo) you need:
# apt-get install libpcsclite-dev zlib1g-dev libssl-devGPG version 2 is required for this:
# apt-get install gnupg2 scdaemonFinally to actually access the card you need pcsc:
# apt-get install pcscdDownload the Java Card Classic Development Kit from http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-javame-419430.html#java_card_kit-2.2.2-oth-JPR, then extract some of the files:
# mkdir jckit
# cd jckit
# unzip /path/to/java_card_kit-2_2_2-linux.zip
# cd java_card_kit-2_2_2/
# unzip java_card_kit-2_2_2-rr-bin-linux-do.zip
Compile the new Applet
Then you will need to download and compile an upgraded applet from https://github.com/Yubico/ykneo-openpgp/tree/features/jckit3. Download the applet source directly from https://github.com/Yubico/ykneo-openpgp/archive/master.zip, unzip and compile it.
# wget https://github.com/Yubico/ykneo-openpgp/archive/master.zipYou should now have a cap file in the sub folder applet/bin/openpgpcard/javacard/openpgpcard.cap
# unzip master.zip
# cd ykneo-openpgp-master
# ant -DJAVACARD_HOME=/path/to/jckit/java_card_kit-2_2_2/
Enable CCID mode on Neo
By default the Yubikey Neo does not have CCID smartcard functionality enabled, so that needs to be turned on. http://opensource.yubico.com/yubikey-personalization/
Note: If you want a slightly quicker way to do this then download the Windows version - it comes with a pre-compiled executable so you can jump straight to running the command.
# wget http://opensource.yubico.com/yubikey-personalization/releases/ykpers-1.15.0.tar.gz
# tar xvf ykpers-1.15.0.tar.gz
# cd ykpers-1.15.0
# ./configure
# make check install
# ldconfig
Plug in your Neo now - you are ready to enable the CCID functionality.
# ykpersonalize -m82
Confirm that you want to set mode 0x82 Take the NEO out and plug it back in to restart it in the new mode.
Install updated openPGP Applet on Neo
Download the gpshell, global platform and the gppcscconnectionplugin from http://sourceforge.net/projects/globalplatform/
# tar zxvf globalplatform-6.0.0.tar.gz
# cd globalplatform-6.0.0
# ./configure
# make
# make install
# cd ..
# tar zxvf gpshell-1.4.4.tar.gz
# cd gpshell-1.4.4
# ./configure
# make
# make install
# cd ..
# tar zxvf gppcscconnectionplugin-1.1.0.tar.gz
# cd gppcscconnectionplugin-1.1.0.tar.gz
# ./configure
# make
# make install
Unplug the Neo and plug it in again so it is detected correctly. Now you need to go back to the ykneo-openpgp-master folder (from when you compiled the applet) and install the applet on the Yubikey:
# LD_LIBRARY_PATH=/usr/local/lib gpshell gpinstall.txtYou should be rewarded with several screens of text rushing by.
Prepare GPG key and back it up
The Yubikey NEO can support GPG keys up to 2048 bit RSA - bigger keys will not fit. A lot of people store their main key offline and generate encryption and signing subkeys which they import onto a card for day to day use. This has the advantage that if the card is lost they can just generate new encryption and signing subkeys and their main GPG identity will not lose all the signatures which validate their real identity. Another advantage is that the main key can then be 4096 bits in strength (if you are that paranoid) and the subkeys only 2048 bit so they fit on the The certification part of the key is not present however so they will not be able to certify any other persons key is genuine without getting access to their main/full key.
By default GPG will create 2 keys - the first is used for signing (files) and certifying (other GPG keys). The second is used for Encryption. I'm going to create a new subkey for signing so only this goes onto the Yubikey. Gpg outputs a lot of text and this post feels big enough already so I'm going to skip most of the output - you will get far more on your screen than is shown here.
First to add a new signing key of 2048 bit size. My main key ID in this example is 3edda8ae - change this for your ID:
Final step before you move the keys to the Neo is to back them all up. If you do not want to trap your only copy of the private key on a Neo then back it up first! Once more because this step is important: BACK UP YOUR KEYS!
Move these backup files somewhere safe - you do not want to accidentally overwrite or delete them. Next lets put the encryption subkey onto the Yubikey (you need to pulg the Yubikey in now if it is not already):
Next we need to move the signing key to the NEO:
As a quick test remove the Neo. Encrypt a random file to this new key and then try to decrypt it - you will get an error:
You can now backup the private key from your computer (which only contains a stub of the full private key). This stub and the public key you saved earlier can be manually imported on any other computer without risking loss of control of your keys as you also need the Yubikey connected to use it.
From your working computer:
If however you do not want to upload this key to the public keyservers you can upload it to a specific url and program the NEO to look there. The --armor switch below instructs gpg to only use a character set that is safe to use in emails (mail programs have a habit of treating some obscure characters inconsistently which is not good if those characters are in the middle of your key!
# gpg2 --armor --export 3edda8ae > public_key_armor.key
Upload this file to anywhere you control and make a note of the direct link to the file. I uploaded to my Dropbox account so for me the file was accessible at https://dl.dropboxusercontent.com/u/120364/public_key_armor.key. We need to add this link to the URL field of the NEO:
Trying to list keys will now just show GPG creating new keyring files:
:~/.gnupg# gpg2 --list-keys
gpg: keyring `/root/.gnupg/pubring.gpg' created
gpg: /root/.gnupg/trustdb.gpg: trustdb created
Time to fetch the public key. Plug in the NEO and run the following commands:
By default GPG will create 2 keys - the first is used for signing (files) and certifying (other GPG keys). The second is used for Encryption. I'm going to create a new subkey for signing so only this goes onto the Yubikey. Gpg outputs a lot of text and this post feels big enough already so I'm going to skip most of the output - you will get far more on your screen than is shown here.
First to add a new signing key of 2048 bit size. My main key ID in this example is 3edda8ae - change this for your ID:
# gpg2 --edit-key 3edda8aeYou should now be able to see the extra line ending in "usage: S" to denote the signing only key. If you are using an existing key and the Encryption key is not shown as "sub 2048R" then you will need to create a new encryption subkey as above but choosing "RSA (encrypt only) as the type.
pub 2048R/3EDDA8AE created: 2014-03-14 expires: never usage: SC
trust: ultimate validity: ultimate
sub 2048R/581671D8 created: 2014-03-14 expires: never usage: E
[ultimate] (1). test key (test 2048R key) <[email protected]>
gpg> addkey
Please enter the passphrase to unlock the secret key: *****
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
What keysize do you want? (2048) 2048
Key is valid for? (0) 1y
Is this correct? (y/N) y
Really create? (y/N) y
pub 2048R/3EDDA8AE created: 2014-03-14 expires: never usage: SC
trust: ultimate validity: ultimate
sub 2048R/581671D8 created: 2014-03-14 expires: never usage: E
sub 2048R/5B48E4AF created: 2014-03-14 expires: 2015-03-14 usage: S
[ultimate] (1). test key (test 2048R key) <[email protected]>
Final step before you move the keys to the Neo is to back them all up. If you do not want to trap your only copy of the private key on a Neo then back it up first! Once more because this step is important: BACK UP YOUR KEYS!
gpg> save
# gpg2 --export -a 3edda8ae >public_key_backup.key
# gpg2 --export-secret-key -a 3edda8ae > private_key_backup.key
# ls
private_key_backup.key public_key_backup.key
Move these backup files somewhere safe - you do not want to accidentally overwrite or delete them. Next lets put the encryption subkey onto the Yubikey (you need to pulg the Yubikey in now if it is not already):
Move the keys to the Neo
# gpg2 --edit-key 3edda8ae
gpg> toggle"key 1" selects the first subkey (it is shown with an asterisk). "keytocard" MOVES the selected subkey to the card after you have confirmed both the gpg pass-phrase as well as the card administrator pin. There is only one slot to store this kind of key so you need to choose option 2. Finally the keys are shown but with the encryption key having a card number underneath it to show it is no longer present on the computer.
sec 2048R/3EDDA8AE created: 2014-03-14 expires: never
ssb 2048R/581671D8 created: 2014-03-14 expires: never
ssb 2048R/5B48E4AF created: 2014-03-14 expires: 2015-03-14
(1) test key (test 2048R key) <[email protected]>
gpg> key 1
sec 2048R/3EDDA8AE created: 2014-03-14 expires: never
ssb* 2048R/581671D8 created: 2014-03-14 expires: never
ssb 2048R/5B48E4AF created: 2014-03-14 expires: 2015-03-14
(1) test key (test 2048R key) <[email protected]>
gpg> keytocard
Please select where to store the key:
(2) Encryption key
Your selection?
2
Please enter the passphrase to unlock the secret key: *****
scdaemon[22389]: 3 Admin PIN attempts remaining before card is permanently locked
Please enter the Admin PIN: *****
writing new key
sec 2048R/3EDDA8AE created: 2014-03-14 expires: never
ssb* 2048R/581671D8 created: 2014-03-14 expires: never
card-no: 0000 00000001
ssb 2048R/5B48E4AF created: 2014-03-14 expires: 2015-03-14
(1) test key (test 2048R key) <[email protected]>
Next we need to move the signing key to the NEO:
gpg> key 1"key 1" deselects the first (encryption) subkey, then "key 2" selects the second (signing) subkey. "keytocard" is used to MOVE the signing subkey to the NEO. Finally quit saving changes.
gpg> key 2
sec 2048R/3EDDA8AE created: 2014-03-14 expires: never
ssb 2048R/581671D8 created: 2014-03-14 expires: never
card-no: 0000 00000001
ssb* 2048R/5B48E4AF created: 2014-03-14 expires: 2015-03-14
(1) test key (test 2048R key) <[email protected]>
gpg> keytocard
Please select where to store the key:
(1) Signature key
(3) Authentication key
Your selection? 1
Please enter the passphrase to unlock the secret key: *****
writing new key
sec 2048R/3EDDA8AE created: 2014-03-14 expires: never
ssb 2048R/581671D8 created: 2014-03-14 expires: never
card-no: 0000 00000001
ssb* 2048R/5B48E4AF created: 2014-03-14 expires: 2015-03-14
card-no: 0000 00000001
(1) test key (test 2048R key) <[email protected]>
gpg> quit
Save changes? (y/N) y
As a quick test remove the Neo. Encrypt a random file to this new key and then try to decrypt it - you will get an error:
# echo "my secret message" > test.txtNow plug the NEO in again and run exactly the same command:
# gpg2 -r test -e test.txt
# ls
test.txt test.txt.gpg
# gpg -d test.txt.gpg
gpg: pcsc_list_readers failed: unknown PC/SC error code (0x8010002e)
gpg: card reader not available
gpg: encrypted with 2048-bit RSA key, ID 581671D8, created 2014-03-14
"test key (test 2048R key) <[email protected]>"
gpg: public key decryption failed: general error
gpg: decryption failed: secret key not available
# gpg -d test.txt.gpg
gpg: detected reader `Yubico Yubikey NEO OTP+CCID 00 00'
Please enter the PIN
Enter PIN:
*****
gpg: encrypted with 2048-bit RSA key, ID 581671D8, created 2014-03-14
"test key (test 2048R key) <[email protected]>"
my secret message
The output at the end will be the secret message you added to test.txt. This would only be possible to decrypt with the NEO plugged in, as only a stub of the private encryption key is stored on the local hard drive.
You can now backup the private key from your computer (which only contains a stub of the full private key). This stub and the public key you saved earlier can be manually imported on any other computer without risking loss of control of your keys as you also need the Yubikey connected to use it.
From your working computer:
# gpg2 --export-secret-key -a 3edda8ae > private_key_backup_STUB.keyCopy those 2 files to another computer and import them with:
# gpg2 --import public_key_backup.keyYou can make life a bit easier in 2 ways. Firstly if you upload your key to a keyserver then you can automatically pull down the required files with this command (after plugging in the NEO):
# gpg2 --allow-secret-key-import --import private_key_backup_STUB.key
# gpg2 --card-edit
gpg/card> fetch
If however you do not want to upload this key to the public keyservers you can upload it to a specific url and program the NEO to look there. The --armor switch below instructs gpg to only use a character set that is safe to use in emails (mail programs have a habit of treating some obscure characters inconsistently which is not good if those characters are in the middle of your key!
# gpg2 --armor --export 3edda8ae > public_key_armor.key
Upload this file to anywhere you control and make a note of the direct link to the file. I uploaded to my Dropbox account so for me the file was accessible at https://dl.dropboxusercontent.com/u/120364/public_key_armor.key. We need to add this link to the URL field of the NEO:
# gpg2 --card-editYou can check this worked as expected by running gpg2 --card-status and checking the output now contains your URL. To make this a decent test I am going to delete the entire local public and private keyring files, then import the keys using the NEO and online public file before repeating the encryption test I performed earlier to prove decryption only works with the NEO installed. First to delete the local files:
Application ID ...: D2760001240102000000000000010000
Version ..........: 2.0
Manufacturer .....: test card
Serial number ....: 00000001
Name of cardholder: [not set]
Language prefs ...: [not set]
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: [not set]
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 ....: 26EF 14F4 A5B6 B24A 0EFE E39C F5E2 68CB 5B48 E4AF
created ....: 2014-03-14 16:56:48
Encryption key....: CFA0 0AE0 1C27 0463 36DE 2960 0FBF CAD4 5816 71D8
created ....: 2014-03-14 16:22:28
Authentication key: [none]
General key info..:
pub 2048R/5B48E4AF 2014-03-14 test key (test 2048R key) <[email protected]>
sec 2048R/3EDDA8AE created: 2014-03-14 expires: never
ssb> 2048R/581671D8 created: 2014-03-14 expires: never
card-no: 0000 00000001
ssb> 2048R/5B48E4AF created: 2014-03-14 expires: 2015-03-14
card-no: 0000 00000001
gpg/card> admin
Admin commands are allowed
gpg/card> url
URL to retrieve public key: https://dl.dropboxusercontent.com/u/120364/public_key_armor.key
scdaemon[2887]: 3 Admin PIN attempts remaining before card is permanently locked
Please enter the Admin PIN :
gpg/card> quit
# cd .gnupg/
:~/.gnupg# ls
gpg.conf private-keys-v1.d pubring.gpg pubring.gpg~ random_seed reader_0.status secring.gpg trustdb.gpg
:~/.gnupg# rm pub ring.gpg
:~/.gnupg# rm pubring.gpg~ :~/.gnupg# rm secring.gpg :~/.gnupg# rm trustdb.gpg
Trying to list keys will now just show GPG creating new keyring files:
:~/.gnupg# gpg2 --list-keys
gpg: keyring `/root/.gnupg/pubring.gpg' created
gpg: /root/.gnupg/trustdb.gpg: trustdb created
Time to fetch the public key. Plug in the NEO and run the following commands:
:~/.gnupg# gpg2 --card-edit
gpg: keyring `/root/.gnupg/secring.gpg' created
scdaemon[3125]: reading public key failed: Card error
Application ID ...: D2760001240102000000000000010000
Version ..........: 2.0
<SNIP extra info>
Sex ..............: unspecified
URL of public key : https://dl.dropboxusercontent.com/u/120364/public_key_armor.key
Login data .......: [not set]
<SNIP extra info>
gpg/card> fetch
gpg: requesting key 5B48E4AF from https server dl.dropboxusercontent.com
gpg: key 3EDDA8AE: public key "test key (test 2048R key) <[email protected]>" imported
gpg: Total number processed: 1
gpg: imported: 1 (RSA: 1)
gpg/card> quit
You can now try encrypting a message to your private key and it will only decrypt if the NEO is plugged in:
# echo "my secret message encrypted to NEO key" > test_file_Neo.txtCongratulations! Firstly for reading through everything above (assuming you didn't cheat and skip all the way down here!) You should now have a GPG key which you can use relatively easily on any computer with GPG but you do not need to place the private key on that computer. For me this means I can freely use my personal GPG key on work computers without any chance of losing control of a copy, but it could just as easily be that you want to protect your work GPG key when visiting client sites.
# gpg2 -r test -e test_file_Neo.txt
# gpg2 -d test_file_Neo.txt.gpg
scdaemon[3285]: DBG: asking for PIN '||Please enter the PIN'
"test key (test 2048R key) <[email protected]>"
my secret message encrypted to NEO key
Changing the user and admin pin on the NEO
Use of the gpg key stored on the NEO requires you to enter a pin code (default is normally 123456). Getting the pin code wrong 3 times locks the user pin. The default admin pin is normally 12345678. Getting the admin pin code wrong 3 times will lock the card and cannot be reset. Make sure you remember these pin codes!use the "gpg --change-pin" command and change both the user and admin pin to something you will remember:
# gpg2 --change-pin
gpg: detected reader `Yubico Yubikey NEO OTP+CCID 00 00'
gpg: OpenPGP card no. D2760001240102000000000000010000 detected
1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit
Other things to do
There are several other things you should do to if you have not already:- Generate revocation certificates
- Upload to public keyservers
- Store your key backups somewhere secure and offsite
- Use the Neo to authenticate SSH connections (good guide at http://www.bradfordembedded.com/2013/12/yubikey-smartcard/)
Problems...
There are a few problems that are worth bearing in mind when following this guide depending on how secure you want your end result to be.Randomness matters. A computer builds up a pool of entropy from various sources during use. This entropy is then used by /dev/random when anything needs random numbers - however on a clean install with no extra software running that has probably only just booted up there is not much entropy to go around. This could lead to weak keys being generated. A program like haveged may well eliminate this problem if you can not use a genuine hardware random number generator like the Entropykey (I know nothing about this project beyond the fact is looks cool and is reasonably cheap).
By using Debian Testing I am also using a system with less immediate security patching. Stable Debian receives security patches very quickly and Unstable Debian also receives them quickly (but then it receives everything quickly, including patches, new software and new bugs/security problems - that is why it is called "Unstable" Testing Debian tends to receive updates after they have been tested a for a while and have no known serious bugs so sometimes a security problem might be unpatched on Testing after both Stable has been patched and Unstable has received a newer version that also fixes the problem. Alternatives if you are concerned - gnupg 2.0.22 is not in Debian Backports so you could either manually install packages from the Debian Jessie repository or use a different distro with a later version of gnupg. Or compile gnupg from source if you were feeling adventurous.
I did all this as the root user. Normally bad but in my defense: A lot of this had to be done as root anyway, you need to trust the system you are generating the keys on completely (eg don't use if for browsing facebook!) and you have to trust the software you are installing completely. Since I'm using a fresh minimal install and not connecting to random internet sites the risks are minimized.
Troubleshooting
Yubikey Neo not recognised as a CCID device.
If you are using an older distro that does not fully recognise the Yubikey Neo as a ccid device then you need to take a few more steps:
A Debian Wheezy install I have been using does not know that the Yubikey can be a smart card. Not too hard to fix though: edit /etc/libccid_Info.plist. You need to add two lines at the top of 3 sections.
Find array ifdVendorID and add the following two lines at the top:
Find array ifdVendorID and add the following two lines at the top:
<string>0x1050</string>Find array ifdProductID and add the following two lines at the top:
<string>0x1050</string>
<string>0x0111</string>Find array ifdFriendlyName and add the following two lines at the top:
<string>0x0112</string>
<string>YubiKey Neo Composite</string>
<string>YubiKey Neo CCID</string>
Restart the service:
Unplug and replug the neo and the output of dmesg should now include "Yubikey NEO OTP+CCID"/etc/init.d/pcscd restart
Guides used to create this guide:
Far too many web pages to list fully, but the main sources of information I used were:
https://github.com/Yubico/ykneo-openpgp
https://github.com/Yubico/ykneo-openpgp
Yubico Forums eg: Adding the Yubikey Neo to known hardware (not required in the end as I switched to Debian Testing) http://forum.yubico.com/viewtopic.php?f=26&t=982&start=10#p3767
Creating subkeys and seperating out from the main key for security reasons: http://www.void.gr/kargig/blog/2013/12/02/creating-a-new-gpg-key-with-subkeys/
How to add GPG keys to cards: http://www.gnupg.org/howtos/card-howto/en/ch05.html
If you have any comments or suggestions then please let me know.
Creating subkeys and seperating out from the main key for security reasons: http://www.void.gr/kargig/blog/2013/12/02/creating-a-new-gpg-key-with-subkeys/
How to add GPG keys to cards: http://www.gnupg.org/howtos/card-howto/en/ch05.html
If you have any comments or suggestions then please let me know.