我想利用SHA1 HMAC的PBKDF2算法(基于this答案)。
如何通过加密库来利用它?
我首先查看man openssl
,但openssl passwd
命令(man page)仅支持少量算法。查看crypto文档,evp模块采用EVP_BytesToKey方法。
仔细选择参数将提供PKCS#5 PBKDF1兼容实现。但是,新应用程序通常不应使用此功能(例如,首选PCKS#5的PBKDF2)。
这让我回到原来的问题,如何通过加密利用PBKDF2?我是否需要深入研究代码并调用非API暴露的方法(例如PKCS5_PBKDF2_HMAC)? (如果是的话,是什么让它不被暴露?)
答案 0 :(得分:9)
我通过my github repository的OpenSSL库确实有一个工作但很差的CKDF2 C示例,包括在Linux和Windows(通过MinGW)下编译的脚本。源代码位于"发布"众所周知;主分支中的源代码是WIP。除了SSLeay许可证OpenSSL之外,此变体还使用相同的4条款BSD进行许可。
我还在努力添加一些功能,然后我将回到Code Review StackExchange网站上的优秀输入并升级到C99语法等等。
核心代码非常原始,尽管传递了非常广泛的基于字符串的测试向量,但可能包含缺陷。它尚未针对纯二进制输入进行测试。
#include <openssl/evp.h>
#include <openssl/sha.h>
// crypto.h used for the version
#include <openssl/crypto.h>
void PBKDF2_HMAC_SHA_1nat_string(const char* pass, const unsigned char* salt, int32_t iterations, uint32_t outputBytes, char* hexResult)
{
unsigned int i;
unsigned char digest[outputBytes];
PKCS5_PBKDF2_HMAC_SHA1(pass, strlen(pass), salt, strlen(salt), iterations, outputBytes, digest);
for (i = 0; i < sizeof(digest); i++)
sprintf(hexResult + (i * 2), "%02x", 255 & digest[i]);
}
如果您有64位系统,我强烈建议您转而使用PBKDF2-HMAC-SHA-512或PBKDF2-HMAC-SHA-384:
#include <openssl/evp.h>
#include <openssl/sha.h>
// crypto.h used for the version
#include <openssl/crypto.h>
void PBKDF2_HMAC_SHA_384_string(const char* pass, const unsigned char* salt, int32_t iterations, uint32_t outputBytes, char* hexResult)
{
unsigned int i;
unsigned char digest[outputBytes];
PKCS5_PBKDF2_HMAC(pass, strlen(pass), salt, strlen(salt), iterations, EVP_sha384(), outputBytes, digest);
for (i = 0; i < sizeof(digest); i++)
sprintf(hexResult + (i * 2), "%02x", 255 & digest[i]);
}
void PBKDF2_HMAC_SHA_512_string(const char* pass, const unsigned char* salt, int32_t iterations, uint32_t outputBytes, char* hexResult)
{
unsigned int i;
unsigned char digest[outputBytes];
PKCS5_PBKDF2_HMAC(pass, strlen(pass), salt, strlen(salt), iterations, EVP_sha512(), outputBytes, digest);
for (i = 0; i < sizeof(digest); i++)
sprintf(hexResult + (i * 2), "%02x", 255 & digest[i]);
}
使用的一个例子是:
// 2*outputBytes+1 is 2 hex bytes per binary byte,
// and one character at the end for the string-terminating \0
char hexResult[2*outputBytes+1];
memset(hexResult,0,sizeof(hexResult));
PBKDF2_HMAC_SHA_1nat_string(pass, salt, iterations, outputBytes, hexResult);
printf("%s\n", hexResult);
或
// 2*outputBytes+1 is 2 hex bytes per binary byte,
// and one character at the end for the string-terminating \0
char hexResult[2*outputBytes+1];
memset(hexResult,0,sizeof(hexResult));
PBKDF2_HMAC_SHA_512_string(pass, salt, iterations, outputBytes, hexResult);
printf("%s\n", hexResult);
使用8到16个二进制字节的随机,每用户盐,即16到32个十六进制数字 - 我的代码没有生成此内容的示例
无论您选择什么,请务必根据测试向量进行验证(有些是在我的存储库中的pbkdf2_test.bat / sh中)。
此外,在您的系统上,进行一些基准测试 - 当然在PBKDF2-HMAC-SHA-384和PBKDF2-HMAC-SHA-512变体上,在64位系统下进行编译可以产生显着更好的结果。将其与my equally poor C++ Crypto++和/或my poor C PolarSSL示例或Jither's C# implementation example进行比较,具体取决于您的目标系统。
您关心速度的原因是您必须根据生产系统可用的性能与在高峰时间登录/创建密码的用户数量选择迭代计数,以免产生太多投诉缓慢。
攻击者会使用像oclHashcat这样的东西,它在具有8x AMD R9 290Xstock核心时钟的单台PC上能够每30天针对PBKDF2-HMAC-SHA尝试3.4E12(2 ^ 41)次猜测1(SSID为salt,密码,32字节输出长度,4096次迭代,又名WPA / WPA2),它或多或少等同于PBKDF2-HMAC-SHA-1(salt,pw,20字节输出长度,8192次迭代)。
当攻击者开始选择攻击时,差异变得很重要。
现在,对于PBKDF2,还有其他一些事情要知道: