yubikey.md 14.7 KB
Newer Older
John Northrup's avatar
John Northrup committed
1 2
# Configuring and Using the Yubikey

3 4 5
## Requirements
* `gpg2`
* `yubikey-personalization`
John Northrup's avatar
John Northrup committed
6 7 8 9 10 11 12 13 14 15

Make sure your Yubikey is inserted - and let's get ready to have some fun!

Let's set the module to behave like we want:
```
ykpersonalize -m86
```
This setting lets us use the Yubikey as both a SmartCard and an OTP device
at the same time.

16 17
**Note:** The above command is not necessary on a YubiKey 5 (and won't work)

John Northrup's avatar
John Northrup committed
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
## Changing the Default PIN Entries on the Yubikey PIV Card
By default the user PIN is `123456` and the ADMIN PIN is `12345678`, keep this
in mind when changing the PINS when it asks for the current PIN

```
> gpg --card-edit

Application ID ...: D2760001240102000006123482780000
Version ..........: 2.1
Manufacturer .....: Yubico
Serial number ....: 12345678
Name of cardholder: [not set]
Language prefs ...: [not set]
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: [none]
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 2
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

gpg/card> admin
Admin commands are allowed

# Change the PIN and Admin PINs
gpg/card> passwd
gpg: OpenPGP card no. D2760001240102000006123482780000 detected

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? 1
PIN changed.

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? 3
PIN changed.

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? q

# Make sure the PIN is entered before signing
gpg/card> forcesig

gpg/card> quit
```

## Master Key Storage

85
We want to keep the master key offline, encrypted, and stored in a super-secret-hiding-place.
John Northrup's avatar
John Northrup committed
86 87 88 89
We'll facilitate this by creating an encrypted portable drive on a USB drive.
For the purpose of this tutorial our USB drive will be called 'transit' and our
encrypted volume will be called 'GitLab'.

90
### MacOS
John Northrup's avatar
John Northrup committed
91

92 93 94 95
1. Create an encrypted sparse bundle using MacOS' `hdiutil`:
  ```
  hdiutil create -fs HFS+ -layout GPTSPUD -type SPARSEBUNDLE -encryption AES-256 -volname "GitLab" -size 100m -stdinpass /Volumes/transit/gitlab.sparsebundle
  ```
John Northrup's avatar
John Northrup committed
96

97 98 99 100
1. Mount it up:
  ```
  hdiutil attach -encryption -stdinpass -mountpoint /Volumes/GitLab /Volumes/transit/gitlab.sparsebundle
  ```
John Northrup's avatar
John Northrup committed
101

102 103
### Linux
There are many options for Linux and an obvious option is LUKS (Linux Unified Key Setup-on-disk-format), which most Linux distributions already have installed when using full disk encryption. However, if you want the encrypted disk file to be available on other platforms such as MacOS and Windows, a better option is to use [VeraCrypt](https://veracrypt.fr). The below instructions are based on **VeraCrypt** version 1.23.
John Northrup's avatar
John Northrup committed
104

105
The actions below are similar to the activities completed above for MacOS.
John Northrup's avatar
John Northrup committed
106

107
You can either perform the below actions using the **VeraCrypt** UI or by using the CLI:
John Northrup's avatar
John Northrup committed
108

109
1. Create volume file
John Northrup's avatar
John Northrup committed
110

111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
  ```bash
  mkdir $HOME/transit
  veracrypt --text --create --encryption AES --hash SHA-512 --size 100M --volume-type normal --filesystem FAT --keyfiles "" $HOME/transit/gitlab.sparsebundle

  Enter password:
  Re-enter password:
  Enter PIM:  [Enter]
  Please type at least 320 randomly chosen characters and then press Enter:
  Done: 100.000%  Speed:   31 MB/s  Left: 0 s         
  The VeraCrypt volume has been successfully created.
  ```

1. Mount the volume

  ```bash
  [sudo] mkdir -m 755 /media/GitLab
  veracrypt --text --keyfiles "" --protect-hidden no $HOME/transit/gitlab.sparsebundle /media/GitLab

  Enter password for ...:
  Enter PIM for ...: [Enter]
  ```

### Common Configuration for MacOS and Linux
1. Set the mountpoint

  ```bash
  export MOUNTPOINT=[According to the OS e.g. /media]
  ```

1. Create the configuration directory where our GnuPG key rings will live:

Peter Dam's avatar
Peter Dam committed
142
  ```bash
143 144 145 146 147 148
  mkdir $MOUNTPOINT/GitLab/gpg_config
  chmod 700 $MOUNTPOINT/GitLab/gpg_config
  ```

1. Export the configuration directory for GnuPG usage:

Peter Dam's avatar
Peter Dam committed
149
  ```bash
150 151 152 153 154
  export GNUPGHOME=$MOUNTPOINT/GitLab/gpg_config
  ```

1. Setup the `gpg.conf` before we create things:

Peter Dam's avatar
Peter Dam committed
155
  ```bash
156 157 158 159
  echo default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAMELLIA256 CAMELLIA192 CAMELLIA128 TWOFISH > $MOUNTPOINT/GitLab/gpg_config/gpg.conf
  echo cert-digest-algo SHA512 >> $MOUNTPOINT/GitLab/gpg_config/gpg.conf
  echo use-agent >> $MOUNTPOINT/GitLab/gpg_config/gpg.conf
  ```
John Northrup's avatar
John Northrup committed
160 161 162

## Master Key Creation

Peter Dam's avatar
Peter Dam committed
163
```bash
164
> gpg --expert --full-generate-key
John Northrup's avatar
John Northrup committed
165 166 167 168 169 170 171 172 173 174
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)
Your selection? 8

Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Alex Hanselka's avatar
Alex Hanselka committed
175
Current allowed actions: Sign Certify Encrypt
John Northrup's avatar
John Northrup committed
176 177 178 179

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
180
   (Q) Finished
John Northrup's avatar
John Northrup committed
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214

Your selection? s
Your selection? e
Your selection? q

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) 4y
Key expires at Wed 25 Aug 2021 01:45:54 AM CST
Is this correct? (y/N) y

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

Real name: John Rando
Email address: rando@gitlab.com
Comment:
You selected this USER-ID:
    "John Rando <rando@gitlab.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o

public and secret key created and signed.
pub   4096R/FAEFD83E 2017-08-25 [expires: 2021-08-25]
      Key fingerprint = 856B 1E1C FAD0 1FE4 5C4C  4E97 961F 703D B8EF B59D
uid                  John Rando <rando@gitlab.com>
```

215
Now that we have a master key, a good practice is to generate a revocation
216
certificate in the event that we lose the password or the key is compromised.
John Northrup's avatar
John Northrup committed
217

218
**Note:** In some versions you do not see the key id in the gpg output. You can use your email here.
Peter Dam's avatar
Peter Dam committed
219

220
**Note:** This is most likely not necessary in Linux since the revocation certificate is generated automatically as per the output line from previous command: `gpg: revocation certificate stored as '/.../GitLab/gpg_config/openpgp-revocs.d/<key_id>.rev'`
221

Peter Dam's avatar
Peter Dam committed
222
```bash
John Northrup's avatar
John Northrup committed
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
> gpg --gen-revoke FAEFD83E > /Volumes/GitLab/gpg_config/FAEFD83E-revocation-certificate.asc

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? 3
Enter an optional description; end it with an empty line:
> Using revocation certificate that was generated when key FAEFD83E was
> first created.  It is very likely that I have lost access to the
> private key.
238
>
John Northrup's avatar
John Northrup committed
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
Reason for revocation: Key is no longer used
Using revocation certificate that was generated when key B8EFD59D was
first created.  It is very likely that I have lost access to the
private key.
Is this okay? (y/N) y

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!
```

## Generating Subkeys
256
We'll use subkeys that are generated on the Yubikey device itself. Keys generated
257
on the Yubikey cannot be copied off, so loss or destruction of the device will
John Northrup's avatar
John Northrup committed
258 259
mean key rotation.

Peter Dam's avatar
Peter Dam committed
260
```bash
John Northrup's avatar
John Northrup committed
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
> gpg --edit-key FAEFD83E

# Let's add the SIGNING subkey
gpg> addcardkey

 Signature key ....: [none]
 Encryption key....: [none]
 Authentication key: [none]

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

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) 1y
Key expires at Sat Aug  25 01:08:14 2018 CST
Is this correct? (y/N) y
Really create? (y/N) y  

pub  3072R/FAEFD83E  created: 2017-08-25  expires: 2018-08-25  usage: C
                     trust: ultimate      validity: ultimate
sub  4096R/79BF274F  created: 2017-08-25  expires: 2018-08-25  usage: S
[ultimate] (1). John Rando <rando@gitlab.com>

# Do the same for the ENCRYPTION subkey
gpg> addcardkey

 Signature key ....: 546D 6A7E EB4B 5B07 B3EA  7373 12E2 68AD 79BF 574F
 Encryption key....: [none]
 Authentication key: [none]

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

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) 1y
Key expires at Sat Aug  25 01:10:41 2018 CST
Is this correct? (y/N) y
Really create? (y/N) y  

pub  4096R/FAEFD83E  created: 2017-08-25  expires: 2018-08-25  usage: C
                     trust: ultimate      validity: ultimate
sub  4096R/AE86E89B  created: 2017-08-25  expires: 2018-08-25  usage: E
sub  4096R/79BF274F  created: 2017-08-25  expires: 2018-08-25  usage: S
[ultimate] (1). John Rando <rando@gitlab.com>

# Do the same for the AUTHENTICATION subkey
gpg> addcardkey

 Signature key ....: 546D 6A7E EB4B 5B07 B3EA  7373 12E2 68AD 79BF 574F
 Encryption key....: [none]
 Authentication key: [none]

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

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) 1y
Key expires at Sat Aug  25 01:21:41 2018 CST
Is this correct? (y/N) y
Really create? (y/N) y

pub  4096R/FAEFD83E  created: 2017-08-25  expires: 2018-08-25  usage: C
                     trust: ultimate      validity: ultimate
sub  4096R/AE86E89B  created: 2017-08-25  expires: 2018-08-25  usage: E
sub  4096R/79BF274F  created: 2017-08-25  expires: 2018-08-25  usage: S
sub  4096R/DE86E396  created: 2017-08-25  expires: 2018-08-25  usage: A
[ultimate] (1). John Rando <rando@gitlab.com>
Peter Dam's avatar
Peter Dam committed
352 353

gpg> save
John Northrup's avatar
John Northrup committed
354 355 356
```

## Backup and Publish your Public Key
Peter Dam's avatar
Peter Dam committed
357
```bash
358
> gpg --armor --export FAEFD83E > $MOUNTPOINT/GitLab/gpg_config/FAEFD83E.asc
359 360 361
```

If your gpg version does not output the key id you should use the full fingerprint instead.
Peter Dam's avatar
Peter Dam committed
362
```bash
John Northrup's avatar
John Northrup committed
363 364 365 366
> gpg --keyserver hkps://hkps.pool.sks-keyservers.net --send-key FAEFD83E
```

## Generate your SSH Public Key
367 368
**Note:** This step should not be necessary assuming the `gpg-agent` is running and configured. See further below.

Peter Dam's avatar
Peter Dam committed
369
```bash
370
> gpg --export-ssh-key FAEFD87E
John Northrup's avatar
John Northrup committed
371 372
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABA ... COMMENT
```
Alex Hanselka's avatar
Alex Hanselka committed
373 374 375 376 377 378 379

## Import Public Key to Regular Keychain

Open up the GPG Keychain app and import the public key that you just created
into your regular keychain. Set the Ownertrust to Ultimate on the public key
you've imported.

380
Or in a fresh terminal we can:
Peter Dam's avatar
Peter Dam committed
381
```bash
Peter Dam's avatar
Peter Dam committed
382
> gpg --import $MOUNTPOINT/GitLab/gpg_config/FAEFD83E.asc
383 384 385 386
gpg: key FAEFD83E: public key imported
gpg: Total number processed: 1
gpg:               imported: 1

387
> gpg --edit-key FAEFD83E
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
Secret subkeys are available.

pub  4096R/FAEFD83E  created: 2017-08-25  expires: 2018-08-25  usage: C
                     trust: ultimate      validity: ultimate
sub  4096R/AE86E89B  created: 2017-08-25  expires: 2018-08-25  usage: E
sub  4096R/79BF274F  created: 2017-08-25  expires: 2018-08-25  usage: S
sub  4096R/DE86E396  created: 2017-08-25  expires: 2018-08-25  usage: A
[ultimate] (1). John Rando <rando@gitlab.com>

gpg> trust
pub  4096R/FAEFD83E  created: 2017-08-25  expires: 2018-08-25  usage: C
                     trust: ultimate      validity: ultimate
sub  4096R/AE86E89B  created: 2017-08-25  expires: 2018-08-25  usage: E
sub  4096R/79BF274F  created: 2017-08-25  expires: 2018-08-25  usage: S
sub  4096R/DE86E396  created: 2017-08-25  expires: 2018-08-25  usage: A
[ultimate] (1). John Rando <rando@gitlab.com>

Please decide how far you trust this user to correctly verify other users' keys
(by looking at passports, checking fingerprints from different sources, etc.)

  1 = I don't know or won't say
  2 = I do NOT trust
  3 = I trust marginally
  4 = I trust fully
  5 = I trust ultimately
  m = back to the main menu

Your decision? 5
Do you really want to set this key to ultimate trust? (y/N) y
gpg> quit
```

Alex Hanselka's avatar
Alex Hanselka committed
420 421
## Ensure proper options are set in gpg-agent.conf

422
Your `gpg-agent.conf` should look something **like**
Alex Hanselka's avatar
Alex Hanselka committed
423

Peter Dam's avatar
Peter Dam committed
424
```bash
Alex Hanselka's avatar
Alex Hanselka committed
425 426 427
$ cat ~/.gnupg/gpg-agent.conf
default-cache-ttl 600
max-cache-ttl 7200
428 429

# For MacOS
430
pinentry-program /usr/local/bin/pinentry-mac
431 432 433 434

# For Linux
pinentry-program /usr/bin/pinentry

Alex Hanselka's avatar
Alex Hanselka committed
435 436
enable-ssh-support
```
437

438
## Ensure your environment knows how to authenticate SSH
439
* Insert one of the following into your `rc` file
440

441
* On OSX you'll need this:
Peter Dam's avatar
Peter Dam committed
442
```bash
443 444 445
export SSH_AUTH_SOCK=$HOME/.gnupg/S.gpg-agent.ssh
```

446
* On Linux you'll need this:
Peter Dam's avatar
Peter Dam committed
447
```bash
448 449 450 451
unset SSH_AGENT_PID
if [ "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
  export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
fi
452
```
Peter Dam's avatar
Peter Dam committed
453
and source the `rc` afterwards.
454

455 456
## Script to Reset gpg-agent and ssh-agent

457
On OSX, use this script will reset `gpg-agent` and `ssh-agent` after you make the
Alex Hanselka's avatar
Alex Hanselka committed
458
above updates to `gpg-agent.conf`.
459

Peter Dam's avatar
Peter Dam committed
460
```bash
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
#!/bin/bash

echo "kill gpg-agent"
code=0
while [ 1 -ne $code ]; do
    killall gpg-agent
    code=$?
    sleep 1
done

echo "kill ssh"
    killall ssh

echo "kill ssh muxers"
    for pid in `ps -ef | grep ssh | grep -v grep | awk '{print $2}'`; do
    kill $pid
done

echo "restart gpg-agent"
    eval $(gpg-agent --daemon)

echo
echo "All done. Now unplug / replug the NEO token."
echo
```
486

487
On Linux modify the `gpg-agent --daemon` with the following: `gpg-connect-agent reloadagent /bye`
488 489 490 491 492 493 494 495 496 497 498

## Personal Cleanup
* If you have anything inside of your own dot files or system configuration that
  may startup the ssh-agent, disable it
* If you have anything that starts up the `gpg-agent`, ensure the options reflect
  the work we've accomplished above
* A good short test to validate all is well, when adding ssh keys (such as your
  git ssh key), should work just fine, as well as a listing `ssh-add -l`

## Reference Material
* https://github.com/drduh/YubiKey-Guide#21-install---linux
499
* https://wiki.archlinux.org/index.php/GnuPG