Hash
Hash(哈希)
首先要知道数据都存储在内存中,假设有几万条商品价格的数据在内存中,我们想从中找到“苹果”价格,如果你事先不知道商品存储规律,就只能一个个去查找,比如第一个是香蕉、第二个是梨,直到第250个才查到苹果。而如果我们记得每个商品价格存在那个位置就没必要去查找,比如直接去查250号的苹果价格。在计算机中的表现就是知道每条数据对应的内存地址,直接去取相应地址的数据。现在的需求是如何在计算机中实现告诉我一个商品描述,瞬间得到该商品信息存储在哪个地址。于是数学家们设计了一套算法,这套算法能够对数据进行一个简单的摘要,可以简单理解为用不同的整数代表不同的数据,这套算法也就是哈希算法。在存储数据时,我们先对数据的一些描述信息,比如“苹果”,进行哈希运算,得到一个整数,将该整数做些简单处理,转化为一个内存地址,然后将数据存在这个地址对应的存储空间。下次取数据时,仍然对描述信息做哈希运算,得到对应的存储地址,然后到该地址直接取到完整的数据。这样就不用一个个去遍历查找了,即便上亿条数据,也可以瞬间得到想要的数据。 还有几个点补充。这种数据储存的地址依赖哈希运算得到的整数,所以存储是不连续的,编程中提到的字典、map一般就是这种数据结构,而另一种数据结构“数组”则是连续存储的,这两种数据结构各有优缺点各有用途。还有哈希具体的算法实现有很多,也可以根据不同的需求进行不断完善改进。哈希可以对任意数据运算,包括文本,电影,图片,这个很容易理解,因为计算机中数据本质都是二进制01。 还有个很重要的点,哈希运算得到的值并不一定唯一,也就是不同数据有可能哈希值相同。这个也很容易理解,比如我们生成一个8位的哈希值,只要正数,最多也就127个数,如果对1000个数据进行运算,生成1-127之间的数,那必然会有重复。当然这个例子比较极端,我们取的位数不可能那么小。一般重复率极低,我们也有其他办法应对重复的问题。
总引
-
定义:哈希是一种单向函数,可以将任意长度的输入(通常称为“消息”)转换为固定长度的输出,这个输出称为“哈希值”或“哈希码”。
-
单向性:哈希函数是单向的,意味着从哈希值几乎不可能反推出原始输入。
-
确定性:对于给定的输入,哈希函数总是产生相同的哈希值。
-
info
所以对于密码的hash操作实际上先把密码进行hash,然后存入数据库,当用户再次登录的时候,会把输入的内容进行hash操作,然后和数据库的内容进行对比看是否一致
-
-
快速计算:哈希函数通常计算速度很快。
-
用途:哈希常用于数据完整性验证、密码存储、数据索引等场景。
-
但是并不是绝对安全的
- 彩虹表:彩虹表是一种预先计算好的哈希值和它们对应的原始输入的数据库。攻击者可以使用彩虹表来查找哈希值对应的原始数据。
- 暴力破解:通过尝试所有可能的输入直到找到一个产生相同哈希值的输入。
- 字典攻击:使用一个包含常见密码或特定词汇的字典来尝试匹配哈希值。
- 哈希碰撞:找到两个不同的输入,它们产生相同的哈希值。
- 侧信道攻击:利用系统实现中的漏洞来获取哈希值。
为了提高安全性,现代的哈希算法(如 SHA-256)设计得非常复杂,以抵抗上述攻击方法。此外,密码存储时通常会采用“盐值”(salt),即一个随机值,与密码结合后再进行哈希,这样可以进一步增强安全性,使得彩虹表攻击变得不可行。
加密
- 定义:加密是一种将原始数据(明文)转换为看起来是随机的、无法理解的形式(密文)的过程。这个过程称为加密,而转换后的密文需要通过解密过程还原为原始数据。
- 可逆性:与哈希不同,加密是可逆的。使用正确的加密密钥和算法,可以解密密文,恢复原始数据。
- 安全性:加密的安全性依赖于加密算法的强度和密钥的保密性。
- 用途:加密用于保护数据的机密性,防止未授权的访问和篡改
数组和hash
-
数组是利用索引来记录内存地址,通过内存地址直接得到对应的数据或值
-
hash里的键需要运算后再找到内存地址,如何运算这个键就叫hash函数。比如对键的ASCII码和进行模运算得到的对应的结果
-
比如有个hash表只能存5个键值对,比如USA会放到4的地址,所以无论输入是多长,输出会根据hash算法变成固定的长度(此时是模运算)
- 但是此时不可避免的会出现余数相等,即不同的输入得到相同的输出,所以会出现hash碰撞
-
开放寻址法
-
线性探测方法,如果当前位置发生冲突,则直接放到下一个没有被占据的位置,但是会让数据聚集,发生一次聚集现象,解决方法是二次探测方法,就是先找11的位置,如果再次冲突就找22的位置然后33
-
开放寻址法是一种解决哈希表冲突的方法,它要求哈希表中的所有槽位都可用于存储数据。当发生冲突时,算法会寻找表中的下一个空闲位置来存储数据。开放寻址法有几种不同的探测技术:
- 线性探测(Linear Probing) :从发生冲突的位置开始,线性地探测下一个空闲位置。
- 二次探测(Quadratic Probing) :使用二次函数(如 𝑖2i2)来确定探测的步长。
- 双重哈希(Double Hashing) :使用第二个哈希函数来确定探测的步长。
开放寻址法的优点是它不需要额外的存储空间来存储数据,因为所有的数据都存储在哈希表本身中。但是,这种方法可能导致聚集现象,即连续的元素聚集在一起,这可能会降低查找效率。
-
-
封闭寻址法
-
链表法,就是对应的位置实际上变成链表进行存储,一个位置可以存一个链的数据,但是当想找的数据都是基于这个位置的时候,查询会很麻烦很慢,也可能发生集群现象,数据会集中出现在某几个节点里
-
封闭寻址法,也称为链地址法(Chaining),是一种通过链表来解决哈希表冲突的方法。在这种方法中,哈希表的每个槽位都包含一个指向链表的指针,所有映射到该槽位的元素都存储在这个链表中。
当发生冲突时,新元素不是替换掉原有元素,而是被添加到该槽位的链表中。这种方法的一个关键优势是它可以处理大量冲突,因为所有的冲突元素都可以存储在同一个槽位的链表中。
封闭寻址法的优点是可以很好地处理冲突,并且可以通过优化链表(如使用平衡树代替链表)来提高性能。但是,这种方法需要额外的存储空间来维护链表,并且当链表变得非常长时,查找效率可能会降低。
-
-
-
优秀的hash算法不会生成相对固定的值,而是直接固定死的值,叫摘要,比如128bits长度的,256bits长度的,512bits的等