Speichern von Passwörtern mit Node.js und MongoDB

70

Ich suche nach Beispielen, wie Passwörter und andere vertrauliche Daten mit node.js und mongodb sicher gespeichert werden können.

Ich möchte, dass alles ein einzigartiges Salz verwendet, das ich neben dem Hash im Mongo-Dokument aufbewahre.

Muss ich zur Authentifizierung nur die Eingabe salzen und verschlüsseln und sie einem gespeicherten Hash zuordnen?

Sollte ich diese Daten jemals entschlüsseln müssen und wenn ja, wie soll ich das tun?

Wie werden die privaten Schlüssel oder sogar die Salting-Methoden sicher auf dem Server gespeichert?

Ich habe gehört, dass AES und Blowfish beide gute Optionen sind. Was soll ich verwenden?

Alle Beispiele, wie man dies gestaltet, wären wunderbar hilfreich!

Vielen Dank!

schick
quelle

Antworten:

35

Verwenden Sie dies: https://github.com/ncb000gt/node.bcrypt.js/

bcrypt ist einer der wenigen Algorithmen, die sich auf diesen Anwendungsfall konzentrieren. Sie sollten niemals in der Lage sein, Ihre Passwörter zu entschlüsseln. Überprüfen Sie nur, ob ein vom Benutzer eingegebenes Klartext-Passwort mit dem gespeicherten / verschlüsselten Hash übereinstimmt.

bcrypt ist sehr einfach zu bedienen. Hier ist ein Ausschnitt aus meinem Mongoose-Benutzerschema (in CoffeeScript). Stellen Sie sicher, dass Sie die asynchronen Funktionen verwenden, da die Verschlüsselung (absichtlich) langsam ist.

class User extends SharedUser
  defaults: _.extend {domainId: null}, SharedUser::defaults

  #Irrelevant bits trimmed...

  password: (cleartext, confirm, callback) ->
    errorInfo = new errors.InvalidData()
    if cleartext != confirm
      errorInfo.message = 'please type the same password twice'
      errorInfo.errors.confirmPassword = 'must match the password'
      return callback errorInfo
    message = min4 cleartext
    if message
      errorInfo.message = message
      errorInfo.errors.password = message
      return callback errorInfo
    self = this
    bcrypt.gen_salt 10, (error, salt)->
      if error
        errorInfo = new errors.InternalError error.message
        return callback errorInfo
      bcrypt.encrypt cleartext, salt, (error, hash)->
        if error
          errorInfo = new errors.InternalError error.message
          return callback errorInfo
        self.attributes.bcryptedPassword = hash
        return callback()

  verifyPassword: (cleartext, callback) ->
    bcrypt.compare cleartext, @attributes.bcryptedPassword, (error, result)->
      if error
        return callback(new errors.InternalError(error.message))
      callback null, result

Lesen Sie auch diesen Artikel, der Sie davon überzeugen sollte, dass bcrypt eine gute Wahl ist und Ihnen hilft, nicht "gut und wirklich effektiv" zu werden.

Peter Lyons
quelle
1
Ich bin mir nicht 100% sicher, ob ich die Logik der Verwendung von bcrypt akzeptiere, nur weil es langsam ist, wie der Artikel feststellt. Es gibt keinen Grund, warum Sie keinen viel "standardmäßigeren" und weit verbreiteten Algorithmus wie SHA-256 verwenden und Ihrem System nur künstliche Latenz auferlegen können. Warten Sie nur eine Viertelsekunde, bevor der Server den übergebenen Hash tatsächlich überprüft. Einige Systeme schreiben auch ein Benutzersperrprotokoll (oder ein Protokoll mit reduzierten Berechtigungen) vor, wenn ihr Kennwort innerhalb von y Stunden x-mal falsch ist. Das kommt mit bestimmten Gepäckstücken, aber es ist eine Option zu berücksichtigen.
d512
19
Sie verpassen den Punkt. Der Punkt ist, wenn ein Angreifer Ihre Datenbank mit Kennwort-Hashes stiehlt, bcrypt für den Angreifer nur langsam auf seinem System ausgeführt werden kann, und daran führt kein Weg vorbei, da der Arbeitsfaktor in den Algorithmus selbst integriert ist. SHA-256 plus künstliche Latenz ist A) Verwendung eines Allzweck-Hashing-Algorithmus und B) Schutz nicht vor Offline-Cracking gestohlener Passwort-Hashes.
Peter Lyons
Ja, in einem Szenario, in dem der Angreifer tatsächlich eine Kopie aller Passwort-Hashes erhalten konnte, würde es ihm schwerer fallen, sie unter bcrypt zu knacken. Der Artikel erwähnt diesen Fall nicht ausdrücklich, sollte es aber wahrscheinlich sein.
d512