Below I describe how to generate an OpenPGP key and import its subkeys to a FST-01G device running Gnuk. See my earlier post on planning for my new OpenPGP key and the post on preparing the FST-01G to run Gnuk. For comparison with a RSA/YubiKey based approach, you can read about my setup from 2014.
Most of the steps below are covered by the Gnuk manual. The primary complication for me is the use of a offline machine and storing GnuPG directory stored on a USB memory device.
Offline machine
I use a laptop that is not connected to the Internet and boot it from a read-only USB memory stick. Finding a live CD that contains the necessary tools for using GnuPG with smartcards (gpg-agent, scdaemon, pcscd) is significantly harder than it should be. Using a rarely audited image begs the question of whether you can trust it. A patched kernel/gpg to generate poor randomness would be an easy and hard to notice hack. I’m using the PGP/PKI Clean Room Live CD. Recommendations on more widely used and audited alternatives would be appreciated. Select “Advanced Options” and “Run Shell” to escape the menus. Insert a new USB memory device, and prepare it as follows:
pgp@pgplive:/home/pgp$ sudo wipefs -a /dev/sdX pgp@pgplive:/home/pgp$ sudo fdisk /dev/sdX # create a primary partition of Linux type pgp@pgplive:/home/pgp$ sudo mkfs.ext4 /dev/sdX1 pgp@pgplive:/home/pgp$ sudo mount /dev/sdX1 /mnt pgp@pgplive:/home/pgp$ sudo mkdir /mnt/gnupghome pgp@pgplive:/home/pgp$ sudo chown pgp.pgp /mnt/gnupghome pgp@pgplive:/home/pgp$ sudo chmod go-rwx /mnt/gnupghome
GnuPG configuration
Set your GnuPG home directory to point to the gnupghome
directory on the USB memory device. You will need to do this in every terminal windows you open that you want to use GnuPG in.
pgp@pgplive:/home/pgp$ export GNUPGHOME=/mnt/gnupghome pgp@pgplive:/home/pgp$
At this point, you should be able to run gpg --card-status
and get output from the smartcard.
Create master key
Create a master key and make a backup copy of the GnuPG home directory with it, together with an export ASCII version.
pgp@pgplive:/home/pgp$ gpg --quick-gen-key "Simon Josefsson <simon@josefsson.org>" ed25519 sign 216d gpg: keybox '/mnt/gnupghome/pubring.kbx' created gpg: /mnt/gnupghome/trustdb.gpg: trustdb created gpg: key D73CF638C53C06BE marked as ultimately trusted gpg: directory '/mnt/gnupghome/openpgp-revocs.d' created gpg: revocation certificate stored as '/mnt/gnupghome/openpgp-revocs.d/B1D2BD1375BECB784CF4F8C4D73CF638C53C06BE.rev' pub ed25519 2019-03-20 [SC] [expires: 2019-10-22] B1D2BD1375BECB784CF4F8C4D73CF638C53C06BE B1D2BD1375BECB784CF4F8C4D73CF638C53C06BE uid Simon Josefsson <simon@josefsson.org> pgp@pgplive:/home/pgp$ gpg -a --export-secret-keys B1D2BD1375BECB784CF4F8C4D73CF638C53C06BE > $GNUPGHOME/masterkey.txt pgp@pgplive:/home/pgp$ sudo cp -a $GNUPGHOME $GNUPGHOME-backup-masterkey pgp@pgplive:/home/pgp$
Create subkeys
Create subkeys and make a backup of them too, as follows.
pgp@pgplive:/home/pgp$ gpg --quick-add-key B1D2BD1375BECB784CF4F8C4D73CF638C53C06BE cv25519 encr 216d pgp@pgplive:/home/pgp$ gpg --quick-add-key B1D2BD1375BECB784CF4F8C4D73CF638C53C06BE ed25519 auth 216d pgp@pgplive:/home/pgp$ gpg --quick-add-key B1D2BD1375BECB784CF4F8C4D73CF638C53C06BE ed25519 sign 216d pgp@pgplive:/home/pgp$ gpg -a --export-secret-keys B1D2BD1375BECB784CF4F8C4D73CF638C53C06BE > $GNUPGHOME/mastersubkeys.txt pgp@pgplive:/home/pgp$ gpg -a --export-secret-subkeys B1D2BD1375BECB784CF4F8C4D73CF638C53C06BE > $GNUPGHOME/subkeys.txt pgp@pgplive:/home/pgp$ sudo cp -a $GNUPGHOME $GNUPGHOME-backup-mastersubkeys pgp@pgplive:/home/pgp$
Move keys to card
Prepare the card by setting Admin PIN, PIN, your full name, sex, login account, and key URL as you prefer, following the Gnuk manual on card personalization.
Move the subkeys from your GnuPG keyring to the FST01G using the keytocard command.
Take a final backup — because moving the subkeys to the card modifes the local GnuPG keyring — and create a ASCII armored version of the public key, to be transferred to your daily machine.
pgp@pgplive:/home/pgp$ gpg --list-secret-keys /mnt/gnupghome/pubring.kbx -------------------------- sec ed25519 2019-03-20 [SC] [expires: 2019-10-22] B1D2BD1375BECB784CF4F8C4D73CF638C53C06BE uid [ultimate] Simon Josefsson <simon@josefsson.org> ssb> cv25519 2019-03-20 [E] [expires: 2019-10-22] ssb> ed25519 2019-03-20 [A] [expires: 2019-10-22] ssb> ed25519 2019-03-20 [S] [expires: 2019-10-22] pgp@pgplive:/home/pgp$ gpg -a --export-secret-keys B1D2BD1375BECB784CF4F8C4D73CF638C53C06BE > $GNUPGHOME/masterstubs.txt pgp@pgplive:/home/pgp$ gpg -a --export-secret-subkeys B1D2BD1375BECB784CF4F8C4D73CF638C53C06BE > $GNUPGHOME/subkeysstubs.txt pgp@pgplive:/home/pgp$ gpg -a --export B1D2BD1375BECB784CF4F8C4D73CF638C53C06BE > $GNUPGHOME/publickey.txt pgp@pgplive:/home/pgp$ cp -a $GNUPGHOME $GNUPGHOME-backup-masterstubs pgp@pgplive:/home/pgp$
Transfer to daily machine
Copy publickey.txt to your day-to-day laptop and import it and create stubs using --card-status
.
jas@latte:~$ gpg --import < publickey.txt gpg: key D73CF638C53C06BE: public key "Simon Josefsson <simon@josefsson.org>" imported gpg: Total number processed: 1 gpg: imported: 1 jas@latte:~$ gpg --card-status Reader ...........: Free Software Initiative of Japan Gnuk (FSIJ-1.2.14-67252015) 00 00 Application ID ...: D276000124010200FFFE672520150000 Version ..........: 2.0 Manufacturer .....: unmanaged S/N range Serial number ....: 67252015 Name of cardholder: Simon Josefsson Language prefs ...: sv Sex ..............: male URL of public key : https://josefsson.org/key-20190320.txt Login data .......: jas Signature PIN ....: not forced Key attributes ...: ed25519 cv25519 ed25519 Max. PIN lengths .: 127 127 127 PIN retry counter : 3 3 3 Signature counter : 0 Signature key ....: A3CC 9C87 0B9D 310A BAD4 CF2F 5172 2B08 FE47 45A2 created ....: 2019-03-20 23:40:49 Encryption key....: A9EC 8F4D 7F1E 50ED 3DEF 49A9 0292 3D7E E76E BD60 created ....: 2019-03-20 23:40:26 Authentication key: CA7E 3716 4342 DF31 33DF 3497 8026 0EE8 A9B9 2B2B created ....: 2019-03-20 23:40:37 General key info..: sub ed25519/51722B08FE4745A2 2019-03-20 Simon Josefsson <simon@josefsson.org> sec ed25519/D73CF638C53C06BE created: 2019-03-20 expires: 2019-10-22 ssb> cv25519/02923D7EE76EBD60 created: 2019-03-20 expires: 2019-10-22 card-no: FFFE 67252015 ssb> ed25519/80260EE8A9B92B2B created: 2019-03-20 expires: 2019-10-22 card-no: FFFE 67252015 ssb> ed25519/51722B08FE4745A2 created: 2019-03-20 expires: 2019-10-22 card-no: FFFE 67252015 jas@latte:~$
Before the key can be used after the import, you must update the trust database for the secret key.
Now you should have a offline master key with subkey stubs. Note in the output below that the master key is not available (sec#) and the subkeys are stubs for smartcard keys (ssb>).
jas@latte:~$ gpg --list-secret-keys sec# ed25519 2019-03-20 [SC] [expires: 2019-10-22] B1D2BD1375BECB784CF4F8C4D73CF638C53C06BE uid [ultimate] Simon Josefsson <simon@josefsson.org> ssb> cv25519 2019-03-20 [E] [expires: 2019-10-22] ssb> ed25519 2019-03-20 [A] [expires: 2019-10-22] ssb> ed25519 2019-03-20 [S] [expires: 2019-10-22] jas@latte:~$
If your environment variables are setup correctly, SSH should find the authentication key automatically.
jas@latte:~$ ssh-add -L ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILzCFcHHrKzVSPDDarZPYqn89H5TPaxwcORgRg+4DagE cardno:FFFE67252015 jas@latte:~$
GnuPG and SSH are now ready to be used with the new key. Thanks for reading!
Hi,
Isn’t it better to create the master key with only certify capability [C] and not certify+sign [SC] ?
See https://github.com/lfit/itpol/blob/master/kernel-developer-pgp-guide.md#understanding-the-master-certify-key
Thanks for yours gpg related guides.
Hi Brian! Thanks for the link, that’s a good walk-through!
I have thought about whether to include the S bit on the master key, and my reason for doing it is purely to be able to sign statements (such as the transition statement) using my offline key. The subkeys are more likely to be compromised, and I wouldn’t want statements signed by them to be read as a key transition statement for the master key. This is a delicate point, though, and I don’t think most people reading a key transition statement thinks about this aspect and make sure it is signed by the master key rather than a subkey.
So this is my reason for including the S bit on the master key. What other reasons are there for including the S bit? What reasons are there for NOT including the S bit? I’m curious, maybe it is possible to establish a best practice based on rational arguments. Or we have the situation where this depends on the use-case for the key, and the preferences of the key owner. More discussion would be useful though 🙂
/Simon
For the record, with a more-less recent GPG version you can switch capability bits on and off as you see fit, even if they’re on a key.
https://security.stackexchange.com/questions/31614/how-to-change-subkey-usage-of-a-pgp-key/206766#206766
Pingback: OpenPGP smartcard under GNOME on Debian 10 Buster – Simon Josefsson's blog
Hi.
Thanks for this post.
Why the Encryption subkey uses CV25519 and, Authentication/Sign/Certify uses ED25519?
Thanks.
Pingback: OpenPGP smartcard with GNOME on Debian 11 Bullseye – Simon Josefsson's blog
Pingback: OpenPGP key on FST-01SZ – Simon Josefsson's blog
Pingback: OpenPGP master key on Nitrokey Start – Simon Josefsson's blog
Pingback: How To Trust A Machine – Simon Josefsson's blog