如何使用PKCS5_PBKDF2_HMAC_SHA1()

pku*_*arn 12 openssl salt pbkdf2

我正在尝试使用PKCS5_PBKDF2_HMAC_SHA1(),以下是我的示例程序.我想确定我的结果PKCS5_PBKDF2_HMAC_SHA1()是否正确所以我通过网站http://anandam.name/pbkdf2/验证了相同的结果,我看到了不同的结果.我正确使用API​​吗?

如果我正确地传递盐值,我有疑问.

我在程序后粘贴了我的结果和网站结果.

请帮我理解这个.

#include <stdio.h>     
#include <types.h> 
#include <string.h> 
#include <stdio.h> 
#include <stdlib.h> 

#include <malloc.h> 

#include <openssl/hmac.h> 
#include <openssl/evp.h> 
#include <openssl/engine.h> 
#include <openssl/aes.h>
#include <openssl/rand.h> 

#include <proto.h> 
#define KEY_LEN    32// 32 bytes - 256 bits 
#define KEK_KEY_LEN   5 
#define ITERATION   1000 

unsigned char salt_value[KEY_LEN]; 
unsigned char AESkey[KEY_LEN]; 
unsigned char XTSkey[KEY_LEN]; 
u8 fuse_key[KEY_LEN]; 

void main() 
{ 
    s32 i=0; 
    s32 len =0; 
    u8 *out; 
    u8 *rspHMAC; 
    const s8 pwd[] = "test"; 
    s8 rspPKCS5[KEK_KEY_LEN * 2]; 
    s32 ret; 

    rspHMAC = (unsigned char *) malloc(sizeof(char) * KEY_LEN); 
    out = (unsigned char *) malloc(sizeof(char) * KEK_KEY_LEN); 

    RAND_bytes(salt_value, KEY_LEN); 

    printf("\n salt_value[0] = %x; salt_value[31]= %x", salt_value[0], salt_value[31]); 
    printf("\n strlen(salt_value) = %d; sizeof(salt_value) = %d\n", strlen(salt_value), sizeof(salt_value));  

    for(i = 0; i < KEY_LEN; i++) { 
        printf("%02x", salt_value[i]); 
    } 

    ret = PKCS5_PBKDF2_HMAC_SHA1(pwd, strlen(pwd), salt_value, strlen(salt_value), ITERATION, KEK_KEY_LEN, out); 
    printf("\n PKCS#5 :"); 

    for(len = 0; len < KEK_KEY_LEN; len++){ 
        printf("%02x", out[len]);

        sprintf(&rspPKCS5[len * 2], "%02x", out[len]); 
    } 

    printf("\n"); 
} 
Run Code Online (Sandbox Code Playgroud)

样本输出:

salt_value[0] = e2; salt_value[31]= 12 
strlen(salt_value) = 32; sizeof(salt_value) = 32 
e258017933f3e629a4166cece78f3162a3b0b7edb2e94c93d76fe6c38198ea12 
PKCS#5 :7d7ec9f411 
Run Code Online (Sandbox Code Playgroud)

网站结果:

The derived 40-bit key is: a5caf6a0d3 
Run Code Online (Sandbox Code Playgroud)

ind*_*div 18

首先,让我们看一下PBKDF2 HMAC-SHA1 的官方测试向量:

Input:
   P = "password" (8 octets)
   S = "salt" (4 octets)
   c = 1
   dkLen = 20

 Output:
   DK = 0c 60 c8 0f 96 1f 0e 71
        f3 a9 b5 24 af 60 12 06
        2f e0 37 a6             (20 octets)
Run Code Online (Sandbox Code Playgroud)

所以现在我们知道我们在网络和你的程序中拍摄的内容.因此,使用该信息,我们发现该网站希望您的salt作为ASCII字符串,然后将其转换为字节.这很重要,因为如果您使用RAND_bytes生成盐,则永远无法匹配网页的输出.

password
salt
1
20
0c60c80f961f0e71f3a9b524af6012062fe037a6
Run Code Online (Sandbox Code Playgroud)

你错了使用盐.在注释行中,您将生成一个包含ASCII字符的字符串.如果要使用该盐,则必须将其声明为字节数组.另外,你错过了一个数字.

unsigned char salt_value[]= { 0x5d, 0x85, 0x94, 0x7b, … /* and so on */ };
Run Code Online (Sandbox Code Playgroud)

在未注释的代码中,您生成一个字节数组,但将其视为字符串.您不调用strlen字节数组,因为字节数组可以包含0,strlen将其解释为空终止符.因此,您可以手动跟踪大小(例如,您对malloc阵列的KEK_KEY_LEN定义),也可以sizeof在适当时使用.

PKCS5_PBKDF2_HMAC_SHA1(pwd, strlen(pwd), salt_value, sizeof(salt_value), ITERATION, KEK_KEY_LEN, out);
Run Code Online (Sandbox Code Playgroud)

所以现在我们知道所有这些事情,我们可以整合一个完整的程序,匹配网站和官方测试向量的输出.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <openssl/evp.h>

#define KEY_LEN      32
#define KEK_KEY_LEN  20
#define ITERATION     1 

int main()
{
    size_t i;
    unsigned char *out;
    const char pwd[] = "password";
    unsigned char salt_value[] = {'s','a','l','t'};

    out = (unsigned char *) malloc(sizeof(unsigned char) * KEK_KEY_LEN);

    printf("pass: %s\n", pwd);
    printf("ITERATION: %u\n", ITERATION);
    printf("salt: "); for(i=0;i<sizeof(salt_value);i++) { printf("%02x", salt_value[i]); } printf("\n");

    if( PKCS5_PBKDF2_HMAC_SHA1(pwd, strlen(pwd), salt_value, sizeof(salt_value), ITERATION, KEK_KEY_LEN, out) != 0 )
    {
        printf("out: "); for(i=0;i<KEK_KEY_LEN;i++) { printf("%02x", out[i]); } printf("\n");
    }
    else
    {
        fprintf(stderr, "PKCS5_PBKDF2_HMAC_SHA1 failed\n");
    }

    free(out);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

(并注意主要需要返回一个int,你应该释放你分配的内存)

gcc pkcs5.c -o pkcs5 -g -lcrypto -Wall
./pkcs5
pass: password
ITERATION: 1
salt: 73616c74
out: 0c60c80f961f0e71f3a9b524af6012062fe037a6
Run Code Online (Sandbox Code Playgroud)

  • @MaxMarchuk:我不知道为什么会这样(但我的猜测是你在指针而不是数组上使用sizeof),但要注意`strlen`.`strlen`在第一个0x00字节处停止扫描.如果您使用的是二进制(非文本)salt,则任何值为0的字节都会破坏它.例如,对于这个salt,`unsigned char salt_value [] = {0x00,0x01,0x02};`,你得到一个0的strlen,这是错误的.如果你只使用盐的文本(ASCII)字符串,你应该没问题. (2认同)