This question came from our site for professional and enthusiast programmers.

7

How can you guarantee that the fixed time always leads to the same number of iterations from run to run?
–
AmberJun 25 '11 at 17:29

1

By securest do you mean having the largest complexity? Sometimes an algorithm that can be considered strong have other flaws.
–
Yet Another GeekJun 25 '11 at 17:29

3

No, cryptographic hash algorithms are designed to be one-way functions that make it difficult for an attacker to modify a piece of data while keeping the hash value the same. The one-way function is designed to make it difficult to determine how a change in input will impact the output hash value. Fundamentally cryptographic hashes are lossy compression functions. The information loss in compression makes it difficult to recover the input data. Design specs for MD5, SHA1, Whirlwind, etc, do not mention confidentiality, because is not a design goal.
–
this.joshJun 27 '11 at 7:31

2

I think the answers here are a little confus(ed|ing) because the time taken by a hashing algorithm is an upper bound on its security. So, except for broken or reduced algorithms, and adjusting for digest length; all hashing algorithms are of equal security if you're iterating for the same amount of time (and doing that in a way that introduces no new vulnerabilities). Except maybe scrypt, since it's memory-hard.
–
user502Jun 27 '11 at 14:07

2

@Core Why is adjusting manually not an option? Having security depend on server load seems like a bad idea.
–
Nick JohnsonJun 28 '11 at 1:29

6 Answers
6

Crypographers could point out that, when you read the fine print, there is no proof that secure hash functions actually exist at all. The only thing we have now are candidates for which no weakness has been found yet.

So the best you can hope for is a function which has survived scrutiny by many cryptographers for a long time. Also, you need it to have a wide enough output (256 bits are enough if you wish to achieve "128-bit security" and getting beyond that has little sense). Right now, as of summer 2011, this points to SHA-256 or SHA-512, not Whirlpool.

Basing the iteration count on the time it takes on a typical machine is a good idea -- but basing it on the time it really takes on your machine is not a good idea. Otherwise, you could end up with low iteration counts for some passwords because the machine was handling many requests at that instant (a situation which an attacker could force, by the way). Using many iterations is meant to thwart attackers by making password hashing slow on the attacker's computer -- that it also makes it slow on your system is an unfortunate byproduct; but the true target is whatever machine power the attacker could muster. Since you cannot really make benchmarks on the attacker's machine, you have to resort to rough estimates, hence a fixed count, as high as possible as long as the average burden is tolerable on your system (the important word here being "average", which disqualifies a dynamic measure as you intend to perform).

Also, the attacker's machine needs not look like yours; it may be, e.g., a GPU or a FPGA, which offers distinct computing abilities from what you can get on a typical server. You want a function for which an attacker will not be able to get huge performance boosts by using non-PC hardware. There again, this promotes SHA-256 or SHA-512, which are meant for CPU efficiency (with 32-bit or 64-bit arithmetic operations), not Whirlpool, which can benefit from hardware optimizations similar to those AES was designed for.

Finally, iterations are just part of the job; you also need a long enough, unique enough salt. Iterations and salting can be a bit tricky to do at the same time; you are warmly encouraged to use a standard construction such as PBKDF2 (although it was meant as a key derivation function, not a password hasher, PBKDF2 turns out to be reasonably good at that too).

"Secure" as in, based on a mathematical problem that has no known fast solution. "Most secure" as in, based on the most complex of such problems. A hashing algorithm is considered "strong" when breaking it would require a major contribution to cryptology/mathematics.

I don't think there is a clear-cut answer. As far as I know, some of the current favorites in the programming community (scrypt & bcrypt) haven't been rigorously peer reviewed as password hashing functions. At least, they have not been peer reviewed by a large number of cryptographers comparable to how the NIST hash function competition entries are vetted.

PBKDF2 and multiple rounds of SHA2 (fx Unix Crypt with SHA256) are thought to be third-best (which one of these is 'best' depends largely on the number of iterations used).

(Note that "Hacker News" is mostly a programming community, and not as the name might imply to some a security specialist community (even though some of those hang out there too).)

If you look around on this site, under the cryptographypasswords and hashing tags fx, then you will see that there usually isn't a single 'best' password hash mentioned. I guess that's in part because the real cryptographers have no clear-cut consensus on which one is 'strongest', due to the relatively limited peer reviewing.

scrypt is not available for PHP. bcrypt and PBKDF2 implement the adjustable cost as an iteration count, and requires fine-tuning for each point in time. I've already solved that by adjusting the cost by time rather than a flat count. Now I'm just wondering what hashing algorithm to use.
–
Core XiiJun 27 '11 at 6:54

5

@Core Xii: You seem bent on implementing your own novel solutions -- it is axiomatic that one shouldn't do that, "Don't roll your own crypto". In your case, I would suggest using PHP > 5.3.2 and use PHP's crypt() with Blowfish and default values (aka bcrypt). php.net/manual/en/function.crypt.php You can see the format description here (not PHP, but same format AFAIK) packages.python.org/passlib/lib/…
–
Jesper MortensenJun 27 '11 at 10:12

I can not fine-tune the cost parameter manually, that is out of the question. And there exist no implementations with dynamic adjustment, so I'm forced to roll my own. I did not ask what tool I should use to crypt my passwords, I asked for the most secure hashing algorithm. Blowfish is not a hashing algorithm.
–
Core XiiJun 27 '11 at 12:36

4

@Core Xii: While "Blowfish" isn't a hashing algorithmn, there is a password hashing algorithm that is called "CRYPT_BLOWFISH" in some circles. That's already covered in @Allan Jude answer and in my links above. You seem to want to create your own password hashing scheme; and I'm not able to assist you further in doing so.
–
Jesper MortensenJun 27 '11 at 14:21

2

You could implement "pick #iters based on time taken" using a library-provided bcrypt -- just time the bcrypt call and if it's "too quick" increase the workload factor and re-try. But are you sure you want that? What if someone deploys your code onto a slow machine (e.g. a small VM) -- you don't want to get too-small work factors as a result. What if your system is left on a "2011" spec machine through to 2019 when all the attackers have 128-way 20GHz boxes? What if the attacker can use a DoS to increase the time your hashing takes? You will at least want a secure-for-now initial work factor.
–
MishaSep 12 '11 at 12:15

CRYPT_BLOWFISH (OpenBSD bcrypt, based on the blowfish symmetric cipher, but is an actual hashing algorithm, there seems to be a lot of confusion about this) and CRYPT_SHA512 are the best. Both of these provide the option to scale the number of 'rounds' used, allowing you to choose a security/performance tradeoff.

For example, the default number of rounds for blowfish is 7 (value range is 4-31). This value is logarithmic, so each increase results in the algorithm being run 10 times more.
A value of 13, takes almost 1 minute per hash on a Core2Duo 2.4ghz

Tuning this as high as is tolerable performance wise, will result in the strongest security.

note: recently a bug was found in some implementations of bcrypt, and as such, you may wish to use SHA-512 instead.

Note: SHA-512 is faster to compute than SHA-256 on 64bit processors (especially if optimized w/ SSE2_64. Specifically, you should consider this and use additional rounds to ensure your hashes are strong enough for their purpose.

The open source application hashkill, publishes some performance benchmarks on how quickly modern GPUs can crack through modern hashing algorithms. Specifically, a Radeon HD 6990 can do: 11001 Megahashes/sec of straight MD5 (CRYPT_MD5 is salted, and the FreeBSD implementation uses 100 rounds). Straight SHA1 at 3444 Megahashes/s.

Once again, I don't want to tune the tradeoff; Hence I wrote a system that iterates automatically by time, thus remaining constant in its security over time. Now I'm just looking for the most secure hashing algorithm to use with it. The benchmark only compares MD5 and SHA-1 (both of which are broken), and so is completely useless.
–
Core XiiJun 27 '11 at 7:00

This is a portable public domain
password hashing framework for use in
PHP applications. It is meant to work
with PHP 3 and above, and it has
actually been tested with at least PHP
3.0.18 through 5.3.0 so far.

The preferred (most secure) hashing
method supported by phpass is the
OpenBSD-style Blowfish-based bcrypt,
also supported with our public domain
crypt_blowfish package (for C
applications), and known in PHP as
CRYPT_BLOWFISH, with a fallback to
BSDI-style extended DES-based hashes,
known in PHP as CRYPT_EXT_DES, and a
last resort fallback to MD5-based
salted and variable iteration count
password hashes implemented in phpass
itself (also referred to as portable
hashes).

Like the website says Blowfish-based bcrypt is the most secure hashing. I believe this is true because it is "Moore's law proof" while most others are not.

@Core Xii, it can use md5, for backward compatibility. But it does not by default and can be configured to only use BCrypt.
–
JaccoJun 27 '11 at 12:32

@Jacco: I'm looking at the source right now and there's a clear comment: "We're kind of forced to use MD5 here since it's the only cryptographic primitive available in all versions of PHP currently in use."
–
Core XiiJun 27 '11 at 12:42

I know the source, if you set 'portable hashes' to false, it will not use md5.
–
JaccoJun 27 '11 at 12:50

If speed is not an issue, just add the outputs of multiple hash functions. (Whirlpool, sha-512, etc). Same principle as multiple encryption, any engineered or found weakness won't work through multiple hash functions. Basically, take string x, run it through n hashes separately (not chained, run each one separate on the same input), add the results into one new block. Repeat by doing the same thing to the new block. I assume you are doing this for secure password storage. Make sure you use a true random salt as well, and an independent one for each hash. (And please use a full length one).

It is a symmetric block cipher that can be used as a drop-in replacement for DES or IDEA. It takes a variable-length key, from 32 bits to 448 bits, making it ideal for both domestic and exportable use. Apart from that, Blowfish is unpatented and license-free, and is available free for all uses.