[转帖]阮一峰:哈希碰撞与生日攻击(代码片段)

jinanxiaolaohu jinanxiaolaohu     2023-01-03     755

关键词:

哈希碰撞与生日攻击

作者: 阮一峰

日期: 2018年9月 5日

技术分享图片

一、哈希碰撞是什么?

所谓哈希(hash),就是将不同的输入映射成独一无二的、固定长度的值(又称"哈希值")。它是最常见的软件运算之一。

如果不同的输入得到了同一个哈希值,就发生了"哈希碰撞"(collision)。

技术分享图片

举例来说,很多网络服务会使用哈希函数,产生一个 token,标识用户的身份和权限。


AFGG2piXh0ht6dmXUxqv4nA1PU120r0yMAQhuc13i8

上面这个字符串就是一个哈希值。如果两个不同的用户,得到了同样的 token,就发生了哈希碰撞。服务器将把这两个用户视为同一个人,这意味着,用户 B 可以读取和更改用户 A 的信息,这无疑带来了很大的安全隐患。

黑客攻击的一种方法,就是设法制造"哈希碰撞",然后入侵系统,窃取信息。

二、如何防止哈希碰撞?

防止哈希碰撞的最有效方法,就是扩大哈希值的取值空间。

16个二进制位的哈希值,产生碰撞的可能性是 65536 分之一。也就是说,如果有65537个用户,就一定会产生碰撞。哈希值的长度扩大到32个二进制位,碰撞的可能性就会下降到 4,294,967,296 分之一。

更长的哈希值意味着更大的存储空间、更多的计算,将影响性能和成本。开发者必须做出抉择,在安全与成本之间找到平衡。

下面就介绍,如何在满足安全要求的前提下,找出哈希值的最短长度。

三、生日攻击

哈希碰撞的概率取决于两个因素(假设哈希函数是可靠的,每个值的生成概率都相同)。

  • 取值空间的大小(即哈希值的长度)
  • 整个生命周期中,哈希值的计算次数

这个问题在数学上早有原型,叫做"生日问题"(birthday problem):一个班级需要有多少人,才能保证每个同学的生日都不一样?

答案很出人意料。如果至少两个同学生日相同的概率不超过5%,那么这个班只能有7个人。事实上,一个23人的班级有50%的概率,至少两个同学生日相同;50人班级有97%的概率,70人的班级则是99.9%的概率(计算方法见后文)。

这意味着,如果哈希值的取值空间是365,只要计算23个哈希值,就有50%的可能产生碰撞。也就是说,哈希碰撞的可能性,远比想象的高。实际上,有一个近似的公式。

技术分享图片

上面公式可以算出,50% 的哈希碰撞概率所需要的计算次数,N 表示哈希的取值空间。生日问题的 N 就是365,算出来是 23.9。这个公式告诉我们,哈希碰撞所需耗费的计算次数,跟取值空间的平方根是一个数量级。

这种利用哈希空间不足够大,而制造碰撞的攻击方法,就被称为生日攻击(birthday attack)。

四、数学推导

这一节给出生日攻击的数学推导。

至少两个人生日相同的概率,可以先算出所有人生日互不相同的概率,再用 1 减去这个概率。

我们把这个问题设想成,每个人排队依次进入一个房间。第一个进入房间的人,与房间里已有的人(0人),生日都不相同的概率是365/365;第二个进入房间的人,生日独一无二的概率是364/365;第三个人是363/365,以此类推。

因此,所有人的生日都不相同的概率,就是下面的公式。

技术分享图片

上面公式的 n 表示进入房间的人数。可以看出,进入房间的人越多,生日互不相同的概率就越小。

这个公式可以推导成下面的形式。

技术分享图片

那么,至少有两个人生日相同的概率,就是 1 减去上面的公式。

技术分享图片

五、哈希碰撞的公式

上面的公式,可以进一步推导成一般性的、便于计算的形式。

根据泰勒公式,指数函数 ex 可以用多项式展开。

技术分享图片

如果 x 是一个极小的值,那么上面的公式近似等于下面的形式。

技术分享图片

现在把生日问题的1/365代入。

技术分享图片

因此,生日问题的概率公式,变成下面这样。

技术分享图片

假设 d 为取值空间(生日问题里是 365),就得到了一般化公式。

技术分享图片

上面就是哈希碰撞概率的公式。

六、应用

上面的公式写成函数。


const calculate = (d, n) => 
  const exponent = (-n * (n - 1)) / (2 * d)
  return 1 - Math.E ** exponent;


calculate(365, 23) // 0.5000017521827107
calculate(365, 50) // 0.9651312540863107
calculate(365, 70) // 0.9986618113807388

一般来说,哈希值由大小写字母和阿拉伯数字构成,一共62个字符(10 + 26 + 26)。如果哈希值只有三个字符的长度(比如abc),取值空间就是 62 ^ 3 = 238,328,那么10000次计算导致的哈希碰撞概率是100%。


calculate(62 ** 3, 10000) // 1

哈希值的长度增加到5个字符(比如abcde),碰撞的概率就下降到5.3%。


calculate(62 ** 5, 10000) // 0.05310946204730993

现在有一家公司,它的 API 每秒会收到100万个请求,每个请求都会生成一个哈希值,假定这个 API 会使用10年。那么,大约一共会计算300万亿次哈希。能够接受的哈希碰撞概率是1000亿分之一(即每天发生一次哈希碰撞),请问哈希字符串最少需要多少个字符?

根据上面的公式倒推,就会知道哈希值的最短长度是22个字符(比如BwQ1W6soXkA1PU120r0yMA),计算过程略。

22个字符的哈希值,就能保证300万亿次计算里面,只有1000亿分之一的概率发生碰撞。常用的 SHA256 哈希函数产生的是64个字符的哈希值,每个字符的取值范围是0~9和a~f,发生碰撞的概率还要低得多。

七、参考链接

(完)

[阮一峰]腾讯的历史.转帖

今天,我读到一篇英语文章,向美国读者介绍腾讯公司的历史。我觉得,这篇文章整理了好多资料,写得非常清楚。腾讯是怎么发展起来的,只看这篇文章就够了。下面就是它的译文,供大家参考。1、1971年,马化腾生于海南。1... 查看详情

[阮一峰]找回密码的功能设计(代码片段)

...储加盐是加上类似于用户名作为盐吗? 作者: 阮一峰日期: 2019年2月7日所有需要登录的网站,都会提供"找回密码"的功能,防止用户忘记密码。正确设计这个功能,保证安全可靠,并不简单。下面就是安全专家TroyHun... 查看详情

如何防止因哈希碰撞引起的dos攻击(代码片段)

如何防止因哈希碰撞引起的DoS攻击理解哈希什么是哈希哈希和数组哈希算法哈希碰撞鸽巢原理为什么不能避免哈希碰撞哈希算法的特点如何解决哈希碰撞开放寻址法线性探测线性探测法适用场景二次探测双重散列链地址法链地址... 查看详情

证明与计算:从加密哈希函数到一致性哈希(代码片段)

目录:**0x01[哈希函数]vs[加密哈希函数]**0x02[哈希碰撞]vs[生日问题]**0x03[哈希表]vs[分布式哈希表]**0x04[欧式距离]vs[三角不等式]**0x05[异或距离]vs[前缀路由表]0x01[哈希函数]vs[加密哈希函数]在哈希表计算索引的时候,我们需要一个哈... 查看详情

阮一峰react-demo(代码片段)

1)<scriptsrc="../build/react.development.js"></script><scriptsrc="../build/react-dom.development.js"></script><scriptsrc="../build/babel.min.js"></script>ReactDOM.r 查看详情

好文种草根域名的知识-阮一峰的网络日志(代码片段)

域名是互联网的基础设施,只要上网就会用到。它还是一门利润丰厚的生意,所有域名每年都必须交注册费,这是很大的一笔钱。这些钱交到了哪里?到底谁控制域名的价格?为什么有的域名注册费很贵,... 查看详情

阮一峰:网页性能管理详解(转)(代码片段)

你遇到过性能很差的网页吗?  这种网页响应非常缓慢,占用大量的CPU和内存,浏览起来常常有卡顿,页面的动画效果也不流畅。  你会有什么反应?我猜想,大多数用户会关闭这个页面,改为访问其他网站。作为一个开发... 查看详情

阮一峰老师的es6入门:async函数(代码片段)

async函数1.含义ES2017标准引入了async函数,使得异步操作变得更加方便。async函数是什么?一句话,它就是Generator函数的语法糖。前文有一个Generator函数,依次读取两个文件。constfs=require(‘fs‘);constreadFile=function(fileName)returnnewPromis... 查看详情

flex布局(引用阮一峰老师的flex布局-语法篇)(代码片段)

一、Flex布局是什么?Flex是FlexibleBox的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。任何一个容器都可以指定为Flex布局。.boxdisplay:flex;行内元素也可以使用Flex布局。.boxdisplay:inline-flex;Webkit内核的浏览器,必须加上-w... 查看详情

阮一峰老师的es6入门:变量的解构赋值(代码片段)

变量的解构赋值数组的解构赋值对象的解构赋值字符串的解构赋值数值和布尔值的解构赋值函数参数的解构赋值圆括号问题用途数组的解构赋值基本用法ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为... 查看详情

阮一峰老师的javascript标准参考教程:object对象和object方法(代码片段)

Object对象1.概述1.1生成方法对象(object)是JavaScript语言的核心概念,也是最重要的数据类型。什么是对象?简单说,对象就是一组“键值对”(key-value)的集合,是一种无序的复合数据集合。varobj=foo:‘Hello‘,bar:‘World‘;... 查看详情

《es6标准入门》(阮一峰)--15.reflect(代码片段)

1.概述Reflect对象与Proxy对象一样,也是ES6为了操作对象而提供的新API。Reflect对象的设计目的有这样几个。(1)将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty),放到Reflect对象上。现阶段,某些方法同时在Obje... 查看详情

ue4c++实现近战攻击,精准检测与碰撞检测(代码片段)

...,素材有限,所以就放了一个火。敌人使用的是碰撞重叠+事件通知。我方攻击采用的是精准识别打击,会触发敌人受伤特效(一个闪,图片中没有体现出来。。)并且弹出输出敌人名字。绿方块代表检... 查看详情

webpack——阮一峰webpackdemo分析(代码片段)

 首先上交阮一峰老师的github地址,一共有15个demo,我们一个一个的进行分析,结合上文所学的知识!其中有一些内容,我做了修改,我是先看一遍然后从新敲了一遍。https://github.com/ruanyf/webpack-demos 准备工作首先还是安装,... 查看详情

阮一峰老师的javascript标准参考教程:数组array对象和array对象方法(代码片段)

数组1.定义数组(array)是按次序排列的一组值。每个值的位置都有编号(从0开始),整个数组用方括号表示。vararr=[‘a‘,‘b‘,‘c‘];上面代码中的a、b、c就构成一个数组,两端的方括号是数组的标志。a是0号位置,b是1号位置... 查看详情

bzoj3098hashkillerii生日共计(尚未理解)(代码片段)

...大意:  让你构造一个字符串,使字符串在题目给出的哈希条件下统计出错。思路:生日攻击,结论题,尚未理解。#include<bits/stdc++.h>#defineCLR(a,b)memset(a,b,sizeof(a))usingnamespacestd;typedeflonglongll;constintmaxn=100000;intmain()intl=20;co 查看详情

flex实例(阮一峰)

Flex布局教程:实例篇 作者: 阮一峰日期: 2015年7月14日上一篇文章介绍了Flex布局的语法,今天介绍常见布局的Flex写法。你会看到,不管是什么布局,Flex往往都可以几行命令搞定。我只列出代码,详细的语法解释请... 查看详情

[转帖]浅析虚拟机逃逸漏洞(代码片段)

浅析虚拟机逃逸漏洞https://www.freebuf.com/column/197651.html  “云时代”的虚拟机安全被提升到至关重要的位置。虚拟机逃逸指的是突破虚拟机的限制,实现与宿主机操作系统交互的一个过程,攻击者可以通过虚拟机逃逸... 查看详情