散列算法之SHA

DinS          Written on 2017/11/23

本文介绍散列算法之SHA,确保阅读过《crypto++框架介绍》,特别是理解pipelining模式。

散列算法跟通常的加密解密算法不太一样,其目的并不是用来加密,而是做文件校验,即判断信息有没有被修改过。

原理:对长度大的信息进行提炼(通过一个Hash函数),提炼过后的信息长度小很多,得到的是一个固定长度的值(Hash值)。也称Digest摘要。对于两个信息量很大的文件通过比较这两个值,就知道这两个文件是否完全一致(另外一个文件有没有被修改),从而避免了把两个文件中的信息进行逐字逐句的比对,减少时间开销。

著名的散列算法家族有MD和SHA。
SHA (Secure Hash Algorithm) 是美国国家安全局 (NSA) 设计,因此质量绝对可以保证。这个家族里有SHA-256\SHA-384\SHA-512等,这个数代表Hash值,实际上就是有多少个bit。

既然不是用来加密解密,所以应该比其他加密算法要简单一点,看代码:

大图点这里

整个流程还是很明确的,准备一个SHA对象,然后喂进一连串byte,得的hash值,即Digest。之后如果要验证就喂进这个Digest即可,可以再试一下失败的情况。

大图点这里

运行结果:

字符串对比当然用不到SHA,杀鸡焉用牛刀。一般而言SHA用来比较大文件,根据上述代码也可以轻松应对。只要按二进制一个byte一个byte读取文件即可,调用Calc和Verify用的都是byte*,用意也在这里。

当然也可以使用pipelining来做,更容易。包含必要头文件:

大图点这里

中间的HexEncoder就是把二进制变成显示16进制的字符串。之前我们一直用的是base64,但是对于散列算法好像习惯上使用16进制表示。
这里使用pipelining可以大大简化代码书写,运行结果:

这是一个字符串,所以可以很方便地传输、对比。
注意这里的字母都是大写。

另外还需要说一点很散列算法有关的东西。
除了SHA外还有MD5,在代码实现上跟上面给出的例子几乎一样,就是头文件改成MD5.h,定义的对象类型从SHA256改为MD5即可(pipelining例子)。
不过MD5已经有些不安全了,不是因为MD5算法本身的问题,而是所谓彩虹表,即预先算好各种对应值,然后知道了MD5值后反查。所以经常会使用散列算法套散列算法来增加安全性,比如MD5(MD5(“password”)),遇到这种需求知道原因就好了。

最后看一下SHA256的完整代码:

(大图点这里)

至于其他加密算法,可见《crypto++框架介绍》文末。