Tech Blog.

Thoughts, stories, ideas.

GnuPG und SmartCards

18. January 2016

Damit GnuPG (Manpage) oder PKCS#11 Keys nicht mehr durch einen Virus oder ähnliches gestohlen werden können, können diese auf ein Hardware Security Modul (HSM) oder eine SmartCard ausgelagert werden. Dieser Blog Artikel soll zeigen, wie ein GnuPG Key nach “best current practice” erstellt und danach in einer SmartCard (z.B. Yubikey oder Nitrokey) gespeichert wird. Gleiches wäre auch mit einem PKCS#11 Key möglich, auf diese wird hier jedoch nicht weiter eingegangen, das Verfahren sollte aber ähnlich sein.
In diesem Beispiel wird ein GnuPG Key erstellt, welcher drei Subkeys (Encryption, Signing und Authentication) hat. Danach werden nur die Subkeys in die SmartCard geladen. Der eigentliche Masterkey wird in eine Datei gespeichert, welche schlussendlich offline an einem möglichst sicheren Ort aufbewahrt werden sollte. Der Vorteil von diesem Setup ist, dass ohne Masterkey die Keys nicht mehr abgeändert werden können (Ablaufdatum, UIDs, Subkeys, …).

GnuPG Key erstellen

$ gpg2 --expert --full-gen-key
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)
Your selection? 8

Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Sign Certify 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 Certify Encrypt Authenticate
Current allowed actions: Certify 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 Certify Encrypt Authenticate
Current allowed actions: Certify

   (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
        = 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) 3y
Key expires at Sam 15 Feb 2020 09:27:17 CET
Is this correct? (y/N) y

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

Real name: Pallando
Email address: pallando@example.org
Comment:
You selected this USER-ID:
    "Pallando <pallando@example.org>"

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

pub   rsa4096/0x0DA3852689C0BC38 2017-02-15 [C] [expires: 2020-02-15]
      01691D7408369C26A5B7D9390DA3852689C0BC38
      Key fingerprint = 0169 1D74 0836 9C26 A5B7  D939 0DA3 8526 89C0 BC38
uid                              Pallando <pallando@example.org>

GnuPG Key mit den Subkeys erweitern

Im obigen Key gibt es nun eine UID und einen Subkey. Dieser wird jetzt mit den anderen Subkeys erweitert.

$ gpg2 --expert --edit-key 0x0DA3852689C0BC38

sec  rsa4096/0x0DA3852689C0BC38
     created: 2017-02-15  expires: 2020-02-15  usage: C
     trust: ultimate      validity: ultimate
[ultimate] (1). Pallando <pallando@example.org>

gpg> addkey
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)
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (12) ECC (encrypt only)
  (13) Existing key
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? e

Possible actions for a RSA key: Sign Encrypt Authenticate 
Current allowed actions: Sign 

   (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
        = 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) 3y
Key expires at Son 24 Mär 2019 09:49:46 CET
Is this correct? (y/N) y
Really create? (y/N) y

gpg> addkey
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)
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (12) ECC (encrypt only)
  (13) Existing key
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? 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) 3y
Key expires at Son 24 Mär 2019 09:49:46 CET
Is this correct? (y/N) y
Really create? (y/N) y

gpg> addkey
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)
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (12) ECC (encrypt only)
  (13) Existing key
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
        = 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) 3y
Key expires at Son 24 Mär 2019 09:49:46 CET
Is this correct? (y/N) y
Really create? (y/N) y

sec  rsa4096/0x0DA3852689C0BC38
     created: 2017-02-15  expires: 2020-02-15  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/0x0B8635FD20045068
     created: 2017-02-15  expires: 2020-02-15  usage: S
ssb  rsa4096/0x8BF4DDB73F29DDAA
     created: 2017-02-15  expires: 2020-02-15  usage: E
ssb  rsa4096/0xC163F1DC0667E483
     created: 2017-02-15  expires: 2020-02-15  usage: A
[ultimate] (1). Pallando <pallando@example.org>

gpg> quit
Save changes? (y/N) y

Nun hat der Key drei Subkeys, jeweils einer für Signing, Encryption und Authentication. Die Capabilities haben folgende Bedeutung:

  • S: Good for signatures
  • E: Good for encryption
  • C: Also good to certify keys
  • A: Good for authentication

Nun sollte der gesamte Key mit dem Command gpg2 --armor --export-secret-keys 0x0DA3852689C0BC38 > 0x0DA3852689C0BC38.asc in ein File exportiert werden, welches danach an einem sicheren Ort aufbewahrt und abgelegt wird.

Mit dem Command gpg2 --armor --export-secret-subkeys 0x0DA3852689C0BC38 > 0x0DA3852689C0BC38_subs.asc exportieren wir die Subkeys und anschliessend wird der gesamte Key aus dem Keyring gpg2 --delete-secret-key 0x0DA3852689C0BC38 (dies muss mit zweimal “y” bestätigt werden) gelöscht.
Nun können die Subkeys (NUR die Subkeys) wieder importiert werden gpg2 --import 0x0DA3852689C0BC38_subs.asc. Somit sollte der Keyring wie folgt aussehen:

$ gpg2 --list-secret-keys
sec#  rsa4096/0x0DA3852689C0BC38 2017-02-15 [C] [expires: 2020-02-15]
      01691D7408369C26A5B7D9390DA3852689C0BC38
uid                   [ultimate] Pallando <pallando@example.org>
ssb   rsa4096/0x0B8635FD20045068 2017-02-15 [S] [expires: 2020-02-15]
ssb   rsa4096/0x8BF4DDB73F29DDAA 2017-02-15 [E] [expires: 2020-02-15]
ssb   rsa4096/0xC163F1DC0667E483 2017-02-15 [A] [expires: 2020-02-15]

Das # nach dem sec in der ersten Zeile des Outputs gibt an, dass der Masterkey nicht, sondern nur die Subkeys, vorhanden ist.

SmartCard konfigurieren

Dieses Beispiel wird anhand eines Yubikeys gemacht, ist aber genau so gültig bei anderen SmartCards, wie z.B. Nitrokeys.
Falls die SmartCard im voraus noch geresetet werden muss, kann dies folgendermassen gemacht werden (nur für SmartCards Version >2!):

$ gpg-connect-agent --hex
# reset your PIN
> scd apdu 00 20 00 81 08 40 40 40 40 40 40 40 40
D[0000]  69 82                                              i.
OK
> scd apdu 00 20 00 81 08 40 40 40 40 40 40 40 40
D[0000]  69 82                                              i.
OK
> scd apdu 00 20 00 81 08 40 40 40 40 40 40 40 40
D[0000]  69 82                                              i.
OK
> scd apdu 00 20 00 81 08 40 40 40 40 40 40 40 40
D[0000]  69 83                                              i.
OK
# reset your Admin PIN
> scd apdu 00 20 00 83 08 40 40 40 40 40 40 40 40
D[0000]  69 82                                              i.
OK
> scd apdu 00 20 00 83 08 40 40 40 40 40 40 40 40
D[0000]  69 82                                              i.
OK
> scd apdu 00 20 00 83 08 40 40 40 40 40 40 40 40
D[0000]  69 82                                              i.
OK
> scd apdu 00 20 00 83 08 40 40 40 40 40 40 40 40
D[0000]  69 83                                              i.

Danach wird die SmartCard konfiguriert:

$ gpg2 --card-edit 

Reader ...........: 1050:0407:X:0
Application ID ...: D2760001240102010006042451460000
Version ..........: 2.1
Manufacturer .....: Yubico
Serial number ....: 04245146
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 ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

gpg/card> admin
Admin commands are allowed

gpg/card> passwd
1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? 3
Admin PIN prompt (default admin PIN is 12345678)
PIN changed.

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

Your selection? 1
PIN prompt (default PIN is 123456)
PIN changed.

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

Your selection? q

gpg/card> name
Cardholder's surname: 
Cardholder's given name: Pallando

gpg/card> lang
Language preferences: de

gpg/card> sex
Sex ((M)ale, (F)emale or space): m

gpg/card> q

Danach sollte die Ausgabe von gpg2 --card-status in etwa so aussehen:

Reader ...........: 1050:0407:X:0
Application ID ...: D2760001240102010006042451460000
Version ..........: 2.1
Manufacturer .....: Yubico
Serial number ....: 04245146
Name of cardholder: Pallando
Language prefs ...: de
Sex ..............: male
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: rsa4096 rsa4096 rsa4096
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

GnuPG Keys in der SmartCard speichern

$ gpg2 --edit-key 0x0DA3852689C0BC38
Secret key is available.

sec# rsa4096/0x0DA3852689C0BC38
     created: 2017-02-15  expires: 2020-02-15  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/0x0B8635FD20045068
     created: 2017-02-15  expires: 2020-02-15  usage: S
ssb  rsa4096/0x8BF4DDB73F29DDAA
     created: 2017-02-15  expires: 2020-02-15  usage: E
ssb  rsa4096/0xC163F1DC0667E483
     created: 2017-02-15  expires: 2020-02-15  usage: A
[ultimate] (1). Pallando <pallando@example.org>

gpg> key 1

sec# rsa4096/0x0DA3852689C0BC38
     created: 2017-02-15  expires: 2020-02-15  usage: C
     trust: ultimate      validity: ultimate
ssb* rsa4096/0x0B8635FD20045068
     created: 2017-02-15  expires: 2020-02-15  usage: S
ssb  rsa4096/0x8BF4DDB73F29DDAA
     created: 2017-02-15  expires: 2020-02-15  usage: E
ssb  rsa4096/0xC163F1DC0667E483
     created: 2017-02-15  expires: 2020-02-15  usage: A
[ultimate] (1). Pallando <pallando@example.org>

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

sec# rsa4096/0x0DA3852689C0BC38
     created: 2017-02-15  expires: 2020-02-15  usage: C
     trust: ultimate      validity: ultimate
ssb* rsa4096/0x0B8635FD20045068
     created: 2017-02-15  expires: 2020-02-15  usage: S
ssb  rsa4096/0x8BF4DDB73F29DDAA
     created: 2017-02-15  expires: 2020-02-15  usage: E
ssb  rsa4096/0xC163F1DC0667E483
     created: 2017-02-15  expires: 2020-02-15  usage: A
[ultimate] (1). Pallando <pallando@example.org>

gpg> key 1

sec# rsa4096/0x0DA3852689C0BC38
     created: 2017-02-15  expires: 2020-02-15  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/0x0B8635FD20045068
     created: 2017-02-15  expires: 2020-02-15  usage: S
ssb  rsa4096/0x8BF4DDB73F29DDAA
     created: 2017-02-15  expires: 2020-02-15  usage: E
ssb  rsa4096/0xC163F1DC0667E483
     created: 2017-02-15  expires: 2020-02-15  usage: A
[ultimate] (1). Pallando <pallando@example.org>

gpg> key 2

sec# rsa4096/0x0DA3852689C0BC38
     created: 2017-02-15  expires: 2020-02-15  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/0x0B8635FD20045068
     created: 2017-02-15  expires: 2020-02-15  usage: S
ssb* rsa4096/0x8BF4DDB73F29DDAA
     created: 2017-02-15  expires: 2020-02-15  usage: E
ssb  rsa4096/0xC163F1DC0667E483
     created: 2017-02-15  expires: 2020-02-15  usage: A
[ultimate] (1). Pallando <pallando@example.org>

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

sec# rsa4096/0x0DA3852689C0BC38
     created: 2017-02-15  expires: 2020-02-15  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/0x0B8635FD20045068
     created: 2017-02-15  expires: 2020-02-15  usage: S
ssb* rsa4096/0x8BF4DDB73F29DDAA
     created: 2017-02-15  expires: 2020-02-15  usage: E
ssb  rsa4096/0xC163F1DC0667E483
     created: 2017-02-15  expires: 2020-02-15  usage: A
[ultimate] (1). Pallando <pallando@example.org>

gpg> key 2

sec# rsa4096/0x0DA3852689C0BC38
     created: 2017-02-15  expires: 2020-02-15  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/0x0B8635FD20045068
     created: 2017-02-15  expires: 2020-02-15  usage: S
ssb  rsa4096/0x8BF4DDB73F29DDAA
     created: 2017-02-15  expires: 2020-02-15  usage: E
ssb  rsa4096/0xC163F1DC0667E483
     created: 2017-02-15  expires: 2020-02-15  usage: A
[ultimate] (1). Pallando <pallando@example.org>

gpg> key 3

sec# rsa4096/0x0DA3852689C0BC38
     created: 2017-02-15  expires: 2020-02-15  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/0x0B8635FD20045068
     created: 2017-02-15  expires: 2020-02-15  usage: S
ssb  rsa4096/0x8BF4DDB73F29DDAA
     created: 2017-02-15  expires: 2020-02-15  usage: E
ssb* rsa4096/0xC163F1DC0667E483
     created: 2017-02-15  expires: 2020-02-15  usage: A
[ultimate] (1). Pallando <pallando@example.org>

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

sec# rsa4096/0x0DA3852689C0BC38
     created: 2017-02-15  expires: 2020-02-15  usage: C
     trust: ultimate      validity: ultimate
ssb  rsa4096/0x0B8635FD20045068
     created: 2017-02-15  expires: 2020-02-15  usage: S
ssb  rsa4096/0x8BF4DDB73F29DDAA
     created: 2017-02-15  expires: 2020-02-15  usage: E
ssb* rsa4096/0xC163F1DC0667E483
     created: 2017-02-15  expires: 2020-02-15  usage: A
[ultimate] (1). Pallando <pallando@example.org>

gpg> save

Danach sollte gpg2 --card-status in etwa so aussehen:

Reader ...........: 1050:0407:X:0
Application ID ...: D2760001240102010006042451460000
Version ..........: 2.1
Manufacturer .....: Yubico
Serial number ....: 04245146
Name of cardholder: Pallando
Language prefs ...: de
Sex ..............: male
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: rsa4096 rsa4096 rsa4096
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
Signature key ....: DF3B 91AD 59A5 BF46 916D  9A32 0B86 35FD 2004 5068
      created ....: 2017-02-15 08:52:56
Encryption key....: 5777 58DA AE13 D7AC 9528  287C 8BF4 DDB7 3F29 DDAA
      created ....: 2017-02-15 08:34:39
Authentication key: EAEF A30B E182 129A CB7A  5D9F C163 F1DC 0667 E483
      created ....: 2017-02-15 08:58:07
General key info..: sub  rsa4096/0x8BF4DDB73F29DDAA 2017-02-15 Pallando <pallando@example.org>
sec#  rsa4096/0x0DA3852689C0BC38  created: 2017-02-15  expires: 2020-02-15
ssb>  rsa4096/0x0B8635FD20045068  created: 2017-02-15  expires: 2020-02-15
                                  card-no: 0006 04245146
ssb>  rsa4096/0x8BF4DDB73F29DDAA  created: 2017-02-15  expires: 2020-02-15
                                  card-no: 0006 04245146
ssb>  rsa4096/0xC163F1DC0667E483  created: 2017-02-15  expires: 2020-02-15
                                  card-no: 0006 04245146

und die Ausgabe von $ gpg2 --list-secret-keys sollte in etwa so aussehen:

sec#  rsa4096/0x0DA3852689C0BC38 2017-02-15 [C] [expires: 2020-02-15]
      01691D7408369C26A5B7D9390DA3852689C0BC38
uid                   [ultimate] Pallando <pallando@example.org>
ssb>  rsa4096/0x0B8635FD20045068 2017-02-15 [S] [expires: 2020-02-15]
ssb>  rsa4096/0x8BF4DDB73F29DDAA 2017-02-15 [E] [expires: 2020-02-15]
ssb>  rsa4096/0xC163F1DC0667E483 2017-02-15 [A] [expires: 2020-02-15]

Das > nach ssb steht dafür, dass der Key ein Stubkey (sprich nicht selber bekannt, sondern auf der SmartCard) ist.

Nun ist der GnuPG Key nur noch über die SmartCard verfügbar. Dabei werden die Daten jeweils an die SmartCard gesendet, diese entschlüsselt oder signiert sie und sendet diese wieder zurück.