> Heads-up: guide inspired by https://github.com/drduh/YubiKey-Guide.
## Requirements
- [Tails USB flash drive or SD card](../how-to-install-tails-on-usb-flash-drive-or-sd-card-on-macos) with VeraCrypt [installed](../how-to-install-and-use-veracrypt-on-tails)
- YubiKey with [OpenPGP](https://www.yubico.com/us/store/compare/) support (firmware version `5.2.3` or higher)
- Computer running macOS Catalina (should work on Big Sur)
## Caveats
- When copy/pasting commands that start with `$`, strip out `$` as this character is not part of the command
- When copy/pasting commands that start with `cat << "EOF"`, select all lines at once (from `cat << "EOF"` to `EOF` inclusively) as they are part of the same (single) command
## Setup guide (on Tails)
### Step 1: boot to Tails and set admin password
> Heads-up: if keyboard layout of computer isn’t “English (US)”, set “Keyboard Layout”.
Click “+” under ”Additional Settings”, then “Administration Password”, set password, click “Add” and finally “Start Tails”.
### Step 2: establish network connection using ethernet cable or Wi-Fi and wait for Tor to be ready
Connected to Tor successfully
👍
### Step 3: import Dennis Fokin’s PGP public key (used to verify downloads below)
### Step 5: verify “YubiKey Manager” AppImage release (learn how [here](../how-to-verify-pgp-digital-signatures-using-gnupg-on-macos)) and make AppImage executable
### Step 7: extract and patch “YubiKey Manager” AppImage (required to run bundled [ykman](https://support.yubico.com/hc/en-us/articles/360016614940-YubiKey-Manager-CLI-ykman-User-Manual), see [issue](https://github.com/Yubico/yubikey-manager/issues/436) on GitHub)
> Heads-up: step is not persistent meaning it has to be completed each time one needs to run `ykman` on Tails.
#### Extract “YubiKey Manager” AppImage
> Heads-up: replace `Downloads` by `Persistent` if “YubiKey Manager” AppImage has been copied to “Persistent” folder.
### Step 8: generate master key (used to sign signing, encryption and authentication subkeys)
When asked for passphrase, create and memorize strong passphrase or use output from `gpg --gen-random --armor 0 24` (and store password in air-gapped password manager).
```console
$ gpg --expert --full-generate-key
gpg (GnuPG) 2.2.12; Copyright (C) 2018 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.
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)
(7) DSA (set your own capabilities)
(8) RSA (set your own capabilities)
(9) ECC and ECC
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(13) Existing key
Your selection? 11
Possible actions for a ECDSA/EdDSA key: Sign Certify Authenticate
Current allowed actions: Sign Certify
(S) Toggle the sign capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? S
Possible actions for a ECDSA/EdDSA key: Sign Certify Authenticate
Current allowed actions: Certify
(S) Toggle the sign capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? Q
Please select which elliptic curve you want:
(1) Curve 25519
(3) NIST P-256
(4) NIST P-384
(5) NIST P-521
(6) Brainpool P-256
(7) Brainpool P-384
(8) Brainpool P-512
(9) secp256k1
Your selection? 1
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) 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: John Doe
Email address: john@example.net
Comment:
You selected this USER-ID:
"John Doe <john@example.net>"
Change (N)ame, (C)omment, (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.
gpg: key 0xC2709D13BAB4763C marked as ultimately trusted
gpg: directory '/home/amnesia/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/amnesia/.gnupg/openpgp-revocs.d/C82270B62BA89271A00A6037C2709D13BAB4763C.rev'
Please type at least 320 randomly chosen characters and then press Enter:
Done: 100.000% Speed: 2.7 MiB/s Left: 0 s
The VeraCrypt volume has been successfully created.
```
The VeraCrypt volume has been successfully created.
👍
### Step 15: mount VeraCrypt encrypted volume
Click “Applications”, then “Utilities”, then “Unlock VeraCrypt Volumes”, then “Add”, select “tails” file on backup volume, click “Open”, enter password and finally click “Unlock”.
### Step 16: rename VeraCrypt encrypted volume
> Heads-up: ignore dirty bit is set error.
```console
$ sudo fatlabel /dev/mapper/tcrypt-1794 Tails
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
#1) Respect the privacy of others.
#2) Think before you type.
#3) With great power comes great responsibility.
[sudo] password for amnesia:
fatlabel: warning - lowercase labels might not work properly with DOS or Windows
0x25: Dirty bit is set. Fs was not properly unmounted and some data may be corrupt.
Automatically removing dirty bit.
```
### Step 17: set VeraCrypt encrypted volume name environment variable
> Heads-up: find name using output of `ls /media/amnesia`.
```console
$ ls /media/amnesia
3FDC-B4EB LaCie 'Samsung BAR'
$ ENCRYPTED_VOLUME_NAME="3FDC-B4EB"
```
### Step 18: export master key, subkeys and public key to VeraCrypt encrypted volume
> Heads-up: configuration lock prevents configuring YubiKey without entering lock code (store lock code in air-gapped password manager).
```console
$ ykman config set-lock-code --generate
Using a randomly generated lock code: cce9181f4a97bac00459419986510d40
Lock configuration with this lock code? [y/N]: y
```
### Step 27 (optional): extend expiry date of signing, encryption and authentication subkeys (required once a year)
#### Mount backup volume (formatted using exFAT)
Click “Places”, then “Home”, then backup volume (“Samsung BAR” in example bellow), enter admin password and finally click “Authenticate”.
#### Mount VeraCrypt encrypted volume
Click “Applications”, then “Utilities”, then “Unlock VeraCrypt Volumes”, then “Add”, select “tails” file on backup volume, click “Open”, enter password and finally click “Unlock”.
#### Import master key
```console
$ gpg --import /media/amnesia/Tails/master.asc
gpg: key 0xC2709D13BAB4763C: 1 signature not checked due to a missing key
gpg: key 0xC2709D13BAB4763C: public key "John Doe <john@example.net>" imported
gpg: key 0xC2709D13BAB4763C: secret key imported
gpg: Total number processed: 1
gpg: imported: 1
gpg: secret keys read: 1
gpg: secret keys imported: 1
gpg: no ultimately trusted keys found
```
#### Set master key ID environment variable
```shell
KEY_ID=0xC2709D13BAB4763C
```
#### Extend expiry date of signing, encryption and authentication subkeys
```console
$ gpg --edit-key $KEY_ID
gpg (GnuPG) 2.2.12; Copyright (C) 2018 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.
sec ed25519/0xC2709D13BAB4763C
created: 2021-07-21 expires: never usage: C
trust: unknown validity: unknown
ssb ed25519/0x02EDC61B6543509B
created: 2021-07-21 expires: 2022-07-21 usage: S
ssb cv25519/0xD4634E0D6E2DD8BF
created: 2021-07-21 expires: 2022-07-21 usage: E
ssb ed25519/0x1E7B69B238FFA21B
created: 2021-07-21 expires: 2022-07-21 usage: A
[ unknown] (1). John Doe <john@example.net>
gpg> key 1
sec ed25519/0xC2709D13BAB4763C
created: 2021-07-21 expires: never usage: C
trust: unknown validity: unknown
ssb* ed25519/0x02EDC61B6543509B
created: 2021-07-21 expires: 2022-07-21 usage: S
ssb cv25519/0xD4634E0D6E2DD8BF
created: 2021-07-21 expires: 2022-07-21 usage: E
ssb ed25519/0x1E7B69B238FFA21B
created: 2021-07-21 expires: 2022-07-21 usage: A
[ unknown] (1). John Doe <john@example.net>
gpg> key 2
sec ed25519/0xC2709D13BAB4763C
created: 2021-07-21 expires: never usage: C
trust: unknown validity: unknown
ssb* ed25519/0x02EDC61B6543509B
created: 2021-07-21 expires: 2022-07-21 usage: S
ssb* cv25519/0xD4634E0D6E2DD8BF
created: 2021-07-21 expires: 2022-07-21 usage: E
ssb ed25519/0x1E7B69B238FFA21B
created: 2021-07-21 expires: 2022-07-21 usage: A
[ unknown] (1). John Doe <john@example.net>
gpg> key 3
sec ed25519/0xC2709D13BAB4763C
created: 2021-07-21 expires: never usage: C
trust: unknown validity: unknown
ssb* ed25519/0x02EDC61B6543509B
created: 2021-07-21 expires: 2022-07-21 usage: S
ssb* cv25519/0xD4634E0D6E2DD8BF
created: 2021-07-21 expires: 2022-07-21 usage: E
ssb* ed25519/0x1E7B69B238FFA21B
created: 2021-07-21 expires: 2022-07-21 usage: A
[ unknown] (1). John Doe <john@example.net>
gpg> expire
Are you sure you want to change the expiration time for multiple subkeys? (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) 1y
Key expires at Thu 21 Jul 2022 03:32:11 PM UTC
Is this correct? (y/N) y
sec ed25519/0xC2709D13BAB4763C
created: 2021-07-21 expires: never usage: C
trust: unknown validity: unknown
ssb* ed25519/0x02EDC61B6543509B
created: 2021-07-21 expires: 2022-07-21 usage: S
ssb* cv25519/0xD4634E0D6E2DD8BF
created: 2021-07-21 expires: 2022-07-21 usage: E
ssb* ed25519/0x1E7B69B238FFA21B
created: 2021-07-21 expires: 2022-07-21 usage: A
[ unknown] (1). John Doe <john@example.net>
gpg> save
```
#### Export public key to VeraCrypt encrypted volume