OpenSSL AES_ecb_encrypt 填充选项?
OpenSSL AES_ecb_encrypt padding option?
我在 Visual Studio 中构建了一个 C 项目,它仅使用 OpenSSL 使用 AES128 ECB 密码对输入数据进行加密。
如果我的输入是 16 字节,输出是正确的,比我得到的错误输出短。
#include <stdio.h>
#include <openssl/ssl.h>
#include <openssl/aes.h>
int main(void)
{
unsigned char aesKey[] =
{
0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
};
const unsigned char aesData[] = {0x35, 0x31, 0x30, 0x30}; // results in wrong output
const unsigned char aesDataa[] = // results in correct output
{
0x35, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30
};
unsigned char out[32];
AES_KEY aes_key;
AES_set_encrypt_key((const unsigned char *)aesKey, 128, &aes_key);
AES_ecb_encrypt(aesDataa, out, &aes_key, AES_ENCRYPT);
for (int i = 0; i < 33; i++)
printf("%x", out[i]);
return 1;
}
我的例子:
输入十六进制:0x35313030
十六进制密钥:0x2B7E151628AED2A6ABF7158809CF4F3C
输出十六进制:0x2ba87a539758d476bb666bb525d14dbc
this 站点已针对其他站点进行测试并在 aes 硬件加速微控制器中实现:
输出十六进制:0xb13278c7f7413d515c549f4042a5de8c
如果我输入这个:5100510051005100 那么他们都同意。
我必须引入我自己的 PKCS#7 填充吗?如果是这样,有人可以指出该实现吗?
我尽量避免使用 EVP,因为我只会使用这种特定的加密方法和密码。
谢谢
AES 128 算法需要正好 16 个字节作为输入。您的 aesData
数组只有 4 个字节长,因此这会导致 AES_ecb_encrypt
读取超过触发 undefined behavior.
的数组末尾
使数组宽度为 16 字节:
const unsigned char aesData[16] = { 0x35, 0x31, 0x30, 0x30 };
这会将其余元素隐式初始化为 0,因此现在结果与链接网站的结果相匹配。
此外,您这里有一个差一错误:
for (int i = 0;i < 33;i++)
printf("%x", out[i]);
读取数组末尾。你想要:
for (int i = 0;i < 32;i++)
printf("%x", out[i]);
此外,只有 16 个字节的输出数组被写入,因此您读取的是未初始化的字节。所以将 out
初始化为全零:
unsigned char out[32] = {0};
我在 Visual Studio 中构建了一个 C 项目,它仅使用 OpenSSL 使用 AES128 ECB 密码对输入数据进行加密。
如果我的输入是 16 字节,输出是正确的,比我得到的错误输出短。
#include <stdio.h>
#include <openssl/ssl.h>
#include <openssl/aes.h>
int main(void)
{
unsigned char aesKey[] =
{
0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
};
const unsigned char aesData[] = {0x35, 0x31, 0x30, 0x30}; // results in wrong output
const unsigned char aesDataa[] = // results in correct output
{
0x35, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30
};
unsigned char out[32];
AES_KEY aes_key;
AES_set_encrypt_key((const unsigned char *)aesKey, 128, &aes_key);
AES_ecb_encrypt(aesDataa, out, &aes_key, AES_ENCRYPT);
for (int i = 0; i < 33; i++)
printf("%x", out[i]);
return 1;
}
我的例子:
输入十六进制:0x35313030
十六进制密钥:0x2B7E151628AED2A6ABF7158809CF4F3C
输出十六进制:0x2ba87a539758d476bb666bb525d14dbc
this 站点已针对其他站点进行测试并在 aes 硬件加速微控制器中实现:
输出十六进制:0xb13278c7f7413d515c549f4042a5de8c
如果我输入这个:5100510051005100 那么他们都同意。
我必须引入我自己的 PKCS#7 填充吗?如果是这样,有人可以指出该实现吗?
我尽量避免使用 EVP,因为我只会使用这种特定的加密方法和密码。
谢谢
AES 128 算法需要正好 16 个字节作为输入。您的 aesData
数组只有 4 个字节长,因此这会导致 AES_ecb_encrypt
读取超过触发 undefined behavior.
使数组宽度为 16 字节:
const unsigned char aesData[16] = { 0x35, 0x31, 0x30, 0x30 };
这会将其余元素隐式初始化为 0,因此现在结果与链接网站的结果相匹配。
此外,您这里有一个差一错误:
for (int i = 0;i < 33;i++)
printf("%x", out[i]);
读取数组末尾。你想要:
for (int i = 0;i < 32;i++)
printf("%x", out[i]);
此外,只有 16 个字节的输出数组被写入,因此您读取的是未初始化的字节。所以将 out
初始化为全零:
unsigned char out[32] = {0};