Как использовать PKCS5_PBKDF2_HMAC_SHA1()

Я пытаюсь использовать 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"); 
} 

Результат вывода:

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

Результат веб-сайта:

The derived 40-bit key is: a5caf6a0d3 

Ответ 1

Во-первых, рассмотрим официальный тестовый вектор для 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)

Итак, теперь мы знаем, что снимаем как в Интернете, так и в вашей программе. Поэтому, используя эту информацию, мы узнаем, что веб-сайт хочет, чтобы ваша соль была как строка ASCII, которая затем преобразуется в байты. Это важно, потому что вы никогда не сможете сопоставить вывод веб-страницы, если вы используете RAND_bytes для генерации соли.

password
salt
1
20
0c60c80f961f0e71f3a9b524af6012062fe037a6

И вы неправильно используете соль. В вашей промаркированной строке вы создаете строку с символами ASCII. Если вы хотите использовать эту соль, вам нужно объявить ее как массив байтов. Кроме того, вам не хватает цифры.

unsigned char salt_value[]= { 0x5d, 0x85, 0x94, 0x7b, … /* and so on */ };

И в раскомментированном коде вы генерируете массив байтов, но рассматриваете его как строку. Вы не вызываете strlen в массив байтов, потому что массивы байтов могут содержать 0, которые strlen будет интерпретировать как нулевой терминатор. Таким образом, вы либо отслеживаете размер вручную (например, ваш KEK_KEY_LEN определяют для массива malloc), либо при необходимости используйте sizeof.

PKCS5_PBKDF2_HMAC_SHA1(pwd, strlen(pwd), salt_value, sizeof(salt_value), ITERATION, KEK_KEY_LEN, out);

Итак, теперь, когда мы знаем все это, мы можем собрать полную программу, которая соответствует выходу как веб-сайта, так и официального тестового вектора.

#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;
}

(и обратите внимание, что main необходимо вернуть int, и вы должны освободить выделенную память)

gcc pkcs5.c -o pkcs5 -g -lcrypto -Wall
./pkcs5
pass: password
ITERATION: 1
salt: 73616c74
out: 0c60c80f961f0e71f3a9b524af6012062fe037a6