2012-03-19 10 views
10

Estoy tratando de usar PKCS5_PBKDF2_HMAC_SHA1() y abajo está mi programa de ejemplo. Quería asegurarme si mi resultado de PKCS5_PBKDF2_HMAC_SHA1() es correcto, así que verifiqué lo mismo con el sitio web http://anandam.name/pbkdf2/ y veo un resultado diferente. ¿Estoy usando la API correctamente?Cómo utilizar PKCS5_PBKDF2_HMAC_SHA1()

Tengo dudas si paso correctamente el valor de sal.

He pegado el resultado y el resultado del sitio web después del programa.

Por favor, ayúdenme a entender esto.

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

Muestra de salida: resultado

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

Sitio Web:

The derived 40-bit key is: a5caf6a0d3 
+0

relacionada, ahora hay una página del manual de '' PKCS5_PBKDF2_HMAC' y PKCS5_PBKDF2_HMAC_SHA1'. Ver ['PKCS5_PBKDF2_HMAC (3)'] (https://www.openssl.org/docs/crypto/PKCS5_PBKDF2_HMAC.html). – jww

Respuesta

15

En primer lugar, vamos a ver un official test vector para 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) 

Así que ahora sabemos lo que estamos filmando tanto en la web como en su programa. Entonces, al usar esa información, descubrimos que el sitio web quiere su sal como una cadena ASCII, que luego convertirá en bytes. Esto es importante porque nunca podrá hacer coincidir el resultado de la página web si usa RAND_bytes para generar una sal.

password 
salt 
1 
20 
0c60c80f961f0e71f3a9b524af6012062fe037a6 

Y está utilizando la sal incorrectamente. En su línea comentada, está generando una cadena con caracteres ASCII. Si quieres usar esa sal, deberías declararla como una matriz de bytes. Además, te falta un dígito.

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

Y en el código no descompuesto, está generando una matriz de bytes pero tratándola como una cadena. No llama al strlen en una matriz de bytes porque las matrices de bytes pueden contener 0, que strlen interpretará como un terminador nulo. Por lo tanto, puede rastrear el tamaño manualmente (por ejemplo, su KEK_KEY_LEN define para la matriz que malloc) o usa sizeof cuando corresponda.

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

Así que ahora que sabemos que todas estas cosas, podemos armar un programa completo que coincide con la salida tanto del sitio web y la prueba del vector oficial.

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

(y tenga en cuenta que las principales necesidades para devolver un int y se debe liberar su memoria asignada)

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

Gracias indiv por la respuesta. Cuando genero sal usando RAND_bytes(), lo convierten en ASCII y puedo hacer coincidir el resultado (como lo hace mi programa) pero estoy buscando usar valores binarios para PKCS5_PBKDF2_HMAC_SHA1(). ¿Hay alguna manera de verificar si el resultado generado usando binarios coincide con la salida del programa? – pkumarn

+1

El documento al que he vinculado tiene un vector de prueba que detectará errores en una implementación binaria utilizando la contraseña "pass \ 0word" y la sal "sa \ 0lt". El '\ 0' representa el byte 0x00.Si su implementación puede pasar todos los casos de prueba del vector de prueba, entonces se considera funcionalmente correcto. – indiv

+0

Gracias por la respuesta, @indiv. Su solución funcionó para mí, pero tuve que usar strlen (salt_value) en lugar de sizeof (salt_value) en la llamada a PKCS5_PBKDF2_HMAC_SHA1(). – MaxMarchuk