❌

Normale Ansicht

Eine OpenPGP-Smartcard, ein ThinkPad, GnuPG, Fedora und ich

26. Oktober 2026 um 06:00

Mit diesem Beitrag teile ich meine Erfahrungen mit der Inbetriebnahme einer OpenPGP–Smartcard und des Smartcard-Leser in meinem ThinkPad T14s Gen1. Ihr erfahrt, was alles zu tun war und was ich davon halte. Aber beginnen wir doch ganz am Anfang.

Motivation

Es war einmal die FrOSCon 2026. Dort sah ich am Merchandise-Stand im Foyer diese schicken OpenPGP-Smartcards und einige Karten-Lese/Schreib-Geräte ausliegen.

Ich sprach meine Bekannten auf ihre Erfahrungen mit diesen Karten und GnuPG an, welche überwiegend mit Kopfschütteln und Stöhnen reagierten. Offenbar sind sie nicht so leicht für etwas zu interessieren wie ich. Doch schien mir das Thema für den Moment weniger reizvoll und ich habe das Thema erstmal vertagt.

Das Thema ließ mich jedoch nicht los und so habe ich auf der Zugfahrt nach Hause nochmal nachgelesen, was es mit GnuPG und OpenPGP auf sich hat. Denn dass ich mich zuletzt damit beschäftigt hatte, war schon eine Weile her.

Mein ThinkPad T14s Gen1 besitzt einen Smartcard-Leser, den ich bisher noch nie verwendet hatte. Dieser lachte mich geradezu an und vielleicht half noch der ein oder andere Satz von Christian und ich bestellte mir die OpenPGP Smart Card V3.4 + MiFare DESFire im FLOSS-Shop.

Inbetriebnahme von Kartenleser und Erkennen der Karte

Das kann doch nicht so schwer sein. Das ist doch schnell erledigt.

Berühmte letzte Worte unbekannter Herkunft.
~]$ gpg --card-status
gpg: selecting card failed: No such device
gpg: OpenPGP card not available: No such device

Vorstehender Code-Block zeigt, dass es nicht auf Anhieb klappte. Dann halt erstmal Fehlersuche bzw. die Suche nach Dokumentation und Anleitungen.

Der erste Fehler war schnell gefunden. Der Smartcard-Leser war im UEFI noch deaktiviert. Ich habe die Angewohnheit, alle Geräte, die ich nicht regelmäßig verwende, dort abzuschalten. Nachdem der Kartenleser aktiviert war, wurde er auch von Linux erkannt – von gpg jedoch nicht.

Auf der Produktseite wird folgende URL zu Anleitungen und Erklärungen zu GnuPG, Kartenlesern mit und ohne Pinpad und zur Einrichtung und Verwendung der OpenPGP-Karte verlinkt: https://wiki.datenkollektiv.net/public/gnupg/gnupg-card-howto. Leider lieferte dieser Link einen HTTP-502-Fehler zurück, als ich die Seite gebraucht hätte. Also habe ich das Sprachmodell meiner Wahl um Rat gebeten, welches mir geraten hat, doch erstmal die erforderlichen Treiber und Tools zur Nutzung des Kartenlesers zu installieren. Na gut:

~]$ sudo dnf install pcsc-lite pcsc-lite-ccid pcsc-tools
~]$ sudo systemctl enable --now pcscd.service

Leider war es damit noch nicht getan und das Sprachmodell fing langsam das Halluzinieren an. Also bediente ich mich der Suchmaschine meines geringsten Misstrauens und recherchierte auf althergebrachte Weise. Ich war schon ziemlich genervt, als ich endlich einen passenden Hinweis in der Nitrokey-Dokumentation fand. Nachdem ich diese durchgearbeitet hatte, war ich einen großen Schritt weiter:

~]$ gpg --card-status
Reader ...........: Alcor Micro AU9540 00 00
Application ID ...: D27600012401030400050000DA260000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: ZeitControl
Serial number ....: 0000DA26
Name of cardholder: [not set]
Language prefs ...: de
Salutation .......: 
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 64 64 64
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: off
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

Die Karte wird von gpg erkannt, ist wie erwartet noch leer und kann nun endlich benutzt werden. Die Karte ist mit einer PIN und einer Admin-PIN versehen, welche bei bestimmten Operationen bzw. zum Entsperren der Karte abgefragt werden. Beide PINs sind auf individuelle PINs zu ändern. Sonst ist das Ganze sinnlos (siehe --change-pin).

GPG-Schlüssel auf der Karte generieren

Ab hier hilft die Manpage gpg(1) weiter. Der folgende Code-Block zeigt die Abfolge von Befehlen zur Generierung von GPG-Schlüsseln auf der Karte:

~]$ gpg --edit-card

Reader ...........: Alcor Micro AU9540 00 00
Application ID ...: D27600012401030400050000DA260000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: ZeitControl
Serial number ....: 0000DA26
Name of cardholder: [not set]
Language prefs ...: de
Salutation .......: 
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 64 64 64
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: off
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

gpg/card> admin
Admin commands are allowed

gpg/card> generate
Make off-card backup of encryption key? (Y/n) Y

Please note that the factory settings of the PINs are
   PIN = '123456'     Admin PIN = '12345678'
You should change them using the command --change-pin

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

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

Real name: Bob
Email address: bob@example.com
Comment: der Baumeister
You selected this USER-ID:
    "Bob (der Baumeister) <bob@example.com>"

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.
rogpg: Note: backup of card key saved to '/home/jkastning/.gnupg/sk_9C88B267003429CB.gpg'
gpg: revocation certificate stored as '/home/jkastning/.gnupg/openpgp-revocs.d/2B3FFC727504AFFAEF0C50C080B662D727FEFF5F.rev'
public and secret key created and signed.

pub   rsa2048 2026-10-23 [SC]
      2B3FFC727504AFFAEF0C50C080B662D727FEFF5F
uid                      Bob (der Baumeister) <bob@example.com>
sub   rsa2048 2026-10-23 [A]
sub   rsa2048 2026-10-23 [E]


gpg/card> list

Reader ...........: Alcor Micro AU9540 00 00
Application ID ...: D27600012401030400050000DA260000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: ZeitControl
Serial number ....: 0000DA26
Name of cardholder: [not set]
Language prefs ...: de
Salutation .......: 
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 64 64 64
PIN retry counter : 3 0 3
Signature counter : 4
KDF setting ......: off
Signature key ....: 2B3F FC72 7504 AFFA EF0C  50C0 80B6 62D7 27FE FF5F
      created ....: 2026-10-23 18:42:38
Encryption key....: 35CD 7AA9 CADB CA74 6103  C261 9C88 B267 0034 29CB
      created ....: 2026-10-23 18:42:38
Authentication key: 04C5 D0D4 E501 B90A 51BF  85FE B6C6 967B EFF5 5EF9
      created ....: 2026-10-23 18:42:38
General key info..: 
pub  rsa2048/80B662D727FEFF5F 2026-10-23 Bob (der Baumeister) <bob@example.com>
sec>  rsa2048/80B662D727FEFF5F  created: 2026-10-23  expires: never     
                                card-no: 0005 0000DA26
ssb>  rsa2048/B6C6967BEFF55EF9  created: 2026-10-23  expires: never     
                                card-no: 0005 0000DA26
ssb>  rsa2048/9C88B267003429CB  created: 2026-10-23  expires: never     
                                card-no: 0005 0000DA26

gpg/card>

Fertig. Auf der Karte befinden sich nun je ein Schlüsselpaar zum Signieren, Ver- und Entschlüsseln und für die Authentisierung (z.B. an einem SSH-Dienst). Ein Backup und ein Widerrufszertifikat wurden in folgenden Pfaden gespeichert:

  • Backup: .gnupg/sk_9C88B267003429CB.gpg
  • Widerrufszertifikat: .gnupg/openpgp-revocs.d/2B3FFC727504AFFAEF0C50C080B662D727FEFF5F.rev

Das Off-Card-Backup enthält nur den Encryption Key, nicht aber den Primärschlüssel. Ich empfehle, beide Dateien sicher und offline aufzubewahren. Sie sollten nicht auf dem Host verbleiben, wo sie kompromittiert werden können. Die Schaltkreise auf der Smartcard verhindern, dass der geheime/private Schlüssel von der Karte ausgelesen werden kann. So ist auch eine nachträgliche Erstellung einer weiteren Sicherheitskopie nicht möglich. Achtung: Mit dem Off-Card-Backup können nicht alle Schlüssel wiederhergestellt werden. Dies wird in meinen Augen im GnuPG HOWTO nicht deutlich.

Mir ist bei der Generierung aufgefallen, dass ich weder das Verfahren noch die Schlüssellänge auswählen konnte. Es wurde RSA 2048 Bit gewählt. Das ist mir ehrlich gesagt zu kurz. Leider gibt weder gpg(1) noch das GnuPG Smartcard HOWTO Hinweise, ob sich die Schlüssellänge beeinflussen lässt. Erst durch Suchen und Ausprobieren habe ich herausgefunden, dass man diese Parameter mit dem Admin-Befehl key-attr ändern kann. Der folgende Code-Block zeigt den Weg dorthin:

~]$ gpg --edit-card
…
gpg/card> admin
Admin commands are allowed

gpg/card> key-attr
Changing card key attribute for: Signature key
Please select what kind of key you want:
   (1) RSA
   (2) ECC
Your selection? 2
Please select which elliptic curve you want:
   (1) Curve 25519 *default*
   (4) NIST P-384
   (6) Brainpool P-256
Your selection? 
The card will now be re-configured to generate a key of type: ed25519
Note: There is no guarantee that the card supports the requested
      key type or size.  If the key generation does not succeed,
      please check the documentation of your card to see which
      key types and sizes are supported.
Changing card key attribute for: Encryption key
Please select what kind of key you want:
   (1) RSA
   (2) ECC
Your selection?

Für die folgenden Beispiele nutze ich jedoch weiterhin den bereits erstellten rsa2048-Schlüssel.

Im Schlüsselbund des Hosts werden die Schlüssel wie folgt dargestellt:

~]$ gpg --list-keys
pub   rsa2048 2026-10-23 [SC]
      2B3FFC727504AFFAEF0C50C080B662D727FEFF5F
uid           [ultimate] Bob (der Baumeister) <bob@example.com>
sub   rsa2048 2026-10-23 [A]
sub   rsa2048 2026-10-23 [E]

~]$ gpg --list-secret-keys
sec>  rsa2048 2026-10-23 [SC]
      2B3FFC727504AFFAEF0C50C080B662D727FEFF5F
      Card serial no. = 0005 0000DA26
uid           [ultimate] Bob (der Baumeister) <bob@example.com>
ssb>  rsa2048 2026-10-23 [A]
ssb>  rsa2048 2026-10-23 [E]

Zuerst werden die öffentlichen Schlüssel angezeigt, die im Schlüsselbund des Hosts gespeichert sind. Ich empfehle, diese ebenfalls zu sichern und auf einem anderen Medium aufzubewahren. Gehen sie verloren, können sie nicht mithilfe der Smartcard rekonstruiert werden. Anschließend werden Informationen zu den privaten Schlüsseln ausgegeben. Das ‚>‘ hinter den Schlüsseln zeigt an, dass sich die geheimen/privaten Schlüssel auf einer Smartcard befinden und nicht im Schlüsselbund vorliegen.

Eine Datei signieren

Schlüsseloperationen funktionieren wie gewohnt. Statt der Passphrase wird man nach der PIN der Smartcard gefragt. Im folgenden Beispiel signiere ich eine Textdatei, wobei ich explizit angebe, welche User-ID für die Signatur benutzt werden soll. Anschließend verifiziere ich die Signatur:

~]$ gpg --sign --local-user bob@example.com datei
~]$ gpg --verify datei
datei      datei.gpg  
[jkastning@t14s ~]$ gpg --verify datei.gpg 
gpg: Signature made Fr 23 Okt 2026 21:31:44 CEST
gpg:                using RSA key 4384D92F686DC876A3CFF458E8AF43DE9E151FF3
gpg:                issuer "bob@example.com"
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   2  signed:   1  trust: 0-, 0q, 0n, 0m, 0f, 2u
gpg: depth: 1  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 1f, 0u
gpg: next trustdb check due at 2030-06-22
gpg: Good signature from "Bob (der Baumeister) <bob@example.com>" [ultimate]

Die Karte auf Werkseinstellungen zurücksetzen

Soll das Schlüsselmaterial von der Karte entfernt werden, z.B. weil man sie weitergeben möchte, kann sie wie folgt auf Werkseinstellungen zurückgesetzt werden:

~]$ gpg --edit-card

Reader ...........: Alcor Micro AU9540 00 00
Application ID ...: D27600012401030400050000DA260000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: ZeitControl
Serial number ....: 0000DA26
Name of cardholder: [not set]
Language prefs ...: de
Salutation .......: 
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 64 64 64
PIN retry counter : 3 0 3
Signature counter : 5
KDF setting ......: off
Signature key ....: 4384 D92F 686D C876 A3CF  F458 E8AF 43DE 9E15 1FF3
      created ....: 2026-10-23 19:29:37
Encryption key....: 245E CD79 8DF9 D0FE 233B  9C95 D955 9262 22CF B708
      created ....: 2026-10-23 19:29:37
Authentication key: 7C86 CC37 9C74 776B 162E  AE31 FD5C 43DB 9DCD 233E
      created ....: 2026-10-23 19:29:37
General key info..: 
pub  rsa2048/E8AF43DE9E151FF3 2026-10-23 Bob (der Baumeister) <bob@example.com>
sec>  rsa2048/E8AF43DE9E151FF3  created: 2026-10-23  expires: never     
                                card-no: 0005 0000DA26
ssb>  rsa2048/FD5C43DB9DCD233E  created: 2026-10-23  expires: never     
                                card-no: 0005 0000DA26
ssb>  rsa2048/D955926222CFB708  created: 2026-10-23  expires: never     
                                card-no: 0005 0000DA26

gpg/card> admin
Admin commands are allowed

gpg/card> factory-reset
gpg: OpenPGP card no. D27600012401030400050000DA260000 detected

gpg: Note: This command destroys all keys stored on the card!

Continue? (y/N) y
Really do a factory reset? (enter "yes") yes

gpg/card> list

Reader ...........: Alcor Micro AU9540 00 00
Application ID ...: D27600012401030400050000DA260000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: ZeitControl
Serial number ....: 0000DA26
Name of cardholder: [not set]
Language prefs ...: de
Salutation .......: 
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 64 64 64
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: off
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

gpg/card>

Bitte denkt dran, auch die entsprechenden Schlüssel aus dem Schlüsselbund eures Hosts zu entfernen. Damit ist der saubere Ausgangszustand wiederhergestellt.

Vorhandene Schlüssel auf die Smartcard verschieben

Bitte erstellt ein Backup des .gnupg-Verzeichnisses, denn eure privaten Schlüssel werden auf die Karte verschoben (nicht kopiert). Ihr könnt sie anschließend von der Karte nicht zurückholen.

Ich demonstriere hier, wie Beispiel-Schlüssel auf die Karte verschoben werden und werfe anschließend alles weg. Der folgende Code-Block zeigt den Vorgang:

~]$ gpg --edit-key B5248E9B6E71B11BD9B979E996E2980D6CF4189E
gpg (GnuPG) 2.4.9; Copyright (C) 2025 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.

gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   2  signed:   1  trust: 0-, 0q, 0n, 0m, 0f, 2u
gpg: depth: 1  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 1f, 0u
gpg: next trustdb check due at 2030-06-22
sec  brainpoolP256r1/96E2980D6CF4189E
     created: 2026-10-24  expires: never       usage: SC  
     trust: ultimate      validity: ultimate
ssb  brainpoolP256r1/2403FEED88DD3FE9
     created: 2026-10-24  expires: never       usage: E   
[ultimate] (1). Kim <kim@example.com>

gpg> key 1

sec  brainpoolP256r1/96E2980D6CF4189E
     created: 2026-10-24  expires: never       usage: SC  
     trust: ultimate      validity: ultimate
ssb* brainpoolP256r1/2403FEED88DD3FE9
     created: 2026-10-24  expires: never       usage: E     
[ultimate] (1). Kim <kim@example.com>

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

sec  brainpoolP256r1/96E2980D6CF4189E
     created: 2026-10-24  expires: never       usage: SC  
     trust: ultimate      validity: ultimate
ssb* brainpoolP256r1/2403FEED88DD3FE9
     created: 2026-10-24  expires: never       usage: E     
[ultimate] (1). Kim <kim@example.com>

Note: the local copy of the secret key will only be deleted with "save".
gpg> save

Ich habe zuvor lokal einen GPG-Schlüssel mit dem Algorithmus Brainpool P-256 erstellt und anschließend den Encryption Key mit keytocard in den Encryption-Slot auf der Karte verschoben. Nicht im Code-Block zu sehen ist, wie ich den Hauptschlüssel in den Signatur-Slot der Karte verschoben habe. Die privaten Schlüssel von Kim befinden sich nun auf der Karte, was sich mit gpg --card-status überprüfen lässt:

~]$ gpg --card-status
Reader ...........: Alcor Micro AU9540 00 00
Application ID ...: D27600012401030400050000DA260000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: ZeitControl
Serial number ....: 0000DA26
Name of cardholder: [not set]
Language prefs ...: de
Salutation .......: 
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: forced
Key attributes ...: brainpoolP256r1 brainpoolP256r1 rsa4096
Max. PIN lengths .: 64 64 64
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: off
Signature key ....: B524 8E9B 6E71 B11B D9B9  79E9 96E2 980D 6CF4 189E
      created ....: 2026-10-24 18:20:39
Encryption key....: 203F 7E4C 23A0 BB06 DB51  B3E9 2403 FEED 88DD 3FE9
      created ....: 2026-10-24 18:20:39
Authentication key: [none]
General key info..: pub  brainpoolP256r1/96E2980D6CF4189E 2026-10-24 Kim <kim@example.com>
sec>  brainpoolP256r1/96E2980D6CF4189E  created: 2026-10-24  expires: never     
                                        card-no: 0005 0000DA26
ssb>  brainpoolP256r1/2403FEED88DD3FE9  created: 2026-10-24  expires: never     
                                        card-no: 0005 0000DA26
ssb   brainpoolP256r1/5B658E197413BAE0  created: 2026-10-24  expires: never

Die Ausgabe von gpg --list-secret-keys zeigt ebenfalls durch das ‚>‘-Zeichen an, dass die privaten Schlüssel auf einer Smartcard liegen:

~]$ gpg --list-secret-keys
sec>  brainpoolP256r1 2026-10-24 [SC]
      B5248E9B6E71B11BD9B979E996E2980D6CF4189E
      Card serial no. = 0005 0000DA26
uid           [ultimate] Kim <kim@example.com>
ssb>  brainpoolP256r1 2026-10-24 [E]

Tut euch selbst einen Gefallen und prüft im Vorfeld, welche Algorithmen ihr für eure Schlüssel verwendet und welche von eurer Smartcard unterstützt werden. Versucht ihr, Schlüssel auf die Karte zu verschieben, die von der Smartcard nicht unterstützt werden, schlägt dies mit kryptischen Fehlermeldungen fehl. Diese sind so irreführend, dass ich ein Sprachmodell um Rat bitten musste, um meinem Fehler auf die Spur zu kommen. Ich hatte zuerst versucht, Schlüssel mit dem Algorithmus Curve 25519 auf die Karte zu verschieben. Dieser wird von der Karte nicht unterstützt. Die Fehlermeldung behauptete jedoch, ich hätte die Admin-PIN falsch eingegeben.

Ähnliche Erfahrungen habe ich gemacht, als ich mit dem Befehl key-attr die Einstellungen für die Key-Slots auf Parameter ändern wollte, welche von der Karte nicht unterstützt werden. Auch hier deutete die Fehlermeldung auf eine falsche Admin-PIN hin.

Fazit

Mit 22,00 Euro zzgl. Versandkosten ist die OpenPGP Smart Card V3.4 + MiFare DESFire erschwinglich, sieht schick aus und passt gut ins Portemonnaie. Darüber hinaus passt sie selbstverständlich auch gut in die Smartcard-Leser, die in vielen ThinkPad-Modellen (und ebenfalls in Business-Laptops anderer Hersteller) verbaut sind.

GnuPG-Dokumentation und -Howto sind zum Thema Smartcard alt und lückenhaft. Es bedarf eines gewissen technischen Interesses und Durchhaltewillens, um hier bis ans Ziel zu kommen. Aus meiner Sicht ist dies klar ein Nischenthema für Nerds und Menschen, die zur Nutzung dieser Technologie gezwungen sind.

Ich selbst bevorzuge, ein Offline-Backup meiner Schlüssel sicher aufzubewahren und vorhandene Schlüssel auf die Smartcard zu verschieben. Denn so kann ich meine GnuPG-Konfiguration wiederherstellen, falls die Smartcard kaputtgeht oder ich zukünftig ein Endgerät ohne Smartcard-Slot verwende.

Links zu verwandten Beiträgen

❌