In der Ausgabe 05/2014 der dotnetpro habe ich – im Rahmen der Rubrik „Frameworks“ – Bouncy Castle unter die Lupe genommen. Dabei handelt es sich um eine Bibliothek mit kryptographischen Funktionen. Also übersetzt für das Ver- und Entschlüsseln von Daten. Trotz einer guten Bibliothek – und Bouncy Castle ist tatsächlich sehr gut und weit verbreitet – können bei dem sensiblen Thema Verschlüsselung immer wieder Fehler passieren.
Fehler, die auch keine Bibliothek verhindern kann, wie die Überschrift so schön heißt. Egal wie gut die Bibliothek tatsächlich ist. Denn: nachdenken müssen wir als Entwickler immer noch selber. Auch wenn hin und wieder eine Bibliothek selbst ein Problem hervorrufen kann, wie der Artikel am Ende deutlich macht.
In der folgenden kleinen Auflistung möchte ich auf einige Fehler hinweisen, die mir selber auch schon passiert sind. Weil ich es einfach nicht besser wusste. Da konnte das Framework beziehungsweise die Bibliothek, die ich damals genutzt habe, überhaupt nichts für. War auch nicht alles unter .NET beziehungsweise C#. Trotzdem können die Fehler beliebig oft wiederholt werden :).
Der MD5-Algorithmus ist tabu!
Egal wie wir das drehen oder wenden. Ein MD5-Hashwert gilt schon länger als nicht mehr sicher. 1996 konnte die erste Kollision zweier unterschiedlicher Nachrichten nachgewiesen werden. Seit 2004 ist es möglich, Kollisionen systematisch zu erzeugen. Ein aktueller PC benötigt dazu nur noch Sekunden. Hoch parallele Grafikkarten können hunderte Millionen MD5-Hashwerte pro Sekunde berechnen, so dass die Hashfunktion praktisch als geknackt gilt. Ergo: Finger weg!
SHA1-Hashwerte für Passwörter speichern
Eine weitere Sache, die ich früher gerne gemacht habe. Na ja, nachdem ich MD5 nicht mehr als Hash für Passwörter in einer Datenbank genutzt habe :). An SHA1 ist zunächst nichts auszusetzen. Allerdings ist es schlecht, die reinen Hashwerte abzuspeichern, ohne die Salts. Damit ist eine zufällig generierte Zeichenkette gemeint, die beim Berechnen des Hashwertes für das eigentliche Passwort angehängt wird. Das Problem dabei ist, dass bei einem Angriff gleich eine ganze Reihe von Zugängen kompromittiert sein können. Nämlich alle Accounts, die das gleich Passwort nutzen – was an gleichen Hashwerten ersichtlichen ist. Durch den Salt, der für jeden Account unterschiedlich sein muss, unterscheiden sich auch alle Hashwerte, was einen Angriff deutlich schwieriger macht. 2012 passierte das beim LinkedIn-Hack. Die veröffentlichten Passwörter enthielten keinen Salt und so waren schon nach kurzer Zeit mehr als 60% der Passwörter geknackt.
DES ist veraltet
Auch wenn Bouncy Castle DES (Data Encryption Standard) unterstützt, sollte dieser nicht mehr zum Einsatz kommen. Er wurde mit einer effektiven Schlüssellänge von 56 Bit im Hinterkopf konzipiert, was mittlerweile nicht mehr ausreichend ist. Ich habe den Standard zwar noch im Artikel erwähnt, bin aber nicht näher darauf eingegangen, sondern habe den Nachfolger AES (Advanced Encryption Standard) vorgestellt. Das nicht ohne Grund. Bitte auf DES verzichten.
Auch ECB ist überholt
Mit ECB ist der Electronic Codebook Mode gemeint, der in Blöcken über den unverschlüsselten Eingabetext läuft und einen Block nach dem anderen verschlüsselt. Das Problem an dieser Methode ist, dass dadurch Muster in den Daten nicht mit verschlüsselt werden, sondern anschließend immer noch sichtbar sind. Ein Bildvergleich auf Wikipedia zeigt das sehr deutlich:
- Abb. 1: Das Originalbild.
- Abb. 2: Verschlüsselt mit dem ECB-Modus.
- Abb. 3: Verschlüsselt mit dem CBC-Modus.
Das Problem tritt mit dem CBC-Verfahren (Cipher-block chaining) nicht auf und sollte daher stattdessen zum Einsatz kommen. Bouncy Castle unterstützt beide Modi.
Fehlerhafte & ungenügende Startwerte
Dieses Problem tritt häufiger auf als gedacht. Um verschiedene Zufallszahlen zu erzeugen, ist es wichtig, dass der Generator mit einem zufälligen Seed, also Startwert, initialisiert wird. Gleiche Seeds sollen gleiche Folgen von Zufallszahlen erzeugen, was beispielsweise für die Reproduzierbarkeit in wissenschaftlichen Experimenten wichtig ist. In der Praxis sind gleiche Zufallszahlen selten erwünscht. Insbesondere nicht bei der Verschlüsselung. Die Bibliothek Portable.Licensing, über die ich ebenfalls im Rahmen der Rubrik „Frameworks“ geschrieben habe, litt unter so einem Fehler. Um es aber gleich vorweg zu nehmen: seit der Version 1.1.0, die mittlerweile vor über einem Jahr veröffentlicht wurde, ist der Fehler behoben.
Hintergrund des Problems war – beziehungsweise ist – Bouncy Castle. In diesem Fall war die Bibliothek für einen Fehler verantwortlich. Bei der C#-Portierung wird, anders als in der Java-Version, standardmäßig kein Startwert für den Zufallszahlengenerator gesetzt. Wenn also explizit kein Seed gesetzt wird, ist der Startwert statisch. Das ist sehr unschön. Bei Portable.Licensing führt das dazu, dass immer gleiche private und öffentliche Schlüssel erzeugt wurden. Ein schwerwiegender Fehler. An der betreffenden Zeile 41 des C#-Codes von Bouncy Castle ist nur folgender Kommentar zu finden:
// TODO Compared to JDK, we don’t auto-seed if the client forgets – problem?
Ein ToDo-Kommentar… Wer kennt das nicht :). Und wenn es jetzt noch Zeile 42 gewesen wäre… Also immer darauf achten, dass der Seed des Zufallszahlengenerators gesetzt und zufällig ist.
Fazit
Fehler können immer passieren. Eine gute Bibliothek sorgt dafür, dass diese minimiert werden. Allerdings kann ebendiese Bibliothek auch für Fehler verantwortlich sein. Und gegen den Einsatz von fehlerhaften beziehungsweise veralteten Standards und Methoden ist sowieso kein Kraut gewachsen. Da hilft nur die eigene Denkleistung.
Dieser Artikel ist selbstverständlich nur ein kleiner Ausschnitt aus dem Themenbereich der Verschlüsselung. Er erhebt in keinster Weise Anspruch auf Vollständigkeit. Beim Artikel zu Bouncy Castle in der dotnetpro bin ich nur ins Grübeln geraten, was ich früher schon alles falsch gemacht habe und was mir mittlerweile hoffentlich nicht mehr passiert.
Schreibe einen Kommentar