How I configured YubiKey to sign and decrypt emails on Mac
Tags: yubikey, gpg
Published: 2024-06-18 15:29:32

_Originally published [on my blog](https://pabis.eu/blog/2024-06-18-YubiKey-OpenGPG-Mail-Sign-Decrypt.html)_

As you see on my ["resume"](https://pabis.eu/cv.html) page, I uploaded my public key for encrypting emails back when I was starting my personal website. However, moving private key from one place to another is never a good option. My YubiKey cost me 55€ and I barely use it for FIDO/U2F. Why not keep the private key in there and have it with me at all times?

Required software (for Mac)
---------------------------
We need some software on Mac to make this work. The process should be similar on Linux. Assuming you have [brew](https://brew.sh) installed, we will install the following packages:

```bash
$ brew install gnupg pinentry-mac ykman
```

I will also use [Thunderbird](https://thunderbird.net) as it integrates with GnuPG directly (with a special cheat code you need to enter in settings). First thing to do is to set up GnuPG to ask for PIN code using a GUI. We will use `pinentry-mac` as our input program and restart GPG Agent.

```bash
$ mkdir -p ~/.gnupg
$ touch ~/.gnupg/gpg-agent.conf
$ PINENTRY=$(which pinentry-mac)
$ echo "pinentry-program $PINENTRY" >> ~/.gnupg/gpg-agent.conf
$ gpgconf --kill gpg-agent
$ gpgagent --daemon
```

Setting up PIN on YubiKey
-------------------------
Now we can set our PIN codes on YubiKey for OpenPGP. You should do this and not use factory default codes. The default Admin PIN is `12345678` and the default PIN is `123456`. **Don't forget them!**

```bash
$ ykman openpgp access change-admin-pin -a 12345678 # Enter your new 8-digit Admin PIN
$ ykman openpgp access change-pin -P 123456 # Enter your new 6-digit PIN
```

Generating key pair on YubiKey
-----------------------------
Now using GnuPG, we can interface with our YubiKey OpenPGP implementation to create a new key pair that will be safely stored on it.

```bash
$ gpg --card-edit
```

You will enter the `gpg/card` prompt. Issue the following commands to the YubiKey and enter PIN (not-admin) code when asked. Do not back up the key as it is safer that way. Set some expiration date you like. Enter your name, email and comment. Finish by giving the Admin PIN when asked.

```bash
gpg/card> admin
gpg/card> generate
Make off-card backup of encryption key? (Y/n) n
Key is valid for? (0) 2y
Real name: John Doe
Email address: john@example.com
Comment: my yubi pgp key
```

In case you want to use a different key size, before `generate` command, type `key-attr` and select key type you want. Verify with Admin PIN.

Next export the public key to a file using GPG. Assuming that you don't have any other keys in your keyring for the same e-mail address, you can write the following. This will be the key you share with others. Otherwise you can run in card edit mode of GPG `list` and copy the key ID to export.

```bash
$ gpg --armor --export john@example.com > mypublickey.asc
$ gpg --import mypublickey.asc
$ gpg --list-keys
```

Look for the key ID you have just imported and save it. We will need it later. It will look something like:

```
pub   rsa4096 2020-05-04 [SC] [expired: 2024-05-03]
      THIS-IS-KEY-ID 01234ABCDEF01234...
uid           [ultimate] My Name <johndoe@example.com>
```

Cross-signing with an old key
----------------------------
This step is optional. In case you have some previous key pair that you used for GPG, you can copy over the new public key to your old keyring and sign it with the old private key. This way, you can have unbroken chain of trust.

```bash
$ gpg --import mypublickey.asc
$ gpg --list-keys # Find your old and new key IDs
$ gpg --default-key OLDKEYID --sign-key NEWKEYID
$ gpg --armor --export NEWKEYID > mypublickey-signed.asc
```

Configuring Thunderbird
-----------------------
By default Thunderbird uses some internal GnuPG storage. We need to ask it to connect to the external GPG agent so that it can connect to our YubiKey.

Open Thunderbird. Add your e-mail account if you didn't already. Click the three lines menu and select `Settings`. Scroll down to the bottom of the `General` page and click `Config Editor...`.

![Thunderbird Config Editor](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/17lc5velc5pkan7fy17f.jpg)

Search for `mail.openpgp.allow_external_gnupg` and double click on it to set it to `true`. Quit Thunderbird with ⌘Q and open it again.

Right click on the account name in the left panel and select `Settings`. Select `End-to-End Encryption` section and click `Add key`. Select `External through GnuPG` and enter the key ID. It won't show any confirmation if that is correct, you will have to just try to use it.

![External through GnuPG](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t49puk2t6b6m4ynuwqw7.jpg)

Try sending encrypted e-mail to yourself with signature. Select `Encrypt` and `OpenPGP` at the top. If you see a warning that there's no key to encrypt this email, simply click `Resolve` and import the public key you exported previously (`mypublickey.asc`).

![Resolve unknown public key](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8uikuvarfeyxijdi8rc2.jpg)

When trying to send or open encrypted e-mail, the PIN dialog should pop up. Type the 6-digit PIN you set for the key.

![PIN dialog](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u5brsdei48ugll7aslve.jpg)

The problem with this setup is that sometimes Thunderbird freezes when trying to decrypt or sign the email. I need then to "Force Quit" it in Activity Monitor on Mac. With touch policy enabled (`ykman openpgp keys set-touch`) it is even more problematic but sometimes it works. Once you enter the PIN for both decryption and signing and don't disconnect the key, don't kill GPG agent and don't quit Thunderbird, it should work smoothly.