13

私は使用しようとしています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 
4

1 に答える 1

19

まず、 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)

これで、Web とプログラムの両方で何を撮影しているかがわかります。その情報を使用して、Web サイトがあなたのソルトを ASCII 文字列として必要としていることがわかり、それをバイトに変換します。RAND_bytesを使用してソルトを生成すると、Web ページの出力と一致することは決してないため、これは重要です。

password
salt
1
20
0c60c80f961f0e71f3a9b524af6012062fe037a6

そしてあなたは塩の使い方を間違っています。コメント行では、ASCII 文字を含む文字列を生成しています。そのソルトを使用する場合は、バイト配列として宣言する必要があります。さらに、桁がありません。

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

コメントを外したコードでは、バイト配列を生成していますが、それを文字列として扱っています。strlenバイト配列には 0 が含まれる可能性があるため、バイト配列を呼び出す必要はありません。0 は strlen によって null ターミネータとして解釈されます。したがって、サイズを手動で追跡するか (たとえば、malloc する配列に対して KEK_KEY_LEN を定義する)、またはsizeof適切な場合に使用します。

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

これらすべてがわかったので、Web サイトと公式のテスト ベクトルの両方の出力に一致する完全なプログラムを作成できます。

#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
于 2012-03-20T05:51:33.773 に答える