生日悖论
在我上初中的时候,我们班的数学老师就提出过一个有趣的问题:“我们班绝对有人生日是在一天。”刚提出这个问题的时候,我们班很多人都质疑这个问题,觉得老师是在吹牛皮。可是后来老师让我们班报生日,结果我们竟然有四队人是生日是一样的(当时我们班是50几人)。竟然概率是这么的大,但是当时我们并没有能力去解决这个问题。也不知道为什么会是大概率事件,只是单单觉得这个事情非常的有趣。什么是生日悖论(Birthday Paradox)?其实就是在日常生活中违背了我们直觉的结果。
现在我们就通过从数学的角度,来计算一下两个人生日相同的概率。设一年有365天,当然每个人生日都是等概率事件,一个班有x(x>=2)个人。生日相同的概率为P(x),不同的概率为Q(x)。
首先计算x个人生日不同的概率是:
Q(x)=(1-
1
365
\frac{1}{365}
3651)(1-
2
365
\frac{2}{365}
3652)(1-
3
365
\frac{3}{365}
3653)…(1-
x
−
1
365
\frac{x-1}{365}
365x−1)
=
365
!
36
5
n
(
365
−
x
)
!
\frac{365!}{365^n(365-x)!}
365n(365−x)!365!
则两人生日相同的概率为:
P(x) = 1-Q(x)
= 1-(1-
1
365
\frac{1}{365}
3651)(1-
2
365
\frac{2}{365}
3652)(1-
3
365
\frac{3}{365}
3653)…(1-
x
−
1
365
\frac{x-1}{365}
365x−1)
= 1-
365
!
36
5
n
(
365
−
x
)
!
\frac{365!}{365^n(365-x)!}
365n(365−x)!365!
当班级有2人的时候:
P(x=2)=1-(1-
2
−
1
365
\frac{2-1}{365}
3652−1)=
1
365
\frac{1}{365}
3651≈0.0027
当班级有23人时:
P(x=23)=1-(1-
1
365
\frac{1}{365}
3651)(1-
2
365
\frac{2}{365}
3652)(1-
3
365
\frac{3}{365}
3653)…(1-
23
−
1
365
)
\frac{23-1}{365})
36523−1)≈0.5073
当班级有50人时:
P(x=50)=1-(1-
1
365
\frac{1}{365}
3651)(1-
2
365
\frac{2}{365}
3652)(1-
3
365
\frac{3}{365}
3653)…(1-
50
−
1
365
)
\frac{50-1}{365})
36550−1)≈0.9704
下面是概率表:
x | p |
---|---|
20 | 0.4114 |
25 | 0.5687 |
30 | 0.7305 |
35 | 0.8144 |
40 | 0.8912 |
45 | 0.9410 |
50 | 0.9704 |
55 | 0.9863 |
60 | 0.9941 |
从上述表格中不难看出当人数达到60时,概率就会接近于1。
所以生日悖论本质就是随着元素数量的增多,复元素的概率就会以惊人的速度往上增加,而我们恰恰就会低估了它的增长速率。这么一说,在日常生活中这种事情也就不足为奇了,可是在密码学的研究中我们就不能忽视这类问题,如果忽略这类问题,我们就会疏忽了散列值碰撞概率。
哈希函数
Hash函数又称为哈希函数,散列函数,是将任意长度的消息输出为定长消息(又称报文摘要)函数,表现形式为:
x = h(m)
哈希函数用于构建数据的指纹,而指纹是用作于数据标识的。Hash函数主要应用于数据完整性,消息认证,数字签名等。
常见的散列函数有:MD5,SHA-1,SM3等,还应用于HMAC(后面会详细介绍这些技术)。
Hash函数具有如下几个特性:
- 单向性(one way):已知x,求x=h(m)的m在计算上是不可行的。
- 弱抗碰撞性(weakly collision free):对于任意给定消息m,如果找到另一个不同的消息m’,使得h(m’)=h(m)在计算上是不可行的。
- 抗强碰撞性(strongly collision free):寻找两个消息m和m’,使得h(m’)=h(m)在计算上是不可行的。
对Hash的攻击就是寻找一对碰撞消息的过程。对散列函数的攻击方法主要有两种:
-
穷举攻击:比较典型的攻击方法就是生日攻击,及产生若干明文消息,并计算出消息摘要,然后进行比对,寻找碰撞点。
-
利用散列函数的代数结构:攻击其函数的弱性质,通常有的方法有:中间相遇攻击,修正分组攻击和差分分析等。
生日攻击
生日攻击(Birthday Attack)通俗上来说就是利用刚才所说的生日悖论的原理结合Hash函数进行攻击。
假设Hash函数值有n个比特,其中m为真消息,M为伪造假消息。m与M分别有c与C个变形的消息。变形消息与消息有着相同的内容,但是表现形式不同。举个例子:如果在消息里面增加空格,内容没有发生变化,但是已经成为了变形消息了。
由于长度为n的散列值为一共有
2
n
2^n
2n个,那么给定的m与M,变形为m’和M不发生碰撞的概率为1-
1
2
n
\frac{1}{2^n}
2n1;所有M与m不发生碰撞的概率为(1-
1
2
n
\frac{1}{2^n}
2n1)^Cc≈1 - e ^ (-Cc/2 ^n)
所有M与m发生碰撞的概率为1-(1-
1
2
n
\frac{1}{2^n}
2n1)^Cc 。
当c=C=2^(n/2)时,碰撞概率为1-
1
e
\frac{1}{e}
e1≈0.63。
这种情况下,攻击者利用伪造的假消息获得真消息相同的hash值得花费仅2^(n/2),n值越大则hash函数越安全。
一般来说Hash值长度为64比特的Hash函数(取值为2的幂),生日攻击的时间复杂度为2^32。碰撞减少了一半,在密码学里是相当不安全的。(数学公式确实不太会弄,不好意思了,凑合看看吧。)