Einführung
Hier wird ein Setup von GnuPG beschrieben, welches den privaten Teil vom Primary Key auf einem verschlüsselten USB Stick offline speichert. Dies hat folgende Vorteile: Wird in das System eingebrochen, hat der Angreifer nur Zugriff auf die Subkeys und nicht auf den Primary Key. Dann muss man nicht alle Keys widerrufen, sondern nur die Subkeys. Dies hat bedeutet, dass die vorhandenen Key Signaturen behalten werden können und man nach belieben neue Keys zum Verschlüsseln und Signieren generieren kann ohne den Personen den neuen Key mitzuteilen, da der Primary Key unverändert bleibt.
GPG Key generieren
Diese Anleitung basiert auf der GnuPG Version 2.1.1
.
Zuerst wird ein neuer GPG Key generiert. Dies wird mit der Option
--full-gen-key
gemacht, da man nur damit eine eigene Schlüsselgrösse angeben
kann.
$ gpg --full-gen-key
Folgende Angaben werden benötigt:
(1) RSA and RSA (default)
: Algorithmus zum Verschlüsseln und Signieren4096
: Schlüsselgrösse wird 4096 Bit2y
: Der Schlüssel läuft in zwei Jahren automatisch ab- (Hinweis: Das Ablaufdatum kann aber jederzeit geändert werden. Falls man den Schlüssel aber verlieren sollte, ist man froh, wenn dieser automatisch nach einer gewissen Zeit ungültig wird)
Rainer Zufall
: Vorname und Namerainer.zufall@example.net
: E-Mail Adresse
Dann wird man aufgefordert eine Passphrase einzugeben. Mit dieser wird der Key
geschützt und sollte deshalb nicht zu einfach sein. Dauert das Generieren des
Keys zu lange, liegt das daran, dass das Device /dev/random
nur sehr wenig
Zufallswerte liefert. Durch Tastatureingaben und Mausbewegungen wird mehr
Entropie erzeugt. Hilfreich ist das Installieren und Aktivieren von haveged
,
ein Daemon welcher mehr Zufallszahlen generiert. Haveged gilt als sicher.
In diesem Beispiel hat der Key die Key ID 0xB1940999
erhalten.
Zusätzliche User IDs hinzufügen
Möchte man den Key für verschiedene E-Mail Adressen verwenden, kann man zusätzliche User IDs hinzufügen:
$ gpg --edit-key 0xB1940999
gpg> adduid
Real name: Rainer Zufall
Email address: rainer.zufall@example.org
gpg> save
Keys und ihre Eigenschaften anzeigen
Mit -K
werden die Private Keys aufgelistet. Mit -k
werden die Public Keys
aufgelistet. Für welche Zwecke die Schlüssel benutzt werden können, ist mit der
Option --list-options show-usage
zu sehen.
$ gpg --list-options show-usage -K 0xB1940999
sec rsa4096/B1940999 2014-12-29 [SC] [expires: 2016-12-28]
uid [ultimate] Rainer Zufall <rainer.zufall@example.org>
uid [ultimate] Rainer Zufall <rainer.zufall@example.net>
ssb rsa4096/3EF3EA29 2014-12-29 [E] [expires: 2016-12-28]
</rainer.zufall@example.net></rainer.zufall@example.org>
Die erste Zeile gibt an, dass dies ein Private Key ist (sec). Danach sieht man die zwei erstellten User IDs. In der letzten Zeile sieht man, dass wir ein Subkey haben.
Was man mit den Keys machen kann, ist in den eckigen Klammern beschrieben.
Dieses Verhalten finde ich nützlich und kann mittels list-options show-usage
in der Konfigurationsdatei ~/.gnupg/gpg.conf
standardmässig aktiviert werden.
Zusätzlich ergänzte ich die Konfigurationsdatei mit keyid-format 0xshort
,
damit die Key IDs mit führendem 0x
angezeigt werden. Aus der Manpage von gpg
liest man zu den Verwendungszwecken folgendes:
E
= encryption: Nachrichten ver/entschlüsselnS
= signing: Nachrichten signieren / Signatur von Nachrichten überprüfenC
= certification: Keys signieren / Signatur von Keys überprüfenA
= authentication: Sich gegenüber einem Dienst ausweisen
Der Primary Key 0xB1940999
wird also zum Signieren und zum Zertifizieren
benötigt. Der Subkey wird zum entschlüsseln benötigt.
Unser Ziel ist es ein separater Key zum Signieren und Zertifizieren zu erstellen.
Separater Key zum signieren erstellen
Jetzt erstellen wir ein neuen Subkey, mit welchem nur signiert wird:
$ gpg --edit-key 0xB1940999
gpg> addkey
(4) RSA (sign only)
[...]
gpg> save
Der Vorgang ist gleich wie beim erzeugen eines komplett neuen Keys, ausser das
als Typ (4) RSA (sign only)
ausgewählt wird.
Werden jetzt die Private Keys aufgelistet, sieht man, dass ein neuer Key
vorhanden ist, mit welchem man Nachrichten signieren ( [S]
) kann (letzte
Zeile):
$ gpg -K
/home/emanuel/.gnupg/pubring.kbx
--------------------------------
sec rsa4096/0xB1940999 2014-12-29 [SC] [expires: 2016-12-28]
uid [ultimate] Rainer Zufall <rainer.zufall@example.org>
uid [ultimate] Rainer Zufall <rainer.zufall@example.net>
ssb rsa4096/0x3EF3EA29 2014-12-29 [E] [expires: 2016-12-28]
ssb rsa4096/0xD142AA3C 2014-12-29 [S] [expires: 2016-12-28]
</rainer.zufall@example.net></rainer.zufall@example.org>
Zusammengefasst sieht unser Setup jetzt so aus:
- Der Primary Key
0xB1940999
kann signieren und zertifizieren - Der Subkey
0x3EF3EA29
kann entschlüsseln - Der Subkey
0xD142AA3C
kann signieren
Wir möchten privaten Teil vom Schlüssel 0xB1940999
auf ein verschlüsselten USB Stick auslagern.
Keys publizieren
Zuerst konfiguriert man GnuPG, dass ein Keyserver aus einem Pool ausgewählt
wird. So hat man keine Probleme, falls der fix eingestellte Keyserver nicht
erreichbar sein sollte. Dies wird in der Konfigurationsdatei ~/.gnupg/gpg.conf
mit keyserver
angegeben. Mit no-honor-keyserver-url
sagt man, dass immer der
lokal eingetragene Keyserver aus dem Pool verwendet werden soll.
keyserver hkps://hkps.pool.sks-keyservers.net
keyserver-options no-honor-keyserver-url
Der Key kann folgendermassen auf ein Keyserver geladen werden:
$ gpg --send-keys 0xB1940999
So kann auf Keyservern nach Public Keys gesucht werden:
$ gpg --search-key Rainer Zufall
Möchte man den Public Key exportieren um beispielsweise auf einer Webseite zu veröffentlichen, kann das so gemacht werden:
$ gpg --armor --export-options export-minimal --export 0xB1940999
Backup der Keys erstellen
Um ein Backup der Keys zu erstellen, kann man das ganze ~/.gnupg
Verzeichnis auf ein externes Medium speichern und sicher aufbewahren. Dieses Medium kann zusätzlich verschlüsselt werden (vgl. nächstes Kapitel).
$ cp -r .gnupg/ /mnt/securedevice
Ein Wiederrufszertifikat kann folgendermassen erstellt werden:
$ gpg --gen-revoke --armor 0xB1940999 > 0xB1940999_revoke.asc
Der Private Key inklusive die privaten Subkeys können folgendermassen exportiert und allenfalls auch ausgedruckt sicher aufbewahrt werden:
$ gpg --armor --export-secret-keys 0xB1940999 > 0xB1940999_private_keys.asc
Verschlüsselten USB Stick erstellen
Hierzu löscht man alle vorhandenen Partitionen und fügt eine neue hinzu. Dies kann man beispielsweise mit cfdisk
machen. In meinem Beispiel wurde dem USB Stick das Device /dev/sdc
zugewiesen.
$ sudo cfdisk /dev/sdc
Jetzt verschlüsselt man mit cryptsetup
das Device:
$ sudo cryptsetup -c aes-xts-plain -y -s 512 luksFormat /dev/sdc1
WARNING!
========
This will overwrite data on /dev/sdc1 irrevocably.
Are you sure? (Type uppercase yes): YES
Enter passphrase:
Verify passphrase:
Das Blöckgerät kann folgendermassen entschlüsselt werden:
$ sudo cryptsetup luksOpen /dev/sdc1 securegpg
Enter passphrase for /dev/sdc1:
Nach dem Eingeben der Passphrase gibt es ein neues Gerät in /dev/mapper/securepgp
. Auf dem wird ein neues Dateisystem angelegt:
$ mkfs.ext4 /dev/mapper/securegpg
Dieses Dateisystem kann gemountet werden:
$ mount /dev/mapper/securegpg /media/securegpg
Folgendermassen entfernt man den USB Stick wieder vom System:
$ umount /media/securegpg
$ cryptsetup luksClose /dev/mapper/securegpg
Der USB Stick ist jetzt einsatzbereit.
Privaten Primary Key auf USB Stick auslagern
Zuerst mounten wir den USB Stick und kopieren das Verzeichnis ~/.gnupg
darauf:
$ sudo cryptsetup luksOpen /dev/sdc1 securegpg
Enter passphrase for /dev/sdc1:
$ mount /dev/mapper/securgpg /media/securegpg
$ cp -r .gnupg /media/securegpg/
Dann löschen wir alle Private Keys (es gibt keine Option zum nur den Primary Key ohne die Subkeys zu löschen):
$ gpg --delete-secret-keys 0xB1940999
Da dies eine eher heikle Operation ist, müssen wir diese für jeden Privat Key bestätigen.
Jetzt besitzen wir aber gar kein Private Key mehr im Verzeichnis ~/.gnupg
. Der
Primary Key wollen wir dort nicht haben, aber die zwei Subkeys zum Entschlüsseln
und Zertifizieren. In GnuPG kann mit der Option --homedir
das GnuPG
Verzeichnis mit dem Schlüsselmaterial angegeben werden. So können wir die
Subkeys vom USB Stick exportieren und in die lokale Installation importieren:
$ gpg --homedir /mnt/securegpg/.gnupg/ --export-secret-subkeys | gpg --import
Dazu müssen wir die Passphrases der Private Keys eingeben.
Werden jetzt die Private Keys aufgelistet, sieht man am Hash ( #
), dass der
private Teil des Primary Keys fehlt, aber der Subkeys vorhanden sind.
$ gpg -K
/home/emanuel/.gnupg/pubring.kbx
--------------------------------
sec# rsa4096/0xB1940999 2014-12-29 [SC] [expires: 2016-12-28]
uid [ultimate] Rainer Zufall <rainer.zufall@example.org>
uid [ultimate] Rainer Zufall <rainer.zufall@example.net>
ssb rsa4096/0x3EF3EA29 2014-12-29 [E] [expires: 2016-12-28]
ssb rsa4096/0xD142AA3C 2014-12-29 [S] [expires: 2016-12-28]
</rainer.zufall@example.net></rainer.zufall@example.org>
Somit ist unser Ziel erreicht: Der Private Teil des Primary Keys ist nur noch
auf dem USB Stick gespeichert. Wenn wir jetzt Nachrichten signieren, wird der
Subkey 0xD142AA3C
verwendet und nicht der Primary Key.
Eigenen Key signieren lassen
Man kann sich wie gewohnt der Primary Key signieren lassen. An diesem Vorgang ändert sich nichts.
Fremde Keys signieren
Der Vorgang um fremde Keys zu signieren ist folgnder:
- Fremder Public Key importieren
- Fingerprint überprüfen
- Falls OK, weiterfahren. Sonst abbrechen.
- USB Stick entschlüsseln und mounten.
- Public Key exportieren auf USB Stick importieren
- Public Key auf USB Stick signieren
- Public Key wieder auf die Keyserver hochladen
- Signierter Key vom USB Stick exportieren und lokal importieren
Angenommen ich möchte den Key 0x23F00BA2
signieren. Dabei geht man folgendermassen vor:
Key von Keyserver importieren:
$ gpg --recv-key 0x23F00BA2
Der Key kann auch von einer Datei importiert werden:
$ gpg --import < key.asc
Fingerprint anzeigen und mit Fingerprint vergleichen, welcher man von der Person erhalten hat.
$ gpg --fingerprint 0x23F00BA2
Falls der Fingerprint ok ist, fährt man weiter. Sonst bricht man ab.
Jetzt wird der USB Stick eingesteckt und gemountet:
$ sudo cryptsetup luksOpen /dev/sdc1 securegpg
Enter passphrase for /dev/sdc1:
$ mount /dev/mapper/securegpg /media/securegpg
Dann wird der Key exportiert und auf dem USB Stick importiert:
$ gpg --export 0x23F00BA2 | gpg --homedir /media/securegpg --import
Und anschliessend auf der GnuPG Installation vom USB Stick signiert:
$ gpg --homedir /media/securegpg --sign-key 0x23F00BA2
Der signierte Key kann wieder auf die Keyserver geladen werden:
$ gpg --homedir /media/securegpg --send-keys 0x23F00BA2
Damit der signierte Key auch lokal vorhanden ist, kann man den vom USB Stick exportieren und lokal wieder importieren:
$ gpg --homedir /media/securegpg --export 0x23F00BA2 | gpg --import
Am Schluss wird der USB Stick wieder entfernt:
$ umount /media/securegpg
$ cryptsetup luksClose /dev/mapper/securegpg
Falls der gpg-agent
noch auf dem Dateisystem sitzt, kann man diesen mit pkill gpg-agent
stoppen. Bei der nächsten Verwendung von GnuPG wird dieser wieder gestartet.
Jetzt ist der Vorgang abgeschlossen: Der Key 0x23F00BA2
wurde mit dem Private
Key welcher sich auf dem USB Stick befindet signiert, auf die Keyserver geladen
und in der lokalen GnuPG Installation importiert.
Fremde Keys mit einem Skript signieren
Der obige Vorgang sieht etwas kompliziert aus und ist wenn man oft Keys signiert nicht sehr praktisch. Folgendes Skript nimmt einem die Tipparbeit ab:
#!/usr/bin/env bash
KEY="$1"
SECUREDEVICE="/dev/${2:-sdc1}"
SECUREDEVICENAME="securegpg"
SECUREHOME="/media/securegpg"
SECUREGPGDIR="$SECUREHOME/.gnupg"
PrintUsage(){
cat <<< EOI
Usage:
securegpgsign key [devicename]
securegpgsign -h | --help
Default Device name is sdc1
Examples:
securegpgsign 0x23FOOBA2
securegpgsign 0x23FOOBA2 sde
EOI
}
if [[ $TEST == "-h" || $TEST == "--help" ]]
then
PrintUsage
fi
if (($# < 1))
then
PrintUsage
exit 1
fi
gpg --recv-key "$KEY"
gpg --fingerprint "$KEY"
echo "Is the fingerprint correct?"
echo "Press Enter to continue or ^C to canel."
read
cryptsetup luksOpen "$SECUREDEVICE" "$SECUREDEVICENAME"
mount "/dev/mapper/$SECUREDEVICENAME" "$SECUREHOME"
gpg --export "$KEY" | gpg --homedir "$SECUREGPGDIR" --import
gpg --homedir "$SECUREGPGDIR" --sign-key "$KEY"
gpg --homedir "$SECUREGPGDIR" --send-keys "$KEY"
gpg --homedir "$SECUREGPGDIR" --export "$KEY" | gpg --import
pkill gpg-agent
umount "$SECUREHOME"
cryptsetup luksClose "/dev/mapper/$SECUREDEVICENAME"
Mit dem Skript kann folgendermassen ein Key signiert werden:
sudo ./securegpgsign 0x23FOOBA2 sde
Die aktuellste Version davon gibt es auf GitHub in meinem Scripts Repository: securegpgsign.
Wir kein Devicename angegeben, wird sdc
verwendet. Das Skript muss mit sudo
aufgerufen werden, da das Einbinden des USB Sticks Rootrechte erfordert.
Links und weitere Informationen
- Haveged: http://www.issihosts.com/haveged/
- OpenPGP Best Practices: https://help.riseup.net/en/security/message-security/openpgp/best-practices
- Generating More Secure GPG Keys: A Step-by-Step Guide: http://spin.atomicobject.com/2013/11/24/secure-gpg-keys-guide/