让我们假设我们得到以下内容:
- 哈希的长度
- 获得碰撞的机会
现在,知道了以上内容,我们如何获得获得给定机会百分比所需的“样本”数量?
When we take the Simplified formula
for the birthday paradox we get:
probability = k^2/2N
So:
sqr(probability*2*n) = k
Where we know that n = 2^lenghtHash
A small test: Hash = 16 bit : N= 65536 probability = 50% = 0.5
sqr(0.5*2*65536) = 256 samples
This is not 100% correct as we started of with the Simplified formula, but for big hashes and lager sample sets it gets very close.
for a link on the formula you can look here.
这里有一个小的 javascript 函数来计算机会,基于https://preshing.com/20110504/hash-collision-probabilities/的“简化近似”算法(感谢链接@Frank)来计算碰撞的机会,并使用Decimal.js bignum 库来管理比 JavascriptNumber
可以处理的更大的数字,例如:
samples=2**64; //
hash_size_bytes=20; // 160 bit hash
number_of_possible_hashes=Decimal("2").pow(8*hash_size_bytes);
console.log(collision_chance(samples,number_of_possible_hashes));
// ~ 0.00000001 % chance of a collision with 2**64 samples and 20-byte-long hashes.
samples=77163;
hash_size_bytes=4; // 32bit hash
number_of_possible_hashes=Decimal("2").pow(8*hash_size_bytes);
console.log(collision_chance(samples,number_of_possible_hashes));
// ~ 49.999% chance of a collision for a 4-byte hash with 77163 samples.
功能:
// with https://github.com/MikeMcl/decimal.js/blob/master/decimal.min.js
function collision_chance(samples,number_of_possible_hashes){
var Decimal100 = Decimal.clone({ precision: 100, rounding: 8 });
var k=Decimal100(samples);
var N=Decimal100(number_of_possible_hashes);
var MinusK=Decimal100(samples);
MinusK.s=-1;
var ret=((MinusK.mul(k.sub(1))).div(N.mul(2))).exp();
ret=ret.mul(100);
ret=Decimal100(100).sub(ret);
return ret.toFixed(100);
}