| 

.NET C# Java Javascript Exception

10
Hallo zusammen,

angeregt durch folgenden Beitrag (http://developer.pidgin.im/wiki/PlainTextPasswords) habe ich mir Gedanken gemacht, ob es einen Weg gibt die Zugangsdaten eines Benutzers sicher auf einem mobilen Gerät (welche Plattform sei mal dahin gestellt) zu speichern. Es geht mir nicht um eine konkrete Implementierung, sondern um Konzepte.

Im anfangs erwähnten Artikel werden vier Wege genannt mit dem Speichern von Passwörtern umzugehen:

  • Passwort hinter einem Passwort abspeichern: Erst nachdem man ein "Master-Passwort" eingegeben hat, wird die eigentliche Passwort-Datei entschlüsselt und man kommt an das gewünschte Passwort ran.

    Kommentar: Wenn ich erst ein Passwort eingeben muss, um ein anderes Passwort zu bekommen, kann ich es direkt sein lassen und das richtige Passwort verlangen?

  • Passwort verschleiern: Man kann das Passwort verschleiern, indem man beispielsweise base64 oder ähnliches anwendet. Oder mit einem festen Schlüssel ver- und entschlüsseln.

    Kommentar: Das halte ich für bedenklich und gefährlich. Der Benutzer sieht im ersten Moment nicht immer, ob es sich bei den Daten um vertrauliche Daten handelt und wägt sich vielleicht in Sicherheit, während der Dateien mit vertraulichem Inhalt an jemand anders weitergibt.

  • Passwort in Klartext ablegen und den Zugriff beschränken: Man legt das zu speichernde Passwort in Klartext ab. Es muss aber dafür gesorgt werden, dass der Zugriff auf diese sensiblen Daten eingeschränkt wird. Das kann beispielsweise mit Berechtigungen im Dateisystem geschehen.

    Kommentar: Das hört sich für mich am "wenigsten schlimm" an. Zwar liegt das Passwort in Klartext vor, allerdings ist sich der Benutzer dann evtl. bewusst, dass es sich um sensible Informationen handelt.
    Hier konkret eine Frage zu Implementierung: Gibt es auf den einzelnen mobilen Plattformen Mechanismen, um den Zugriff auf Daten so einzuschränken, dass nur die derzeitige App an die Daten rankommt?

  • Keine Passwörter speichern: Es werden schlicht und ergreifend keine Passwörter abgelegt.

    Kommentar: Das ist zwar der sicherste Weg, mir geht es aber auch um die Benutzerfreundlichkeit. Und diese wird, sofern man ein sicheres Passwort benutzen will, deutlich reduziert. Ein Passwort mit Ziffern, Buchstaben und Sonderzeichen auf einem mobilen Gerät einzugeben macht einfach keinen Spaß.


Jetzt kommt Ihr! Gibt es Alternativen zu den genannten Vorgehensweisen? Seht Ihr weitere Vor- und Nachteile, die ich nicht erwähnt habe?
25.07.2011
wlami 736 1 8
3 Antworten
10
Zuerst ein Einstieg in das Thema "Einwegverschlüsselung":
(Weiter unten kommen wir dann zum Thema "Mehrwegverschlüsselung" was dich, bezogen auf deine Frage, besonders interessiert. Zum Verständnis und als Grundlage solltest du den ersten Teil trotzdem überfliegen.)

Das einfache Speichern eines Passworts als MD5 gilt heutzutage als unsicher. Für den MD5-Algorithmus gibt es so genannte Rainbow-Tables in denen Millionen bis Millarden von Varianten bereits vorberechnet sind.

Grundsätzlich geht man heute dazu über die Cryp-Funktionen im Zusammenhang mit mechanismen wie "Salt" und "Runden" zu verwenden was Rainbow-Tables unmöglich macht und den Aufwand eines Brude-Force um den Faktor 100 bis 1000 erhöht.

"Salt"

Was "Salt" ist wurde im zugehörigen Wikipedia Artikel bereits sehr gut erklärt weshalb ich ihn hier zitiere:
Salt (deutsch Salz) bezeichnet in der Kryptographie eine zufällig gewählte Zeichenfolge, die an einen gegebenen Klartext vor der Verwendung als Eingabe einer Hashfunktion angehängt wird, um die Entropie der Eingabe zu erhöhen. Es wird häufig für Speicherung und Übermittlung von Computer-Passwörtern benutzt.

Wikipedia

Ein Beispiel:

string salt = "mySalt"
return hashFn(salt + "geheimnis")


"Runden"

Bei den "Runden" handelt es sich um nichts anderes als das Konzept einer Schleife die wir bereits alle aus der Programmierung kennen. Das Ergebnis der Hash-Funktion (ob MD5, AES, DES, SHA, etc. spielt dabei keine Rolle) wird als Eingangswert für einen weiteren Aufruf selbiger benutzt. Das ganze wird einige tausend mal wiederholt.
Ziel der Aktion ist es, die Laufzeit des Hash-Algorithmus zu erhöhen.
Dir als Anwender oder Programmerer ist es egal ob ein dein Passwort in 1 Millisekunden oder 100 Millisekunden gehashed wurde. Für einen Angreifer bedeutet das jedoch eine Steigerung des Aufwands um den Faktor 100 da er jetzt pro Sekunden nicht mehr 1000 Passwörter durchprobieren kann, sondern nurnoch 10.

Ein Beispiel:

string myHash = hashFn("geheimnis")
for(int i=0; i<(2^12); i++){ //2^12 = 4096 Runden
myHash = hashFn(myHash)
}
return myHash


"Salt" + "Runden" Kombiniert

Kommen wir jetzt zum interessanten Teil. Der Kombination von Salt und Runden.
Wir bereits oben beschrieben ist der Salt ein einmal generierter zufällig String. Beispielsweise kann man alternativ auch ein Masterpasswort als Salt verwenden.
Im Normalfall ist der Salt nicht als geheim einzustufen und darf ruhig im Klartext gespeichert werden (in der Variante mit dem Masterpasswort natürlich nicht!, in diesem Fall darf der Salt nirgendwo gespeichert werden). Es haben sich Schreibweise für Hash etabliert in denen dem eigendlichen Hash der Salt, der Exponent der die Anzahl an Runden definiert und ein Index für den Algorithmus vorrangestellt sind:

//Beispiel:
// 1$12$MySALT$DerEigendlicheHash
//Erklärung:
// Index für MD5$Anzahl Runden (2^12 = 4096)$Salt$Hash


Dadurch kann man den Salt für jedes einzelne Passwort das du speichern willst neu generieren was die Erstellung neuer Rainbow-Tables quasi unmöglich macht. Zusätzlich läßt sich das Verschlüsselungsverfahren nachträglich verändern (Index 2 könnte für AES stehen) und die Anzahl der Runden ließe sich erhöhen ohne das die bestehenden Passwörter entschlüsselt und neu berechnet werden müßten.

Praktische Anwendungen

Die einfachste Variante:

string salt = "mySalt"
string myHash = hashFn(salt + "geheimnis")
for(int i=0; i<(2^12); i++){
myHash = hashFn(myHash)
}
return myHash

Die bessere Variante:

string salt = "mySalt"
string myHash = hashFn(salt + "geheimnis")
for(int i=0; i<(2^12); i++){
myHash = hashFn(salt + myHash)
}
return myHash


Diese beiden Varianten dienen nur als Einsteig in das Konzept. Es gibt noch Varianten die den Abhängig von der aktuellen Runde nur Teile des Salts verwenden und/oder Salt und Hash mit XOR verknüpft werden, und und und.

Soviel von mir als kleiner praktischer Einstieg in das Thema "Einweg-Verschlüsselung for Dummys" :D
Um es nochmals zu erwähnen. Diese beiden Verfahren sowie ihre Kombination sind anerkannte Verfahren der Cryptographie welche unabhängig von Algorithmus eingesetzt werden sollten.
Im speziellen aber sollte man gerade bei MD5 für das Thema "Salt" angehen und bei AES aufgrund der Hardware-Beschleinigung von Crypt-Funktionen durch die neuen Intel-Prozessoren auf jeden Fall das Thema "Runden" angehen.

---------------------------------------------------------------------

Lesenswertes:
Die Rainbow Table (zu Deutsch: Regenbogentabelle) ist eine von Philippe Oechslin entwickelte Datenstruktur, die eine schnelle, probabilistische Suche nach einem Element des Urbilds (i. d. R. ein Passwort) eines gegebenen Hashwerts ermöglicht. Der sogenannte Time-Memory-Tradeoff gestattet die Suche nach fast allen Klartexten eines bestimmten Zeichenraums innerhalb einer erheblich kürzeren Zeit, als diesen komplett zu bruteforcen und ohne alle für diesen Zeichenraum möglichen Hashwerte speichern zu müssen.

Dieses funktioniert bei Hashfunktionen ohne Salt, wie es z. B. bei den Passwörtern für die Windows-Familie oder vielen Routern der Fall ist. Vergleichsweise umfangreiche Tabellen wurden für LM Hashes und MD5 berechnet und stehen aus diversen Quellen zur Verfügung.

Verwendung finden Rainbow Tables bei der Wiederherstellung von Passwörtern, innerhalb der IT-Forensik, bei Penetrationstests und beim illegitimen Passwortcracken.

Rainbow Table


---------------------------------------------------------------------

Und nun zum eigendlichen Thema "Mehrwegverschlüsselung":

Für symmetrische Verschlüsselung dh. das heißt, das eine Zeichenkette sowohl Ver- als Entschlüsselt werden kann bietet sich Algorithmen wie AES und Blowfish an.
Diese erlauben es ein eine Zeichenkette in zusammenhang mit einem Passwort zu verschlüsseln. Bei der Entschlüsselung ist das selbe Passwört von nöten.
In deinem Fall (bezgnehmend auf Punkt 1) bietet sich das nur an, wenn du mehrere Passwörter oder Context-Daten abspeichern möchtest.
Sinnvoll ist es vorallem nicht das von Nutzer gewählte Passwort als Passwort (folgend Key genannt) für den Cryp-Algorithmus zu verwenden, sondern selbiges mit den oben beschriebnen Verfahrfahren der Einwegverschlüsselung zu Verschlüsseln. In der Regel sind Nutzerpasswörter recht einfach gestrickt weshalb dieses im Schnitt eine Länge von 6-9 Zeichen aufweisen. Zu wenig um als sicherer Key für einen symetrischen Cryp-Algorithmus zu dienen. Ein MD5-Hash zum Beispiel hat dagegen 128-Bit und ist somit deutlich besser geeignet.
Der Key selbst darf natürlich nicht auf dem Gerät gespeichert werden sondern muss in Zusammenhang mit einem Salt aus dem Nutzerpasswort errechnet werden.
So kannst du sicherstellen, das ein Angreifer der die Verschlüsselte Datei entwendet diese nur unter großen Technischen Aufwand wieder entschlüsseln kann.
Das Konzept der Runden läßt sich übrigens auch bei symmetrische Verschlüsselungsverfahren anwenden. Hierzu ein Beispiel:

string runden = 2^12
string myKey = MD5("geheimnis", "salt", runden )
string[] keys = new string[){ myKey, "geheimnis", "salt" }
string myCryp = "meine super geheimen daten"
for(int i<0; i<runden; i++){
myCryp = AES(myCryp, keys[i % 3]) //AES(string, key)
}
return myCryp


Zum entschlüsseln sollte es genügen die Schleife umzukehren.

---------------------------------------------------------------------

Ich hoffe meine Ausführungen helfen dir weiter und beantworten die meißten deiner Fragen. Sicherheit erkauft man sich letztlich immer durch Aufwand. Entweder durch Aufwand beim Benutzer oder durch Programmieraufwand / Rechenleistung.
25.07.2011
Floyd 14,6k 3 9
Floyd 14,6k 3 9
2
Sehr schöne und ausführliche Darstellung. +1!
ffordermaier 25.07.2011
Mit ein paar dutzend Rechtschreibfehlern zur allgemeinen Belustigung ;)
Floyd 25.07.2011
1
Gute Erklärung. Aber: Geht das nicht am Thema vorbei? Wenn ich den OP richtig verstanden habe, wollte er doch wissen, wie er Passwörter speichern kann, die er später wieder im Klartext erhält um sich bei einem Dienst automatisch anmelden zu können.

MD5 & Co sind, soviel wie ich weiß, eine Einbahnstraße. Aus einem MD5 Hash kann ich das ursprüngliche Passwort doch nicht wieder herstellen? Sie dienen lediglich dazu, ein eingegebenes Passwort gegen ein gespeichertes validieren zu können.
Andreas Richter 25.07.2011
Aus eben diesem Grund besteht mein Artikel auch aus 2 Teilen (den zweiten Teil hatte ich nachträglich hinzugefügt da ich hier auf Arbeit bin und mir kurz was dazwischen gekommen ist :D). Da bei diesem Thema sowohl die verfahren der symetrischen Verschlüsselung, als auch der asymetrischen eine Rolle spielen (Speicherung des Masterkennworts zu Authenfifizierungszwecken als Hash, Speicherung der Geheimen Daten als symetrische Verschlüsselung) und beide Verfahren a) Verwand und b) in diesem Fall kombiniert werden können, hab ich mich für eine etwas ausführlichere Betrachtungsweise entschieden.
Floyd 25.07.2011
Ich muss aber zugeben das der asymetrische Teil vielleicht etwas zu ausführlich geworden ist. Im Eifer des Gefechts hab ich einfach nur geschrieben, geschrieben und geschrieben :D
Floyd 25.07.2011
Ok. Den zweiten Teil habe ich vor meinem Kommentar nicht gesehen. Hast du den nachträglich eingefügt bzw. ergänzt?
Andreas Richter 25.07.2011
Ja, etwa 2 Minuten bevor du deinen Kommentar abgespeichert hattest.
Floyd 25.07.2011
Siehst. Das erklärt dann die Verwirrung :)
Andreas Richter 25.07.2011
Achso: +1 von mir für die überarbeitete Antwort :)
Andreas Richter 25.07.2011
Vielen Dank für deinen ausführlichen Beitrag. Der erste Teil des Beitrags trifft, wie Andreas Richter es bereits angemerkt hat, auf meine Frage nicht ganz zu, da man aus dem Hash nicht auf das ursprüngliche Passwort schließen kann (und das ist ja auch gewollt).
wlami 25.07.2011
Bei der symmetrischen Verschlüsselung (Teil 2) stimme ich Dir vollkommen zu. Ich ordne dieses Vorgehen unter meinem 1. Punkt an (Passwort mit einem Passwort absichern) Allerdings sehe ich hier das Problem, dass die Verschlüsselung nur so gut ist wie der Key. Und ein sicheres Passwort (Buchstaben, Groß und Klein, Zahlen, Sonderzeichen) mit einem Smartphone einzugeben ist ein Krampf. Deshalb habe ich nach Alternativen gefragt :)
wlami 25.07.2011
Und genau an diesem Punkt setzt mein erste Teil des Beitrags an.
Im Zweiten Teil bin ich gesondert auf das Thema Nutzerpasswörter eingegangen und wie man, mit hilfe asymetrischer Verschlüsselungsverfahren, aus den unzureichenden Nutzerpasswörtern, sichere Keys erzeugen kann. Zitat:
Floyd 25.07.2011
"Sinnvoll ist es vorallem nicht das von Nutzer gewählte Passwort [...] für den Cryp-Algorithmus zu verwenden, sondern selbiges mit den oben beschriebnen Verfahrfahren der Einwegverschlüsselung zu Verschlüsseln. In der Regel sind Nutzerpasswörter recht einfach gestrickt weshalb dieses im Schnitt eine Länge von 6-9 Zeichen aufweisen. Zu wenig um als sicherer Key für einen symetrischen Cryp-Algorithmus zu dienen. Ein MD5-Hash zum Beispiel hat dagegen 128-Bit und ist somit deutlich besser geeignet."
Floyd 25.07.2011
Das Problem, was ich hier sehe ist der Werte-Raum, der für die Generierung des Keys verwendet wird: wenn ich z.B. eine vierstellige Zahl als Benutzereingabe erwarte und daraus einen Hash berechne, dann ist der Hash zwar ein guter Key. Die Menge der möglichen Hashes ist aber durch die Menge der Originaleingaben beschränkt.

Ein Hash auf eine kurze Eingabe macht das Passwort nicht sicherer, da der Angreifer die Generierung des Hashes nachvollziehen kann und dann den begrenzten Original-Passwortraum ausprobieren kann. An dieser Stelle empfinde ich deinen Vorschlag eher als Obscurity als Security.
wlami 25.07.2011
1
Natürlich du recht das bei einem Werteraum mit maximal 9999 Kombinationsmöglichkeiten ist kein Passwort sicher, und wird es auch nie werden. Egal wieviel Aufwand du rein steckst.
Durch die Verwendung eines Salts den du nicht direkt in oder an der verschlüsselten Datei ablegst kannst du einem einfachen Datenklau aber entgegenwirken da die Anzahl der Kombinationsmöglichkeiten jetzt auch noch von der Qualität deines Salts abhängt.
Durch die ausreichend hohe Anzahl der Runde ist es nun nicht mehr möglich ohne wissen des Salts alle Kombinationsmöglichkeiten auszuprobieren.
Floyd 25.07.2011
1
Die Runden verlängern zusätzlich den technischen Aufwand der für eine Entschlüsselung betrieben werden muss. Wenn du zum Beispiel deinem Nutzer eine Entschlüsselungszeit von 2 Sekunden zumuten kannst, beträgt die Entschlüsselungszeit bei bekanntem Salt+Passwort immerhin schon 5,5 Stunden. Nicht viel aber besser als garnichts. Wichtig ist vorallem des du den Wertebereich des Passworts erweiterst. Auf mind. 6-9 Alphanumerische Zeilen.
Floyd 25.07.2011
3
Hallo,

je nach Anwendung würde ich eine Kombination von allen Varianten wählen.

Zuersteinmal kann dem Benutzer angeboten werden das Passwort zu speichern bzw. nicht zu speichern. Somit kann er selber wählen ob er das Risiko eingeht oder das Passwort jedes mal neu eingibt.

Wenn er das Passwort speichert wäre es auf jeden Fall vernünftig dieses zu verschlüsseln. Als Schlüssel könnte eine Kombination aus konstantem Schlüssel und Smartphone ID o.ä. dienen.

Das verschlüsselte Passwort muss dann selbstverständlich in einem Speicherbereich abgelegt werden, auf den andere Apps keinen Zugriff haben.
25.07.2011
Tachyon 690 1 7
2
Ich würde das Passwort als MD5 Hash im System ablegen. Wenn das Passwort lang genug ist, bzw nach bestimmten Regeln gewählt wird (Alpha+Numerisch+Sonderzeichen) dann denke ich, wäre das soweit sicher.
25.07.2011
Mario Priebe 6,0k 3 9
Diese Vorgehensweise ist auf jedenfall zu empfehlen. Um das Passwort noch sicherer zu machen sollte man noch zusätzlich [url=http://de.wikipedia.org/wiki/Salt_%28Kryptologie%29]"Salt"[/url] verwenden.
michael2011 25.07.2011
Auch hier: Ist das nicht am Thema vorbei? Hashes sind eine Einbahnstraße. Aus einem Hash kann ich das ursprüngliche Passwort nicht wieder herstellen.

Wenn ich den OP richtig verstanden habe, möchte er aber genau das. Auf dem mobilen Device soll z.B. das Passwort für seinen EMail-Account gespeichert werden, mit dem sich seine EMail-App am Server anmelden kann.

In diesem Szenario ist MD5 & Co. nicht die richtige Wahl.
Andreas Richter 25.07.2011

Stelle deine Android-Frage jetzt!