Take the 2-minute tour ×
Cryptography Stack Exchange is a question and answer site for software developers, mathematicians and others interested in cryptography. It's 100% free, no registration required.

Over on the bitcoin forums I asked why the bitcoin client computes SHA-256(SHA-256(x)) as its cryptographic hash for a variety of purposes. The leading theory--since the bitcoin author has disappeared--seems to be that from a security standpoint it could be sort-of analogous to upping the number of rounds in SHA-256 from 64 to 128, thereby providing a margin of safety as it is probable that the first preimage attack against SHA-256 (if such a thing exists) wouldn't work against SHA-256(SHA-256(x)), giving time to transition to a new hash function.

First of all, is that true? Would hashing twice make it any more difficult to mount a preimage attack, at least for certain types of attacks?

If the answer is yes, my related question is: is there a mode for encrypting twice to provide a similar increase in security? How would one feed the result of the 1st round of encryption into the setup of the 2nd (or 3rd)? Would you use the same key twice? Would you derive the 2nd key from (a hash of) the ciphertext of the first round (and the 3rd round from the 2nd, etc.)? Would you need an odd number of rounds and alternate Encrypt(Decrypt(Encrypt())) like Triple-DES does to prevent a meet-in-the-middle attack? How would this interact with the various modes of symmetric key encryption? Anything else I'm not thinking of that I would have to know about this if I were to implement it in a real product?

share|improve this question
add comment

3 Answers 3

SHA-256(SHA-256(x)) was proposed by Ferguson and Schneier in their excellent book "Practical Cryptography" (later updated by Ferguson, Schneier, and Kohno and renamed "Cryptography Engineering") as a way to make SHA-256 invulnerable to "length-extension" attack. They called it "SHA-256d". We started using SHA-256d for everything when we launched the Tahoe-LAFS project in 2006, on the principle that it is hardly less efficient than SHA-256, and that it frees us from having to reason about whether length-extension attacks are dangerous every place that we use a hash function. I wouldn't be surprised if the inventors of Bitcoin used it for similar reasons. Why not use SHA-256d instead of SHA-256?

Note that the SHA-3 project required all candidates to have some method of preventing length-extension attacks. Some of them use a method that is rather like SHA-256d, i.e. they do an extra "finalization" hash of their state at the end, before emitting a result.

share|improve this answer
add comment

Yes (to the encrypting part of the titular question). In fact, Bruce Schneier has recommended encrypting using multiple rounds for AES due to attacks (each word a link):

Cryptography is all about safety margins. If you can break n round of a cipher, you design it with 2n or 3n rounds. What we're learning is that the safety margin of AES is much less than previously believed. And while there is no reason to scrap AES in favor of another algorithm, NST should increase the number of rounds of all three AES variants. At this point, I suggest AES-128 at 16 rounds, AES-192 at 20 rounds, and AES-256 at 28 rounds. Or maybe even more; we don't want to be revising the standard again and again.

Edit: Apparently, my understanding of this was incorrect. The number of rounds is internal to the algorithm and not "multiple encryption operations". By design, AES has 10 rounds for 128-bit keys, 12 rounds for 192-bit keys, and 14 rounds for 256-bit keys.

Sorry about that.

share|improve this answer
    
How exactly did he propose extending the key expansion to fit the new quantity of rounds? –  Dakota West Dec 5 '12 at 16:21
add comment

For a second preimage attack:

hash(x) = hash(y) implies hash(hash(x) = hash(hash(y))

So it wouldn't protect against a direct preimage attack. Bitcoin builds a Merkle tree for a b c like this: hash(hash(hash(a)+hash(b))+hash(hash(c)+hash(c))).

You can see again that if someone found a c' that has the same SHA-256 hash as c, they could substitute it and the final result would still be the same.

While it's true that this might improve resistance to first preimage attacks, there aren't any obvious cases where those would matter -- an attacker typically would have the plaintext that generated the hash. (And preimage attacks on addresses seem far fetched, given that the ECDSA operation is in there.)

share|improve this answer
    
So is there any reason to perform hash(hash(x)), in general? –  maaku Sep 27 '11 at 15:42
    
I think an argument could be made that it might provide better protection against an attack where an attacker, given only the hash, attempts to find text that hashes to that. (But in every realistic Bitcoin situation, the attacker would have more than just the hash.) –  David Schwartz Sep 27 '11 at 16:39
    
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.