一. 前言
当我们在网上下载一个软件包时,一般会附带一个hash文件,这个里面就保存了通过软件包计算的哈希值,官方名字叫散列值,用来让使用者确认软件包有没有被篡改的,而计算这个散列值就是由单向散列函数生成的。单向散列函数有一个输入和一个输出,输入成为消息,输出就成为散列值。
二. 术语
1. 单向散列函数
也被称为消息摘要函数(message digest function),哈希函数和杂凑函数。
2. 消息
也被称为原像(pre-image)。
3. 散列值
也称为消息摘要(message digest)或者指纹(fingerprint)。
三. 单向散列函数的性质
1. 根据任意长度的消息计算出固定长度的散列值
单向散列函数可以处理任意长度的消息,无论消息多长,产生的散列值都是固定的。
2. 能够快速计算出散列值
计算散列值应该随着消息长度的增加线性增加,而不能是指数增加。如果不能在可接受的计算时间内完成就没有意义。
3. 消息不同散列值不同
哪怕是消息中的其中一个字节发生改变,也必须产生完全不同的散列值,这种不同的消息产生相同的散列值的情况称为碰撞。抗碰撞性是衡量一个单向散列函数安全的重要指标。
4. 具备单向性
表示由散列值无法计算出消息的性质。就如同砸碎玻璃很简单,但是把玻璃碎片拼成玻璃很难是一个道理。
四. 单向散列函数的种类
1. MD4,MD5
MD4和MD5分别是在1990和1991年设计出来的,都能够产生128比特(16字节)的散列值,由于这两个函数的强抗碰撞性都已经被攻破,已经不再安全,所以,现在已经不推荐使用了。
2. SHA-1,SHA-256,SHA-384,SHA-512
SHA-1是由NIST设计的一种160比特(20字节)的散列值的单向散列函数。SHA-1已经在2005年被攻破,现在已经不推荐使用了。
SHA-256,SHA-384和SHA-512统称为SHA-2。SHA-2包含六种版本,分别是SHA-224,SHA-256,SHA-512/224,SHA-512/256,SHA-384和SHA-512,它们都是SHA-256和SHA-512的变种。输出的散列值的长度分别为224(28字节),256(32字节),224(28字节),256(32字节),384(48字节)和512(64字节)比特。
3. SHA-3
在2005年SHA-1被攻破的背景下,NIST开始着手研究SHA-3,也是和AES一样,通过公开竞选的方式进行标准化,SHA-3的选拔于2012年完成,由名为Keccak的算法胜出,成为SHA-3。
NIST规定,参与竞选的算法必须和AES一样,能够让所有人自由免费的使用SHA-3算法。
注意:
由于SHA-2还没有被攻破,所以SHA-2和SHA-3目前都是安全的。
五. openssl实践
openssl通过dgst选项来进行单向散列函数操作的,通过openssl dgst -list可以列出当前openssl支持的单向单列函数,例如:
[root@ sha1]#openssl dgst -list
Supported digests:
-blake2b512 -blake2s256 -md4
-md5 -md5-sha1 -mdc2
-ripemd -ripemd160 -rmd160
-sha1 -sha224 -sha256
-sha3-224 -sha3-256 -sha3-384
-sha3-512 -sha384 -sha512
-sha512-224 -sha512-256 -shake128
-shake256 -sm3 -ssl3-md5
-ssl3-sha1 -whirlpool
1. MD4,MD5
MD4:
infile内容:
hello, md4
openssl dgst -md4 infile
MD4(infile)= 4462e317a5ebbdb5f0d3774c1c45c103
从stdin获取内容:
echo -n "hello, md4" | openssl dgst -md4
(stdin)= 4462e317a5ebbdb5f0d3774c1c45c103
MD5:
从stdin获取内容:
echo -n "hello, md5" | openssl dgst -md5
(stdin)= 33b3bc8e05b4fcc16bd531dd9adac166
注意,MD4和MD5的散列值是16字节,以上都是以16进制显示的"33b3bc8e05b4fcc16bd531dd9adac166"其实是0x33 0xb3 0xbc 0x8e 0x05 0xb4 0xfc......0xac。
2. SHA-1
echo -n 'hello,sha1' | openssl dgst -sha1
(stdin)= 73eb2c728f810753c9537ab9b876c9c0305255f5
同样,SHA-1的输出是20字节,上面是以16进制显示的。
3. SHA-2
SHA256:
echo -n "hello,sha2" | openssl dgst -sha256
(stdin)= 2124f3c215a468c4cef31fb974b7093baccad0180a415e34031f551372ff2d4cSHA-384:
echo -n "hello,sha384" | openssl dgst -sha384
(stdin)= e15397fd702d3535b063ce4261a9bb6a6f8c6086b5d7af48a843c90bb25419c6df8206c8655cd3e1db20b4668c7c2433SHA-512:
echo -n "hello,sha512" | openssl dgst -sha512
(stdin)= 30fc79c63ebe7cbd1d6d5d2b5e4759bb13415b5e5284973b9fd5bd26a8f5beea3d277d549234e1d4c13c7f5027240eb70c92f831c3c157f87274a2802d48e379
3. SHA-3
SHA3-256:
echo -n "hello,sha3-256" | openssl dgst -sha3-256
(stdin)= 125419436802bc6d47c8100b6fd130492a404d48a935299e367da1bbdfae22d6
openssl除了支持sha3-256,还支持sha3-224,sha3-384和sha3-512。
六. 总结
单向散列函数能够很容易的根据消息计算出散列值,但是却很难根据散列值计算出消息的内容,所以,单向散列函数通常用于确定一个消息是否被篡改。单向散列函数有MD4和MD5,由于它们已经被攻破,所以现在一般不建议使用了,SHA-1也于2005年被攻破,所以也不建议使用了,SHA-2和SHA-3由于目前还未被攻破,所以认为是安全的,可以使用。