哈希表及其原理
定义
Hash ,俗称“哈希”,也叫散列, 是一种将任意长度的消息(数据〕压缩到某一固定长度的消息摘要(数
据) 的算法。常见的Hash 算法有MD5, SHA 等。Hash 算法具有几个重要的特性: 不可逆性(从Hash 值反
推出原消息是不可能的)、抗冲突性(给定消息Ml ,不存在另一条消息M2 ,使得Hash(MI)=Hash(M2))和
分布均匀性(Hash) 算法的结果是均匀分布的) 。
好的哈希函数应该具备以下特点:
- 相同的数据得到的哈希值唯一
- 通过哈希值无法通过反向推导得到源数据
- 源数据发生微小改变,得到的哈希值完全不同,
- 长的字符也能快速的计算出哈希值
- 要尽量避免冲突(不同的数据得到的编码要尽量不同
分类
常用哈希算法的实现
一般的说,Hash函数可以划分为如下几类:
-
加法Hash
-
位运算Hash
-
乘法Hash
-
除法Hash
-
查表Hash
-
混合Hash
7.数组Hash
下面详细的介绍以上各种方式在实际中的运用。
哈希函数的应用
不同的应用对Hash函数有着不同的要求;比如,用于加密的Hash函数主要考虑它和单项函数的差距,而用于查找的Hash函数主要考虑它映射到小范围的冲突率。
加密算法
哈希存储
为什么哈希表查询非常快?
哈希存储用一句话概括就是:将每个数据通过哈希函数编码成一个二进制编码,然后将这个二进制编码作为地址来保存这个数据
顺序表和链表在查找数据时,都需要从列表的第一个元素开始进行比对,直到检索到目标元素或者检索不到;而哈希存储可以根据源数据直接计算出数据的存储的地址,根据地址直接修改删除或校验数据即可,节省了数据比对的时间。
哈希表适用于那种查找性能要求高,数据元素之间无逻辑关系要求的情况。例如做文件校验或数字签名。当然还有快速查询功能的实现。
1 优点
哈希存储在数据的查找、删除、修改方面有较高的效率,可以在O(1)内遍历元素;
2 缺点
哈希是以 key-value的形式存储数据的,因此数据之间没有顺序,无法通过下标访问数据
占的空间大,牺牲空间换取了效率
当哈希表接近装满的状态时,性能下降得非常严重;因为当哈希表空间不足时需要执行扩容操作且扩容操作非常耗时。例如哈希表的长度是100,现在有第101个数要插入,这时,不仅哈希表的长度可能要扩展到150,且扩展之后所有的数都需要重新rehash。因此在设计哈希表时最好能够提前预知数据量的大小。
为什么哈希函数不可逆?
Stack Overflow解释
why hash function is not reversible
It is irreversible in the sense that for each input you have exactly one output, but not the other way around. There are multiple inputs that yields the same output.
To achieve this, irreversible math is used. For instance, it is easy to calculate 10%3. The answer to that is simply 10%3=1. But if I give you the equation x%3=1, what would you do? This equation is true for all x=3*k+1. Thus, you cannot get the number I started with.
从MD5看哈希函数的性质和特点
1、 MD5 MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一,主流编程语言普遍已有MD5实现。将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。 MD5是输入不定长度信息,输出固定长度128-bits的算法。经过程序流程,生成四个32位数据,最后联合起来成为一个128-bits散列。基本方式为,求余、取余、调整长度、与链接变量进行循环运算。得出结果。
MD5一度被广泛应用于安全领域。但是在2004年王小云教授公布了MD5、MD4、HAVAL-128、RIPEMD-128几个 Hash函数的碰撞。这是近年来密码学领域最具实质性的研究进展。使用他们的技术,在数个小时内就可以找到MD5碰撞。使本算法不再适合当前的安全环境。目前,MD5计算广泛应用于错误检查。例如在一些BitTorrent下载中,软件通过计算MD5和检验下载到的碎片的完整性。
MD5现在不安全了
什么样的哈希函数是安全的?
一个安全的散列算法需要满足如下两个条件,也是散列算法的两个特性。
(1)抗碰撞性。根据一个输入,找到一个其它输入得到相同的输出,在计算上是不可行的;
(2)不可逆性。根据一个输出,找到一个输入其散列值等于输出,在计算上是不可行的,即不可能从结果逆向推导初始值。
注意,抗碰撞性并不是说散列算法无碰撞,无碰撞的算法不可能是一个散列算法,而只能是一个无损压缩算法,因为散列算法在计算过程中必然会丢失原文部分信息。
MD5作为一个应用广泛散列算法,满足上述两个特点。根据第一个特点,MD5可用于信息的数字签名用来验证信息传输的完整性和发送者的身份认证。根据第二个特点,MD5可用于用户密码的散列存储。
(1)信息的数字签名。
对重要信息进行MD5计算生成散列值,作为信息的数字签名,用于确定信息在传输过程中是否被篡改以及发送者的身份认证。
(2)用户密码的散列存储。
常见用途就是网站敏感信息加密,比如用户名密码。将用户密码进行散列计算后落地存储,即使被拖库,用户的密码仍是安全的,因为MD5算法的不可逆性决定无法通过散列值逆向推算出密码。当然,密码破解有很多方法,比如暴力破解、彩虹表等,还是有可能从正向破解密码散列值的。
为什么MD5不安全了?在哪些方面不安全?
省流:MD5不能作信息签名了,因为抗碰撞性被证伪了,很容易找到碰撞,因此可以伪造签名,因为签名是由公钥通过哈希函数算出来的。但是仍然可以用来做密码的散列存储,因为不可逆性还是很靠得住
好文:王小云院士真地破解了MD5吗
https://cloud.tencent.com/developer/article/1400937
所谓的“破解”其实误导了很多人,并不是说扔给王小云一个MD5散列值,然后她马上就能算出一个原文来。从密文推算出明文理论上是不可能的,所以王小云的研究成果并不能通过MD5的散列值逆向推算出明文。即给定Hash值,王小云不能逆向计算出M。
MD5(M)=Hash
其中M指的是密码的明文,Hash表示密码散列后的密文。
实际上,王小云的研究成果如下:
MD5(M1)=MD5(M2)
上面那些是官网说的,具体去官网看,我就不再赘述了,具体意思是说了3个MD5不安全的原因:
(1)现在的电脑计算能力都很强,即使md5加密很牛逼,但是由于强大的现代化计算机,一秒可以穷举数以亿次的密码,所以一般那些所谓的破解都是使用穷举类型破解;
(2)字典表很大,意思是说由于md5很流行,所以有人建立了一个数据库,里面记录了很多简单的密码组合对应的md5密文,如果你经常使用的密码在里面,就会变得很不安全
(3)md5产生碰撞的几率可能比其他密码函数的几率会大一点,这个我是感受不了,因为我没有仔细研究过为什么会产生碰撞,以及那种类型的密码组合会产生碰撞。
产生碰撞:即两个不同的密码使用md5加密后可能密文一样,比如我的密码是:‘’abc‘’,那么假设:‘’你滚‘’加密后的md5密文也与我的密码abc加密后的结果一致,那么就叫碰撞,由于碰撞是很不安全的,比如用户1输入了它的密码,然后一个黑客使用穷举的方式进行匹配用户1加密后的密文,如果产生碰撞,那么黑客无需找到和用户1一样的密码加密后才能匹配,他只需要找到别的字符的加密结果也与用户1输入的密码一致就好了。
MD5用于数字签名将存在严重问题,因为可以篡改原始消息,而生成相同的Hash值。
这里,简单地用王教授的碰撞法给大家举个简单的例子。假如用户A给B写了个Email内容为Hello,然后通过王教授的碰撞法,可能得到Fuck这个字符串的摘要信息和Hello这个这个字符串产生的摘要信息是一样的(碰撞很容易找到)。 如果B收到的Email内容为Fuck,经过MD5计算后的,B也将认为是A发来的Email,并且没有被修改过!但是事实并非如此。
知乎问题:为什么说MD5是不可逆的
总结:
- 大部分人在抖机灵,大意是举反例:①不可能把全宇宙的信息压缩到16个字节还能自由还原;②无限->有限是多对一,因此不可逆
- 本质应该是MD5刻意让信息丢失
回答例子:
-
比如10%3 = 1是单射,但是从3、1和%运算倒推不出10
-
数据摘要算法不是压缩/加密算法。几百m的东西摘要一下就一个字符串还能逆向的话,恭喜你发现了二十一世纪最强压缩算法
-
简短回答:哈希函数不是单射。
-
MD5也是数字签名的一种,基本的思想是一样的,也就是通过散列函数提取出部分信息用于验证信息真伪,只不过散列的过程远远不只是提取个尾数那么简单,安全性也远远在此之上,而且散列函数本身并非是双射,所以逆向的可能性也是不存在的,不然MD5就投奔压缩算法了。但不要把它视为“绝对安全”,因为理论上存在破解的途径和概率,只不过就现有的科技水平提供的算力,暴力破解的成功率和收益小到大部分情况下可以直接忽略罢了,正因为如此我们把它当作是安全有效的。
-
很多答案不斷地說:不可能把所有的組合都放進128bit。但如果來源是少於128bit 呢?當然你可以查表馬上找出可能值,但能確定這個值的信息失去了嗎?不是完全地推測來源所有信息才叫可逆的。md5 在計算原理上有故意捨去信息才是重點,它不單是一個散列,而且是在過程中就有意讓信息丟失不能預測的散列。這是它不可逆的原因。舉個反例: crc 也是固定長度的散列,但它卻包含了部分的來源信息,具有部分可逆性。
哈希冲突,有什么办法解决?
突然,我只觉得眼前一花,只见那墙上多了许多个大字:线性探测法,二次探测法,随机法,再哈希法,链表法,公共溢出区。
线性探测法
在计算 hash 值后,发现产生了冲突,则从当前的哈希表位置开始依次向下寻找空位,直到找到空位为止。
二次探测法
一种改进方法,对哈希表进行双向探测,这是为了防止在一个方向上长时间找不到空位而进行的改进:平方
随机法
随机法在发生冲突后,每次产生一个随机数,对哈希表进行探测,实际上就是在哈希表中随机选择位置进行查找,直到找到空位置。
再哈希法
如果发生了哈希冲突,则直接换一种哈希算法,直到找到空位为止。
以上所有方法都很难解决一个问题,那就是随着哈希表被准建填满,想要找到一个空位置难如登天,以及被填满后,需要对哈希表进行扩容的问题。
而链表法则解决了这一痛点。
链表法
在链表法中,我们不再在哈希表中存储值,而是存储指向一个链表的指针,如果指针指向的链表还不存在,则创建一个链表,并将值存入其中。
如果发生了哈希冲突,说明哈希表中该位置的指针指向的链表已经被创建,我们要做的就是在链表后继续存入指向下一个节点的指针,在下一个节点存入数据即可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?