2012-02-21 16 views
1

OpenSSLの文書に従って、私がやっていることは正しいですが、明らかにそうではありません。ファイルをコンパイルすると(gcc -g -Wall -Wextra -lssl sign.c)、エラーまたは警告は発生しません。 EVP_VerifyFinal()は常に0を返します(チェックに失敗したことを意味します)。その原因は何ですか?opensslが正しく署名を検証していない

static const EVP_MD * type; 

unsigned char * sha(char * input) 
{ 
    EVP_MD_CTX c; 
    unsigned char *md; 
    unsigned int md_len; 

    md = malloc(EVP_MAX_MD_SIZE); 

    EVP_MD_CTX_init(&c); 
    EVP_DigestInit_ex(&c, type, NULL); 
    EVP_DigestUpdate(&c, input, strlen(input)); 
    EVP_DigestFinal_ex(&c, md, &md_len); 
    EVP_MD_CTX_cleanup(&c); 

    return md; 
} 

unsigned char * sign(EVP_PKEY * key, unsigned char * data) 
{ 
    EVP_MD_CTX c; 
    unsigned char *sig; 
    unsigned int len; 

    EVP_MD_CTX_init(&c); 
    sig = malloc(EVP_PKEY_size(key)); 

    EVP_SignInit(&c, type); 
    EVP_SignUpdate(&c, data, strlen((char *)data)); 
    EVP_SignFinal(&c, sig, &len, key); 

    EVP_MD_CTX_cleanup(&c); 

    return sig; 
} 

int verify(EVP_PKEY * key, unsigned char * data, unsigned char * original) 
{ 
    EVP_MD_CTX c; 
    int ret; 

    EVP_MD_CTX_init(&c); 
    EVP_VerifyInit(&c, type); 
    EVP_VerifyUpdate(&c, data, (unsigned int)sizeof(data)); 
    ret = EVP_VerifyFinal(&c, original, (unsigned int)strlen((char *)original), key); 
    return ret; 
} 

int main(void) 
{ 
    EVP_PKEY *sk, *pk; 
    FILE *sfd, *pfd; 
    unsigned char *hash, *sig; 
    unsigned int i; 

    sfd = fopen("secret.pem", "r"); 
    pfd = fopen("public.pem", "r"); 
    sk = PEM_read_PrivateKey(sfd, NULL, NULL, NULL); 
    pk = PEM_read_PUBKEY(pfd, NULL, NULL, NULL); 
    fclose(sfd); 
    fclose(pfd); 

    OpenSSL_add_all_digests(); 
    type = EVP_get_digestbyname("SHA1"); 

    hash = sha("moo"); 

    for(i = 0; i < sizeof(hash); i++) 
     printf("%02x", hash[i]); 
    printf("\n"); 

    sig = sign(sk, hash); 
    switch(verify(pk, sig, hash)) 
    { 
     case 0: 
      printf("Check failed.\n"); 
      break; 
     case 1: 
      printf("Check succeeded!\n"); 
      break; 
     default: 
      printf("Oh look, an error: %d", ERR_get_error()); 
      break; 
    } 

    return 0; 
} 

答えて

0

正しいサイズを渡していない。dataので

EVP_VerifyUpdate(&c, data, (unsigned int)sizeof(data)); 

sizeof(data)はおそらく4または8(ポインタを保持するために必要なバイト数)であり、unsigned char *として定義されます。

割り当てた実際のバイト数、つまりEVP_PKEY_size(key)を渡してみてください。それをあなたのverify()関数に渡す必要があります。

他の何かも間違っている可能性がありますが、これは私の目を引くものです。

0

これは古い質問ですが、1つのバグがユーザーを混乱させる可能性があります。

ベリファイ機能では、オリジナルとデータを交換する必要があります。オリジナルは過去のEVP_VerifyUpdateに、データはEVP_VerifyFinalにスワップします。バイト配列に0x00を "\ 0"として認識される有効な値として含めることができるため、文字列の長さは使用しないでください。

関連する問題