aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/README.md
blob: 9714a18179ba57153f8517656ff819c3bfc813d6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
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
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
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
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
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
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
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
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
This is a guide to using YubiKey as a SmartCard for storing GPG keys.

An authentication key can also be created for SSH using gpg-agent.

Keys stored on a smartcard like YubiKey seem more difficult to steal than ones stored on disk, and are convenient for everyday use.

Instructions written on Debian GNU/Linux 8 (jessie) using YubiKey 4 in OTP+CCID mode.

Debian live install images are available from [here](https://www.debian.org/CD/live/) and are suitable for writing to USB keys.

If you have a comment or suggestion, please open an issue on GitHub.

- [Purchase YubiKey](#purchase-yubikey)
- [Install required software](#install-required-software)
- [Creating keys](#creating-keys)
  - [Create temporary working directory for GPG](#create-temporary-working-directory-for-gpg)
  - [Create configuration](#create-configuration)
  - [Create master key](#create-master-key)
  - [Create revocation certificate](#create-revocation-certificate)
  - [Back up master key](#back-up-master-key)
  - [Create subkeys](#create-subkeys)
    - [Signing key](#signing-key)
    - [Encryption key](#encryption-key)
    - [Authentication key](#authentication-key)
  - [Check your work](#check-your-work)
  - [Export subkeys](#export-subkeys)
  - [Back up everything](#back-up-everything)
  - [Configure YubiKey](#configure-yubikey)
  - [Configure smartcard](#configure-smartcard)
    - [Change PINs](#change-pins)
    - [Set optional card information](#set-optional-card-information)
  - [Transfer keys](#transfer-keys)
    - [Signature key](#signature-key)
    - [Encryption key](#encryption-key-1)
    - [Authentication key](#authentication-key-1)
  - [Check your work](#check-your-work-1)
  - [Export public key](#export-public-key)
- [Using keys](#using-keys)
  - [Insert YubiKey](#insert-yubikey)
  - [Import public key](#import-public-key)
  - [Trust master key](#trust-master-key)
  - [GnuPG](#gnupg)
    - [Encryption/decryption](#encryptiondecryption)
    - [Signing](#signing)
  - [SSH](#ssh)
    - [Create configuration](#create-configuration-1)
    - [Replace ssh-agent with gpg-agent](#replace-ssh-agent-with-gpg-agent)
    - [Copy public key to server](#copy-public-key-to-server)
    - [Connect with public key authentication](#connect-with-public-key-authentication)
- [Notes](#notes)
- [References](#references)

# Purchase YubiKey

https://www.yubico.com/products/yubikey-hardware/

https://www.yubico.com/store/

https://www.amazon.com/Yubico/b/ref=bl_dp_s_web_10358012011?ie=UTF8&node=10358012011

Consider purchasing a pair and programming both in case of loss or damage.

# Install required software

    $ sudo apt-get install gnupg-agent pinentry-curses scdaemon pcscd yubikey-personalization

# Creating keys

## Create temporary working directory for GPG

    $ export GNUPGHOME=$(mktemp -d) ; echo $GNUPGHOME
    /tmp/tmp.EBbMfyVDDt

## Create configuration

    $ cat > $GNUPGHOME/gpg.conf
    use-agent
    personal-cipher-preferences AES256 AES192 AES CAST5
    personal-digest-preferences SHA512 SHA384 SHA256 SHA224
    default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
    cert-digest-algo SHA512
    s2k-digest-algo SHA512
    charset utf-8
    fixed-list-mode
    no-comments
    no-emit-version
    keyid-format 0xlong
    list-options show-uid-validity
    verify-options show-uid-validity
    with-fingerprint
    ^D (Press Control-D)

## Create master key

    $ gpg --gen-key
    gpg (GnuPG) 1.4.18; Copyright (C) 2014 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)
    Your selection? 4
    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
          <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

    You need a user ID to identify your key; the software constructs the user ID
    from the Real Name, Comment and Email Address in this form:
        "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"

    Real name: Doctor Duh
    Email address: drduh@users.noreply.github.com
    Comment:
    You selected this USER-ID:
        "Doctor Duh <drduh@users.noreply.github.com>"

    Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
    You need a Passphrase to protect your secret key.

    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: /tmp/tmp.eBbMfyVDDt/trustdb.gpg: trustdb created
    gpg: key 0x47FE984F98EE7407 marked as ultimately trusted
    public and secret key created and signed.

    gpg: checking the trustdb
    gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
    gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
    pub   4096R/0x47FE984F98EE7407 2016-01-30
          Key fingerprint = 044C ABD0 9043 F1E0 3785  3979 47FE 984F 98EE 7407
    uid                 [ultimate] Doctor Duh <drduh@users.noreply.github.com>

    Note that this key cannot be used for encryption.  You may want to use
    the command "--edit-key" to generate a subkey for this purpose.

## Create revocation certificate

    $ gpg --gen-revoke 0x47FE984F98EE7407 --output $GNUPGHOME/revoke.txt

    sec  4096R/0x47FE984F98EE7407 2016-01-30 Doctor Duh <drduh@users.noreply.github.com>

    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? 1
    Enter an optional description; end it with an empty line:
    >
    Reason for revocation: Key has been compromised
    (No description given)
    Is this okay? (y/N) y

    You need a passphrase to unlock the secret key for
    user: "Doctor Duh <drduh@users.noreply.github.com>"
    4096-bit RSA key, ID 0x47FE984F98EE7407, created 2016-01-30

    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!

## Back up master key

    $ gpg --armor --export-secret-keys 0x47FE984F98EE7407 > $GNUPGHOME/master.key

## Create subkeys

    $ gpg --expert --edit-key 0x47FE984F98EE7407

    gpg (GnuPG) 1.4.18; Copyright (C) 2014 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.

    pub  4096R/0x47FE984F98EE7407  created: 2016-01-30  expires: never       usage: SC

                                   trust: ultimate      validity: ultimate
    [ultimate] (1). Doctor Duh <drduh@users.noreply.github.com>

### Signing key

    gpg> addkey
    Key is protected.

    You need a passphrase to unlock the secret key for
    user: "Doctor Duh <drduh@users.noreply.github.com>"
    4096-bit RSA key, ID 0x47FE984F98EE7407, created 2016-01-30

    Please select what kind of key you want:
       (3) DSA (sign only)
       (4) RSA (sign only)
       (5) Elgamal (encrypt only)
       (6) RSA (encrypt only)
       (7) DSA (set your own capabilities)
       (8) RSA (set your own capabilities)
    Your selection? 4
    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
          <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
    Really create? (y/N) y
    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.
    .....+++++
    .+++++

    pub  4096R/0x47FE984F98EE7407  created: 2016-01-30  expires: never       usage: SC

                                   trust: ultimate      validity: ultimate
    sub  4096R/0xE8E7855AA5AE79A7  created: 2016-01-30  expires: never       usage: S

    [ultimate] (1). Doctor Duh <drduh@users.noreply.github.com>

### Encryption key

    gpg> addkey
    Key is protected.

    You need a passphrase to unlock the secret key for
    user: "Doctor Duh <drduh@users.noreply.github.com>"
    4096-bit RSA key, ID 0x47FE984F98EE7407, created 2016-01-30

    Please select what kind of key you want:
       (3) DSA (sign only)
       (4) RSA (sign only)
       (5) Elgamal (encrypt only)
       (6) RSA (encrypt only)
       (7) DSA (set your own capabilities)
       (8) RSA (set your own capabilities)
    Your selection? 6
    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
          <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
    Really create? (y/N) y
    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.

    .+++++
    ...........+++++

    pub  4096R/0x47FE984F98EE7407  created: 2016-01-30  expires: never       usage: SC
 
                                   trust: ultimate      validity: ultimate
    sub  4096R/0xE8E7855AA5AE79A7  created: 2016-01-30  expires: never       usage: S
 
    sub  4096R/0x39988E0390CB4B0C  created: 2016-01-30  expires: never       usage: E

    [ultimate] (1). Doctor Duh <drduh@users.noreply.github.com>

### Authentication key

    gpg> addkey
    Key is protected.
 
    You need a passphrase to unlock the secret key for
    user: "Doctor Duh <drduh@users.noreply.github.com>"
    4096-bit RSA key, ID 0x47FE984F98EE7407, created 2016-01-30
    
    Please select what kind of key you want:
       (3) DSA (sign only)
       (4) RSA (sign only)
       (5) Elgamal (encrypt only)
       (6) RSA (encrypt only)
       (7) DSA (set your own capabilities)
       (8) RSA (set your own capabilities)
    Your selection? 8
    
    Possible actions for a RSA key: Sign Encrypt Authenticate
    Current allowed actions: Sign Encrypt
    
       (S) Toggle the sign capability
       (E) Toggle the encrypt capability
       (A) Toggle the authenticate capability
       (Q) Finished
    
    Your selection? s
    
    Possible actions for a RSA key: Sign Encrypt Authenticate
    Current allowed actions: Encrypt
    
       (S) Toggle the sign capability
       (E) Toggle the encrypt capability
       (A) Toggle the authenticate capability
       (Q) Finished
    
    Your selection? e
    
    Possible actions for a RSA key: Sign Encrypt Authenticate
    Current allowed actions:
    
       (S) Toggle the sign capability
       (E) Toggle the encrypt capability
       (A) Toggle the authenticate capability
       (Q) Finished
    
    Your selection? a
    
    Possible actions for a RSA key: Sign Encrypt Authenticate
    Current allowed actions: Authenticate
    
       (S) Toggle the sign capability
       (E) Toggle the encrypt capability
       (A) Toggle the authenticate capability
       (Q) Finished

    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
          <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
    Really create? (y/N) y
    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.

    +++++
    .....+++++

    pub  4096R/0x47FE984F98EE7407  created: 2016-01-30  expires: never       usage: SC

                                   trust: ultimate      validity: ultimate
    sub  4096R/0xE8E7855AA5AE79A7  created: 2016-01-30  expires: never       usage: S

    sub  4096R/0x39988E0390CB4B0C  created: 2016-01-30  expires: never       usage: E

    sub  4096R/0x218BCF996C7A6E31  created: 2016-01-30  expires: never       usage: A

    [ultimate] (1). Doctor Duh <drduh@users.noreply.github.com>

    gpg> save

## Check your work

    $ gpg --list-secret-keys
    /tmp/tmp.eBbMfyVDDt/secring.gpg
    -------------------------------
    sec   4096R/0x47FE984F98EE7407 2016-01-30
          Key fingerprint = 044C ABD0 9043 F1E0 3785  3979 47FE 984F 98EE 7407
    uid                            Doctor Duh <drduh@users.noreply.github.com>
    ssb   4096R/0xE8E7855AA5AE79A7 2016-01-30
    ssb   4096R/0x39988E0390CB4B0C 2016-01-30
    ssb   4096R/0x218BCF996C7A6E31 2016-01-30

## Export subkeys

    $ gpg --armor --export-secret-keys 0x47FE984F98EE7407 > $GNUPGHOME/mastersub.key

    $ gpg --armor --export-secret-subkeys 0x47FE984F98EE7407 > $GNUPGHOME/sub.key
    
## Back up everything

Once keys are moved to hardware, they cannot be extracted again (otherwise, what would be the point?), so make sure you have made a backup before proceeding.

    $ cp -avi $GNUPGHOME /mnt/offline-encrypted-usb/backup/

## Configure YubiKey

    $ ykpersonalize -m82
    Firmware version 4.2.7 Touch level 527 Program sequence 4

    The USB mode will be set to: 0x82

    Commit? (y/n) [n]: y

>The -m option is the mode command. To see the different modes, enter ykpersonalize –help. Mode 82 (in hex) enables the YubiKey NEO as a composite USB device (HID + CCID) and allows OTPs to be emitted while in use as a smart card.  Once you have changed the mode, you need to re-boot the YubiKey – so remove and re-insert it.

https://www.yubico.com/2012/12/yubikey-neo-openpgp/

## Configure smartcard

    $ gpg --card-edit

    Application ID ...: D2760001240102010006055532110000
    Version ..........: 2.1
    Manufacturer .....: unknown
    Serial number ....: 05553211
    Name of cardholder: [not set]
    Language prefs ...: [not set]
    Sex ..............: unspecified
    URL of public key : [not set]
    Login data .......: [not set]
    Private DO 1 .....: [not set]
    Private DO 2 .....: [not set]
    Signature PIN ....: not forced
    Key attributes ...: 2048R 2048R 2048R
    Max. PIN lengths .: 127 127 127
    PIN retry counter : 3 3 3
    Signature counter : 0
    Signature key ....: [none]
    Encryption key....: [none]
    Authentication key: [none]
    General key info..: [none]

### Change PINs

The default PIN codes are `12345678` and `123456`.

    gpg/card> admin
    Admin commands are allowed

    gpg/card> passwd
    gpg: OpenPGP card no. D2760001240102010006055532110000 detected

    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

    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? q

### Set optional card information

    gpg/card> name
    Cardholder's surname: Duh
    Cardholder's given name: Dr

    gpg/card> lang
    Language preferences: en

    gpg/card> login
    Login data (account name): drduh@users.noreply.github.com

    gpg/card>

    Application ID ...: D2760001240102010006055532110000
    Version ..........: 2.1
    Manufacturer .....: unknown
    Serial number ....: 05553211
    Name of cardholder: Dr Duh
    Language prefs ...: en
    Sex ..............: unspecified
    URL of public key : [not set]
    Login data .......: drduh@users.noreply.github.com
    Private DO 4 .....: [not set]
    Signature PIN ....: not forced
    Key attributes ...: 2048R 2048R 2048R
    Max. PIN lengths .: 127 127 127
    PIN retry counter : 3 3 3
    Signature counter : 0
    Signature key ....: [none]
    Encryption key....: [none]
    Authentication key: [none]
    General key info..: [none]

    gpg/card> quit

## Transfer keys

This is a one-way operation only. Make sure you've made a backup before proceeding!

    $ gpg --edit-key 0x47FE984F98EE7407
    gpg (GnuPG) 1.4.18; Copyright (C) 2014 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.

    pub  4096R/0x47FE984F98EE7407  created: 2016-01-30  expires: never       usage: SC

                                   trust: ultimate      validity: ultimate
    sub  4096R/0xE8E7855AA5AE79A7  created: 2016-01-30  expires: never       usage: S

    sub  4096R/0x39988E0390CB4B0C  created: 2016-01-30  expires: never       usage: E

    sub  4096R/0x218BCF996C7A6E31  created: 2016-01-30  expires: never       usage: A

    [ultimate] (1). Doctor Duh <drduh@users.noreply.github.com>

    gpg> toggle

    sec  4096R/0x47FE984F98EE7407  created: 2016-01-30  expires: never
    ssb  4096R/0xE8E7855AA5AE79A7  created: 2016-01-30  expires: never
    ssb  4096R/0x39988E0390CB4B0C  created: 2016-01-30  expires: never
    ssb  4096R/0x218BCF996C7A6E31  created: 2016-01-30  expires: never
    (1)  Doctor Duh <drduh@users.noreply.github.com>

    gpg> key 1

    sec  4096R/0x47FE984F98EE7407  created: 2016-01-30  expires: never
    ssb* 4096R/0xE8E7855AA5AE79A7  created: 2016-01-30  expires: never
    ssb  4096R/0x39988E0390CB4B0C  created: 2016-01-30  expires: never
    ssb  4096R/0x218BCF996C7A6E31  created: 2016-01-30  expires: never
    (1)  Doctor Duh <drduh@users.noreply.github.com>

### Signature key

    gpg> keytocard
    Signature key ....: [none]
    Encryption key....: [none]
    Authentication key: [none]

    Please select where to store the key:
       (1) Signature key
       (3) Authentication key
    Your selection? 1

    You need a passphrase to unlock the secret key for
    user: "Doctor Duh <drduh@users.noreply.github.com>"
    4096-bit RSA key, ID 0xE8E7855AA5AE79A7, created 2016-01-30


    sec  4096R/0x47FE984F98EE7407  created: 2016-01-30  expires: never
    ssb* 4096R/0xE8E7855AA5AE79A7  created: 2016-01-30  expires: never
                         card-no: 0006 05553211
    ssb  4096R/0x39988E0390CB4B0C  created: 2016-01-30  expires: never
    ssb  4096R/0x218BCF996C7A6E31  created: 2016-01-30  expires: never
    (1)  Doctor Duh <drduh@users.noreply.github.com>

### Encryption key

Type `key 1` again to deselect and switch to the next key.

    gpg> key 1

    sec  4096R/0x47FE984F98EE7407  created: 2016-01-30  expires: never
    ssb  4096R/0xE8E7855AA5AE79A7  created: 2016-01-30  expires: never
                         card-no: 0006 05553211
    ssb  4096R/0x39988E0390CB4B0C  created: 2016-01-30  expires: never
    ssb  4096R/0x218BCF996C7A6E31  created: 2016-01-30  expires: never
    (1)  Doctor Duh <drduh@users.noreply.github.com>

    gpg> key 2

    sec  4096R/0x47FE984F98EE7407  created: 2016-01-30  expires: never
    ssb  4096R/0xE8E7855AA5AE79A7  created: 2016-01-30  expires: never
                         card-no: 0006 05553211
    ssb* 4096R/0x39988E0390CB4B0C  created: 2016-01-30  expires: never
    ssb  4096R/0x218BCF996C7A6E31  created: 2016-01-30  expires: never
    (1)  Doctor Duh <drduh@users.noreply.github.com>

    gpg> keytocard
    Signature key ....: 04CB BB4B 1D99 3398 A0B1  4C4B E8E7 855A A5AE 79A7
    Encryption key....: [none]
    Authentication key: [none]

    Please select where to store the key:
       (2) Encryption key
    Your selection? 2

    You need a passphrase to unlock the secret key for
    user: "Doctor Duh <drduh@users.noreply.github.com>"
    4096-bit RSA key, ID 0x39988E0390CB4B0C, created 2016-01-30


    sec  4096R/0x47FE984F98EE7407  created: 2016-01-30  expires: never
    ssb  4096R/0xE8E7855AA5AE79A7  created: 2016-01-30  expires: never
                         card-no: 0006 05553211
    ssb* 4096R/0x39988E0390CB4B0C  created: 2016-01-30  expires: never
                         card-no: 0006 05553211
    ssb  4096R/0x218BCF996C7A6E31  created: 2016-01-30  expires: never
    (1)  Doctor Duh <drduh@users.noreply.github.com>

### Authentication key

    gpg> key 2

    sec  4096R/0x47FE984F98EE7407  created: 2016-01-30  expires: never
    ssb  4096R/0xE8E7855AA5AE79A7  created: 2016-01-30  expires: never
                         card-no: 0006 05553211
    ssb  4096R/0x39988E0390CB4B0C  created: 2016-01-30  expires: never
                         card-no: 0006 05553211
    ssb  4096R/0x218BCF996C7A6E31  created: 2016-01-30  expires: never
    (1)  Doctor Duh <drduh@users.noreply.github.com>

    gpg> key 3

    sec  4096R/0x47FE984F98EE7407  created: 2016-01-30  expires: never
    ssb  4096R/0xE8E7855AA5AE79A7  created: 2016-01-30  expires: never
                         card-no: 0006 05553211
    ssb  4096R/0x39988E0390CB4B0C  created: 2016-01-30  expires: never
                         card-no: 0006 05553211
    ssb* 4096R/0x218BCF996C7A6E31  created: 2016-01-30  expires: never
    (1)  Doctor Duh <drduh@users.noreply.github.com>

    gpg> keytocard
    Signature key ....: 04CB BB4B 1D99 3398 A0B1  4C4B E8E7 855A A5AE 79A7
    Encryption key....: 8AB0 607B A1C1 0F19 2627  6EA6 3998 8E03 90CB 4B0C
    Authentication key: [none]

    Please select where to store the key:
       (3) Authentication key
    Your selection? 3

    You need a passphrase to unlock the secret key for
    user: "Doctor Duh <drduh@users.noreply.github.com>"
    4096-bit RSA key, ID 0x218BCF996C7A6E31, created 2016-01-30


    sec  4096R/0x47FE984F98EE7407  created: 2016-01-30  expires: never
    ssb  4096R/0xE8E7855AA5AE79A7  created: 2016-01-30  expires: never
                         card-no: 0006 05553211
    ssb  4096R/0x39988E0390CB4B0C  created: 2016-01-30  expires: never
                         card-no: 0006 05553211
    ssb* 4096R/0x218BCF996C7A6E31  created: 2016-01-30  expires: never
                         card-no: 0006 05553211
    (1)  Doctor Duh <drduh@users.noreply.github.com>

    gpg> save

## Check your work

    gpg --list-secret-keys
    /tmp/tmp.eBbMfyVDDt/secring.gpg
    -------------------------------
    sec   4096R/0x47FE984F98EE7407 2016-01-30
          Key fingerprint = 044C ABD0 9043 F1E0 3785  3979 47FE 984F 98EE 7407
    uid                            Doctor Duh <drduh@users.noreply.github.com>
    ssb>  4096R/0xE8E7855AA5AE79A7 2016-01-30
    ssb>  4096R/0x39988E0390CB4B0C 2016-01-30
    ssb>  4096R/0x218BCF996C7A6E31 2016-01-30

`ssb>` indicates a stub to the private key on smartcard.

## Export public key

    $ gpg --armor --export 0x47FE984F98EE7407 > /mnt/public-usb-key/

# Using keys

## Insert YubiKey

    $ gpg --card-status
    Application ID ...: D2760001240102010006055532110000
    Version ..........: 2.1
    Manufacturer .....: unknown
    Serial number ....: 05553211
    Name of cardholder: Dr Duh
    Language prefs ...: en
    Sex ..............: unspecified
    URL of public key : [not set]
    Login data .......: drduh@users.noreply.github.com
    Signature PIN ....: not forced
    Key attributes ...: 4096R 4096R 4096R
    Max. PIN lengths .: 127 127 127
    PIN retry counter : 3 3 3
    Signature counter : 0
    Signature key ....: 04CB BB4B 1D99 3398 A0B1  4C4B E8E7 855A A5AE 79A7
          created ....: 2016-01-30 16:36:40
    Encryption key....: 8AB0 607B A1C1 0F19 2627  6EA6 3998 8E03 90CB 4B0C
          created ....: 2016-01-30 16:42:29
    Authentication key: 3B81 E129 B7C3 26F4 2EA1  2F19 218B CF99 6C7A 6E31
          created ....: 2016-01-30 16:44:48
    General key info..: pub  4096R/0xE8E7855AA5AE79A7 2016-01-30 Doctor Duh <drduh@users.noreply.github.com>
    sec#  4096R/0x47FE984F98EE7407  created: 2016-01-30  expires: never
    ssb>  4096R/0xE8E7855AA5AE79A7  created: 2016-01-30  expires: never
                          card-no: 0006 05553211
    ssb>  4096R/0x39988E0390CB4B0C  created: 2016-01-30  expires: never
                          card-no: 0006 05553211
    ssb>  4096R/0x218BCF996C7A6E31  created: 2016-01-30  expires: never
                          card-no: 0006 05553211

`sec#` indicates master key is not available (as it should be stored encrypted and offline).

## Import public key

    $ gpg --import < /mnt/public-usb-key/pubkey.txt

## Trust master key

    $ gpg --edit-key 0x47FE984F98EE7407
    gpg (GnuPG) 1.4.18; Copyright (C) 2014 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.

    pub  4096R/0x47FE984F98EE7407  created: 2016-01-30  expires: never       usage: SC

                                   trust: unknown       validity: unknown
    sub  4096R/0xE8E7855AA5AE79A7  created: 2016-01-30  expires: never       usage: S

    sub  4096R/0x39988E0390CB4B0C  created: 2016-01-30  expires: never       usage: E

    sub  4096R/0x218BCF996C7A6E31  created: 2016-01-30  expires: never       usage: A

    [ unknown] (1). Doctor Duh <drduh@users.noreply.github.com>

    gpg> trust
    pub  4096R/0x47FE984F98EE7407  created: 2016-01-30  expires: never       usage: SC

                                   trust: unknown       validity: unknown
    sub  4096R/0xE8E7855AA5AE79A7  created: 2016-01-30  expires: never       usage: S

    sub  4096R/0x39988E0390CB4B0C  created: 2016-01-30  expires: never       usage: E

    sub  4096R/0x218BCF996C7A6E31  created: 2016-01-30  expires: never       usage: A

    [ unknown] (1). Doctor Duh <drduh@users.noreply.github.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

    pub  4096R/0x47FE984F98EE7407  created: 2016-01-30  expires: never       usage: SC

                                   trust: ultimate      validity: unknown
    sub  4096R/0xE8E7855AA5AE79A7  created: 2016-01-30  expires: never       usage: S

    sub  4096R/0x39988E0390CB4B0C  created: 2016-01-30  expires: never       usage: E

    sub  4096R/0x218BCF996C7A6E31  created: 2016-01-30  expires: never       usage: A

    [ unknown] (1). Doctor Duh <drduh@users.noreply.github.com>
    Please note that the shown key validity is not necessarily correct
    unless you restart the program.

    gpg> quit

## GnuPG

### Encryption/decryption

    $ echo "$(uname -a)" | gpg --encrypt --armor -r 0x47FE984F98EE7407 | gpg --debug --decrypt --armor

    Please enter the PIN
    gpg: encrypted with 4096-bit RSA key, ID 0x39988E0390CB4B0C, created 2016-01-30
          "Doctor Duh <drduh@users.noreply.github.com>"
    Linux workstation 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt20-1+deb8u3 (2016-01-17) x86_64 GNU/Linux

### Signing

    $ echo "$(uname -a)" | gpg --encrypt --armor --sign -r 0x47FE984F98EE7407
    gpg: signatures created so far: 0

    Please enter the PIN
    [sigs done: 0]
    -----BEGIN PGP MESSAGE-----

    hQIMAzmYjgOQy0sMAQ//bG8YyEinTOFzL/aL/BN54/PAFzBZj6B//dEFXYu5NlHJ
    [...]
    sjLN5ZhJkQKJeUWIVdGeuZN+pIeIRWQHeKD7xRUgij6/nC7qCfPPkHFYxQ==
    =jztu
    -----END PGP MESSAGE-----

## SSH

### Create configuration

    $ cat > ~/.gnupg/gpg-agent.conf
    pinentry-program /usr/bin/pinentry-curses
    default-cache-ttl 60
    max-cache-ttl 120
    enable-ssh-support
    write-env-file
    use-standard-socket
    ^D (Press Control-D)

### Replace ssh-agent with gpg-agent

    $ pkill ssh-agent && \
      eval $(gpg-agent --daemon --enable-ssh-support --use-standard-socket \
      --log-file ~/.gnupg/gpg-agent.log --write-env-file)

### Copy public key to server

    $ ssh-add -L
    ssh-rsa AAAAB4NzaC1yc2EAAAADAQABAAACAz[...]zreOKM+HwpkHzcy9DQcVG2Nw== cardno:000605553211

### Connect with public key authentication

    $ ssh git@github.com -vvv
    [...]
    debug2: key: cardno:000605553211 (0x1234567890),
    debug1: Authentications that can continue: publickey
    debug3: start over, passed a different list publickey
    debug3: preferred gssapi-keyex,gssapi-with-mic,publickey,keyboard-interactive,password
    debug3: authmethod_lookup publickey
    debug3: remaining preferred: keyboard-interactive,password
    debug3: authmethod_is_enabled publickey
    debug1: Next authentication method: publickey
    debug1: Offering RSA public key: cardno:000605553211
    debug3: send_pubkey_test
    debug2: we sent a publickey packet, wait for reply
    debug1: Server accepts key: pkalg ssh-rsa blen 535
    debug2: input_userauth_pk_ok: fp e5:de:a5:74:b1:3e:96:9b:85:46:e7:28:53:b4:82:c3
    debug3: sign_and_send_pubkey: RSA e5:de:a5:74:b1:3e:96:9b:85:46:e7:28:53:b4:82:c3
    debug1: Authentication succeeded (publickey).
    [...]

# Notes

- Don't write to drduh@users.noreply.github.com, open an issue on GitHub instead.
- Programming YubiKey for GPG keys still lets you use its two slots - OTP and static password modes, for example.
- ECC may be preferred to RSA 4096, but the 1.4.x branch of GnuPG does not support it.
- If you encounter problems, try unplugging and re-inserting your YubiKey. Also try installing and using GnuPG 2.x (`sudo apt-get install gnupg2` and `gpg2`)

# References

<https://developers.yubico.com/yubikey-personalization/>

<https://developers.yubico.com/PGP/Card_edit.html>

<https://blog.josefsson.org/2014/06/23/offline-gnupg-master-key-and-subkeys-on-yubikey-neo-smartcard/>

<https://www.esev.com/blog/post/2015-01-pgp-ssh-key-on-yubikey-neo/>

<https://blog.habets.se/2013/02/GPG-and-SSH-with-Yubikey-NEO>

<https://trmm.net/Yubikey>

<https://rnorth.org/8/gpg-and-ssh-with-yubikey-for-mac>

<https://jclement.ca/articles/2015/gpg-smartcard/>

<https://github.com/herlo/ssh-gpg-smartcard-config>

<http://www.bootc.net/archives/2013/06/09/my-perfect-gnupg-ssh-agent-setup/>

<https://help.riseup.net/en/security/message-security/openpgp/best-practices>