2016-11-02 3 views
0

Auf der Udacity.com gibt es einen Kurs namens Web-Entwicklung. Der Dozent hat uns über Cookies, wie man Cookies signiert, was Salz ist und dass wir immer Hashes von Passwörtern in der Datenbank halten müssen. Dann gab er uns Hausaufgaben und dann veröffentlichte er eine Lösung. Und nur hier haben wir das ganze Bild gesehen: wie alles zusammen funktionieren sollte.Salz, Hashes und Sicherheit in Web-Entwicklung

Unten ist Python und Code für Google App Engine. Aber bitte, habe keine Angst. Der Code scheint wie Pseudocode lesbar zu sein. Und die Frage ist allgemein, nicht über diese speziellen Technologien.

import hashlib 
import hmac 

secret = 'iamsosecret' 

def make_secure_val(val): 
    return '%s|%s' % (val, hmac.new(secret, val).hexdigest()) 

def check_secure_val(secure_val): 
    val = secure_val.split('|')[0] 
    if secure_val == make_secure_val(val): 
     return val 

def make_salt(length = 5): 
    return ''.join(random.choice(letters) for x in xrange(length)) 

def make_pw_hash(name, pw, salt = None): 
    if not salt: 
     salt = make_salt() 
    h = hashlib.sha256(name + pw + salt).hexdigest() 
    return '%s,%s' % (salt, h) 

def valid_pw(name, password, h): 
    salt = h.split(',')[0] 
    return h == make_pw_hash(name, password, salt) 

class User(db.Model): 
    name = db.StringProperty(required = True) 
    pw_hash = db.StringProperty(required = True) 
    email = db.StringProperty() 

    @classmethod 
    def register(cls, name, pw, email = None): 
     pw_hash = make_pw_hash(name, pw) 
     return User(parent = users_key(), 
        name = name, 
        pw_hash = pw_hash, 
        email = email) 

    @classmethod 
    def login(cls, name, pw): 
     u = cls.by_name(name) 
     if u and valid_pw(name, pw, u.pw_hash): 
      return u 


class BlogHandler(webapp2.RequestHandler): 

    def set_secure_cookie(self, name, val): 
     cookie_val = make_secure_val(val) 
     self.response.headers.add_header(
      'Set-Cookie', 
      '%s=%s; Path=/' % (name, cookie_val)) 

    def read_secure_cookie(self, name): 
     cookie_val = self.request.cookies.get(name) 
     return cookie_val and check_secure_val(cookie_val) 

    def login(self, user): 
     self.set_secure_cookie('user_id', str(user.key().id())) 

    def logout(self): 
     self.response.headers.add_header('Set-Cookie', 'user_id=; Path=/') 

    def initialize(self, *a, **kw): 
     webapp2.RequestHandler.initialize(self, *a, **kw) 
     uid = self.read_secure_cookie('user_id') 
     self.user = uid and User.by_id(int(uid)) 

Lassen Sie uns prüfen, was wir hier haben.

  1. Funktion make_secure_val erzeugt so etwas wie dieses: 'Schlüsselwort | 6f21001bbf8bfbd8c04b9d537df1e314'
  2. Funktion make_secure_val wird in der Funktion set_secure_cookie verwendet. So wird es für die Anmeldung verwendet.
  3. Die Funktion make_secure_val verwendet einen geheimen Schlüssel, verwendet aber kein Salz.
  4. Funktion make_pw_hash (Name, pw, Salz = None) produziert etwa so: 'some_salt, c984cade696390b71ff914293c53767502ea542bfd0e7240a051e7ead2c60077'
  5. Funktion make_pw_hash eine gehashte Passwort bereitet, die in der Datenbank gespeichert werden. Der Benutzer gibt den Benutzernamen und das Passwort in das Formular ein, dann werden die Daten aus dem Formular zu Argumenten dieser make_pw_hash-Funktion.
  6. Die Funktion make_pw_hash verwendet Salz, verwendet aber keinen geheimen Schlüssel.
  7. Funktion make_pw_hash aus verschiedenen Gründen gemischt Benutzername in den Hash.

Nun, ich kann hier nichts verstehen. Ich würde sagen, das ist alles nicht sicher.

Fragen:

  1. Warum der Lehrer für Cookies verwenden, nicht Salz?

  2. Warum hat er den geheimen Schlüssel nicht benutzt, um Hashes zu erstellen, um Passwörter in die Datenbank zu schreiben?

  3. Warum hat er den Benutzernamen für die Erstellung von Hashes gemischt, um Passwörter in die Datenbank zu schreiben?

  4. Wir können zwei Ansätze zum Erstellen von Hashes sehen: einen für Cookies und einen für die Datenbank. Warum sind sie getrennt? Ist es nicht praktischer zu vereinheitlichen: Verwenden Sie immer einen geheimen Schlüssel und Salz. Weniger Code Und gute Sicherheit. Aber er trennte sich. Warum?

Durch die Art und Weise The teacher's solution

Antwort

0

Das wichtigste zuerst: Diese Methode Passwörter zum Speichern ist nicht sicher und sollte nicht verwendet werden, noch teached. Das Problem ist, dass ein einzelner Durchlauf von SHA-256 viel zu schnell ist (3 Giga SHA-256 per second) und daher zu einfach zu erzwingen ist. Wir benötigen einen Kostenfaktor, wie er in BCrypt, PBKDF2 oder SCrypt verfügbar ist.

Einige Antworten auf Ihre Fragen:

  1. salzen schwache Passwörter und starke Token sind zwei verschiedene Dinge. Salzen und Key-Stretching ist für kurze/schwache Passwörter notwendig, kann aber für starke Token weggelassen werden. Dazu muss der Parameter val ein starkes zufälliges Token sein (mindestens 20 Zeichen a..z, A..Z, 0..9). Dies kann nicht anhand des angezeigten Codes beurteilt werden, sollte aber Teil der Dokumentation von set_secure_cookie() sein.
  2. Das Hinzufügen eines Serverseitengeheimnisses zu Kennworthashes kann getan werden, aber es ist wichtig zu verstehen, was Sie mildern und wie Sie es tun. Wenn Sie interessiert sind, werfen Sie einen Blick auf meine tutorial über sicheres Passwort Hashing.
  3. Das Mischen des Benutzernamens ist keine gebräuchliche Möglichkeit, Passwörter zu hashen. Es verbessert zwar nicht die Sicherheit, verhindert aber die Änderung des Benutzernamens.
  4. Siehe den ersten Punkt.
+0

Vielen Dank. – Michael