介紹如何在 C 語言中使用 OpenSSL 函式庫實作各種 PBKDF2 密鑰延伸演算法。
PBKDF2(Password-Based Key Derivation Function)是一種密鑰延伸(key stretching)演算法,透過反覆的大量運算,降低密鑰產生的速度,讓暴力破解的難度變高。實務上 PBKDF2 會搭配 SHA1、SHA256、SHA512 等雜湊演算法,以下是以 OpenSSL 函式庫實作的 C 語言範例。
OpenSSL 的 PKCS5_PBKDF2_HMAC_SHA1()
可以用來計算 PBKDF2-HMAC-SHA1,以下是使用範例:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/evp.h> int main() { const char password[] = "password"; // 文字密碼 unsigned char salt[] = {'s','a','l','t'}; // Salt const int KEY_LEN = 20; // 輸出密鑰長度 unsigned char key[KEY_LEN]; // 輸出的密鑰 int iter = 2; // 迭代次數 // 以 OpenSSL 計算 PBKDF2-HMAC-SHA1 PKCS5_PBKDF2_HMAC_SHA1( password, // 文字密碼(輸入) strlen(password), // 文字密碼長度(輸入) salt, // Salt(輸入) sizeof(salt), // Salt 長度(輸入) iter, // 迭代次數 KEY_LEN, // 密鑰長度(輸出) key); // 密鑰(輸出) // 輸出 PBKDF2-HMAC-SHA1 計算結果 BIO_dump_fp(stdout, key, KEY_LEN); return EXIT_SUCCESS; }
將其儲存為 pbkdf2_hmac_sha1.c
之後,使用以下指令進行編譯:
# 編譯 OpenSSL 程式 gcc -o pbkdf2_hmac_sha1 pbkdf2_hmac_sha1.c -lcrypto # 執行程式 ./pbkdf2_hmac_sha1
0000 - ea 6c 01 4d c7 2d 6f 8c-cd 1e d9 2a ce 1d 41 f0 .l.M.-o....*..A. 0010 - d8 de 89 57 ...W
我們可以參考 RFC6070,跟文件中的範例對照,確認自己程式的正確性,以下是 RFC6070 中對應的範例:
Input: P = "password" (8 octets) S = "salt" (4 octets) c = 2 dkLen = 20 Output: DK = ea 6c 01 4d c7 2d 6f 8c cd 1e d9 2a ce 1d 41 f0 d8 de 89 57 (20 octets)
若要採用 SHA1 以外的雜揍演算法,可以使用 OpenSSL 的 PKCS5_PBKDF2_HMAC()
函數,並自行指定要採用的雜湊方式,以下是採用 SHA-256 的範例:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/evp.h> int main() { const char password[] = "password"; // 文字密碼 unsigned char salt[] = {'s','a','l','t'}; // Salt const int KEY_LEN = 20; // 輸出密鑰長度 unsigned char key[KEY_LEN]; // 輸出的密鑰 int iter = 2; // 迭代次數 // 以 OpenSSL 計算 PBKDF2-HMAC-SHA256 PKCS5_PBKDF2_HMAC( password, // 文字密碼(輸入) strlen(password), // 文字密碼長度(輸入) salt, // Salt(輸入) sizeof(salt), // Salt 長度(輸入) iter, // 迭代次數 EVP_sha256(), // 採用 SHA-256 雜湊 KEY_LEN, // 密鑰長度(輸出) key); // 密鑰(輸出) // 輸出 PBKDF2-HMAC-SHA256 計算結果 BIO_dump_fp(stdout, key, KEY_LEN); return EXIT_SUCCESS; }
將其儲存為 pbkdf2_hmac_sha256.c
之後,使用以下指令進行編譯:
# 編譯 OpenSSL 程式 gcc -o pbkdf2_hmac_sha256 pbkdf2_hmac_sha256.c -lcrypto # 執行程式 ./pbkdf2_hmac_sha256
0000 - ae 4d 0c 95 af 6b 46 d3-2d 0a df f9 28 f0 6d d0 .M...kF.-...(.m. 0010 - 2a 30 3f 8e *0?.
在 PKCS5_PBKDF2_HMAC()
函數呼叫時,可以自由搭配各種雜湊演算法,常見的雜湊方式有 EVP_md5()
、EVP_sha1()
、EVP_sha224()
、EVP_sha256()
、EVP_sha384()
、EVP_sha512()
等。
我們也可以使用 Python 的程式來驗證 PBKDF2 的計算結果,以下是使用 PyCryptodome 模組來計算 PBKDF2 的程式:
from Crypto.Protocol.KDF import PBKDF2 from Crypto.Hash import SHA1, SHA256 # 文字密碼與 Salt password = b'password' salt = b'salt' # 計算 PBKDF2-HMAC-SHA1 key1 = PBKDF2(password, salt, 20, count=2, hmac_hash_module=SHA1) print("PBKDF2-HMAC-SHA1: {}".format(key1.hex()))
PBKDF2-HMAC-SHA1: ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957
# 計算 PBKDF2-HMAC-SHA256 key256 = PBKDF2(password, salt, 20, count=2, hmac_hash_module=SHA256) print("PBKDF2-HMAC-SHA256: {}".format(key256.hex()))
PBKDF2-HMAC-SHA256: ae4d0c95af6b46d32d0adff928f06dd02a303f8e
另外 Python 的 Cryptography 模組也可以用來驗證 PBKDF2 的計算結果,使用方式大同小異。