Using YubiKey to Protect Email With MFA

Electronic mail has been around for over 40 years, and we still have not managed to properly secure it. The emails we receive are often not…

My YubiKey

Using YubiKey to Protect Email With MFA

Electronic mail has been around for over 40 years, and we still have not managed to properly secure it. The emails we receive are often not digitally signed, and where we cannot really tell if the email has been read by anyone else and where we can’t prove the sender. So let’s look at MFA (Multi-factor Authentication) for secure email, and only let it be accessible with a YubiKey that stores the private key for a given user, and for the YubiKey to perform the decryption.

First, we will generate your key pair for a fake user (Yubi123) and which will secure emails that are sent to him:

% gpg --generate-key
gpg (GnuPG/MacGPG2) 2.2.34; Copyright (C) 2022 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Note: Use "gpg --full-generate-key" for a full featured key generation dialog.

GnuPG needs to construct a user ID to identify your key.

Real name: Yubi123
Email address: Yube123@home
You selected this USER-ID:
"Yubi123 <Yube123@home>"

Change (N)ame, (E)mail, or (O)kay/(Q)uit? O
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.
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: revocation certificate stored as '/Users/billbuchanan/.gnupg/openpgp-revocs.d/C06F84CED5CFD8E4B0CA471D37D258F159EC3CF3.rev'
public and secret key created and signed.

pub rsa3072 2022-03-27 [SC] [expires: 2024-03-26]
C06F84CED5CFD8E4B0CA471D37D258F159EC3CF3
uid Yubi123 <Yube123@home>
sub rsa3072 2022-03-27 [E] [expires: 2024-03-26]

If Alice sends Yubi123 a secure email, she will use his public key to encrypt the message, and where Yubi123 will have the private key to decrypt the encrypted messages. But, the private key will not be stored on Yubi123’s machine, but will only exist on the YubiKey. Thus it will not be possible to read the email without inserting the YubiKey.

Backing up the key

Yubi123 will delete the key on his machine, but can create a backup of the private key with:

% gpg --list-secret-keys
/Users/billbuchanan/.gnupg/pubring.kbx
--------------------------------------

sec   rsa3072 2022-03-27 [SC] [expires: 2024-03-26]
C06F84CED5CFD8E4B0CA471D37D258F159EC3CF3
uid [ultimate] Yubi123 <Yube123@home>
ssb rsa3072 2022-03-27 [E] [expires: 2024-03-26]
ssb> rsa2048 2022-03-27 [E]

And so we can make a backup of the key:

% gpg --export-secret-ke --armor C06F84CED5CFD8E4B0CA471D37D258F159EC3CF3 > mykey.key

This shows the key as:

% cat mykey.key
-----BEGIN PGP PRIVATE KEY BLOCK-----
lQdFBGAtkzYBEACkIejC2VRgZQ9uWwDlgdwtzNb6zQ3TPk6hU604XB+8eYAhM8q7
+u19vbnKQfT+asaunJO6VGdTAyUwJqYAnQAguAMOJpYcMVfLFdFkxmJ/WHssxtZN
Y5Y0uJ8w5jQhPhBTN0CIFBgcM95gUxADbIDZoxhL8PcCz7C/d9a1AItZLg/QWkXp
...
9+JfEBJScpe254QVIN0BIWpN9Yiboq4PJWgazxtxPjNfcDsx8KpdKAuqi/uq5NPo
oCTmx2UN3qZC9dX1vBAxSggIt29Xg0EQyW8FW7cL/C2ISN5Ngz5QUKuN0BeOnqRo
PaBdFrTTnW7uXsl4LXpP23rfpisKVtEfiXb13322SByXgTAYItr3IsyMEYriggMB
pjqKaE3TxdwxETxHh9ktvj5aITWHWkq7corz/hR+POnFnucbcNB98DkLlND905oV
=pW79
-----END PGP PRIVATE KEY BLOCK-----

This key can be stored on a USB device, and put away for safe keeping. In order for Yubi123 to receive emails, he needs to export his public key, and give it to Alice:

% gpg --export --armor C06F84CED5CFD8E4B0CA471D37D258F159EC3CF3 > mykey.pub 
% cat mykey.pub
-----BEGIN PGP PUBLIC KEY BLOCK-----

mQGNBGJAvucBDADewhJi9NbngVruw8wvRgNDjGaK3aPYUN1c88D43LmfG6aO8ikb
X6J1P7rEW1LFF9eQpdJj+o1gFrXVLLc4jMlYHjB8LTdDX378njuc6TeNjoJ1I8EK
uE+OCgkdjL4JtCOLwy9tsKtVLJqPuIzD5eBnFokTdqROgsVgKPh5Bqhg3raJIhqo
xAi6F4+oxVGeRbC3MlwgxwAchRvz6VT0KGBuXLbqOyYeofVSdZDrM+oVUEZkIF3e
...
HJM775qHJZVzcKqH6A3s9pJprepAYvxT9leJIDAITMzMzrnmuxWbOZEKj5SJbsvw
ylvdkp1iX9SaHuoJcOPyqjjOhmit2JzlatY9HxbBj5F67/b1CS99p4899755zWh3
f6gJ0xdMf2NMmHznIEWuGnjPdv8n5f2eHHsfpHPBWfQZiMrovwJ1f7H+GRyiyZtk
4YYTExAfWw==
=rO0T
-----END PGP PUBLIC KEY BLOCK-----

Adding the private key to YubiKey

Next, we will edit this key, and add the private key onto the YubiKey:

% gpg --edit-key C06F84CED5CFD8E4B0CA471D37D258F159EC3CF3
gpg (GnuPG/MacGPG2) 2.2.34; Copyright (C) 2022 g10 Code GmbH
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.

sec rsa3072/37D258F159EC3CF3
created: 2022-03-27 expires: 2024-03-26 usage: SC
trust: ultimate validity: ultimate
ssb rsa3072/D9199C3869F0EC65
created: 2022-03-27 expires: 2024-03-26 usage: E
[ultimate] (1). Yubi123 <Yube123@home>

gpg> addcardkey
Signature key ....: [none]
Encryption key....: 70CD 6D9C 260D A521 0216 08D5 9D90 A5F1 4E3E FEF2
Authentication key: [none]

Please select the type of key to generate:
(1) Signature key
(2) Encryption key
(3) Authentication key
Your selection? 2

gpg: WARNING: such a key has already been stored on the card!

Replace existing key? (y/N) y
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) y
Really create? (y/N) y

sec rsa3072/37D258F159EC3CF3
created: 2022-03-27 expires: 2024-03-26 usage: SC
trust: ultimate validity: ultimate
ssb rsa3072/D9199C3869F0EC65
created: 2022-03-27 expires: 2024-03-26 usage: E
ssb rsa2048/58CEA6B17B38FF48
created: 2022-03-27 expires: never usage: E
card-no: 0006 15526276
[ultimate] (1). Yubi123 <Yube123@home>

We will then be asked for the PIN number of the YubiKey. Next, we can link the decryption process to the Yubikey:

% gpg-connect-agent --hex "scd apdu 00 f1 00 00" /bye
D[0000] 05 02 07 90 00 .....
OK

We can view the key loaded here:

% gpg --card-edit
Reader ...........: Yubico YubiKey OTP FIDO CCID
Application ID ...: D2760001240103040006155262760000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: 15526276
Name of cardholder: [not set]
Language prefs ...: [not set]
Salutation .......:
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: off
Signature key ....: [none]
Encryption key....: 583D 2DB5 25C0 D0AE 8554 BEC9 58CE A6B1 7B38 FF48
created ....: 2022-03-27 19:53:42
Authentication key: [none]
General key info..:
sub rsa2048/58CEA6B17B38FF48 2022-03-27 Yubi123 <Yube123@home>
sec rsa3072/37D258F159EC3CF3 created: 2022-03-27 expires: 2024-03-26
ssb rsa3072/D9199C3869F0EC65 created: 2022-03-27 expires: 2024-03-26
ssb> rsa2048/58CEA6B17B38FF48 created: 2022-03-27 expires: never
card-no: 0006 15526276

Encrypting and decrypting

First we will encrypt for “Yubi123” with a file of 1.txt:

% gpg -armor -r Yubi123  -e 1.txt 

This creates an armored file of 1.txt.asc:

 % cat 1.txt.asc
-----BEGIN PGP MESSAGE-----

hQEMA1jOprF7OP9IAQgAkjPkHLsNKOETI30E7AAh9XJBKYZAOfQxRhHuyOKTQz6y
W0YlQukiY/UoWgcq/i02Lm+O8s9qIv1CV83SU46+AYvJZf+gr7k8cCp/dKcblqDP
XepCUbYLbUfvLzQ71oE4LBOku1mv5izLYHsDTopWzg3zSmuKxm+T1OB3NutLe+R+
o9xWA5rNFAw0BImRc05ZWdwZcx1BKVhPIIAHoU0V8loRfcjCs5zQPpM3ktpiqH7F
jvXQVY68v44Hl7DtKtJSnrTDiP70+rrle34TyGYQwsbqQt3YVgUibRoEt+/m2IuW
n1S3bPadMf2jEC63tcWgr2nGKh9sf7dRdtUUvq25mtJGAYFD1mahwNheMn9cknzJ
kz431P1CzkrVYAdCC+4wkf34alx5qVBX1RTl0k/fV3O8RRiWHmFgzEPVs1DdNagm
FmWSyIgtCg==
=G7jC
-----END PGP MESSAGE-----

To decrypt, we perform a decryption operation:

% gpg -d 1.txt.gpg

This will then prompt to unlock the card to perform the decryption process:

And, if the PIN number on the Yubikey is correct, we should be able to decrypt it:

(base) billbuchanan@MacBook-Pro-6 yubi % gpg -d 1.txt.gpg
gpg: encrypted with 2048-bit RSA key, ID 58CEA6B17B38FF48, created 2022-03-27
"Yubi123 <Yube123@home>"
Hello

It should be noted that the decryption happens on the YubiKey, and not on the host machine. This means that Yubi123 does not store his private key on the machine. He could thus use any machine to read his emails in a secure way, but only if they YubiKey is present.

And, here’s a quick overview, of how Bob can decrypt GPG messages sent to him with his private key, and also how he can signed messages with his private key:

Conclusions

Do you work in a highly secure environment, and need to encrypt email? Well, integrating with a YubiKey is a great way to enhance the security of the email, and where the presence of the key is required to read the email. And, with the YubiKey, you can make it that you just have to touch the device, instead of entering a PIN number.

As we can see, we can see, we can also load our private key so that the YubiKey would sign the email, and where our private key is stored on the device:

Please select the type of key to generate:
(1) Signature key
(2) Encryption key
(3) Authentication key
Your selection?

Again, the private key will not be stored on any machine, and where we can sign only when the YubiKey is present.

Professionals in Cybersecurity has been saying for years that passwords are finished and that we need to move to MFA to security, so why aren’t we there yet?