32

According to the wiki specification of the bitcoin protocol, hashes are typically "computed twice". For example:

hello
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 (first round of sha-256)
9595c9df90075148eb06860365df33584b75bff782a510c6cd4883a419833d50 (second round of sha-256)

What is the reasoning for this? I imagine it somehow provides additional security, or protection against potential attack vectors, but I can't reason what those attacks might be.

19

We don't know for sure, but the most popular theory is that a double hash was chosen to protect against length extension attacks.

13

The wiki answers this. TLDR: to prevent against birthday attacks.

Bitcoin is using two hash iterations (denoted SHA256^2 ie "SHA256 function squared") and the reason for this relates to a partial attack on the smaller but related SHA1 hash. SHA1's resistance to birthday attacks has been partially broken as of 2005 in O(2^64) vs the design O(2^80). While hashcash relies on pre-image resistance and so is not vulnerable to birthday attacks, a generic method of hardening SHA1 against the birthday collision attack is to iterate it twice. A comparable attack on SHA256 does not exist so far, however as the design of SHA256 is similar to SHA1 it is probably defensive for applications to use double SHA256. And this is what bitcoin does, it is not necessary given hashcash reliance on preimage security, but it is a defensive step against future cryptanalytic developments. The attack on SHA1 and in principle other hashes of similar design like SHA256, was also the motivation for the NIST SHA3 design competition which is still ongoing.

  • 7
    That may be what the Wiki says, but that is not actually what it does. A collision in the single version (hash(x)==hash(y)) implies a collision in the double version. So the Wiki article is wrong. – mikeazo Jan 5 '17 at 18:34
  • The wiki answer is wrong. See my answer below for a more thorough explanation – Zain Rizvi Apr 10 '18 at 20:17
11

The wiki claim that this is to prevent birthday attacks is wrong. If you can successfully execute a birthday attack on a single call to the hash function, you get a successful birthday attack on the second call. This is easy to see as having hash(x) == hash(y) implies hash(hash(x)) == hash(hash(y)).

If you really wanted to guard against this, you would do something like hash(x||hash(x)). Finding a collision in a single call to hash in this case would not directly yield a collision in the double call.

8

Like others have said, the wiki claim of this preventing birthday attacks is wrong. Rather, this was meant to prevent against length extension attacks.

From https://crypto.stackexchange.com/a/884/56797:

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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