我正在玩OpenSSL EVP例程以使用AES 128 cbc模式進行解密。OpenSSL上的EVP_DecryptFinal_ex錯誤
我使用在NIST站點指定的測試向量來測試我的程序。
該程序似乎在EVP_DecryptFinal_ex例程失敗。
任何人都可以告訴我有什麼問題嗎?
另外我該如何做錯誤檢查來找出這個例程失敗的原因?
更新:
請檢查下面的代碼。我已經添加了加密和解密部分。加密作品。但是在解密過程中,雖然兩個匹配的結果相同,但密碼的十六進制值似乎是80字節,而不是預期的64字節(在NIST中提到),儘管解密工作並且解密文本與明文匹配! 有人可以澄清?
預期的密文值應爲:
cipher: 0000 76 49 ab ac 81 19 b2 46 ce e9 8e 9b 12 e9 19 7d
0010 50 86 cb 9b 50 72 19 ee 95 db 11 3a 91 76 78 b2
0020 73 be d6 b8 e3 c1 74 3b 71 16 e6 9e 22 22 95 16
0030 3f f1 ca a1 68 1f ac 09 12 0e ca 30 75 86 e1 a7
這裏是代碼:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>
int AES_BLOCK_SIZE;
int main(int argc, char **argv)
{
EVP_CIPHER_CTX en;
EVP_CIPHER_CTX de;
EVP_CIPHER_CTX_init(&en);
EVP_CIPHER_CTX_init(&de);
const EVP_CIPHER *cipher_type;
unsigned char *mode;
unsigned char *passkey, *passiv, *plaintxt;
int vector_len = 0;
char *plain;
char *plaintext;
unsigned char *ciphertext;
int olen, len;
int i =0;
//NIST VALUES TO CHECK
unsigned char iv[] =
{ 0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f, 0 };
unsigned char key[] =
{ 0x2b, 0x7e, 0x15, 0x16,
0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88,
0x09, 0xcf, 0x4f, 0x3c , 0 };
unsigned char input[] =
{ 0x6b, 0xc1, 0xbe, 0xe2,
0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11,
0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57,
0x1e, 0x03, 0xac, 0x9c,
0x9e, 0xb7, 0x6f, 0xac,
0x45, 0xaf, 0x8e, 0x51,
0x30, 0xc8, 0x1c, 0x46,
0xa3, 0x5c, 0xe4, 0x11,
0xe5, 0xfb, 0xc1, 0x19,
0x1a, 0x0a, 0x52, 0xef,
0xf6, 0x9f, 0x24, 0x45,
0xdf, 0x4f, 0x9b, 0x17,
0xad, 0x2b, 0x41, 0x7b,
0xe6, 0x6c, 0x37, 0x10, 0 };
printf("AES ALGORITHM FOR 128 bit CBC MODE\n");
cipher_type = EVP_aes_128_cbc();
AES_BLOCK_SIZE = 128;
passkey = key;
passiv = iv;
plain = input;
printf("iv=");
for(i = 0; i < sizeof iv; i++){
printf("%02x", iv[i]);
}
printf("\n");
printf("key=");
for(i = 0; i < sizeof key; i++){
printf("%02x", key[i]);
}
printf("\n");
printf("Initializing AES ALGORITHM FOR CBC MODE..\n");
EVP_EncryptInit_ex(&en, cipher_type, NULL, passkey, passiv);
EVP_DecryptInit_ex(&de, cipher_type, NULL, passkey, passiv);
olen = len = strlen(input)+1;
printf("len value before aes_encrypt \"%d\"\n", len);
int c_len = len + AES_BLOCK_SIZE - 1;
int f_len = 0;
ciphertext = (unsigned char *)malloc(c_len);
if(!EVP_EncryptInit_ex(&en, NULL, NULL, NULL, NULL)){
printf("ERROR in EVP_EncryptInit_ex \n");
return NULL;
}
if(!EVP_EncryptUpdate(&en, ciphertext, &c_len, plain, len)){
printf("ERROR in EVP_EncryptUpdate \n");
return NULL;
}
printf("strlen value of ciphertext after update \"%d\"\n", strlen(ciphertext));
if(!EVP_EncryptFinal_ex(&en, ciphertext+c_len, &f_len)){
printf("ERROR in EVP_EncryptFinal_ex \n");
return NULL;
}
printf("strlen value of ciphertext after final \"%d\"\n", strlen(ciphertext));
EVP_CIPHER_CTX_cleanup(&en);
len = c_len + f_len;
printf("len value after aes_encrypt \"%d\"\n", len);
len = strlen(ciphertext);
printf("strlen value of ciphertext after aes_encrypt \"%d\"\n", len);
int p_len = len;
f_len = 0;
plaintext = (unsigned char *)malloc(p_len);
//memset(plaintext,0,sizeof(plaintext));
if(!EVP_DecryptInit_ex(&de, NULL, NULL, NULL, NULL)){
printf("ERROR in EVP_DecryptInit_ex \n");
return NULL;
}
EVP_CIPHER_CTX_set_padding(&de, 0);
if(!EVP_DecryptUpdate(&de, plaintext, &p_len, ciphertext, len)){
printf("ERROR in EVP_DecryptUpdate\n");
return NULL;
}
if(!EVP_DecryptFinal_ex(&de, plaintext+p_len, &f_len)){
printf("ERROR in EVP_DecryptFinal_ex\n");
return NULL;
}
EVP_CIPHER_CTX_cleanup(&de);
len = p_len + f_len;
printf("Decrypted value = %s\n", plaintext);
printf("len value after aes_decrypt \"%d\"\n", len);
if (strncmp(plaintext, input, olen))
printf("FAIL: enc/dec failed for \"%s\"\n", input);
else
printf("OK: enc/dec ok for \"%s\"\n", plaintext); // \"%s\"\n
printf("OK: ciphertext is \"%s\"\n", ciphertext); // \"%s\"\n
printf("\n");
unsigned char *s3 = ciphertext;
printf("s3 =\n");
int nc = 0;
while(*s3 != '\0'){
printf("%02x", *s3);
s3++;
nC++;
if(nc == 16){
printf("\n");
nc = 0;
}
}
printf("\n");
//printf("nc = %d\n", nc);
free(ciphertext);
free(plaintext);
return 0;
}
填充標準錯誤導致我行:改用EVPerr(EVP_F_EVP_DECRYPTFINAL_EX,EVP_R_WRONG_FINAL_BLOCK_LENGTH);如果我設置填充如上(零)我得到的錯誤是:EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);但如何糾正這一點?在解密程序中我沒有提到塊長度還是應該? – pimmling 2011-04-15 07:38:24
但根據你的解釋沒有填充設置,因此我不需要設置填充功能,仍然解密應該正常工作?我編輯了代碼。你可以請現在檢查? – pimmling 2011-04-15 12:51:28
@pimmling:EVP_R_WRONG_FINAL_BLOCK_LENGTH表示它正在尋找填充但沒有找到它,所以你解決了這個問題。現在你看到的是AES數據長度必須是16個字節。您不使用以空字符結尾的字符串。你正在處理二進制數據。在所有事情結束時取消空終止符。不要使用strlen(),因爲它不是以空字符結尾的字符串。在你的情況下使用sizeof()。只需給解密器一次16個字節,它就可以工作,並且您必須弄清楚如何將更大的數據塊分成16個字節的塊。 – indiv 2011-04-15 15:03:46