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

Я знаю, что это старый вопрос, но одна ошибка может смутить пользователей.

В функции проверки подлинности и данных необходимо поменять местами исходное прошлое на EVP_VerifyUpdate и данные в EVP_VerifyFinal. Длина строки не должна использоваться, поскольку массив байтов может содержать 0x00 в качестве допустимого значения, которое будет распознаваться как «\ 0».

Смежные вопросы