security password - Ist das "doppelte Hashing" eines Passworts weniger sicher als nur einmal zu hashen?




salt generator (14)

From what I've read, it may actually be recommended to re-hash the password hundreds or thousands of times.

The idea is that if you can make it take more time to encode the password, it's more work for an attacker to run through many guesses to crack the password. That seems to be the advantage to re-hashing -- not that it's more cryptographically secure, but it simply takes longer to generate a dictionary attack.

Of course computers get faster all the time, so this advantage diminishes over time (or requires you to increase the iterations).

Ist ein Passwort zweimal vor dem Speichern mehr oder weniger sicher als nur einmal Hashing?

Worüber ich spreche, ist Folgendes:

$hashed_password = hash(hash($plaintext_password));

anstatt nur das:

$hashed_password = hash($plaintext_password);

Wenn es weniger sicher ist, können Sie eine gute Erklärung (oder einen Link zu einem) geben?

Macht die verwendete Hash-Funktion auch einen Unterschied? Macht es einen Unterschied, wenn Sie zum Beispiel md5 und sha1 mischen anstatt die gleiche Hash-Funktion zu wiederholen?

Hinweis 1: Wenn ich "Doppel-Hashing" sage, spreche ich über das doppelte Hashing eines Passworts, um es undurchsichtiger zu machen. Ich spreche nicht über die Technik zur Auflösung von Kollisionen .

Hinweis 2: Ich weiß, dass ich ein zufälliges Salz hinzufügen muss, um es wirklich sicher zu machen. Die Frage ist, ob Hashing zweimal mit dem gleichen Algorithmus hilft oder den Hash verletzt.


Ein Passwort einmal zu hacken ist unsicher

Nein, mehrere Hashes sind nicht weniger sicher; Sie sind ein wesentlicher Bestandteil der sicheren Passwortnutzung.

Das Iterieren des Hash erhöht die Zeit, die ein Angreifer benötigt, um jedes Passwort in seiner Kandidatenliste auszuprobieren. Sie können die Zeit für das Angreifen eines Kennworts von Stunden auf Jahre leicht erhöhen.

Einfache Iteration ist nicht genug

Das bloße Verketten der Hash-Ausgabe an die Eingabe reicht für die Sicherheit nicht aus. Die Iteration sollte im Kontext eines Algorithmus stattfinden, der die Entropie des Passworts bewahrt. Zum Glück gibt es mehrere veröffentlichte Algorithmen, die genug Kontrolle haben, um Vertrauen in ihr Design zu geben.

Ein guter Schlüsselableitungsalgorithmus wie PBKDF2 injiziert das Passwort in jede Hash-Runde und mildert dadurch Bedenken über Kollisionen in der Hash-Ausgabe. PBKDF2 kann unverändert für die Passwort-Authentifizierung verwendet werden. Bcrypt folgt der Schlüsselableitung mit einem Verschlüsselungsschritt; Auf diese Weise muss ein Angreifer, wenn ein schneller Weg zur Umkehrung der Schlüsselableitung gefunden wird, einen bekannten Klartextangriff ausführen.

Wie man ein Passwort bricht

Gespeicherte Passwörter müssen vor einem Offline-Angriff geschützt werden. Wenn Kennwörter nicht gesalzen sind, können sie mit einem vorberechneten Wörterbuchangriff (z. B. mithilfe einer Rainbow-Tabelle) unterbrochen werden. Andernfalls muss der Angreifer Zeit aufwenden, um für jedes Kennwort einen Hashwert zu berechnen und festzustellen, ob es mit dem gespeicherten Hashwert übereinstimmt.

Alle Passwörter sind nicht gleich wahrscheinlich. Angreifer können alle kurzen Passwörter erschöpfend durchsuchen, aber sie wissen, dass ihre Chancen für einen Brute-Force-Erfolg mit jedem zusätzlichen Charakter stark sinken. Stattdessen verwenden sie eine geordnete Liste der wahrscheinlichsten Passwörter. Sie beginnen mit "password123" und gehen zu weniger häufig verwendeten Passwörtern über.

Nehmen wir an, eine Angreiferliste ist lang, mit 10 Milliarden Kandidaten; Angenommen, ein Desktop-System kann 1 Million Hashes pro Sekunde berechnen. Der Angreifer kann ihre gesamte Liste in weniger als drei Stunden testen, wenn nur eine Iteration verwendet wird. Aber wenn nur 2000 Iterationen verwendet werden, erstreckt sich diese Zeit auf fast 8 Monate. Um einen anspruchsvolleren Angreifer zu besiegen, der beispielsweise ein Programm herunterladen kann, das die Leistung seiner GPU anzapfen kann, benötigen Sie weitere Iterationen.

Wieviel ist genug?

Die Anzahl der zu verwendenden Iterationen ist ein Kompromiss zwischen Sicherheit und Benutzererfahrung. Spezialisierte Hardware, die von Angreifern genutzt werden kann, ist zwar billig, kann aber Hunderte von Millionen Iterationen pro Sekunde ausführen. Die Leistung des Angreifer- Systems bestimmt, wie lange es dauert, ein Passwort bei einer Anzahl von Iterationen zu brechen. Aber Ihre Anwendung wird diese spezielle Hardware wahrscheinlich nicht verwenden. Wie viele Iterationen Sie durchführen können, ohne Benutzer zu verärgern, hängt von Ihrem System ab.

Sie können Benutzer möglicherweise während der Authentifizierung ca. ¾ Sekunde warten lassen. Profilieren Sie Ihre Zielplattform und verwenden Sie so viele Iterationen, wie Sie sich leisten können. Plattformen, die ich getestet habe (ein Benutzer auf einem mobilen Gerät oder viele Benutzer auf einer Serverplattform) können PBKDF2 mit zwischen 60.000 und 120.000 Iterationen oder bcrypt mit einem Kostenfaktor von 12 oder 13 bequem unterstützen.

Mehr Hintergrund

Lesen Sie PKCS # 5 für autorisierende Informationen zur Rolle von Salt und Iterationen in Hashing. Obwohl PBKDF2 zum Generieren von Verschlüsselungsschlüsseln aus Kennwörtern gedacht war, funktioniert es gut als Einweg-Hash für die Kennwortauthentifizierung. Jede Iteration von bcrypt ist teurer als ein SHA-2-Hash. Sie können also weniger Iterationen verwenden, aber die Idee ist dieselbe. Bcrypt geht auch einen Schritt weiter als die meisten PBKDF2-basierten Lösungen, indem es den abgeleiteten Schlüssel verwendet, um einen bekannten Klartext zu verschlüsseln. Der resultierende verschlüsselte Text wird zusammen mit einigen Metadaten als "Hash" gespeichert. Nichts hält dich jedoch davon ab, das Gleiche mit PBKDF2 zu tun.

Hier sind weitere Antworten, die ich zu diesem Thema geschrieben habe:


Ja.

Absolutely do not use multiple iterations of a conventional hash function, like md5(md5(md5(password))) . At best you will be getting a marginal increase in security (a scheme like this offers hardly any protection against a GPU attack; just pipeline it.) At worst, you're reducing your hash space (and thus security) with every iteration you add. In security, it's wise to assume the worst.

Do use a password has that's been designed by a competent cryptographer to be an effective password hash, and resistant to both brute-force and time-space attacks. These include bcrypt, scrypt, and in some situations PBKDF2. The glibc SHA-256-based hash is also acceptable.


As several responses in this article suggest, there are some cases where it may improves security and others where it definately hurts it. There is a better solution that will definately improve security. Instead of doubling the number of times you calculate the hash, double the size of your salt, or double the number of bits used int the hash, or do both! Instead of SHA-245, jump up to SHA-512.


The concern about reducing the search space is mathematically correct, although the search space remains large enough that for all practical purposes (assuming you use salts), at 2^128. However, since we are talking about passwords, the number of possible 16-character strings (alphanumeric, caps matter, a few symbols thrown in) is roughly 2^98, according to my back-of-the-envelope calculations. So the perceived decrease in the search space is not really relevant.

Aside from that, there really is no difference, cryptographically speaking.

Although there is a crypto primitive called a "hash chain" -- a technique that allows you to do some cool tricks, like disclosing a signature key after it's been used, without sacrificing the integrity of the system -- given minimal time synchronization, this allows you to cleanly sidestep the problem of initial key distribution. Basically, you precompute a large set of hashes of hashes - h(h(h(h....(h(k))...))) , use the nth value to sign, after a set interval, you send out the key, and sign it using key (n-1). The recepients can now verify that you sent all the previous messages, and no one can fake your signature since the time period for which it is valid has passed.

Re-hashing hundreds of thousands of times like Bill suggests is just a waste of your cpu.. use a longer key if you are concerned about people breaking 128 bits.


Double hashing makes sense to me only if I hash the password on the client, and then save the hash (with different salt) of that hash on the server.

That way even if someone hacked his way into the server (thereby ignoring the safety SSL provides), he still can't get to the clear passwords.

Yes he will have the data required to breach into the system, but he wouldn't be able to use that data to compromise outside accounts the user has. And people are known to use the same password for virtually anything.

The only way he could get to the clear passwords is installing a keygen on the client - and that's not your problem anymore.

So in short:

  1. The first hashing on the client protects your users in a 'server breach' scenario.
  2. The second hashing on the server serves to protect your system if someone got a hold of your database backup, so he can't use those passwords to connect to your services.

Let us assume you use the hashing algorithm: compute rot13, take the first 10 characters. If you do that twice (or even 2000 times) it is possible to make a function that is faster, but which gives the same result (namely just take the first 10 chars).

Likewise it may be possible to make a faster function that gives the same output as a repeated hashing function. So your choice of hashing function is very important: as with the rot13 example it is not given that repeated hashing will improve security. If there is no research saying that the algorithm is designed for recursive use, then it is safer to assume that it will not give you added protection.

That said: For all but the simplest hashing functions it will most likely take cryptography experts to compute the faster functions, so if you are guarding against attackers that do not have access to cryptography experts it is probably safer in practice to use a repeated hashing function.


I just look at this from a practical standpoint. What is the hacker after? Why, the combination of characters that, when put through the hash function, generates the desired hash.

You are only saving the last hash, therefore, the hacker only has to bruteforce one hash. Assuming you have roughly the same odds of stumbling across the desired hash with each bruteforce step, the number of hashes is irrelevant. You could do a million hash iterations, and it would not increase or reduce security one bit, since at the end of the line there's still only one hash to break, and the odds of breaking it are the same as any hash.

Maybe the previous posters think that the input is relevant; it's not. As long as whatever you put into the hash function generates the desired hash, it will get you through, correct input or incorrect input.

Now, rainbow tables are another story. Since a rainbow table only carries raw passwords, hashing twice may be a good security measure, since a rainbow table that contains every hash of every hash would be too large.

Of course, I'm only considering the example the OP gave, where it's just a plain-text password being hashed. If you include the username or a salt in the hash, it's a different story; hashing twice is entirely unnecessary, since the rainbow table would already be too large to be practical and contain the right hash.

Anyway, not a security expert here, but that's just what I've figured from my experience.


Most answers are by people without a background in cryptography or security. And they are wrong. Use a salt, if possible unique per record. MD5/SHA/etc are too fast, the opposite of what you want. PBKDF2 and bcrypt are slower (wich is good) but can be defeated with ASICs/FPGA/GPUs (very afordable nowadays). So a memory-hard algorithm is needed: enter scrypt .

Here's a layman explanation on salts and speed (but not about memory-hard algorithms).


Ja, Re-Hashing reduziert den Suchraum, aber nein, es spielt keine Rolle - die effektive Reduktion ist unbedeutend.

Re-Hashing erhöht die Zeit bis zur Brute-Force, aber nur zwei Mal ist auch suboptimal.

Was Sie wirklich wollen, ist das Passwort mit PBKDF2 zu PBKDF2 - eine bewährte Methode, einen sicheren Hash mit Salt und Iterationen zu verwenden. Überprüfen Sie diese SO-Antwort .

EDIT : Ich hätte fast vergessen - Verwenden Sie nicht MD5 !!!! Verwenden Sie einen modernen kryptographischen Hash wie die SHA-2-Familie (SHA-256, SHA-384 und SHA-512).


In general, it provides no additional security to double hash or double encrypt something. If you can break the hash once, you can break it again. It usually doesn't hurt security to do this, though.

In your example of using MD5, as you probably know there are some collision issues. "Double Hashing" doesn't really help protect against this, since the same collisions will still result in the same first hash, which you can then MD5 again to get the second hash.

This does protect against dictionary attacks, like those "reverse MD5-databases", but so does salting.

On a tangent, Double encrypting something doesn't provide any additional security because all it does is result in a different key which is a combination of the two keys actually used. So the effort to find the "key" is not doubled because two keys do not actually need to be found. This isn't true for hashing, because the result of the hash is not usually the same length as the original input.


Personally I wouldn't bother with multiple hashses, but I'd make sure to also hash the UserName (or another User ID field) as well as the password so two users with the same password won't end up with the same hash. Also I'd probably throw some other constant string into the input string too for good measure.

$hashed_password = md5( "xxx" + "|" + user_name + "|" + plaintext_password);

I'm going to go out on a limb and say it's more secure in certain circumstances... don't downvote me yet though!

From a mathematical / cryptographical point of view, it's less secure, for reasons that I'm sure someone else will give you a clearer explanation of than I could.

However , there exist large databases of MD5 hashes, which are more likely to contain the "password" text than the MD5 of it. So by double-hashing you're reducing the effectiveness of those databases.

Of course, if you use a salt then this advantage (disadvantage?) goes away.


I usually use SHA1 and salt with the user ID (or some other user-specific piece of information), and sometimes I additionally use a constant salt (so I have 2 parts to the salt).

SHA1 is now also considered somewhat compromised, but to a far lesser degree than MD5. By using a salt (any salt), you're preventing the use of a generic rainbow table to attack your hashes (some people have even had success using Google as a sort of rainbow table by searching for the hash). An attacker could conceivably generate a rainbow table using your salt, so that's why you should include a user-specific salt. That way, they will have to generate a rainbow table for each and every record in your system, not just one for your entire system! With that type of salting, even MD5 is decently secure.







security hash passwords cryptography password-hash