Algorithm 64位哈希码冲突的概率
《数字配方》一书提供了一种计算64位哈希码的方法,以减少冲突的数量 算法如所示,并复制到此处以供参考:Algorithm 64位哈希码冲突的概率,algorithm,math,hash,statistics,probability,Algorithm,Math,Hash,Statistics,Probability,《数字配方》一书提供了一种计算64位哈希码的方法,以减少冲突的数量 算法如所示,并复制到此处以供参考: private static final createLookupTable() { byteTable = new long[256]; long h = 0x544B2FBACAAF1684L; for (int i = 0; i < 256; i++) { for (int j = 0; j < 31; j++) { h = (h >&g
private static final createLookupTable() {
byteTable = new long[256];
long h = 0x544B2FBACAAF1684L;
for (int i = 0; i < 256; i++) {
for (int j = 0; j < 31; j++) {
h = (h >>> 7) ^ h;
h = (h << 11) ^ h;
h = (h >>> 10) ^ h;
}
byteTable[i] = h;
}
return byteTable;
}
public static long hash(CharSequence cs) {
long h = HSTART;
final long hmult = HMULT;
final long[] ht = byteTable;
final int len = cs.length();
for (int i = 0; i < len; i++) {
char ch = cs.charAt(i);
h = (h * hmult) ^ ht[ch & 0xff];
h = (h * hmult) ^ ht[(ch >>> 8) & 0xff];
}
return h;
}
这并不是为了安全,但执行速度至关重要,所以避免进一步检查密钥将节省时间。如果概率如此之低,比如说小于(100000个密钥为十亿分之一),那么它可能是可以接受的
蒂亚
考虑到所谓的生日悖论,有没有一个计算碰撞概率的公式
使用生日悖论公式可以简单地告诉你在什么时候开始担心碰撞的发生。这大约是Sqrt[n]
,其中n
是可能的哈希值的总数。在本例中,n=2^64
因此生日悖论公式告诉您,只要键的数量明显小于Sqrt[n]=Sqrt[2^64]=2^32
或大约40亿,您就不必担心冲突。n
越高,此估计越准确。事实上,当n
变大时,与k
键发生碰撞的概率p(k)
接近阶跃函数,其中阶跃发生在k=Sqrt[n]
处
您能否估计冲突的概率(即两个散列为相同值的键)?比如说1000把钥匙和10000把钥匙 假设散列函数是均匀分布的,那么推导公式就很简单了
p(no collision for k keys) = 1 * (n-1)/n * (n-2)/n * (n-3)/n * ... * (n-(k-1))/n
这个公式直接从1个键开始:1个键没有碰撞的概率当然是1。与两个键没有碰撞的概率为1*(n-1)/n
。对于所有k
键,依此类推。为了方便起见,Mathematica有一个函数用于简洁地表达:
p(no collision for k keys) = Pochhammer[n-(k-1),k]/n^k
然后,要计算k
键至少发生1次碰撞的概率,请将其从1中减去:
p(k) = 1 - p(no collision for k keys) = 1 - Pochhammer[n-(k-1),k]/n^k
使用Mathematica,可以计算n=2^64
:
- p(1000)=3.7*1013中的1
- p(10000)=3.7*1011中的1
假设合理数量的密钥(例如,少于10000个密钥)发生冲突是不可能的,因此如果两个哈希码相同,我们可以说密钥相同,而无需进一步检查,这是否安全 要准确回答这一问题,取决于10000个键中有2个相同的概率。我们正在寻找的是:
p(a=b|h(a)=h(b)) = The probability that a=b given h(a)=h(b)
其中a
和b
是键(可能相同),而h()
是散列函数。我们可以直接申请:
p(a=b|h(a)=h(b)) = p(h(a)=h(b)|a=b) * p(a=b) / p(h(a)=h(b))
我们立即看到p(h(a)=h(b)| a=b)=1(如果a=b
,那么当然h(a)=h(b)
),所以我们得到
p(a=b|h(a)=h(b)) = p(a=b) / p(h(a)=h(b))
如您所见,这取决于p(a=b)
,这是a
和b
实际上是同一个键的概率。这取决于10000个关键点组最初是如何选择的。前两个问题的计算假设所有键都是不同的,因此需要更多关于此场景的信息才能完全回答此问题
考虑到所谓的生日悖论,有没有一个计算碰撞概率的公式
请参阅:
假设散列的分布是均匀的,则n
键的冲突概率约为n2/265
假设合理数量的密钥(例如,少于10000个密钥)发生冲突是不可能的,因此如果两个哈希码不同,我们可以说密钥不同,而无需进一步检查,这安全吗
只有使用加密哈希函数时才安全。即使你每3×1011次都能容忍一个错误,你可能不得不考虑输入是专门用来创建一个哈希冲突,作为对程序的攻击。 < P>我将提供一个粗略的近似,以提供在其他答案中的确切公式;近似值可以帮助您回答#3。粗略的近似是,对于k,使用良好的哈希算法,k个键和n个可能的哈希值发生冲突的概率约为(k^2)/2n 1) 有没有一个公式来估计碰撞发生的概率 考虑到所谓的生日悖论 单个冲突发生的概率取决于生成的密钥集,因为哈希函数是统一的。我们可以执行以下操作来计算在生成k个密钥时不发生冲突的概率,如下所示:-
x = hash size
p(k=2) = (x-1)/x
p(k=3) = p(k=2)*(x-2)/x
..
p(k=n) = (x-1)*(x-2)..(x-n+1)/x^n
p(k=n) ~ e^-(n*n)/2x
p(collision|k=n) = 1-p(k=n) = 1 - e^(-n^2)/2x
p(collision) > 0.5 if n ~ sqrt(x)
因此,如果生成的sqrt(2^64)
键是2^32
键,则发生单一冲突的可能性更高
2) 您能否估计碰撞的概率(即两个键
散列到相同的值)?比如说1000把钥匙和10000把钥匙
钥匙
3) 假设一次合理数量的碰撞
密钥(比如,少于10000个密钥)是不可能的,因此如果2散列
代码是一样的,我们可以说钥匙是一样的,没有任何区别
进一步检查
这是一个非常有趣的问题,因为它取决于键空间的大小。假设您的密钥是从size=s
的空间随机生成的,散列空间是x=2^64
。碰撞概率为Pc(k=n | x)=1-e^(-n^2)/2x。如果在密钥空间中选择相同密钥的概率为P(k=n | s)=1-e^(-n^2)/2s
。为确保哈希相同,则键相同:-
P(k=n|s) > Pc(k=n|x)
1-e^-(n^2/2s) > 1-e^-(n^2/2x)
n^2/2s > n^2/2x
s < x
s < 2^64
P(k=n | s)>Pc(k=n | x)
1-e^-(n^2/2s)>1-e^-(n^2/2x)
n^2/2s>n^2/2x
s
因此,它表明,如果哈希值相同,则密钥集大小必须小于2^64
近似值,否则哈希值中的冲突几率大于密钥集中的冲突几率。结果与k的个数无关
x = 2^64
Use the formula pc(k=n) = 1 - e^-(n^2)/2x
P(k=n|s) > Pc(k=n|x)
1-e^-(n^2/2s) > 1-e^-(n^2/2x)
n^2/2s > n^2/2x
s < x
s < 2^64