This post describes setup and example usages of Smartcard with a Thinkpad's onboard reader and OpenPGP to handle keys for authentication and encryption.
Your master key will be stored (securely I hope) on a USB drive and rarely used, with your Smart Card containing a couple of subkeys which will be used to sign and authenticate day-to-day.
At the end of the guide you should have a master key securely stored on a USB key, a hard-copy of revocation certificate, some sub-keys stored on your Smart Card and some knowledge about how to use it to emails, and authenticate via ssh:
There are already very technical guides on how to set this up like the one on jclement.ca which steps 1-5 heavily lean on but even if you're pretty tech-savvy you may end up not 100% understanding exactly what you've actually done.
I got my Smart Card by becoming a member of the EFSF fellowship or by picking up another OpenPGP smartcard (or a YubiKey if you don't have a reader, here).
Step 1. Securely create and boot from a Debian Live USB image
Download and verify a Debian live image per my previous guide here. We can now flash the USB key we're going to boot from:
$ sudo dd bs=4M if=./debian-live-8.3.0-amd64-xfce-desktop+nonfree.iso of=/dev/sdb && sync 272+0 records in 272+0 records out 1140850688 bytes (1.1 GB) copied, 214.052 s, 5.3 MB/s
Step 2. Setup the packages
$ sudo apt-get install haveged gnupg2 gnupg-agent libpth20 pinentry-curses libccid pcscd scdaemon libksba8 paperkey opensc jpegoptim xloadimageChange the configuration file for GnuPG so that it uses a different, stronger set of ciphers by default:
$ mkdir ~/.gnupg $ cat > ~/.gnupg/gpg.conf << ! no-emit-version no-comments keyid-format 0xlong with-fingerprint use-agent personal-cipher-preferences AES256 AES192 AES CAST5 personal-digest-preferences SHA512 SHA384 SHA256 SHA224 cert-digest-algo SHA512 default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed !
At this point jclement.ca advise that you disconnect from the network - which is probably a good idea since we're about to generate a handful of keys and we don't want anything to leak.
What we're going to do is create a Master Key - which will be stored on a USB drive - and then use it to create a handful of Sub Keys which will be stored on the Smart Card for day-to-day use. Since the Sub Keys could conceivably be compromised we'll generate a revocation certificate which we can use to notify everyone that they should no longer be trusted - at this point we'd generate a new set of Sub Keys and load them onto our card.
Since there are a number of utilities and technologies you may not be familiar with I'm going to show a diagram at the end of each step in the key-creation process to help visualise what exactly is going on where. Here's a little diagram showing what symbols I'll be using.
Step 3. Creating the Master Key
$ gpg2 --gen-key gpg (GnuPG) 2.0.26; Copyright (C) 2013 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. gpg: keyring `/home/sean/.gnupg/secring.gpg' created gpg: keyring `/home/sean/.gnupg/pubring.gpg' created 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) Your selection? 4 RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (2048) 4096 Requested keysize is 4096 bits Please specify how long the key should be valid. 0 = key does not expire = key expires in n days w = key expires in n weeks m = key expires in n months y = key expires in n years Key is valid for? (0) 0 Key does not expire at all Is this correct? (y/N) y GnuPG needs to construct a user ID to identify your key. Real name: Sean McLemon Email address: sean.mclemon@gmail.com Comment: You selected this USER-ID: "Sean McLemon " Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O You need a Passphrase to protect your secret key. 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: /home/sean/.gnupg/trustdb.gpg: trustdb created gpg: key 0xC87419541EAC16A8 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 pub 4096R/0xC87419541EAC16A8 2016-04-01 Key fingerprint = D90B 2575 6FD3 D781 A856 9AE3 C874 1954 1EAC 16A8 uid [ultimate] Sean McLemon 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.
And add a pic:
$ gpg2 --edit-key 0xC87419541EAC16A8 gpg (GnuPG) 2.0.26; Copyright (C) 2013 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 4096R/0xC87419541EAC16A8 created: 2016-04-01 expires: never usage: SC trust: ultimate validity: ultimate [ultimate] (1). Sean McLemon gpg> addphoto Pick an image to use for your photo ID. The image must be a JPEG file. Remember that the image is stored within your public key. If you use a very large picture, your key will become very large as well! Keeping the image close to 240x288 is a good size to use. Enter JPEG filename for photo ID: test.jpg Is this photo correct (y/N/q)? y You need a passphrase to unlock the secret key for user: "Sean McLemon " 4096-bit RSA key, ID 0xC87419541EAC16A8, created 2016-04-01 pub 4096R/0xC87419541EAC16A8 created: 2016-04-01 expires: never usage: SC trust: ultimate validity: ultimate [ultimate] (1). Sean McLemon [ unknown] (2) [jpeg image of size 746] gpg> save
Step 4. Creating the Sub Keys
A bit of a better explanation of Sub Keys is at https://wiki.debian.org/Subkeys. Remember, these are the keys we'll be using day-to-day and will be stored on our Smart Card.
$ gpg2 --expert --edit-key 0xC87419541EAC16A8 gpg (GnuPG) 2.0.26; Copyright (C) 2013 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. 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 pub 4096R/0xC87419541EAC16A8 created: 2016-04-01 expires: never usage: SC trust: ultimate validity: ultimate [ultimate] (1). Sean McLemon [ultimate] (2) [jpeg image of size 746] gpg> addkey Key is protected. You need a passphrase to unlock the secret key for user: "Sean McLemon " 4096-bit RSA key, ID 0xC87419541EAC16A8, created 2016-04-01 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? 4 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 = key expires in n days w = key expires in n weeks m = key expires in n months y = key expires in n years Key is valid for? (0) 6m Key expires at Wed 28 Sep 2016 21:41:58 CEST 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 4096R/0xC87419541EAC16A8 created: 2016-04-01 expires: never usage: SC trust: ultimate validity: ultimate sub 2048R/0x191900DBF062921B created: 2016-04-01 expires: 2016-09-28 usage: S [ultimate] (1). Sean McLemon [ultimate] (2) [jpeg image of size 746] gpg> addkey Key is protected. You need a passphrase to unlock the secret key for user: "Sean McLemon " 4096-bit RSA key, ID 0xC87419541EAC16A8, created 2016-04-01 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? 6 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 = key expires in n days w = key expires in n weeks m = key expires in n months y = key expires in n years Key is valid for? (0) 6m Key expires at Wed 28 Sep 2016 21:42:14 CEST 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 4096R/0xC87419541EAC16A8 created: 2016-04-01 expires: never usage: SC trust: ultimate validity: ultimate sub 2048R/0x191900DBF062921B created: 2016-04-01 expires: 2016-09-28 usage: S sub 2048R/0x46BDB50E980A2B9B created: 2016-04-01 expires: 2016-09-28 usage: E [ultimate] (1). Sean McLemon [ultimate] (2) [jpeg image of size 746] gpg> addkey Key is protected. You need a passphrase to unlock the secret key for user: "Sean McLemon " 4096-bit RSA key, ID 0xC87419541EAC16A8, created 2016-04-01 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? s Possible actions for a RSA key: Sign Encrypt Authenticate Current allowed actions: Encrypt (S) Toggle the sign capability (E) Toggle the encrypt capability (A) Toggle the authenticate capability (Q) Finished Your selection? e Possible actions for a RSA key: Sign Encrypt Authenticate Current allowed actions: (S) Toggle the sign capability (E) Toggle the encrypt capability (A) Toggle the authenticate capability (Q) Finished Your selection? a Possible actions for a RSA key: Sign Encrypt Authenticate Current allowed actions: Authenticate (S) Toggle the sign capability (E) Toggle the encrypt capability (A) Toggle the authenticate capability (Q) Finished Your selection? q 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 = key expires in n days w = key expires in n weeks m = key expires in n months y = key expires in n years Key is valid for? (0) 6m Key expires at Wed 28 Sep 2016 21:42:43 CEST 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 4096R/0xC87419541EAC16A8 created: 2016-04-01 expires: never usage: SC trust: ultimate validity: ultimate sub 2048R/0x191900DBF062921B created: 2016-04-01 expires: 2016-09-28 usage: S sub 2048R/0x46BDB50E980A2B9B created: 2016-04-01 expires: 2016-09-28 usage: E sub 2048R/0xF1D25AD8AC008AA1 created: 2016-04-01 expires: 2016-09-28 usage: A [ultimate] (1). Sean McLemon [ultimate] (2) [jpeg image of size 746] gpg> save
Now we've got the newly created Master and Sub-keys on the local filesystem.
Step 5. Generate a revocation certificate
$ gpg2 --gen-revoke 0xC87419541EAC16A8 sec 4096R/0xC87419541EAC16A8 2016-04-01 Sean McLemon Create a revocation certificate for this key? (y/N) y 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? 1 Enter an optional description; end it with an empty line: > FSB got hold of my private key > Reason for revocation: Key has been compromised y Is this okay? (y/N) y You need a passphrase to unlock the secret key for user: "Sean McLemon " 4096-bit RSA key, ID 0xC87419541EAC16A8, created 2016-04-01 ASCII armored output forced. Revocation certificate created. Please move it to a medium which you can hide away; if Mallory gets access to this certificate he can use it to make your key unusable. It is smart to print this certificate and store it away, just in case your media become unreadable. But have some caution: The print system of your machine might store the data and make it available to others! -----BEGIN PGP PUBLIC KEY BLOCK----- Comment: A revocation certificate should follow iQIgBCABCgAKBQJW/s+XAx0CeQAKCRDIdBlUHqwWqEsbEACFj7ZDRgwcvG99F1Hb PHzqGPXh5X04nnjpPbnWaKviycvdCQtFT3N3Hg0c1fmgBBDMXHXKcP8dBwrsgmU0 x1vEFUSmzvaW+s/EZXh8xwfXhGVmBG+H+i5JqfiPXelaKH12/pDPqIIE+jlwFx5O a+I3TMg5x5pBzpSWmCNmFgxU4jEJ6SBwsYYDCwGjStS3C8Dojk7RfJug/+wZAhk2 nuGbHKeL48TmLwVsoqlbut57yUzqJ16wC9u46oOwKUeUnluEhOm8eT8fvQsHwM11 THx8UshfjY1/2p5oA4e7GOyB93u7mS5+u57dkKiHwDbNKVq++rMnJH5nesgOT3f6 D/5quHjQNUXwGJsxu3H+ZSxAmmj2q8ooaPZfDxeAqSgjLSu3vTQGK8HtsnJ3Cgu5 tANW4SrDrqqvmpNzutGkmfLRgN/stSLi+MJz78h87nCDPQkMUmp6fEk2kEnVmj1B BEMY5SSrJrIDGwf4CGn4kzHDb9/GlS47x33LcE8g7F1lM1LQ7eNvRNpDU36dmiwj luJLtl0tKVW4YBz4Yo7AxmT0QYSCgXHWStt9XB1devps1CJ45dlbPNzAE8rJH2+1 3YjZfFAgiSFFHMsq0C1M2+mQaqrAyGUVT/lR42Tok0GgwaZK48VWeP+cRZu07NDr pxodVfJ7TjcVUF04AEtSxayfbg== =ck5O -----END PGP PUBLIC KEY BLOCK-----
$ pip install qrcode Downloading/unpacking qrcode Downloading qrcode-5.2.2-py2.py3-none-any.whl (89kB): 89kB downloaded Requirement already satisfied (use --upgrade to upgrade): colorama in /usr/lib/python2.7/dist-packages (from qrcode) Requirement already satisfied (use --upgrade to upgrade): six in /usr/lib/python2.7/dist-packages (from qrcode) Installing collected packages: qrcode Successfully installed qrcode Cleaning up... $ python Python 2.7.9 (default, Mar 1 2015, 12:57:24) [GCC 4.9.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import qrcode >>> cert = open("revoke_cert.asc") >>> cert_text = cert.read() >>> cert_qr = qrcode.make(cert_text) >>> cert_qr.save("revoke_cert.png")
Step 6. Backup GPG and store keys on SD/USB
$ tar -czf gnupg.tgz ~/.gnupg tar: Removing leading `/' from member names $ gpg2 -a --export-secret-key 0xC87419541EAC16A8 >> 0xC87419541EAC16A8.master.key $ gpg2 -a --export-secret-subkeys 0xC87419541EAC16A8 >> 0xC87419541EAC16A8.subkeys.key $ gpg2 -a --export 0xC87419541EAC16A8 > 0xC87419541EAC16A8.public.key.asc $ sudo cp gnupg.tgz 0xC87419541EAC16A8.master.key 0xC87419541EAC16A8.subkeys.key 0xC87419541EAC16A8.public.key.asc /media/SDCARD/
Note - it is important to do this. Once we restart the filesystem of the live CD will no longer exist, and we'll lose all of our keys. then load the subkeys to the card.
Now we can distribute the key:
$ gpg2 --keyserver hkp://pool.sks-keyservers.net --send-keys 0xC87419541EAC16A8 gpg: sending key 0xC87419541EAC16A8 to hkp server pool.sks-keyservers.net
Now we can reboot, upload our public key to the internet and here's what we have - a master key stored offline/disconnected, a set of sub-keys on the smartcard we can use for everyday tasks, a printed certificate we can use to revoke our subkeys, and a public key somewhere on the net we can share with anyone we need to communicate securely with.
Step 7. Boot into usual OS + load keys
When you're sufficiently certain you've got a nice backup of the .gnupg directory, and the subkeys loaded to the card we can boot into our normal OS and remove the live USB card.
We'll need to
$ gpg2 --import 0xC87419541EAC16A8.public.key.asc gpg: /home/sean/.gnupg/trustdb.gpg: trustdb created gpg: key C3969A6B: public key "Sean McLemon " imported gpg: Total number processed: 1 gpg: imported: 1 (RSA: 1)
Example 1. Signing/Encrypting a text file using your card
There's a very good guide produced by the Free Software Foundation @ https://emailselfdefense.fsf.org which you can follow if you want to use EnigMail and Thunderbird - if you want an easy way to sign/encrypt emails you should follow that. However if we just want to sign a message in a text file from the command line, we could do something like the below
$ echo > msg << EOF > paddy schwartz party time > EOF $ gpg2 --output msg.sig --sign msg
Example 2. Decrypting a file using your card
If someone's sent you a file they'll encrypt it using your public key. You can use the keys stored on your card to decrypt it.
To set this up we'll first encrypt a simple text file using our own public key:
$ echo "a funky test message" > plaintext.asc
$ gpg2 --out cyphertext --recipient 0x2F3F79CDC3969A6B --encrypt plaintext.asc gpg: 720D24AD: There is no assurance this key belongs to the named user pub 2048R/720D24AD 2016-03-24 Sean McLemon Primary key fingerprint: 63EB 6DF3 C42E 1AB3 92B5 BF02 2F3F 79CD C396 9A6B Subkey fingerprint: 3E3C 084E 622A BB06 EEFB A739 A3FE 2BC1 720D 24AD It is NOT certain that the key belongs to the person named in the user ID. If you *really* know what you are doing, you may answer the next question with yes. Use this key anyway? (y/N) y
OK now we'll verify that the card isn't connected, and that we cannot decrypt it without the card
$ gpg2 --card-status gpg: selecting openpgp failed: Card not present gpg: OpenPGP card not available: Card not present $ gpg2 --out plaintext-decrypted.asc --decrypt cyphertext gpg: selecting openpgp failed: Card not present gpg: encrypted with 2048-bit RSA key, ID 720D24AD, created 2016-03-24 "Sean McLemon " gpg: public key decryption failed: Operation cancelled gpg: decryption failed: No secret key
Now if we insert the smart card and try to decrypt again we'll be prompted for our PIN, and the file will be decrypted successfully:
$ gpg2 --out plaintext-decrypted.asc --decrypt cyphertext gpg: encrypted with 2048-bit RSA key, ID 720D24AD, created 2016-03-24 "Sean McLemon " $ cat plaintext-decrypted.asc a funky test message
Example 3. Authenticating with a remote machine using your card
$ echo enable-ssh-support >> ~/.gnupg/gpg-agent.conf $ sudo emacs /etc/X11/Xsession.options # and comment/remove the line "use-ssh-agent"Now we'll add our public key to the computer we want to connect to using ssh - in my case it's mokpo.local
$ ssh-add -L | ssh mokpo.local 'cat >> ~/.ssh/authorized_keys'and we can now test logging in
Example 4. Revoking your keys using the QR code
If our key is ever compromised and we'd like to revoke we will need to issue a revocation certificate to say that this key shouldn't ever be trusted. We can use the QR code we previously generated + printed out - first scan the QR code and save the results into a file revoke-certificate-qr.txt, and perform the following steps:
$ gpg2 --import revoke-certificate-qr.txt $ gpg2 --keyserver hkp://pool.sks-keyservers.net --send-keys 0xC87419541EAC16A8Now the world should know not to trust our old keypair, and we can go back to the start of this article and generate a completely new one - this time being extra careful to keep it safe!