3.5、HASH哈希(散列)函数
目录
- 哈希算法 Hash
- HASH应用(一)文件完整性校验
- HASH应用(二)账号密码存储
- HASH应用(三)用户身份认证
- MAC
哈希算法 Hash
哈希算法也叫HASH函数,有些地方又称为杂凑函数、散列函数。哈希是能够将任意长度的信息转换成固定长度的哈希值,任意长度可以是一比特,也可以是一百比特,把它转换成固定长度,具体是多少长度要看你使用的哈希算法,比如说用最后生成的哈希值就是128位,如果用的是国产的哈希算法,最后生成256位
它生成的哈希值,我们也把它叫做数字摘要或者叫散列值,并且任意不同的消息或文件生成的哈希值是不一样的
这里面如果用h来表示哈希函数,h满足下列的条件,第1,h的输入可以是任意长度的消息或者文件,第二个h的输出长度是固定的,根据你选用的不同的哈希函数,它的输出长度是有差异的,这也是一个重点。第三个根据h和m,m是消息,h是哈希函数,就是给你一个消息或者文件,你把哈希计算出来很快,你直接去网站上,随便找一个哈希网站,你就可以可以得到一个哈希结果。
第四个,就是给定h的描述找两个不同的消息m1和m2,让他们的哈希值相等,这个在计算上是不可行的,就基本上是不可能找得到的,只要这两个消息不相同,那生成的哈希值肯定是不一样的,有人说我能不能找到有两个数生成的哈希值是一模一样的,而这两个数是不一样的,是可以找到的,但是这玩意儿不好找,这是算科研领域的
我们普通应用来讲,反正它就是找不到的,计算上是不可行的,因为按照我们常规的理解,就是两个消息或者两个文件不相同,哈希值肯定是不相同的。这是哈希值哈希函数的几个条件,第一个不可逆,它是单向的,比如说一比特生成了128位的哈希函数,不能通过这128位把它恢复成以前的原始消息,原始值,恢复不了
第二个叫无碰撞性,就是你找不到两个消息,让他们哈希值相等,这是没有碰撞的
第三个是雪崩效应,比如说这10t文件,我生成一个哈希值128比特,如果我10t,我再加一个一比特,我生成的哈希值跟以前10t是完全不一样的,差别非常大,会产生血崩,虽然你10t没有变,你只变了一个比特,但是正是由于你这一比特的变化,造成哈希值的输出会发生翻天覆地的变化,这个叫雪崩效应
HASH应用(一)文件完整性校验
完整性,就是文件有没有被修改,文件如果被增加了内容或者被删除了内容,调换了里面的顺序,它都是不完整的,被修改过就不完整了
HASH应用(二)账号密码存储
在我们网站后台,我们需要进行一些注册,注册可能就有一个表单,用户名密码不能通过明文去保存,如果网站管理员,他想干坏事情,他就可以窃取我们用户的用户名和密码,因为一个公司里面好人和坏人可能都有,有些时候堡垒是从内部攻破的,我们既要防外面的黑客,也要防内贼,所以网站或者一些核心的数据库,我们密码保存,是不能做明文存储的,这样安全风险太大了,所以就可以用哈希存储我们用户名,但是密码我给你弄成哈希,即使你这个内部的管理员知道了我的哈希值,但是你想通过哈希去解密我们的密文,在理论上是不行的,但是还是可能存在能够把哈希还原成密码,特别是一些常规的哈希,一些常规的密码是可以对应的,这个攻击的话一般叫彩虹表攻击
查找我们已经存在的哈希和明文存在的关系对比表,所以如果是一二三四五六,你去网上去解,肯定是能够解得开的,也就是说这么存储也不太安全
我们实际的项目应用会在它这个密码的基础上,给它加点盐,比如说我们把用户注册的时间跟这个一二三四五六加起来,然后哈希生成一个哈希值,这玩意就不太好破解。破解起来,你查彩虹表,就不太管用了,因为每个人注册时间不一样,所以最后生出来的哈希值,真的是千奇百怪的,这就是实际应用
实际的应用就比较难破解了,所以这是第二种应用,用来存储我们账号的密码
HASH应用(三)用户身份认证
比如这里面有个客户端,有台服务器,他们之间要进行身份认证,比如说我的客户端,我直接把密码或者用户名发过去,密码一二三,这边能查到张三一二三,那就通过了,这是一种非常简单的方式,但是这种认证方式容易被截获
认证里面有一种更高级的方式,就是借助哈希实现,主要就是增加一个随机数R来做哈希,然后最后生成一个MAC值,MAC值叫认证码,双方要预先知道随机数r,该认证方式可以用来消除中间人攻击,也能进行身份的原认证
具体的过程,一共分成三步,首先客户端向服务器发起认证,当然有些时候是服务器向客户端去发起认证,然后我们的服务器他检查你是张三,检查有没有张三,有张三,就给你返回一个随机数r,他的数据库里面有用户张三,然后给你返回一个随机数,这个随机数返回我们的客户端之后,客户端其实他本地是不知道张三他自己是张三,密码是一二三他是知道的,这时候客户端在本地把密码取出来一二三,然后你不是给我返了一个随机数,把r找出来,然后生成一个哈希值,这个哈希值,我们把它叫做Mac,或叫hMac,然后把它返给我们的服务器这端,他把张三的密码也取出来,一二三,不是还有一个随机数,随机数拿出来再生成一个哈希值,然后生成这个哈希值跟对方发过来的哈希值一对比,它们两个相不相等,如果相等的话,就证明客户端你是有张三的用户名和密码,如果不相等,那就证明你没有或者你的密码是错的
这样可以进行身份认证,同时也避免了我们密码在我们的网络上传播,我们只传了一个哈希值,而且这个哈希值还是加了一个随机数的哈希值,你想破解是比较难的。一般的一二三,如果说这个哈希值还比较好破解,但是我们加了一个随机数,就很难破解
通过这种方式来进行身份认证,又避免了密码在网络上传输,觉得还是挺巧妙的,像ppp协议,它里面有个认证叫chap,它底层的机制就是这种方式
MAC
哈希里面有个东西叫Mac,消息认证码
哈希值就是通过一个消息生成一个哈希值,MAC它主要是把一个消息再加一个key就生成消息,之后再加点东西,然后通过一个算法,最后生成一个MAC,它本质上还是哈希。只是我在哈希的基础上加入了一个k,然后通过某一个算法来生成MAC值,第一种我可以过哈希算法,当然也可以通过分组密码算法来实现
常规用的比较多,其实还是通过哈希算法来生成消息认证码,典型的就是哈希消息,再加上一个k或者一个随机数,通过分组密码来实现,比如说有基于aes的CBC-MAC算法,我不是用的哈希,我是用的分组加密,分组加密也就是对称加密,典型的就是aes这一类的
有两种算法可以生成Mac值,一个是哈希算法,一个是分组加密算法,常用的是aes。哈希,它是能够校验数据的完整性,无法进行身份认证,因为计算过程它是没有必要参与的,就是一个消息或者一个文件,我把它生成一个哈希值,Mac是能够保证数据的完整性,同时可以进行身份认证,因为它有key的参与,有一个key,我们可以采用哈希算法和对称加密算法两种方法来产生Mac值,消息认证码,然后hMac是Mac当中的一种