My set theory is a bit rusty, but here's my shot at a proof sketch (corrections or objections welcome):
Assumptions and definitions
- Hash is a one-way function producing an output which is a binary string of length h satisfying the avalanche effect. (note that I don't care if h is the full output size of some underlying hash function, or if it's been truncated to h; as long as the underlying hash function is a well-behaved cryptographic hash, then we're ok to abstract this away to a hash function of length h.)
- M is a finite set of possible messages. Binary strings of length l (let's call that Ml) would be an example message space.
- Size(M) is the number of possible messages. For binary strings of length l, Size(Ml) = 2l.
- I assume that any given hash value h has at least two messages that hash to it. In particular I assume that the message space is much larger than the hash space (ex.: h << l) such that this is true. If there are fewer possible messages than hash values, then you aren't guaranteed that any given hash value actually has a corresponding message, let alone two, and all this math blows up.
Formula and proof sketch
So for m1, m2 \in M, we want to know the probability that m1 = m2 given that H = Hash(m1) = Hash(m2).
Let's partition the set of messages m \in M into classes according to their hash value Hash(m). There will be 2h classes. Given the avalanche effect of Hash, we expect M to partition uniformly over these classes (ie each class will have an equal number of members), which will be Size(M) / 2h members per class. Or stated differently, a given hash value H will have Size(M) / 2h messages which hash to it.
Assuming the messages m1, m2 were pulled independently and uniformly randomly (aka uniformly IID) from M, then given that we know they are in the same class, there is a 1 / class_size = 1 / (Size(M) / 2h) = 2h / Size(M) chance that they are the same element.
For messages of length l that will be 2h / 2l = 2h - l chance that they are the same element.
Playing with some numbers:
- Messages of length l = 256 bits (say, AES keys) and h = 32 bits, you have 232 - 256 = 2-224 chance that they are the same message.
- Messages of length l = 600,000 bits (size of an average email) and h = 32 bits, you have 232 - 600,000 = 2-599,968 chance that they are the same message. (see footnote 1)
- Messages of length l = 1,120,000 bits (size of an average bitcoin block) and h = 19 bits (the current number of leading zeros), you have 219 - 1,120,000 = 2-1,119,981 chance that they are the same message. (see footnote 1)
Footnotes
- The assumption that m1, m2 \in M are chosen uniformly randomly is very much not true for most real-world examples of things we hash (passwords, TLS messages, emails, bitcoin blocks, etc) which all have structure, and therefore it is very much not the case that any bit string {0,1}l is equally likely. So this math may or may not have anything to do with the real world in which cryptography is used. Modifying this to accommodate messages that are not uniformly-distributed is well beyond my stats and set theory skills.
M'
happens to matchM
, thenH
would also matchH'
. Note however from the question that only the firsth
bits ofH
are known, so there is no direct way of telling whetherM == M'
, only the odds can be known.2^(h/2)
- you're right. I was thinking of a chosen prefix collision