2012-03-19 24 views
10

Tôi đang cố sử dụng PKCS5_PBKDF2_HMAC_SHA1() trở xuống là chương trình mẫu của mình. Tôi muốn đảm bảo rằng kết quả của tôi là PKCS5_PBKDF2_HMAC_SHA1() là chính xác vì vậy tôi đã xác minh tương tự với trang web http://anandam.name/pbkdf2/ và tôi thấy một kết quả khác. Tôi có đang sử dụng API chính xác không?Cách sử dụng PKCS5_PBKDF2_HMAC_SHA1()

Tôi có nghi ngờ nếu tôi chuyển giá trị muối chính xác.

Tôi đã dán kết quả và kết quả trang web của mình sau chương trình.

Hãy giúp tôi hiểu điều này.

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

Sample Output:

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

Trang kết quả:

The derived 40-bit key is: a5caf6a0d3 
+0

liên quan, bây giờ có một người đàn ông trang cho 'PKCS5_PBKDF2_HMAC' và 'PKCS5_PBKDF2_HMAC_SHA1'. Xem ['PKCS5_PBKDF2_HMAC (3)'] (https://www.openssl.org/docs/crypto/PKCS5_PBKDF2_HMAC.html). – jww

Trả lời

15

Đầu tiên, chúng ta hãy nhìn vào một official test vector cho 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) 

Vì vậy, bây giờ chúng tôi biết những gì chúng tôi đang chụp cho cả trên web và trong chương trình của bạn. Vì vậy, bằng cách sử dụng thông tin đó, chúng tôi phát hiện ra rằng trang web muốn muối của bạn dưới dạng chuỗi ASCII, sau đó nó sẽ chuyển thành byte. Điều này rất quan trọng vì bạn sẽ không bao giờ có thể khớp với đầu ra của trang web nếu bạn sử dụng RAND_bytes để tạo ra một muối.

password 
salt 
1 
20 
0c60c80f961f0e71f3a9b524af6012062fe037a6 

Và bạn đang sử dụng muối không chính xác. Trong dòng nhận xét của bạn, bạn đang tạo một chuỗi ký tự ASCII. Nếu bạn muốn sử dụng muối đó, bạn phải khai báo nó như là một mảng các byte. Ngoài ra, bạn đang thiếu một chữ số.

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

Và trong mã không được chú thích, bạn đang tạo một mảng byte nhưng coi đó là chuỗi. Bạn không gọi strlen trên một mảng byte vì mảng byte có thể chứa 0, mà strlen sẽ giải thích như một terminator null. Vì vậy, bạn theo dõi kích thước theo cách thủ công (ví dụ: KEK_KEY_LEN của bạn xác định cho mảng bạn malloc) hoặc bạn sử dụng sizeof khi thích hợp.

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

Bây giờ chúng ta biết tất cả những điều này, chúng ta có thể đặt cùng một chương trình đầy đủ khớp với đầu ra của cả trang web và vectơ thử nghiệm chính thức.

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

(và lưu ý rằng nhu cầu chính để trả lại một int và bạn nên giải phóng bộ nhớ phân bổ của bạn)

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

Cảm ơn indiv đã trả lời. Khi tôi tạo ra muối bằng cách sử dụng RAND_bytes(), chuyển đổi nó sang ASCII i am có thể phù hợp với kết quả (như chương trình của tôi hiện nó) nhưng tôi đang xem xét sử dụng giá trị nhị phân cho PKCS5_PBKDF2_HMAC_SHA1(). Có cách nào để xác minh nếu kết quả được tạo ra bằng cách sử dụng các kết quả nhị phân khớp với đầu ra của chương trình không? – pkumarn

+1

Tài liệu tôi liên kết có một vectơ thử nghiệm sẽ bắt gặp lỗi trong quá trình triển khai nhị phân bằng cách sử dụng mật khẩu "pass \ 0word" và muối "sa \ 0lt". '\ 0' đại diện cho byte 0x00.Nếu việc triển khai của bạn có thể vượt qua tất cả các trường hợp thử nghiệm vectơ thử nghiệm, thì nó được coi là đúng chức năng. – indiv

+0

Cảm ơn câu trả lời, @indiv. Giải pháp của bạn làm việc cho tôi, nhưng tôi đã phải sử dụng strlen (salt_value) thay vì sizeof (salt_value) trong cuộc gọi đến PKCS5_PBKDF2_HMAC_SHA1(). – MaxMarchuk