2012-02-21 239 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

您還沒有傳遞正確的尺寸:

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

由於data被定義爲unsigned char *sizeof(data)可能是4或8(用於保持指針所需要的字節數)。

嘗試傳遞您分配的實際字節數,即EVP_PKEY_size(key)。您必須將其傳遞給您的verify()函數。

其他的東西也有可能是錯的,但是這引起了我的注意。

0

我知道這是一個老問題,但是一個bug可能會讓用戶感到困惑。

在驗證函數原始和數據應該交換,原始過去到EVP_VerifyUpdate和數據到EVP_VerifyFinal。不應該使用字符串長度,因爲字節數組可以包含0x00作爲有效值,該值將被識別爲「\ 0」。