Как использовать PKCS5_PBKDF2_HMAC_SHA1 () - PullRequest
12 голосов
/ 19 марта 2012

Я пытаюсь использовать 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 Ответ

17 голосов
/ 20 марта 2012

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