What algorithm should I use to hash passwords into my database? [duplicate] - security

This question already has answers here:
Secure Password Hashing [closed]
(9 answers)
Closed 7 years ago.
Is there anything available that isn't trivially breakable?

This 2008 answer is now dangerously out of date. SHA (all variants) is now trivially breakable, and best practice is now (as of Jan 2013) to use a key-stretching hash (like PBKDF2) or ideally a RAM intensive one (like Bcrypt) and to add a per-user salt too.
Points 2, 3 and 4 are still worth paying attention to.
See the IT Security SE site for more.
Original 2008 answer:
Use a proven algorithm. SHA-256 uses 64 characters in the database, but with an index on the column that isn't a problem, and it is a proven hash and more reliable than MD5 and SHA-1. It's also implemented in most languages as part of the standard security suite. However don't feel bad if you use SHA-1.
Don't just hash the password, but put other information in it as well. You often use the hash of "username:password:salt" or similar, rather than just the password, but if you play with this then you make it even harder to run a dictionary attack.
Security is a tough field, do not think you can invent your own algorithms and protocols.
Don't write logs like "[AddUser] Hash of GeorgeBush:Rep4Lyfe:ASOIJNTY is xyz"

First rule of cryptography and password storage is "don't invent it yourself," but if you must here is the absolute minimum you must do to have any semblance of security:
Cardinal rules:
Never store a plain text password (which means you can never display or transmit it either.)
Never transmit the stored representation of a password over an unsecured line (either plain text, encoded or hashed).
Speed is your enemy.
Regularly reanalyze and improve your process as hardware and cryptanalysis improves.
Cryptography and process is a very small part of the solution.
Points of failure include: storage, client, transmission, processing, user, legal warrants, intrusion, and administrators.
Steps:
Enforce some reasonable minimum password requirements.
Change passwords frequently.
Use the strongest hash you can get - SHA-256 was suggested here.
Combine the password with a fixed salt (same for your whole database).
Combine the result of previous step with a unique salt (maybe the username, record id, a guid, a long random number, etc.) that is stored and attached to this record.
Run the hash algorithm multiple times - like 1000+ times. Ideally include a different salt each time with the previous hash. Speed is your enemy and multiple iterations reduces the speed. Every so often double the iterations (this requires capturing a new hash - do it next time they change their password.)
Oh, and unless you are running SSL or some other line security then don't allow your password to be transmitted in plain text. And if you are only comparing the final hash from the client to your stored hash then don't allow that to be transmitted in plain text either. You need to send a nonce (number used once) to the client and have them hash that with their generated hash (using steps above) hash and then they send you that one. On the server side you run the same process and and see if the two one time hashes match. Then dispose of them. There is a better way, but that is the simplest one.

CodingHorror had a great article on this last year. The recommendation at the end of the article is bcrypt.
Also see: https://security.stackexchange.com/questions/4781/do-any-security-experts-recommend-bcrypt-for-password-storage/6415#6415

The aforementioned algorithms are cryptographically secure hashing algorithms (but MD5 isn't considered to be secure today).
However there are algorithms, that specifically created to derive keys from passwords. These are the key derivation functions. They are designed for use with symmetric ciphers, but they are good for storing password too. PBKDF2 for example uses salt, large number of iterations, and a good hash function. If you have a library, what implements it (e.g. .NET), I think you should consider it.

Add a unique salt to the hashed password value (store the salt value in the db). When a unique salt is used the benefit of using a more secure algorithm than SHA1 or MD5 is not really necessary (at that point it's an incremental improvement, whereas using a salt is a monumental improvement).

Use a strong crytographic hash function like MD5 or SHA1, but make sure you use a good salt, otherwise you'll be susceptible to rainbow table attacks.

Update Jan 2013
The original answer is from 2008, and things have moved a bit in the last 5 years. The ready availability of cloud computing and powerful parallel-processor graphics cards means that passwords up to 8 or 9 characters hashed as MD5 or SHA1 are now trivially breakable.
Now a long salt is a must, as is something tougher like SHA512.
However all SHA variant hashes are designed for communication encryption - messages back and forth where every message is encrypted, and for this reason they are designed to be fast.
In the password hashing world this design is a big disadvantage as the quicker the hash is the generate the less time it takes to generate large numbers of hashes.
A fast hash like SHA512 can be generated millions, even billions of times a second. Throw in cheap parallel processing and every possible permutation of a password becomes an absolute must.
Key-stretching is one way to combat this. A key-stretching algorithm (like PBKDF2) applies a quicker hash (like SHA512) thousands of times, typically causing the hash generation to take 1/5 of a second or so. Someone logging in won't notice, but if you can only generate 5 hashes per second brute force attacks are much tougher.
Secondly there should always be a per-user random salt. This can be randomly generated as the first n bytes of the hash (which are then stripped off and added to the password text to be checked before building the hashes to compare) or as an extra DB column.
So:
What algorithm should I use to hash passwords into my database?
Key-stretching to slow down hash generation. I'd probably go with PBKDF2.
Per-user salt means a new attack per user, and some work figuring out how to get the salt.
Computing power and availability are going up exponentially - chances are these rules will change again in another 4 years. If you need future-proof security I'd investigate bcrypt/scrypt style hashes - these take the slower key-stretching algorithms and add a step that uses a lot of RAM to generate the hash. Using so much RAM reduces the effectiveness of cheap parallel processors.
Original Sept 2008 (left in so comments make sense)
MD5+salt or SHA1+salt is not 'trivially breakable' - most hacks depend on huge rainbow tables and these become less useful with a salt [update, now they are].
MD5+salt is a relatively weak option, but it isn't going to be easily broken [update, now it is very easy to break].
SHA2 goes all the way up to 512 - that's going to be pretty impossible to crack with readily available kit [update, pretty easy up to 9 char passwords now] - though I'm sure there's a Cray in some military bunker somewhere that can do it [You can now rent this 'Cray' from Amazon]

MD5 or SHA in combination with a randomly generated salt value for every entry

as mentioned earlier simple hashing algorithms should not be used here is reason why :
http://arstechnica.com/security/2012/08/passwords-under-assault/
so use something else such as http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx

All hashing algorithms are vulnerable to a "dictionary attack". This is simply where the attacker has a very large dictionary of possible passwords, and they hash all of them. They then see if any of those hashes match the hash of the password they want to decrypt. This technique can easily test millions of passwords. This is why you need to avoid any password that might be remotely predictable.
But, if you are willing to accept the threat of a dictionary attack, MD5 and SHA1 would each be more than adequate. SHA1 is more secure, but for most applications this really isn't a significant improvement.

MD5 / SHA1 hashes are both good choices. MD5 is slightly weaker than SHA1.

Related

Best Practices: Salting & peppering passwords?

I came across a discussion in which I learned that what I'd been doing wasn't in fact salting passwords but peppering them, and I've since begun doing both with a function like:
hash_function($salt.hash_function($pepper.$password)) [multiple iterations]
Ignoring the chosen hash algorithm (I want this to be a discussion of salts & peppers and not specific algorithms but I'm using a secure one), is this a secure option or should I be doing something different? For those unfamiliar with the terms:
A salt is a randomly generated value usually stored with the string in the database designed to make it impossible to use hash tables to crack passwords. As each password has its own salt, they must all be brute-forced individually in order to crack them; however, as the salt is stored in the database with the password hash, a database compromise means losing both.
A pepper is a site-wide static value stored separately from the database (usually hard-coded in the application's source code) which is intended to be secret. It is used so that a compromise of the database would not cause the entire application's password table to be brute-forceable.
Is there anything I'm missing and is salting & peppering my passwords the best option to protect my user's security? Is there any potential security flaw to doing it this way?
Note: Assume for the purpose of the discussion that the application & database are stored on separate machines, do not share passwords etc. so a breach of the database server does not automatically mean a breach of the application server.
Ok. Seeing as I need to write about this over and over, I'll do one last canonical answer on pepper alone.
The Apparent Upside Of Peppers
It seems quite obvious that peppers should make hash functions more secure. I mean, if the attacker only gets your database, then your users passwords should be secure, right? Seems logical, right?
That's why so many people believe that peppers are a good idea. It "makes sense".
The Reality Of Peppers
In the security and cryptography realms, "make sense" isn't enough. Something has to be provable and make sense in order for it to be considered secure. Additionally, it has to be implementable in a maintainable way. The most secure system that can't be maintained is considered insecure (because if any part of that security breaks down, the entire system falls apart).
And peppers fit neither the provable or the maintainable models...
Theoretical Problems With Peppers
Now that we've set the stage, let's look at what's wrong with peppers.
Feeding one hash into another can be dangerous.
In your example, you do hash_function($salt . hash_function($pepper . $password)).
We know from past experience that "just feeding" one hash result into another hash function can decrease the overall security. The reason is that both hash functions can become a target of attack.
That's why algorithms like PBKDF2 use special operations to combine them (hmac in that case).
The point is that while it's not a big deal, it is also not a trivial thing to just throw around. Crypto systems are designed to avoid "should work" cases, and instead focus on "designed to work" cases.
While this may seem purely theoretical, it's in fact not. For example, Bcrypt cannot accept arbitrary passwords. So passing bcrypt(hash(pw), salt) can indeed result in a far weaker hash than bcrypt(pw, salt) if hash() returns a binary string.
Working Against Design
The way bcrypt (and other password hashing algorithms) were designed is to work with a salt. The concept of a pepper was never introduced. This may seem like a triviality, but it's not. The reason is that a salt is not a secret. It is just a value that can be known to an attacker. A pepper on the other hand, by very definition is a cryptographic secret.
The current password hashing algorithms (bcrypt, pbkdf2, etc) all are designed to only take in one secret value (the password). Adding in another secret into the algorithm hasn't been studied at all.
That doesn't mean it is not safe. It means we don't know if it is safe. And the general recommendation with security and cryptography is that if we don't know, it isn't.
So until algorithms are designed and vetted by cryptographers for use with secret values (peppers), current algorithms shouldn't be used with them.
Complexity Is The Enemy Of Security
Believe it or not, Complexity Is The Enemy Of Security. Making an algorithm that looks complex may be secure, or it may be not. But the chances are quite significant that it's not secure.
Significant Problems With Peppers
It's Not Maintainable
Your implementation of peppers precludes the ability to rotate the pepper key. Since the pepper is used at the input to the one way function, you can never change the pepper for the lifetime of the value. This means that you'd need to come up with some wonky hacks to get it to support key rotation.
This is extremely important as it's required whenever you store cryptographic secrets. Not having a mechanism to rotate keys (periodically, and after a breach) is a huge security vulnerability.
And your current pepper approach would require every user to either have their password completely invalidated by a rotation, or wait until their next login to rotate (which may be never)...
Which basically makes your approach an immediate no-go.
It Requires You To Roll Your Own Crypto
Since no current algorithm supports the concept of a pepper, it requires you to either compose algorithms or invent new ones to support a pepper. And if you can't immediately see why that's a really bad thing:
Anyone, from the most clueless amateur to the best cryptographer, can create an algorithm that he himself can't break.
Bruce Schneier
NEVER roll your own crypto...
The Better Way
So, out of all the problems detailed above, there are two ways of handling the situation.
Just Use The Algorithms As They Exist
If you use bcrypt or scrypt correctly (with a high cost), all but the weakest dictionary passwords should be statistically safe. The current record for hashing bcrypt at cost 5 is 71k hashes per second. At that rate even a 6 character random password would take years to crack. And considering my minimum recommended cost is 10, that reduces the hashes per second by a factor of 32. So we'd be talking only about 2200 hashes per second. At that rate, even some dictionary phrases or modificaitons may be safe.
Additionally, we should be checking for those weak classes of passwords at the door and not allowing them in. As password cracking gets more advanced, so should password quality requirements. It's still a statistical game, but with a proper storage technique, and strong passwords, everyone should be practically very safe...
Encrypt The Output Hash Prior To Storage
There exists in the security realm an algorithm designed to handle everything we've said above. It's a block cipher. It's good, because it's reversible, so we can rotate keys (yay! maintainability!). It's good because it's being used as designed. It's good because it gives the user no information.
Let's look at that line again. Let's say that an attacker knows your algorithm (which is required for security, otherwise it's security through obscurity). With a traditional pepper approach, the attacker can create a sentinel password, and since he knows the salt and the output, he can brute force the pepper. Ok, that's a long shot, but it's possible. With a cipher, the attacker gets nothing. And since the salt is randomized, a sentinel password won't even help him/her. So the best they are left with is to attack the encrypted form. Which means that they first have to attack your encrypted hash to recover the encryption key, and then attack the hashes. But there's a lot of research into the attacking of ciphers, so we want to rely on that.
TL/DR
Don't use peppers. There are a host of problems with them, and there are two better ways: not using any server-side secret (yes, it's ok) and encrypting the output hash using a block cipher prior to storage.
Fist we should talk about the exact advantage of a pepper:
The pepper can protect weak passwords from a dictionary attack, in the special case, where the attacker has read-access to the database (containing the hashes) but does not have access to the source code with the pepper.
A typical scenario would be SQL-injection, thrown away backups, discarded servers... These situations are not as uncommon as it sounds, and often not under your control (server-hosting). If you use...
A unique salt per password
A slow hashing algorithm like BCrypt
...strong passwords are well protected. It's nearly impossible to brute force a strong password under those conditions, even when the salt is known. The problem are the weak passwords, that are part of a brute-force dictionary or are derivations of them. A dictionary attack will reveal those very fast, because you test only the most common passwords.
The second question is how to apply the pepper ?
An often recommended way to apply a pepper, is to combine the password and the pepper before passing it to the hash function:
$pepperedPassword = hash_hmac('sha512', $password, $pepper);
$passwordHash = bcrypt($pepperedPassword);
There is another even better way though:
$passwordHash = bcrypt($password);
$encryptedHash = encrypt($passwordHash, $serverSideKey);
This not only allows to add a server side secret, it also allows to exchange the $serverSideKey, should this be necessary. This method involves a bit more work, but if the code once exists (library) there is no reason not to use it.
The point of salt and pepper is to increase the cost of a pre-computed password lookup, called a rainbow table.
In general trying to find a collision for a single hash is hard (assuming the hash is secure). However, with short hashes, it is possible to use computer to generate all possible hashes into a lookup onto a hard disk. This is called a Rainbow Table. If you create a rainbow table you can then go out into the world and quickly find plausable passwords for any (unsalted unpeppered) hash.
The point of a pepper is to make the rainbow table needed to hack your password list unique. Thus wasting more time on the attacker to construct the rainbow table.
The point of the salt however is to make the rainbow table for each user be unique to the user, further increasing the complexity of the attack.
Really the point of computer security is almost never to make it (mathematically) impossible, just mathematically and physically impractical (for example in secure systems it would take all the entropy in the universe (and more) to compute a single user's password).
I want this to be a discussion of salts & peppers and not specific algorithms but I'm using a secure one
Every secure password hashing function that I know of takes the password and the salt (and the secret/pepper if supported) as separate arguments and does all of the work itself.
Merely by the fact that you're concatenating strings and that your hash_function takes only one argument, I know that you aren't using one of those well tested, well analyzed standard algorithms, but are instead trying to roll your own. Don't do that.
Argon2 won the Password Hashing Competition in 2015, and as far as I know it's still the best choice for new designs. It supports pepper via the K parameter (called "secret value" or "key"). I know of no reason not to use pepper. At worst, the pepper will be compromised along with the database and you are no worse off than if you hadn't used it.
If you can't use built-in pepper support, you can use one of the two suggested formulas from this discussion:
Argon2(salt, HMAC(pepper, password)) or HMAC(pepper, Argon2(salt, password))
Important note: if you pass the output of HMAC (or any other hashing function) to Argon2 (or any other password hashing function), either make sure that the password hashing function supports embedded zero bytes or else encode the hash value (e.g. in base64) to ensure there are no zero bytes. If you're using a language whose strings support embedded zero bytes then you are probably safe, unless that language is PHP, but I would check anyway.
Can't see storing a hardcoded value in your source code as having any security relevance. It's security through obscurity.
If a hacker acquires your database, he will be able to start brute forcing your user passwords. It won't take long for that hacker to identify your pepper if he manages to crack a few passwords.

Multiple Salts to protect passwords

If you use a salt before hashing a password - it will make the hash more secure. It makes sense, because rainbow table attacks become much more difficult (impossible?).
What if you use multiple salts? For example - you check if the day is Monday, or the Month, the hour, etc (or some combination). Then you have a database which stores the fields: (userid, hash1, hash2, hash3...).
Would this make the information any more (or less) secure?
Example:
1) User registers with password 'PASS'.
2) System (php in this example) stores values (md5($password.$this_day)) for each day (7 passwords). into table password, column hash_monday, hash_tuesday etc.
3) user logs in, and script checks password where 'hash_'.$this_day matches what is entered.
Your system will be no more secure - you end up with several single salt databases instead of one. In principle it may be even less secure, since you helpfully provide the attacker with 7 hashes to the same string to choose from and he only needs to guess one. These multiple hashes of the same plaintext may also lead to implications to cryptographic strength of the encryption used for passwords (not sure on that one and it will depend on the algorithm used).
Maybe you should have a look at this small article. There are several things wrong with your approach.
A salt does not protect against a dictionary attack. It protects against rainbow-tables if correctly used.
Use a unique salt for each password. The salt should be a random value, not derrived from known information. It has to be stored with the password.
Do not use MD5 for hashing passwords. Md5 is considered broken, and it is ways too fast to hash passwords. With an off-the-shelf GPU, you are able to calculate 8 Giga MD5-hashes per second (in 2012). That makes it possible to brute-force a whole english dictionary with about 500000 words, in less than 0.1 milliseconds!
Use Bcrypt for hashing passwords. It is recommended to use a well established library like phpass, and if you want to understand how it can be implemented, you can read the article above.
If you want to add a secret to your hash function (like a hidden key, or a hidden function), you can add a pepper to the password. The pepper should not be stored in the database, and should remain secret. The pepper can protect against dictionary attacks, as long as the attacker has only access to your password-hashes (SQL-Injection), but not to the server with the secret.
I do not believe multiple hashes are going to help you in this scenario, primarily because when someone compromises your database they will notice that you have 7 different salts to go against and may make an educated guess that they are based on days of the week. There is nothing fundamentally wrong with MD5, as so many people like to jump on that bandwagon. The types of people that say MD5 is a broken hash have a fundamental misunderstanding between a hash function and a cryptographic hash function, I would recommend ignoring them. In the event you need a cryptographic hash function, use SHA-2 (or something from that family or greater).
You will need to salt the user input, as you know, a random value is generally recommended,but it can also be a value you store in a separate application space (outside of the database), you just have to protect that information as well. I highly recommend making the password hashing function take several thousand iterations for any input. As this will slow down the automated process of matching hashes on the database.
If your users use easy to guess passwords, dictionary attacks will beat you every day, cant protect against stupidity.

Is there a standard way to store passwords in a DB?

So passwords should not be stored in plaintext but many do anyway. For the others is there a standard way passwords are stored? I mean a SHA1 hash or MD5 hash and if so what will the salt size be? Is there a better place to ask this?
I am trying to pick the brains of sys admins and consultants working on directory services. I am trying to see if there is a pattern or not.
EDIT: I would like to clarify that I am not trying to learn how to store the passwords better myself but more trying to see how many different ways they are stored and if there is a standard if any.
MD5 has been broken for a while and SHA-1 also has problems.
If you want to store a hash that will be secure for a long time to come, SHA-256 or SHA-512 (part of the SHA-2 family of hashes, designed as secure replacements for SHA-1) are a good choice and somewhere between 128 and 256 bits of salt are standard.
However, the use of plain hashes is not the best way to do this nowadays. Adaptive hashes are specifically designed for this type of storage as the amount of time necessary to compute a result can be made to slow down with additional computations. This is a very important trait to have to prevent brute-force attacks against your stored passwords. A strong, and standard, implementation of an adaptive hash is bcrypt, based on modifications to the Blowfish encryption algorithm to make it suitable for this purpose (which is explained well here).
Passwords should be hashed and the hashes should be stored in the database.
However SHA* and MD5 are too fast a hashing algorithms to be used for the purpose of hashing passwords.
For hashing passwords, you'd ideally want something much slower which doesn't lend itself well to brute force/rainbow table attacks.
You can sure hash a password 1000s of times before storing the hash to make it time and computationally intensive but why bother doing that when you have algorithms like bcrypt that do the job for you.
You should use bcrypt to hash your password. Read more about it at
http://codahale.com/how-to-safely-store-a-password/
In bcrypt, since the salt is appended to hash - you don't even need two columns 'password_hash' and 'salt' in the table. Just 'password_hash'. The less clutter the better.
You can see this question for the answer to how long the salt should be (between 128-256 bits seems to be the consensus).
As far as what algorithm to use, you should definitely use SHA1. MD5 was considered broken long ago even though it is still commonly used (see wikipedia MD5.

Salting Hashes - why is the salt treated by the literature as being known to Eve?

The title says everything. I don't understand: why you shouldn't keep your salt a secret like the password. Or did I misunderstand something?
The salt is treated as public primarily because keeping it secret isn't necessary.
The point of salt is primarily to make dictionary attacks more difficult/less practical. In a dictionary attack, the attacker hashes common words from a dictionary, and (if he's serious at all) supplements those with things like common names. Equipped with this, if he can get a hold of your list of hashed passwords, he can see if any of them matches a hash in his list. Assuming you have a significant number of users, he has a pretty good chance of finding at least one. When he does, he looks in his list to find what word produced that hash, and he can now use it to log in and impersonate that user.
Adding a salt means that instead of doing this once, he has to do it once for each possible salt value. For example, if you use a 24-bit salt, he has to hash each word in the dictionary ~16 million times, and store the results of all ~16 million hashes.
Just for the sake of argument, let's assume that without salt, it would take the attacker 8 hours to hash all the candidate words, and 16 megabytes to store the results (hashes and word that produced each). We'll further assume that the storage is equally divided between the hashes themselves and the list of words/names/whatever that produced them.
Using the same 24-bit salt, that means his time is multiplied by the same factor of ~16 million. His storage for the words that produced the hashes remains the same, but for the hashes themselves is (again) multiplied by the ~16 million. Working out the math, those come out to approximately 15,000 years of computation and 128 terabytes of storage.
In short, without salt, a dictionary attack is within easy reach of almost anybody. I could easily believe that (for example) somebody would let their computer run overnight to do the hashing just to pull a good April fools joke on a few of his co-workers (easy to believe, because I've seen it done).
When you get down to it, it's all a numbers game: a dictionary attack isn't betting that every user will have a password that's easy to guess, only that enough will for them to find at least a few open holes. Likewise, making the salt public does allow a somewhat simpler attack, by downloading the salt for each hash, and doing individual dictionary attacks on each, using the known salt for each one. Assuming a system has fewer users than possible hash values, this is a more practical attack. Nonetheless, he's now stuck with attacking each password individually, rather than using a single dictionary not only for an entire system, but in fact for all systems he might want to attack that use the same hash algorithm.
In summary: salt can do its job perfectly well even though it's made public. One of the aims of almost any security system is to minimize the amount of information that needs to be kept secret. Since salt can work even if it is public, it's generally assumed to be public knowledge. In a practical system, you certainly don't try to publish it to attackers, but you don't (shouldn't, anyway) rely on its remaining a secret either.
The purpose of salt is making an attack on several crypted passwords at the same time harder. It doesn't make an attack on a single crypted password harder.
With a salt, an attacker has to test each candidate plaintext password once for every different salt.
The reason as I found in this article is, that you actually need the salt to check an incoming password with the salted and hashed one in your database.
You should keep your salt a secret for the same reason that you salt in the first place.
Hackers can and have created Rainbow Tables whereby they hash using (md5, sha1, sha256, sha512, etc.) a list of the top 1,000 or so most common passwords.
If a hacker manages to get a hold of your database... its good that your passwords are hashed, but if they do a quick comparison and find a hash that matches one they have in their list, they know what the password is for that account.
The key to them doing the hack, is having that rainbow table handy. If you've added a salt, their rainbow table is useless... but if you make the salt east to find or you share it with others, then the hackers can re-build a new rainbow table using your salt.(*) e.g. you've made it easier for them to hack.
(*) Note this is a little harder than described, since the hacker may not know if you added the salt as a prefix, suffix, both, etc.
As said above, unique secret salt for each password will prevent anyone from pre-computing the hashes in a rainbow table; this is the sole purpose of unique salts.

Recommended hash for passwords in ASP Classic

What is the slowest (therefore best) hash algorithm for passwords in ASP Classic?
EDIT: For those unaware, when hashing passwords, slower hashes are preferred to faster to help slow rainbow table style attacks.
EDIT2: And yes, of course speed isn't the only valid concern for hash selection. My question assumes that All other things being equal, the slowest hash method is preferred when hashing a password. Though collision/reverse engineering is of course a concern too, I'm prioritizing speed in this question since it is arguably the most critical factor to consider when comparing popular hash algorithms for use on passwords.
Thanks!
A lot of people seem to be beating on the question-asker because he's looking for a slow hash function. Actually, all other aspects being equal, a slower hash function is more secure than a fast one. This is because a slower hash function results in slower generation of rainbow tables and slower brute forcing or dictionary attacks on the password.
From Thomas Ptacek at http://www.securityfocus.com/blogs/262, as referenced in this Coding Horror article:
The problem is that MD5 is fast. So
are its modern competitors, like SHA1
and SHA256. Speed is a design goal of
a modern secure hash, because hashes
are a building block of almost every
cryptosystem, and usually get
demand-executed on a per-packet or
per-message basis.
Speed is exactly what you don’t want
in a password hash function.
Modern password schemes are attacked
with incremental password crackers.
Incremental crackers don’t
precalculate all possible cracked
passwords. They consider each password
hash individually, and they feed their
dictionary through the password hash
function the same way your PHP login
page would. Rainbow table crackers
like Ophcrack use space to attack
passwords; incremental crackers like
John the Ripper, Crack, and LC5 work
with time: statistics and compute.
The password attack game is scored in
time taken to crack password X. With
rainbow tables, that time depends on
how big your table needs to be and how
fast you can search it. With
incremental crackers, the time depends
on how fast you can make the password
hash function run.
The better you can optimize your
password hash function, the faster
your password hash function gets, the
weaker your scheme is. MD5 and SHA1,
even conventional block ciphers like
DES, are designed to be fast. MD5,
SHA1, and DES are weak password
hashes. On modern CPUs, raw crypto
building blocks like DES and MD5 can
be bitsliced, vectorized, and
parallelized to make password searches
lightning fast. Game-over FPGA
implementations cost only hundreds of
dollars.
Some comments on the PHP MD5 documentation also discuss preference for slowness.
To answer your question, it looks like BCrypt is the way to go. However, I have not been able to find any implementations for ASP Classic. If that's true, I would stick with a regular hash function like SHA512.
I'll ignore the slow part, and instead go for the "good" part.
I suggest you use SHA-512 with a salt to defeat dictionary and rainbow table attacks. I don't believe there are any known vulnerabilities for SHA-512.
If you are trying to defeat brute force attacks you are better off enforcing some failed attempts window/count rather than relying on the speed of the hashing (or hash comparison) mechanism to make the attack take longer to succeed. Lock out the account after a certain number of failed attempts within the failure window and only let new attempts be made after a significant amount of time has elapsed.
This could leave you open to a DOS attack against a well-known (administrative) account, but you could exempt certain accounts from the lockout policy or have an alternate way -- using a security question/answer -- to logon to a locked out account before the reset period has elapsed.
[EDIT] To help defeat rainbow attacks -- where the attacker has retrieved your hashed passwords and finds suitable matches that hash to the same values -- consider both using a random salt unique to each user's hashed password and a fixed salt that is part of the algorithm, not the data. For example:
testHash = computeHash( user.salt + "98hloj5674" + password );
if (testHash == user.hashedPassword)
{
valid = true;
}
This should invalidate the rainbow tables since, even knowing the user's salt and the hash algorithm, the values in the attacker's rainbow tables won't map onto your hashed passwords because of the addition of the fixed salt in the algorithm.
With ASP Classic, you'd have to do this in a library instead of on the page to make sure that the user couldn't see your fixed salt.
Dim sPassword, sSalt
sPassword = "Lorem"
sSalt = "Ipsum"
With CreateObject("CAPICOM.HashedData")
.Algorithm = 0 ' CAPICOM_HASH_ALGORITHM_SHA1
.Hash sPassword & sSalt
Response.Write "Here is your hash: " & .Value
End With
Capicom documentation
Algorithm is any of the following:
CAPICOM_HASH_ALGORITHM_SHA1 = 0
CAPICOM_HASH_ALGORITHM_MD2 = 1
CAPICOM_HASH_ALGORITHM_MD4 = 2
CAPICOM_HASH_ALGORITHM_MD5 = 3
CAPICOM_HASH_ALGORITHM_SHA_256 = 4 - Not supported on Windows XP or 2000
CAPICOM_HASH_ALGORITHM_SHA_384 = 5 - Not supported on Windows XP or 2000
CAPICOM_HASH_ALGORITHM_SHA_512 = 6 - Not supported on Windows XP or 2000
Actually, the best hash function is the one that generates no colisions and is not suspectible to rainbow-table attacks.
That means: Add a Salt (preferably a different Salt for every user), and think of using a SHA2 Hash function (or maybe RIPE-MD, I have not looked at that much):
One implementation of SHA-256 is here (i love how they call it "one-way encryption"):
http://www.freevbcode.com/ShowCode.Asp?ID=2565
Have not tested it though, but there are certainly SHA2 implementations for Classic ASP.
I personally prefer the Whirlpool algorithm for all of my hashing needs. It produces a 512 bit output and thus has equal space requirements to SHA-512. Regretfully, I cannot speak authoritatively as to whether one is more secure than the other, but there do not appear to be any flagrant weaknesses in this the third version of Whirlpool.
The reference implementations are in the public domain, which is good because I rarely find this implemented by default in various tools and languages.
(If anyone knows of a good reason why SHA should be favored over Whirlpool, please let me know.)
psuedocode for the slowest method:
function hashPassword(password)
sleep for 10 seconds
return password
end function
This certainly isn't the most secure (or at all) but it's slow...
(I'm just pointing out that making it slower is not the answer...)

Resources