Passwörter sicher speichern – Dos & Don'ts

Marja-Liisa Jöckel

Die Sicherheit von persönlichen Daten und der Schutz gegen Zugriff Unbefugter sind die wichtigsten Aufgaben eines Software-Entwicklers. Zwar ist es nicht möglich ein 100 Prozent sicheres System zu bauen, allerdings können zumindest in Bezug auf die Passwort-Sicherheit Vorsichtsmaßnahmen getroffen werden, um Script-Kiddies und Möchtegern-Hacker auf der Suche nach leichter Beute auszubremsen. Jerry Orr hat auf seinem Blog einige Tipps zusammengefasst, wie Sie die Sicherheit Ihrer Applikation verbessern.

Die Don’ts

Vermeiden Sie die Speicherung von Daten zur Authentifizierung

Wenn Sie eine externe Applikation entwickeln, ziehen Sie in Betracht OAuth Anbieter, wie Google oder Facebook zu verwenden. Wenn Sie an einer interne Enterprise App arbeiten, ist es ratsam, einen internen Authentifizierungsservice zu nutzen, der bereits existiert – wie beispielsweise ein LDAP oder Kerneros Service. Bei einer externen oder internen Applikation gilt gleichermaßen: Ihre Benutzer sind froh, wenn Sie sich keine andere User-ID oder ein neues Passwort merken müssen; außerdem gibt es für Hacker ein potentielles Einfallstor weniger.

Speichern Sie niemals Benutzerdaten in Klartext

Man sollte meinen, dies versteht sich von selbst. Allerdings ist dieser Punkt nicht unerwähnenswert. Arbeiten Sie statt mit Klartext ausschließlich mit Hashwerten! Diese sind schwerer zu rekonstruieren, womit man im Ernstfall zumindest Zeit gewinnt, die Nutzer über den Vorfall zu informieren, damit sie ihre Kontodaten ändern können.

Verwenden Sie keine 2-Wege-Verschlüsselung um das Passwort in Klartext aufzurufen

Um Authentifizierung für eine Applikation zu gewährleisten, müssen Sie keine Klartext-Passwort-Authentifizierung verwenden. Es ist völlig ausreichend während der Authentifizierung einen Verschlüsselungsalgorithmus laufen zu lassen, der das eingegebene Passwort des Nutzers mit dem verschlüsselten Passwort in der Datenbank vergleicht.

Vermeiden Sie veraltete Hashing Technologien

Leider kommt es immer noch häufig vor, dass Passwörter zum Beispiel mittels MD5 verschlüsselt werden. Die Verwendung solcher veralteter Algorithmen ist absolut nutzlos, da diese in wenigen Sekunden über www.md5hacker.com entschlüsselt werden können.

Verwenden Sie kein selbst entworfenes Verschlüsselungsverfahren

Da es auf der Welt nur sehr wenige richtige Verschlüsselungsexperten gibt, denken Sie nicht, Sie könnten einer von Ihnen sein. Schreiben Sie also keine eigenen Verfahren in dem Glauben, dass diese sicher sind – es sei denn, Sie entwickeln wirklich einen ernstzunehmenden Nachfolger von PBKDF2 oder bcrypt.

Die Dos

Verwenden Sie einen One-Way-Encryption-Algorithmus

Wie bereits erwähnt, müssen Sie den realen Wert des Passwortes, das Sie einmal verschlüsselt und gespeichert haben nie wieder wissen. Ein Algorithmus für die Eingabe und den Vergleich des gespeicherten Passwortes ist völlig ausreichend.

Verlangsamen Sie die Verschlüsselung so weit wie möglich

Aktuelle Verschlüsselungsalgorithmen bieten die Möglichkeit, Parameter für die Dauer des Verschlüsselungsprozesses anzugeben. Bei PBKDF2 kann beispielsweise die Anzahl der Iterationen verändert werden. Der Nutzer merkt von der Verlängerung des Verschlüsselungsprozesses nichts, Hacker die einen Brute-Force-Angriff starten, allerdings schon.

Wählen Sie einen bekannten Verschlüsselungs-Algorithmus

Bekannte, etablierte Algorithmen sind häufig auch empfehlenswert. Das National Institute of Standards and Technology empfiehlt beispielsweise PBKDF2. bcrypt oder scrypt sind aktuell beliebte Alternativen. Der Vorteil von PBKDF2 ist besonders die Integration in Java SE 6. Dadurch sind keine zusätzlichen Bibliotheken notwendig. Zudem schützt das einstellbare Key-Stretching vor Brute-Force-Attacken.

Der Beispielcode

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Arrays;

import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

public class PasswordEncryptionService {

 public boolean authenticate(String attemptedPassword, byte[] encryptedPassword, byte[] salt)
   throws NoSuchAlgorithmException, InvalidKeySpecException {
  // Encrypt the clear-text password using the same salt that was used to
  // encrypt the original password
  byte[] encryptedAttemptedPassword = getEncryptedPassword(attemptedPassword, salt);

  // Authentication succeeds if encrypted password that the user entered
  // is equal to the stored hash
  return Arrays.equals(encryptedPassword, encryptedAttemptedPassword);
 }

 public byte[] getEncryptedPassword(String password, byte[] salt)
   throws NoSuchAlgorithmException, InvalidKeySpecException {
  // PBKDF2 with SHA-1 as the hashing algorithm. Note that the NIST
  // specifically names SHA-1 as an acceptable hashing algorithm for PBKDF2
  String algorithm = "PBKDF2WithHmacSHA1";
  // SHA-1 generates 160 bit hashes, so that's what makes sense here
  int derivedKeyLength = 160;
  // Pick an iteration count that works for you. The NIST recommends at
  // least 1,000 iterations:
  // http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf
  // iOS 4.x reportedly uses 10,000:
  // http://blog.crackpassword.com/2010/09/smartphone-forensics-cracking-blackberry-backup-passwords/
  int iterations = 20000;

  KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterations, derivedKeyLength);

  SecretKeyFactory f = SecretKeyFactory.getInstance(algorithm);

  return f.generateSecret(spec).getEncoded();
 }

 public byte[] generateSalt() throws NoSuchAlgorithmException {
  // VERY important to use SecureRandom instead of just Random
  SecureRandom random = SecureRandom.getInstance("SHA1PRNG");

  // Generate a 8 byte (64 bit) salt as recommended by RSA PKCS5
  byte[] salt = new byte[8];
  random.nextBytes(salt);

  return salt;
 }
}  

 

Anmerkungen
  • Rufen Sie beim Hinzufügen eines neuen Nutzers, generateSalt() und anschließend getEncryptedPassword() auf und speichern Sie beide Werte. Speichern Sie nicht das Passwort in Klartext.
  • Bei der Authentifizierung eines Nutzers rufen Sie beide Werte aus der Datenbank ab und senden diese und das eingegebene Klartext-Passwort an authenticate(). Wird true zurückgegeben, war die Authentifizierung erfolgreich.
  • Sollte ein Nutzer sein Passwort ändern, ist der Salt nach wie vor sicher und verwendbar.
Geschrieben von
Marja-Liisa Jöckel
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.