Neulich, im Krypto-Sumpf... verschlüsseln und signieren mit OpenSSL

Daemotron

Well-Known Member
Ich weiß, der Standard-Ratschlag lautet: Finger weg von Krypto. In dem Fall versuche ich allerdings auch "nur", vorgefertigte Komponenten zu nutzen, um Backup-Dateien vor dem Wegspeichern auf einem potenziell unsicheren System zu verschlüsseln und zu signieren. Ich möchte das ganze nur mit OpenSSL umsetzen, da es nur ein Shell-Skript werden soll (damit fallen NaCl oder Sodium leider aus) und ich möglichst dafür kein Third Party Zeugs (z. B. GnuPG) installieren müssen möchte (Recovery soll aus einem Rettungssystem heraus möglich sein).

Folgendes Vorgehen habe ich mir bei Colin Percival und Daniel Bernstein's NaCl Bibliothek abgeguckt (falls ich das alles richtig verstanden habe):

  1. Datenstrom komprimieren (ich nutze dazu xz)
  2. Erzeugen eines Random Schlüssels, eines Random Salts und eines Random IVs plus ein Random HMAC Passwort
  3. Datenstrom verschlüsseln (in Ermangelung einer Salsa20 Implementierung in OpenSSL würde ich dazu aes265-cbc verwenden, mit dem soeben generierten Schlüssel, Salt & IV)
  4. Erstellung einer HMAC (in Ermangelung von Salsa20 und Poly1305 mit SHA512)
  5. Erstellung einer Signatur (in Ermangelung von Curve 25519 mit SHA512 und RSA)
  6. Verpacken von Schlüsseln, Salt und IV zusammen mit dem HMAC in einer Datei
  7. Diese Datei mit xz komprimieren
  8. Das Komprimat mit RSA verschlüsseln
Im Ergebnis hätte ich also drei Dateien: die eigentlichen Daten gepackt und AES-verschlüsselt, eine Signatur-Datei für die verschlüsselten Daten und eine RSA-verschlüsselte Datei mit den AES Schlüsseldaten und dem HMAC. Der HMAC ist dabei eigentlich doppelt gemoppelt (schließlich gibt es ja eine Signatur-Datei), andererseits gibt der HMAC ein gutes zusätzliches Padding für die AES Schlüsseldaten ab... Die Signatur muss übrigens aus praktischen Gründen in einer separaten Datei bleiben - sie ist einfach zu groß, um per RSA verschlüsselt zu werden.

Vorteil aus meiner Sicht:
Man benötigt immer nur den öffentlichen und privaten RSA Schlüssel zur Backup-Erstellung (verzichtet man auf die Signatur und verlässt sich ausschließlich auf den HMAC, benötigt man sogar nur den öffentlichen Schlüssel für die Backup-Erstellung; der private Schlüssel kann dann schön im Safe bleiben)

Potenzielle Risiken:
  • Wenn die Schlüsseldatei beschädigt wird, kommt man an das eigentliche Backup nicht mehr ran.
  • Jemand könnte die Schlüsseldateien aufmachen (wie wahrscheinlich ist sowas?) und käme dann an alles heran, könnte auch den Inhalt des Backups in bösartiger Weise manipulieren und mit einem veränderten HMAC Integrität vortäuschen... (insb. wenn auf die Signatur verzichtet wird, was aber das Leak-Risiko für den privaten RSA Schlüssel wiederum senkt...)
Wie bewertet Ihr die Sicherheit und die Praktikabilität bei diesem Vorgehen? Welche Fettnäpfe habe ich übersehen?
 
Finger weg von Krypto.

Zur Not würde ich an der Stelle halt statische GPG-Binaries für das Rettungssystem bauen und vorhalten oder so.
 
Ich denke, "Finger weg von Krypto" ist eher so gemeint, dass man nicht selbst implementieren sollte. Eine Anwendung der Verfahren unter Nutzung bestehender Implementierungen sollte doch wohl möglich sein. Oder verstehe ich da was falsch?

Rob
 
Prinzipiell ist der Hinweis korrekt.

Aber: Man muss unterscheiden zwischen der Eigenentwicklung einer Implementation eines Algorithmus (bspw: "Ich programmiere mir eine eigene AES-Bibliothek") und der Eigenentwicklung eines Sicherheits-"Protokolls".

Ein Protokoll ist die Abfolge der Anwendung von Aktionen um ein Ziel zu erreichen / Nachrichten auszutauschen - also sprechen wir in diesem Fall von einem Solchen.
Ziel des TE ist die verschlüsselte Ablage von Backupdaten unter der Anwendung "fremdentwickelter" Implementationen von Verschlüsselungstechniken, die aber selbst zu einem Protokoll zusammengebaut wurden.

Dieses Protokoll muss man eben auch auf Schwachstellen untersuchen, da ansonsten die Verwendung der eigentlich sicheren Bausteine erfolglos bleiben.
Leider hab ich im Moment wenig Zeit das o.g. genau zu untersuchen.

@TE: Evtl. kannst du die Idee mal auf http://security.stackexchange.com/ - da sind einige fähige Leute mit mehr Zeit :)

Gruß
Markus
 
Jemand könnte die Schlüsseldateien aufmachen
Die Schlüsseldatei kann selber ja noch paßwortgeschützt sein, so in der Art:
Code:
openssl pkcs8 -in RSApriv.pem -topk8 -v2 camellia256 -out RSAprivpk8.pem
rm RSApriv.pem
Ich denke auch, daß der Rat "Finger weg von Krypto" sich eher auf Programmierung und Verwendung der Bibliotheken bezieht. OpenSSL ist da ein wenig schlecht dokumentiert, wie man hört. Die Kommandozeilentools sind zwar ein wenig sperrig, aber im großen und ganzen schon okay.
 
Die Schlüsseldatei kann selber ja noch paßwortgeschützt sein, so in der Art:
Code:
openssl pkcs8 -in RSApriv.pem -topk8 -v2 camellia256 -out RSAprivpk8.pem
rm RSApriv.pem
Ach so, ich meinte damit eher die Dateien, in denen die one-time secrets und der HMAC gespeichert sind. Den RSA-Schlüssel könnte man auch direkt bei Erzeugung verschlüsseln, dann kommt erst gar nix unverschlüsselt auf Platte:
Code:
openssl genrsa -aes256 -out private.key 8192

Ich denke auch, daß der Rat "Finger weg von Krypto" sich eher auf Programmierung und Verwendung der Bibliotheken bezieht. OpenSSL ist da ein wenig schlecht dokumentiert, wie man hört. Die Kommandozeilentools sind zwar ein wenig sperrig, aber im großen und ganzen schon okay.
Markus hat schon recht, hier geht es um's Protokoll - OpenSSL CLI Tools implementieren eher Primitiven und müssen noch richtig zusammengesetzt werden. Würde ich z. B. obiges Beispiel mit AES im CBC Modus durchziehen (das ist immerhin der Default bei OpenSSL), aber auf HMAC und/oder Signatur verzichten, wäre das Konstrukt durch einen Padding Oracle Angriff kompromittierbar. Der Teufel steckt halt selbst bei Shell-Skripten in solchen Details...
 
Hi Tronar, danke für den Hinweis, das war mir noch nicht bewusst. Man kann RSA Schlüssel tatsächlich direkt im PKCS#8 Format erzeugen:
Code:
openssl genpkey -aes-256-cbc -algorithm RSA -pkeyopt 'rsa_keygen_bits:8192' -out private.key
openssl pkey -in private.key -out public.key -pubout
 
Danke, Daemotron, das war wiederum mir noch nicht bewußt. (Und wo steht das eigentlich, daß er mit diesem Kommando wirklich PKCS#8 macht?)
Es gibt in OpenSSL etliche neuere Subkommandos wie "genpkey", wohingegen dann solche wie "genrsa" wohl als obsolet anzusehen sind. Kennt jemand von Euch da eine Zusammenstellung, wie man OpenSSL zeitgemäß einsetzen sollte bzw. welche Subkommandos man heute eher vergessen kann?
 
Ich hab mal gehört, dass das OpenSSL-CLI mehr oder weniger ein Tor für die Entwickler in die Lib ist und gar nicht für echte "Endanwender" gedacht ist. Wirklich einsetzen sollte man komplette Kryptosysteme, die die Lib (hoffentlich richtig) benutzen.

Kann aber auch alles nur Gerücht sein.
 
Leider nein... in manchen man pages steht es drin, dass das Tool obsolet ist, aber konsequent dokumentiert ist das nicht. Hier ein Beispiel aus der rsa man page:
The rsa command processes RSA keys. They can be converted between various forms and their components printed out. Note this command uses the traditional SSLeay compatible format for private key encryption: newer applications should use the more secure PKCS#8 format using the pkcs8 utility.

genpkey ist ziemlich neu; wurde erst mit 1.0.0 eingeführt. In dessen man page wiederum steht, man solle es bevorzugen:
The use of the genpkey program is encouraged over the algorithm specific utilities because additional algorithm options and ENGINE provided algorithms can be used.
Da fehlt aber der klare Hinweis, dass genpkey endlich umsetzt, was die Entwickler schon früher in der rsa man page vermerkt haben. In der genrsa man page fehlt gleich jeglicher Hinweis auf PKCS#8 und genpkey.

Die besten Hinweise finden sich noch im Changelog (http://openssl.org/news/changelog.html); dieses ist aber nicht wirklich übersichtlich gestaltet. Ansonsten gibt es noch eine Wiki-Seite (https://wiki.openssl.org/index.php/Command_Line_Utilities), auf der die neueren Tools teilweise erwähnt werden; alte Tools aber nicht als deprecated gekennzeichnet sind.

Aus dem Changelog habe ich mir folgendes zusammengereimt:
  • Zur Generierung von asymmetrischen Schlüsselpaaren nutze man genpkey anstelle der älteren Algorithmus-spezifischen Tools (schon allein um in den Genuss von PKCS#8 zu gelangen)
  • Für's Schlüssel-Handling (Konvertierung, Pubkey-Extraktion etc.) nutze man pkey anstelle der alten rsa und dsa Befehle (mehr oder minder aus demselben Grund)
  • Zur Generierung von Hashes nutze man dgst anstelle der Hash-spezifischen Befehle, da diese nicht mehr weiter gepflegt werden und neuere Hash-Algorithmen nur noch per dgst zur Verfügung stehen.
  • Für Pubkey Krypto nutze man pkeyutl anstelle von rsautl
  • Für shared secret Krypto nutze man weiterhin enc - das ist sozusagen alternativlos :ugly:
Die neueren Kommandos arbeiten i. d. R. mit PKCS#8 für die Ablage von Schlüsseln. Das kann man z. B. an den Headern recht gut erkennen:
Code:
# alt
$ openssl genrsa -aes256 -out private.x.key 2048
$ head -3 private.x.key
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,B1B2277F443D25C5D834D211F0DC958E

# neu
$ openssl genpkey -aes-256-cbc -algorithm RSA -pkeyopt 'rsa_keygen_bits:2048' -out private.s.key
$ head -3 private.s.key
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIEGuZCkYmoyUCAggA
MB0GCWCGSAFlAwQBKgQQRA5p/751N2ssfWsKBD+zuwSCBNB5zexli2sap8H+cXFn

Den älteren Container kann man dann wie von Martin Kleppermann beschrieben aufmachen.

Insgesamt werden die CLI Tools von OpenSSL wohl eher als Test-Spielzeuge für die Entwickler betrachtet (zumindest kann ich mich dieses Eindrucks nicht immer ganz erwehren); so ändert etwa OpenSSL die Ausgabeformate in inkompatibler Weise (z. B. openssl dgst -hex gibt je nach Version unterschiedliche Ausgaben - der Hashwert selbst bleibt natürlich gleich), enc kann noch immer nicht mit AEAD Chiffren umgehen, obwohl das Library Interface damit kein Problem hat, etc.

Ich setze da ein wenig Hoffnung auf LibreSSL - die haben es immerhin schon geschafft, enc so zu erweitern, dass es mit AEAD Chiffren umgehen kann. Den Zoo an CLI Tools haben sie aber noch nicht aufgeräumt; die Prio scheint momentan auf libtls zu liegen.
 
Ich hab mal gehört, dass das OpenSSL-CLI mehr oder weniger ein Tor für die Entwickler in die Lib ist und gar nicht für echte "Endanwender" gedacht ist. Wirklich einsetzen sollte man komplette Kryptosysteme, die die Lib (hoffentlich richtig) benutzen.

Kann aber auch alles nur Gerücht sein.
Teils stimmt das wohl; ich finde den Link grade nicht, aber ganz von der Hand zu weisen ist das nicht. Allerdings sollte das nicht für die Tools gelten, die "öffentliche" Funktionen erfüllen, wie etwa die Generierung von Schlüsseln, CSRs, etc.
 
Oh, und noch ein Anekdötchen dazu, wie sauber die CLI Tools implementiert sind:
Code:
$ grep 'goto' apps/*.c | wc -l
1738

$ ls -1 apps/*pkey*
apps/genpkey.c
apps/pkey.c
apps/pkeyparam.c
apps/pkeyutl.c

$ grep 'goto' apps/*pkey*.c | wc -l
52
Die Unsitte ist also mit den neueren Tools nicht ausgestorben... (getestet am Source Code von 1.0.2d)
 
Zurück
Oben