Wie Devise Ihre Rails-App-Passwörter schützt

Devise ist eine unglaubliche Authentifizierungslösung für Rails mit mehr als 40 Millionen Downloads. Da es jedoch die meisten kryptografischen Operationen abstrahiert, ist es nicht immer leicht zu verstehen, was hinter den Kulissen passiert.

Eine dieser Abstraktionen gipfelt in der Persistenz eines encrypted_passworddirekt in der Datenbank. Ich war schon immer neugierig, was es eigentlich darstellt. Hier ist ein Beispiel:

$2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO

Aber was bedeutet dieser Kauderwelsch?

Devise verwendet Bcrypt, um Informationen sicher zu speichern. Auf seiner Website wird erwähnt, dass der " OpenBSD bcrypt () - Passwort-Hashing-Algorithmus verwendet wird, mit dem Sie auf einfache Weise einen sicheren Hash der Passwörter Ihrer Benutzer speichern können ". Aber was genau ist dieser Hash? Wie funktioniert es und wie schützt es gespeicherte Passwörter?

Das möchte ich Ihnen heute zeigen.

Lassen Sie uns rückwärts arbeiten - vom gespeicherten Hash in Ihrer Datenbank bis zum Ver- und Entschlüsselungsprozess.

Dieser Hash $2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yObesteht eigentlich aus mehreren Komponenten:

  • Bcrypt version ( 2a) - Die Version des bcrypt () -Algorithmus, der zur Erzeugung dieses Hashs verwendet wird (nach dem ersten $Zeichen gespeichert ).
  • Cost ( 11) - Der Kostenfaktor, der zum Erstellen des Hashs verwendet wird (gespeichert nach dem zweiten $Zeichen).
  • Salt ( $2a$11$yMMbLgN9uY6J3LhorfU9iu) - eine zufällige Zeichenfolge, die in Kombination mit Ihrem Passwort eindeutig ist (die ersten 29 Zeichen)
  • Prüfsumme ( LAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO) - der tatsächliche Hash-Teil des gespeicherten encrypted_password(verbleibende Zeichenfolge nach den 29 Zeichen)

Lassen Sie uns die letzten 3 Parameter untersuchen:

  • Bei Verwendung von Devise wird der CostWert durch eine Klassenvariable namens strecken festgelegt und der Standardwert ist 11. Es gibt an, wie oft das Passwort gehasht wird. ( Auf Ihrem devise.rb-Initialisierer können Sie diesen Wert auf einen niedrigeren Wert für die Testumgebung konfigurieren, damit Ihre Testsuite schneller ausgeführt wird. ) *
  • Das Salz ist die zufällige Zeichenfolge, die zum Kombinieren mit dem ursprünglichen Kennwort verwendet wird. Aus diesem Grund hat dasselbe Kennwort unterschiedliche Werte, wenn es verschlüsselt gespeichert wird. ( Weitere Informationen dazu, warum dies wichtig ist und was Rainbow Table Attack s sind, finden Sie weiter unten .) **
  • Die Prüfsumme ist der tatsächlich generierte Hash des Passworts, nachdem er mit dem zufälligen Salt kombiniert wurde.

Wenn sich ein Benutzer in Ihrer App registriert, muss er ein Kennwort festlegen. Bevor dieses Passwort in der Datenbank gespeichert wird, wird über BCrypt :: Engine.generate_salt (Kosten) unter Berücksichtigung des zuvor genannten Kostenfaktors ein zufälliges Salt generiert. (Hinweis: Wenn der pepperWert der Klassenvariablen festgelegt ist, wird sein Wert vor dem Salzen an das Kennwort angehängt.)

Mit diesem Salt (z. $2a$11$yMMbLgN9uY6J3LhorfU9iuB. einschließlich des Kostenfaktors) wird BCrypt :: Engine.hash_secret (Kennwort, Salt) aufgerufen, das den endgültigen Hash berechnet, der unter Verwendung des generierten Salt und des vom Benutzer ausgewählten Kennworts gespeichert werden soll. Dieser letzte Hash (zum Beispiel $2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO) wird wiederum in der encrypted_passwordSpalte der Datenbank gespeichert.

Aber wenn dieser Hash nicht umkehrbar ist und das Salz beim BCrypt::Password.createAufruf von zufällig generiert wird BCrypt::Engine.generate_salt(cost), wie kann es verwendet werden, um den Benutzer anzumelden ?

Hier sind diese verschiedenen Hash-Komponenten nützlich. Nachdem der Datensatz gefunden wurde, der mit der vom Benutzer zur Anmeldung angegebenen E-Mail übereinstimmt, wird das verschlüsselte Kennwort abgerufen und in die verschiedenen oben genannten Komponenten ( Bcrypt-Version , Kosten , Salz und Prüfsumme ) unterteilt.

Nach dieser ersten Vorbereitung geschieht Folgendes:

  1. Holen Sie sich das eingegebene Passwort ( 1234)
  2. Holen Sie sich das Salz des gespeicherten Passworts ( $2a$11$yMMbLgN9uY6J3LhorfU9iu)
  3. Generieren Sie den Hash aus dem Passwort und Salt mit derselben bcrypt-Version und demselben Kostenfaktor ( BCrypt::Engine.hash_secret(“1234”, “$2a$11$yMMbLgN9uY6J3LhorfU9iu”))
  4. Überprüfen Sie, ob der gespeicherte Hash mit dem in Schritt 3 ( $2a$11$yMMbLgN9uY6J3LhorfU9iuLAUwKxyy8w42ubeL4MWy7Fh8B.CH/yO) berechneten übereinstimmt.

Auf diese Weise speichert Devise Kennwörter sicher und schützt Sie vor einer Reihe von Angriffen, selbst wenn Ihre Datenbank gefährdet ist.

Kontaktieren Sie uns auf Twitter @alvesjtiago und lassen Sie mich wissen, wenn Sie diesen Artikel interessant fanden! Danke fürs Lesen.

PS: Ich bin auf keinen Fall ein Sicherheits- oder Kryptografieexperte. Bitte wenden Sie sich an uns, wenn Sie etwas falsch finden. Ich hoffe, dass durch die Vereinfachung einiger Konzepte leichter zu verstehen ist, was passiert.

Vielen Dank an @filipepina, @ivobenedito, @jackveiga, @joao_mags und @pedrosmmoreira für die Bewertungen und Vorschläge. Dieser Artikel ist auch unter //blog.tiagoalves.me/how-does-devise-keep-your-passwords-safe verfügbar.

Weitere Informationen zu einigen Themen.

Kostenfaktor *

  • Gefahren des Standard-bcrypt-Kostenfaktors
  • Empfohlene Anzahl von Runden für bcrypt

Regenbogentischangriffe **

  • Regenbogentisch - Wikipedia
  • Was sind Regenbogentische und wie werden sie verwendet?