哈希(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);
}