2012-03-19 8 views
10

Próbuję użyć PKCS5_PBKDF2_HMAC_SHA1(), a poniżej jest mój przykładowy program. Chciałem się upewnić, czy mój wynik z PKCS5_PBKDF2_HMAC_SHA1() jest poprawny, więc zweryfikuję to samo z witryną http://anandam.name/pbkdf2/ i widzę inny wynik. Czy poprawnie używam interfejsu API?Jak używać PKCS5_PBKDF2_HMAC_SHA1()

Mam wątpliwości, czy prawidłowo podaję wartość soli.

Po zakończeniu programu wkleiłem mój wynik i wynik witryny.

Proszę, pomóżcie mi to zrozumieć.

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

Próbka wyjściowa: wynik

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

WWW:

The derived 40-bit key is: a5caf6a0d3 
+0

pokrewnych, jest obecnie strona podręcznika dla 'PKCS5_PBKDF2_HMAC' i' PKCS5_PBKDF2_HMAC_SHA1'. Zobacz ['PKCS5_PBKDF2_HMAC (3)'] (https://www.openssl.org/docs/crypto/PKCS5_PBKDF2_HMAC.html). – jww

Odpowiedz

15

Po pierwsze, spójrzmy na official test vector dla 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) 

Teraz wiemy, co kręcimy zarówno w Internecie, jak i w programie. Używając tej informacji, dowiadujemy się, że strona internetowa potrzebuje twojej soli jako ciągu ASCII, który następnie zamieni na bajty. Jest to ważne, ponieważ nigdy nie będziesz w stanie dorównać wynikowi strony internetowej, jeśli użyjesz RAND_bytes do wygenerowania soli.

password 
salt 
1 
20 
0c60c80f961f0e71f3a9b524af6012062fe037a6 

I używasz soli nieprawidłowo. W linii komentarza generujesz ciąg znaków ASCII. Jeśli chcesz użyć tej soli, musisz zadeklarować ją jako tablicę bajtów. Dodatkowo brakuje ci cyfry.

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

W nieskomunikowanym kodzie generujesz tablicę bajtów, ale traktujesz ją jako ciąg znaków. Nie wywołujemy strlen na tablicy bajtów, ponieważ tablice bajtów mogą zawierać 0, które strlen interpretuje jako terminator o wartości null. Więc albo śledzisz rozmiar ręcznie (np. Twój KEK_KEY_LEN definiują dla tablicy, którą masz malloc) lub używasz sizeof, gdy jest to odpowiednie.

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

Więc teraz wiemy, że wszystkie te rzeczy, możemy umieścić razem pełny program, który pasuje wyjście zarówno na stronie internetowej i oficjalnego wektora testowego.

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

(i pamiętać, że główne potrzeby, aby zwracać int i należy uwolnić przydzieloną pamięć)

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

Podzięka za odpowiedź. Kiedy generuję sól za pomocą RAND_bytes(), konwertuję ją do ASCII, jestem w stanie dopasować wynik (jak robi to mój program), ale patrzę na użycie wartości binarnych dla PKCS5_PBKDF2_HMAC_SHA1(). Czy istnieje sposób sprawdzenia, czy wynik uzyskany przy użyciu dopasowań binarnych z danymi wyjściowymi programu? – pkumarn

+1

Dokument, z którym się łączyłem, ma wektor testowy, który będzie wychwytywał błędy w implementacji binarnej za pomocą hasła "pass \ 0word" i soli "sa \ 0lt". '\ 0' reprezentuje bajt 0x00.Jeśli twoja implementacja może przejść wszystkie przypadki testowe wektora testowego, to jest uważana za poprawną funkcjonalnie. – indiv

+0

Dzięki za odpowiedź, @indiv. Twoje rozwiązanie działało dla mnie, ale musiałem użyć strlen (salt_value) zamiast sizeof (salt_value) w wywołaniu PKCS5_PBKDF2_HMAC_SHA1(). – MaxMarchuk