浅谈散列函数

本文从程序员的视角介绍md5、sha1、sha256、sha512这几个散列函数。 散列函数(hash function),又名哈希(音译)函数。散列函数将不定长的输入转换为定长的输出。输出结果通常被称为消息摘要(message digest)。一个理想的散列函数应该有几个主要特性: * 对于任何一个给定的消息,它很容易就能运算出散列值。这意味算法的着时间和空间复杂度低。 * 难以由一个已知的散列值推算出原始消息,即可认为是单向函数。 * 不同的消息得到的散列值是不同的,散列值不同消息必然不同。

在常见的编程环境中,散列函数有以下用途: * 数字签名,比如在接入支付宝和微信的支付接口时需要验证签名由此确定通信双方的身份。 * 文件索引,例如Git采用文件的sha1值作为object id。 * 密码存储,对密码明文hash提高安全性 *(另外再开文章展开探讨)*。 * 消息校验,例如下载文件的完整性。

下面将要介绍的四种散列函数都不是绝对理想的散列函数,但是在一定的时间和场景下具有重大的应用意义。应用领域的进步离不开理论基础的支持,在此为数学的美,为理论界科学家们孜孜不懈的努力致敬。

MD5由罗纳德·李维斯特(Ronald Linn Rivest)设计,它的散列值为128bits(即16字节,32个十六进制数)组成。 SHA散列算法的英文名称为Secure Hash Algorithm,常用的是SHA1和SHA256、SHA512。SHA-1 (*Secure Hash Algorithm 1*) 由美国国家安全局设计,它的散列值为160bits(即20字节,40个十六进制数)组成。SHA-2(*Secure Hash Algorithm 2*)是SHA-1的后继者,其下又可再分为六个不同的算法标准,即SHA-224, SHA-256, SHA-384, SHA-512, SHA-512224, SHA-512/256。SHA-256和SHA-512是很新的散列函数,前者以定义一个word为32位,后者则定义一个word为64位。它们分别使用了不同的偏移量,或用不同的常量,然而,实际上二者结构是相同的,只在循环运行的次数上有所差异。SHA-224以及SHA-384则是前述二种散列函数的截短版,利用不同的初始值做计算。

散列函数 二进制长度 十六进制长度
MD5 128 32
SHA-1 160 40
SHA-256 256 64
SHA-512 512 128

性能比较

由性能比较可见,散列函数的性能和散列值长度基本上是正相关的。采用MD5对密码进行散列是性能最佳选择,采用SHA-1作为代码文件散列(Git采用的)是性能最佳选择。

macOS系统自带了本文介绍的散列值计算工具,以计算*123456*的散列值为例,命令分别是:

echo -n "123456" | md5             # md5
echo -n "123456" | shasum          # sha1
echo -n "123456" | shasum -a 256   # sha256
echo -n "123456" | shasum -a 512   # sha512