C 什么是「;“长度”;AES EVP_解密的参数?
这与 我试图找出AES解密无法工作的原因,最后我找到了问题所在,现在正在寻找帮助我解决问题的人:) 下面是我测试的代码(来自这里的各种帖子):C 什么是「;“长度”;AES EVP_解密的参数?,c,openssl,encryption,C,Openssl,Encryption,这与 我试图找出AES解密无法工作的原因,最后我找到了问题所在,现在正在寻找帮助我解决问题的人:) 下面是我测试的代码(来自这里的各种帖子): #包括 #包括 #包括 #包括 int AES_块大小=128; int main(int argc,字符**argv) { 执行副总裁; 执行副总裁; EVP_CIPHER_CTX_init(&en); EVP_CIPHER_CTX_init(&de); const EVP_CIPHER*CIPHER_类型; 无符号字符*密钥,*被动,*明文; 字符*
#包括
#包括
#包括
#包括
int AES_块大小=128;
int main(int argc,字符**argv)
{
执行副总裁;
执行副总裁;
EVP_CIPHER_CTX_init(&en);
EVP_CIPHER_CTX_init(&de);
const EVP_CIPHER*CIPHER_类型;
无符号字符*密钥,*被动,*明文;
字符*普通;
字符*纯文本;
无符号字符*密文;
内奥伦;
int i=0;
无符号字符iv[]={0x00,0x01,0x02,0x03,
0x04、0x05、0x06、0x07,
0x08、0x09、0x0a、0x0b、,
0x0c,0x0d,0x0e,0x0f,0};
无符号字符键[]={0x2b,0x7e,0x15,0x16,
0x28,0xae,0xd2,0xa6,
0xab,0xf7,0x15,0x88,
0x09,0xcf,0x4f,0x3c,0};
unsigned char*input=“您好,我是patrick immling\n'Doctor”。\n'Doctor'谁?\n确切地说!123910!§$§%!%%$&$(/=)?=(#++Ü**首先,不要从main()返回NULL.其次,我对它进行了修复并对其进行了注释,希望您能够了解长度变量的含义。我认为您缺少的关键点是,您为OpenSSL函数提供了一个缓冲区,它可以在其中写入数据。与许多使用缓冲区的函数一样,您为它提供了一个缓冲区大小,它会返回它实际写入t的字节数为什么?因为你必须知道你的缓冲区什么时候满了,或者如果你正在递增地填充你的缓冲区,你必须知道在哪里写入下一个数据块
此外,我认为您应该阅读一些关于如何使用二进制数据以及它与C样式字符串的区别的教程。OpenSSL EVP函数使用二进制数据,这就是为什么您需要告诉每个函数数据的字节数
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>
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 *passkey, *passiv, *plaintxt;
unsigned char *plaintext = NULL;
unsigned char *ciphertext = NULL;
int input_len = 0;
unsigned char iv[] = { 0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f };
unsigned char key[] = { 0x2b, 0x7e, 0x15, 0x16,
0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88,
0x09, 0xcf, 0x4f, 0x3c };
const char *string_to_encrypt = "hi this is patrick immling\n'Doctor'.\n'Doctor' who ?\nPrecisely! 123910!§$$§% !%%$&$(/=))?=(#ü++Ü**<,.here we go sometimes it i s difficult but 187! 1$5 78@2 14 .TӒ��틪�ձ1z.$�?�U���<y";
cipher_type = EVP_aes_128_cbc();
EVP_EncryptInit_ex(&en, cipher_type, NULL, key, iv);
EVP_DecryptInit_ex(&de, cipher_type, NULL, key, iv);
// The data we want to encrypt is a string. So we can just do a simple
// strlen to calculate its length. But the encrypted buffer is going to
// be padded with PKCS padding. In the worst case, our string is a
// multiple of the AES block size (16 bytes). In that case, the PKCS
// padding will be an additional 16 bytes after our data. So we could
// precisely calculate the buffer with this:
// int input_len = strlen(string_to_encrypt);
// malloc( input_len + 16 - (input_len % 16) );
// But why get fancy? Just add an extra AES block and have at most 16
// unused bytes at the end, and usually less than that.
static const int MAX_PADDING_LEN = 16;
// We add 1 because we're encrypting a string, which has a NULL terminator
// and want that NULL terminator to be present when we decrypt.
input_len = strlen(string_to_encrypt) + 1;
ciphertext = (unsigned char *) malloc(input_len + MAX_PADDING_LEN);
// This function works on binary data, not strings. So we cast our
// string to an unsigned char * and tell it that the length is the string
// length + 1 byte for the null terminator.
int bytes_written = 0;
int ciphertext_len = 0;
if(!EVP_EncryptUpdate(&en,
ciphertext, &bytes_written,
(unsigned char *) string_to_encrypt, input_len) ) {
printf("ERROR in EVP_EncryptUpdate \n");
return 1;
}
ciphertext_len += bytes_written;
// Right now the ciphertext buffer contains only the encrypted version
// of the input data up to the last full AES block. E.g., if your input
// size is 206, then ciphertext_len will be 192 because you have 14 bytes
// left to encrypt and those bytes can't fill a full AES block. But the
// encryptor has stored those bytes and is waiting either for more bytes
// or the call to EVP_EncryptFinal where it will add padding to make the
// encrypted data the same size as the AES block (i.e., 2 bytes of padding
// in the above example).
printf("Input len: %d, ciphertext_len: %d\n", input_len, ciphertext_len);
// EVP_EncryptFinal_ex writes the padding. The whole point of the
// bytes_written variable from EVP_EncryptUpdate is to tell us how much
// of the buffer is full so we know where we can write the padding.
// Note that we know our buffer is large enough so we're not bothering to
// keep track of the buffer size. We just keep track of how much data is
// in it.
if(!EVP_EncryptFinal_ex(&en,
ciphertext + bytes_written,
&bytes_written)){
printf("ERROR in EVP_EncryptFinal_ex \n");
return 1;
}
ciphertext_len += bytes_written;
EVP_CIPHER_CTX_cleanup(&en);
printf("Input len: %d, ciphertext_len: %d\n", input_len, ciphertext_len);
// We'll pretend we don't know the input length here. We do know that
// the ciphertext length is at most 16 bytes + the input length. So
// since the ciphertext is always greater than the input length, we can
// declare plaintext buffer size = ciphertext buffer size and know that
// there's no way we'll overflow our plaintext buffer. It will have at
// most 16 bytes of wasted space on the end, but that's ok.
plaintext = (unsigned char *) malloc(ciphertext_len);
// No! You're encrypting arbitrary data, so you should use padding. You
// don't use padding only if you know in advance that you're encrypting
// data whose length is a multiple of the block size. Like when running
// the AES known-answer tests.
// EVP_CIPHER_CTX_set_padding(&de, 0); /* no! */
int plaintext_len = 0;
if(!EVP_DecryptUpdate(&de,
plaintext, &bytes_written,
ciphertext, ciphertext_len)){
printf("ERROR in EVP_DecryptUpdate\n");
return 1;
}
plaintext_len += bytes_written;
// This function verifies the padding and then discards it. It will
// return an error if the padding isn't what it expects, which means that
// the data was malformed or you are decrypting it with the wrong key.
if(!EVP_DecryptFinal_ex(&de,
plaintext + bytes_written, &bytes_written)){
printf("ERROR in EVP_DecryptFinal_ex\n");
return 1;
}
plaintext_len += bytes_written;
EVP_CIPHER_CTX_cleanup(&de);
// We encrypted a string, so we know that we decrypted a string. So we
// can just print it. Note that we know our binary data is a string so
// we just cast it to a char *. We could just have easily declared it
// originally as a char * (I think I changed that from your original
// program, actually) and then cast it in the call to EVP_DecryptUpdate.
printf("input_len: %d, ciphertext_len: %d, plaintext_len: %d\n",
input_len, ciphertext_len, plaintext_len);
printf("Decrypted value = %s\n", plaintext);
if( strcmp(string_to_encrypt, (char *) plaintext) == 0 ) {
printf("Decrypted data matches input data.\n");
}
else {
printf("Decrypted data does not match input data.\n");
}
free(ciphertext);
free(plaintext);
return 0;
}
#包括
#包括
#包括
#包括
int main(int argc,字符**argv)
{
执行副总裁;
执行副总裁;
EVP_CIPHER_CTX_init(&en);
EVP_CIPHER_CTX_init(&de);
const EVP_CIPHER*CIPHER_类型;
无符号字符*密钥,*被动,*明文;
无符号字符*纯文本=空;
无符号字符*密文=空;
int input_len=0;
无符号字符iv[]={0x00,0x01,0x02,0x03,
0x04、0x05、0x06、0x07,
0x08、0x09、0x0a、0x0b、,
0x0c,0x0d,0x0e,0x0f};
无符号字符键[]={0x2b,0x7e,0x15,0x16,
0x28,0xae,0xd2,0xa6,
0xab,0xf7,0x15,0x88,
0x09,0xcf,0x4f,0x3c};
const char*string_to_encrypt=“你好,我是patrick immling\n'Doctor”“\n'Doctor'谁?\n确切地说!123910!§$$§%!%%$&$(/=)=(#ü++Ü**亲爱的大家,有人能帮我吗?我真的被卡住了,正在寻找一些想法。提前谢谢!有没有办法多次调用加密更新?我在第一次加密更新后尝试了以下几行,但解密的数据只有第一个字符串(字符串到加密)如果(!EVP_EncryptUpdate(&en,密文+字节写入,&bytes写入,(无符号字符*)字符串到字节加密2,(strlen(字符串到加密2)+1)){printf(“EVP_EncryptUpdate中的错误”);return 1;}我喜欢评论。:-)解释得很好。比documentation/wikif(!EVP_EncryptInit_ex(&en,NULL,NULL,NULL,NULL))要好得多为什么会再次调用它?@Srikan:问得好!这一行在这个程序中没有任何用处。在一个普通程序中,你可以调用带有空参数的EVP\u EncryptInit\u ex
,在调用EVP\u EncryptFinal\u ex
后重置你的EVP\u CIPHER\u CTX
上下文,这样你就可以使用与你所调用的参数完全相同的参数重复使用它最初初始化为。但在这里它什么也不做,所以我从答案中删除了它。
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>
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 *passkey, *passiv, *plaintxt;
unsigned char *plaintext = NULL;
unsigned char *ciphertext = NULL;
int input_len = 0;
unsigned char iv[] = { 0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f };
unsigned char key[] = { 0x2b, 0x7e, 0x15, 0x16,
0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88,
0x09, 0xcf, 0x4f, 0x3c };
const char *string_to_encrypt = "hi this is patrick immling\n'Doctor'.\n'Doctor' who ?\nPrecisely! 123910!§$$§% !%%$&$(/=))?=(#ü++Ü**<,.here we go sometimes it i s difficult but 187! 1$5 78@2 14 .TӒ��틪�ձ1z.$�?�U���<y";
cipher_type = EVP_aes_128_cbc();
EVP_EncryptInit_ex(&en, cipher_type, NULL, key, iv);
EVP_DecryptInit_ex(&de, cipher_type, NULL, key, iv);
// The data we want to encrypt is a string. So we can just do a simple
// strlen to calculate its length. But the encrypted buffer is going to
// be padded with PKCS padding. In the worst case, our string is a
// multiple of the AES block size (16 bytes). In that case, the PKCS
// padding will be an additional 16 bytes after our data. So we could
// precisely calculate the buffer with this:
// int input_len = strlen(string_to_encrypt);
// malloc( input_len + 16 - (input_len % 16) );
// But why get fancy? Just add an extra AES block and have at most 16
// unused bytes at the end, and usually less than that.
static const int MAX_PADDING_LEN = 16;
// We add 1 because we're encrypting a string, which has a NULL terminator
// and want that NULL terminator to be present when we decrypt.
input_len = strlen(string_to_encrypt) + 1;
ciphertext = (unsigned char *) malloc(input_len + MAX_PADDING_LEN);
// This function works on binary data, not strings. So we cast our
// string to an unsigned char * and tell it that the length is the string
// length + 1 byte for the null terminator.
int bytes_written = 0;
int ciphertext_len = 0;
if(!EVP_EncryptUpdate(&en,
ciphertext, &bytes_written,
(unsigned char *) string_to_encrypt, input_len) ) {
printf("ERROR in EVP_EncryptUpdate \n");
return 1;
}
ciphertext_len += bytes_written;
// Right now the ciphertext buffer contains only the encrypted version
// of the input data up to the last full AES block. E.g., if your input
// size is 206, then ciphertext_len will be 192 because you have 14 bytes
// left to encrypt and those bytes can't fill a full AES block. But the
// encryptor has stored those bytes and is waiting either for more bytes
// or the call to EVP_EncryptFinal where it will add padding to make the
// encrypted data the same size as the AES block (i.e., 2 bytes of padding
// in the above example).
printf("Input len: %d, ciphertext_len: %d\n", input_len, ciphertext_len);
// EVP_EncryptFinal_ex writes the padding. The whole point of the
// bytes_written variable from EVP_EncryptUpdate is to tell us how much
// of the buffer is full so we know where we can write the padding.
// Note that we know our buffer is large enough so we're not bothering to
// keep track of the buffer size. We just keep track of how much data is
// in it.
if(!EVP_EncryptFinal_ex(&en,
ciphertext + bytes_written,
&bytes_written)){
printf("ERROR in EVP_EncryptFinal_ex \n");
return 1;
}
ciphertext_len += bytes_written;
EVP_CIPHER_CTX_cleanup(&en);
printf("Input len: %d, ciphertext_len: %d\n", input_len, ciphertext_len);
// We'll pretend we don't know the input length here. We do know that
// the ciphertext length is at most 16 bytes + the input length. So
// since the ciphertext is always greater than the input length, we can
// declare plaintext buffer size = ciphertext buffer size and know that
// there's no way we'll overflow our plaintext buffer. It will have at
// most 16 bytes of wasted space on the end, but that's ok.
plaintext = (unsigned char *) malloc(ciphertext_len);
// No! You're encrypting arbitrary data, so you should use padding. You
// don't use padding only if you know in advance that you're encrypting
// data whose length is a multiple of the block size. Like when running
// the AES known-answer tests.
// EVP_CIPHER_CTX_set_padding(&de, 0); /* no! */
int plaintext_len = 0;
if(!EVP_DecryptUpdate(&de,
plaintext, &bytes_written,
ciphertext, ciphertext_len)){
printf("ERROR in EVP_DecryptUpdate\n");
return 1;
}
plaintext_len += bytes_written;
// This function verifies the padding and then discards it. It will
// return an error if the padding isn't what it expects, which means that
// the data was malformed or you are decrypting it with the wrong key.
if(!EVP_DecryptFinal_ex(&de,
plaintext + bytes_written, &bytes_written)){
printf("ERROR in EVP_DecryptFinal_ex\n");
return 1;
}
plaintext_len += bytes_written;
EVP_CIPHER_CTX_cleanup(&de);
// We encrypted a string, so we know that we decrypted a string. So we
// can just print it. Note that we know our binary data is a string so
// we just cast it to a char *. We could just have easily declared it
// originally as a char * (I think I changed that from your original
// program, actually) and then cast it in the call to EVP_DecryptUpdate.
printf("input_len: %d, ciphertext_len: %d, plaintext_len: %d\n",
input_len, ciphertext_len, plaintext_len);
printf("Decrypted value = %s\n", plaintext);
if( strcmp(string_to_encrypt, (char *) plaintext) == 0 ) {
printf("Decrypted data matches input data.\n");
}
else {
printf("Decrypted data does not match input data.\n");
}
free(ciphertext);
free(plaintext);
return 0;
}