**生日攻擊**是密碼學的一種破譯手段，利用了機率論中的生日問題，用於干擾兩個或以上群體之間的通訊。此攻擊是對固定的重新排列模式作隨機嘗試攻擊，仰賴較高的命中率（鴿籠原理）。生日攻擊可在{\textstyle {\sqrt {2^{n}}}=2^{n/2}}等級的時間內找到雜湊碰撞，低於原像攻擊的 {\textstyle 2^{n}}。有研究給出一個籠統（但尚存爭議）的估計，表示量子電腦能夠進行生日攻擊，進而可以破解防雜湊碰撞的抵禦，並能把時間壓縮到 {\textstyle {\sqrt[{3}]{2^{n}}}=2^{n/3}} 的等級。

理解問題
----

条目：生日問題
舉個例子：當老師問一個有30名學生的班級（n = 30）每個人的生日在哪一天（為簡便，此處省略閏年）以確定是否有兩個學生同一天生日（對應碰撞 ）。從直覺角度考慮，機率看起來很小。若老師選擇特定日期（例如9月16日），則至少有一名學生在那天出生的概率是{\displaystyle 1-(364/365)^{30}}，約為7.9%。但是，與我們的直覺相反的是，至少一名學生和另外任意一名學生有著相同生日的概率大約為70.63%（n = 30時），從方程 {\displaystyle 1-{\frac {365!}{(365-n)!\cdot 365^{n}}}}中可看出。

數學
--

定函数f，攻击目标是找到符合{\displaystyle f(x\_{1})=f(x\_{2})}的两个不同输入值{\displaystyle x\_{1},x\_{2}}。这一对{\displaystyle x\_{1},x\_{2}}被称之为碰撞。找出一對碰撞的方法可以是，隨機或偽隨機地輸入不同的數值，直到找出至少兩個相同的結果為止。但由於生日問題，這種方法的效率不高。明確的說，若函数f(x)所拥有的H的不同输出有着相同可能性且H足够大的话，我们可估計出，要取得符合{\displaystyle f(x\_{1})=f(x\_{2})}的一对不同的自变量x\_{{1}}和x\_{{2}}，函数平均需要大约{\displaystyle 1.25{\sqrt {H}}}个不同个自变量。

思考下面一个实验。从下列的*H*数集中我们将随机均匀地选择*n*个值，因此将允许重复。使*p*（*n*; *H*）成为此实验中至少一个值被选择多于一次的概率。则概率可估计为

{\displaystyle p(n;H)\approx 1-e^{-n(n-1)/(2H)}\approx 1-e^{-n^{2}/(2H)}}
使*n*（*p*; *H*）为我们将选择的最小数值，这种情况下找到碰撞的概率至少为 *p*。通过颠倒上方的表达式，我们得到了下列估计公式：

{\displaystyle n(p;H)\approx {\sqrt {2H\ln {\frac {1}{1-p}}}}}
将碰撞概率设为0.5我们将得到

{\displaystyle n(0.5;H)\approx 1.1774{\sqrt {H}}}
使*Q*（*H*）成为我们在寻找首次碰撞前所期望的值的数量。此数量可通过下列公式进行估计：

{\displaystyle Q(H)\approx {\sqrt {{\frac {\pi }{2}}H}}}
举个例子，若使用64位哈希，则估计将有1.8 × 1019个不同的输出。若这些输出均可能发生（理想情况下），则攻击者"仅仅"需要约50亿次尝试（5.38 × 109）就能通过暴力攻击生成碰撞。此值被称为 **生日界限**（birthday bound）而对于*n*位密码则需要2*n*/2次。下列举出其他例子


| 位数 | 可能输出（H） | 期望的随机碰撞可能性（2安全系数）（p） |
| --- | --- | --- |
| 10−18 | 10−15 | 10−12 | 10−9 | 10−6 | 0.1% | 1% | 25% | 50% | 75% |
| 16 | 216 (~6.5 x 104) | <2 | <2 | <2 | <2 | <2 | 11 | 36 | 190 | 300 | 430 |
| 32 | 232 （~4.3 × 109） | <2 | <2 | <2 | 3 | 93 | 2900 | 9300 | 50,000 | 77,000 | 110,000 |
| 64 | 264 （~1.8 × 1019） | 6 | 190 | 6100 | 190,000 | 6,100,000 | 1.9 × 108 | 6.1 × 108 | 3.3 × 109 | 5.1 × 109 | 7.2 × 109 |
| 128 | 2128 （~3.4 × 1038） | 2.6 × 1010 | 8.2 × 1011 | 2.6 × 1013 | 8.2 × 1014 | 2.6 × 1016 | 8.3 × 1017 | 2.6 × 1018 | 1.4 × 1019 | 2.2 × 1019 | 3.1 × 1019 |
| 256 | 2256 （~1.2 × 1077） | 4.8 × 1029 | 1.5 × 1031 | 4.8 × 1032 | 1.5 × 1034 | 4.8 × 1035 | 1.5 × 1037 | 4.8 × 1037 | 2.6 × 1038 | 4.0 × 1038 | 5.7 × 1038 |
| 384 | 2384 （~3.9 × 10115） | 8.9 × 1048 | 2.8 × 1050 | 8.9 × 1051 | 2.8 × 1053 | 8.9 × 1054 | 2.8 × 1056 | 8.9 × 1056 | 4.8 × 1057 | 7.4 × 1057 | 1.0 × 1058 |
| 512 | 2512 （~1.3 × 10154） | 1.6 × 1068 | 5.2 × 1069 | 1.6 × 1071 | 5.2 × 1072 | 1.6 × 1074 | 5.2 × 1075 | 1.6 × 1076 | 8.8 × 1076 | 1.4 × 1077 | 1.9 × 1077 |

表格展示了需要达到给定成功可能性的哈希数量*n*(*p*)，且假设所有哈希均有相同概率。为了比较，通常一块硬盘的不可修正比特错误率为10−18至10−15。理论上说，使用128位的MD5哈希或通用唯一识别码将在8200亿份文档时得到破解，即使它们的可能输出还要更多。
显而易见，若函数的输出不平均分布，碰撞则可能将被更快找到。哈希函数的"平衡"概念量化了其能抵御生日攻击（攻击平均的密钥分布）的次数。然而，确定哈希函数的平衡将需要计算所有输入，因此这种方法对于诸如MD及SHA系的流行哈希函数是不切实际的。
当计算{\displaystyle n(p;H)}中的子表达式{\displaystyle \ln {\frac {1}{1-p}}}翻译到常见的编程语言如`log(1/(1-p))`下，公式由于有效位丢失（英语：）对较小的p的计算精度不高。例如，当`log1p`（如C99中一样）可用时，应直接使用可达到相同效果的表达式`-log1p(-p)`。 If this is not done, the first column of the above table is computed as zero, and several items in the second column do not have even one correct significant digit.

### 源码示例

下列是能准确生成上方表格中大多数数值的Python函数：

```
from math import log1p, sqrt

def birthday(probability\_exponent, bits):
    probability = 10.0\*\*probability\_exponent
    outputs = 2.0\*\*bits
    return sqrt(2.0\*outputs\*-log1p(-probability))

```

若代码保存在命名为`birthday.py`的文件中，您可和下面的例子一样交互运行此程序：

```
$ python -i birthday.py
>>> birthday(-15, 128)
824963474247.1193
>>> birthday(-6, 32)
92.68192319417072

```

### 简单估计

一项經驗法則可适用于此关系中的心算流程

{\displaystyle p(n)\approx {n^{2} \over 2H}}
可改写为

{\displaystyle H\approx {n^{2} \over 2p(n)}}.
或

{\displaystyle n\approx {\sqrt {2H\times p(n)}}}.
此公式在概率小于等于0.5时有效。

此近似方案在使用指数时可轻易使用。例如，假设您正构建32位哈希（{\displaystyle H=2^{32}}）且希望碰撞概率为100万分之一（{\displaystyle p\approx 2^{-20}}），则最多我们需要多少份文档？

{\displaystyle n\approx {\sqrt {2\times 2^{32}\times 2^{-20}}}={\sqrt {2^{1+32-20}}}={\sqrt {2^{13}}}=2^{6.5}\approx 90.5}
即与正确答案93次近似。

数字签名敏感度
-------

數位簽章可对生日攻击十分敏感。设想一条被首次计算{\displaystyle f(m)}（f为密碼雜湊函數）所签名的信息，且随后又使用了一些密钥来签名{\displaystyle f(m)}。假设愛麗絲與鮑伯牵涉到签名詐騙合同。马洛里准备了一份正常合同m和一份伪造合同{\displaystyle m'}。馬洛里随后发现m所在的位置数可在不改变原意的情况下（如插入逗号、清空行、在句后增加一两个空格、替换同义词等等）被更改。通过结合这些更改，她可新建诸多m的变体且均为正常合同。

相似情况下，马洛里也为伪造合同{\displaystyle m'}新建了诸多变体。她随后应用哈希函数到所有变体直到她找到与正常合同有着相同哈希值{\displaystyle f(m)=f(m')}的伪造合同位置。她随后将正常合同带给鲍勃签名。在鲍勃签名完后，马洛里将签名取下并依附到伪造签名上。此签名"证实了"鲍勃签署了伪造合同。

此例中，攻击概率与原始的生日问题稍有不同，因为马洛里将在寻找两份具有相同哈希的正常合同与伪造合同时将一无所获。马洛里的策略是生成一份伪造和一份正常的合同。生日问题公式适用于n为合同对数的情况下。但马洛里所生成的哈希数实际上为2n。

为避免这种攻击，用于签名方案的哈希函数的输出长度应够大以从计算角度防止生日攻击。换言之，位数应为防止普通暴力破解所需位数的两倍。

除了使用更大的位数长度外，签名者（鲍勃）可以在签名前做出一些随机且无害的更改，并且在自己的手上留下一份合同副本以在法庭上展示出他的签名与正常合同上的匹配，而不匹配伪造合同。

离散对数的波拉德ρ算法是使用生日攻击以计算离散对数的算法。

另请参阅
----

* 碰撞攻击（英语：）
* 中途相遇攻擊

参考文献
----

* 米希尔·贝拉尔（英语：），《等一下：哈希函数平衡及其对生日攻击的影响》（Tadayoshi Kohno: Hash Function Balance and Its Impact on Birthday Attacks） EUROCRYPT（英语：） 2004: pp401–418
* 《应用密码学》, 第二版。（Applied Cryptography, 2nd ed.） 布魯斯·施奈爾所著

外部链接
----

* "What is a digital signature and what is authentication?" 来自RSA安全（英语：）加密的常見問題集。
* "Birthday Attack" （页面存档备份，存于） X5网络加密问答

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * 
* 论
* 编
 雜湊函數 & 訊息鑑別碼 |
| --- |
|  |
| 
* 列表
* 比较
* 已知攻击

 |
|  |
| 常用函数 | 
* MD5
* SHA-1
* SHA-2
* SHA-3/Keccak
* BLAKE2

 |
|  |
| SHA-3入围（英语：） | 
* BLAKE
* Grøstl
* JH（英语：）
* Skein（英语：）
* Keccak（胜出）

 |
|  |
| 其他函数 | 
* ECOH（英语：）
* FSB（英语：）
* GOST（英语：）
* HAS-160（英语：）
* HAVAL（英语：）
* Kupyna（英语：）
* LM hash（英语：）
* MD2（英语：）
* MD4
* MD6
* MDC-2（英语：）
* N-Hash（英语：）
* RIPEMD
* RadioGatún（英语：）
* SWIFFT（英语：）
* SipHash（英语：）
* Snefru（英语：）
* Streebog（英语：）
* Tiger（英语：）
* VSH（英语：）
* WHIRLPOOL（英语：）
* SM3
* X11

 |
|  |
| 密码散列/密钥延伸函数 | 
* Argon2
* Balloon
* bcrypt
* Catena（英语：）
* crypt(3)（英语：） (DES)
* LM散列（英语：）
* Lyra2
* Makwa（英语：）
* PBKDF2
* scrypt
* yescrypt

 |
|  |
| 通用密钥派生函数 | 
* HKDF
* KDF1/KDF2

 |
|  |
| MAC算法 | 
* DAA（英语：）
* CBC-MAC（英语：）
* HMAC
* OMAC（英语：）/CMAC（英语：）
* PMAC（英语：）
* VMAC（英语：）
* UMAC（英语：）
* Poly1305

 |
|  |
| 认证加密模式 | 
* CCM（英语：）
* CWC（英语：）
* EAX（英语：）
* GCM
* IAPM（英语：）
* OCB（英语：）

 |
|  |
| 攻击 | 
* 碰撞攻击（英语：）
* 原像攻击
* 生日攻击
* 穷举攻击/蛮力攻击
* 彩虹表
* 旁路攻击
* 长度扩展攻击

 |
|  |
| 设计 | 
* 雪崩效应
* 碰撞
* 默克尔-达姆加德结构（英语：）

 |
|  |
| 标准化 | 
* CRYPTREC（英语：）
* NESSIE（英语：）
* NIST散列函数竞赛（英语：）

 |
|  |
| 实际应用 | 
* 盐
* 密钥延伸
* 信息鉴定

 |

 |

 |
|  |
| 

| * 
* 论
* 编
密码学 |
| --- |
|  |
| 
* 密码学历史
* 密码分析
* 密碼學主題列表

 |
|  |
| 
* 對稱密鑰加密
* 分组密码
* 流密码
* 公开密钥加密
* 密碼雜湊函數
* 訊息鑑別碼
* 随机数
* 隐写术

 |
|  |
| 
* 分类 分类
* 主题 主题
* 专题 专题

 |

 |

 |