哈希(Hash
)函数,又称为哈希算法或者散列函数,是可以用来将任意大小的数据映射到固定大小的数据的任何函数。哈希函数返回的值称为哈希值、哈希码、哈希和或哈希。其中一个用途是一种称为哈希表的数据结构,广泛用于计算机软件中快速查找数据。
哈希算法
哈希算法具有下面的5种特性。
- 不可逆性:从哈希值不能反向推导出原始数据。
- 难以破解性:如果要得到算法细节,你只能暴力枚举,没有比这更好的方法。
- 发散性:哪怕原始数据只修改了一个
Bit
,最后得到的哈希值也大不相同。 - 抗碰撞性:对于不同的原始数据,哈希值相同的概率非常小。
- 高效性:针对较长的文本,也能快速地计算出哈希值。
目前流行的 Hash
算法包括了 MD5
、SHA-1
和 SHA-2
,其中 MD5
和 SHA-1
被证明不具有强抗碰撞性。为了提高安全性,第二代 SHA-2
一共包含了 SHA-224
、SHA-256
、SHA-384
,和 SHA-512
算法(统称为 SHA-2
),SHA-3
相关算法也已被提出,它的出现并不是要取代 SHA-2
,因为 SHA-2
目前并没有出现明显的弱点。目前使用比较多的是 SHA-2
系列中的 SHA-256
算法。
命令行生成SHA-256
哈希值
首先我们可以使用这个网站http://hash.online-convert.com/sha256-generator 生成字符串“simpleiot
”的SHA-256
哈希值:
0141e02518527ccde0fb8ca204383b5e2cd4db7fb33af88edeac7ada227cbd84
我们可以使用如下三种命令行方式生成和验证改字符串的SHA-256
哈希值:
$ echo -n "simpleiot" | shasum -a 256
0141e02518527ccde0fb8ca204383b5e2cd4db7fb33af88edeac7ada227cbd84 -
$ echo -n "simpleiot" | sha256sum
0141e02518527ccde0fb8ca204383b5e2cd4db7fb33af88edeac7ada227cbd84 -
$ echo -n "simpleiot" | openssl dgst -sha256
(stdin)= 0141e02518527ccde0fb8ca204383b5e2cd4db7fb33af88edeac7ada227cbd84
使用OpenSSL API
实现哈希函数
EVP
消息摘要(Message Digests
)
消息摘要就是哈希函数,它将任意消息(具有任何内容或长度)作为输入,并提供固定大小的哈希值作为结果。OpenSSL
库支持大量不同的哈希函数,包括流行的SHA-2
哈希函数集(即SHA-224
,SHA-256
,SHA-384
和SHA-512
)。
哈希函数的示例使用
使用OpenSSL
消息摘要/哈希函数,包括以下步骤:
- 创建消息摘要上下文
- 通过识别要使用的算法初始化上下文(内置算法定义参考
evp.h
) - 提供需要计算摘要的消息。如有必要,可以将消息分成多个部分,并通过对库的多次调用提供这些消息部分
- 计算摘要
- 如果不再需要,清理上下文
使用EVP_MD
对象标识消息摘要算法。它们内置于库中,并通过适当的库调用(例如EVP_sha256()
或者EVP_sha512()
)获得。
void digest_message(const unsigned char *message, size_t message_len, unsigned char **digest, unsigned int *digest_len)
{
EVP_MD_CTX *mdctx;
if((mdctx = EVP_MD_CTX_create()) == NULL)
handleErrors();
if(1 != EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL))
handleErrors();
if(1 != EVP_DigestUpdate(mdctx, message, message_len))
handleErrors();
if((*digest = (unsigned char *)OPENSSL_malloc(EVP_MD_size(EVP_sha256()))) == NULL)
handleErrors();
if(1 != EVP_DigestFinal_ex(mdctx, *digest, digest_len))
handleErrors();
EVP_MD_CTX_destroy(mdctx);
}