openssl - d openssl aes 加密字节数组在执行之间不是恒定的
问题描述
我使用 D 的 Deimos openssl 标头将 D 链接到 OpenSsl,并使用 ldc 1.8.0 编译器尝试加密字符串作为小测试。加密的字节数组与我的预期不一致。当我运行程序并加密字符串并随后解密时,我会取回原始字符串。但是中间的加密字节数组在代码的执行之间并不一致。
所以我的问题是,这是预期的行为吗,OpenSsl 中的 AES 是否在内容中添加了某种盐,因此更难攻击,或者这是我的错误?
import std.stdio;
import std.conv;
import std.string;
import std.outbuffer;
import deimos.openssl.aes;
void main()
{
writeln("hello world");
const auto encryption_passphrase = "foo!";
writeln("The encryption key is \"" ~ encryption_passphrase ~ "\"");
const auto encryption_content = "bar";
writeln("The to be encrypted content is: \"" ~ encryption_content ~ "\"");
writeln("The content lenght is " ~ encryption_content.length.to!string);
writeln("----------");
writeln("encrypting");
AES_KEY encryption_key;
AES_set_encrypt_key(cast(ubyte*) encryption_passphrase.toStringz, 128, &encryption_key);
OutBuffer buf = new OutBuffer();
buf.write(encryption_content);
ubyte[] inbuffer = buf.toBytes();
ubyte[] encryptedbuffer = new ubyte[inbuffer.length];
AES_encrypt(&inbuffer[0], &encryptedbuffer[0], &encryption_key);
writeln("The encrypted content is: \"" ~ (cast(char*)encryptedbuffer).fromStringz ~ "\"");
writeln("----------");
writeln("decrypting");
AES_KEY decryption_key;
AES_set_decrypt_key(cast(ubyte*) encryption_passphrase.toStringz, 128, &decryption_key);
ubyte[] outbuffer = new ubyte[inbuffer.length];
AES_decrypt(&encryptedbuffer[0], &outbuffer[0], &decryption_key);
writeln("the decrypted content is: \"" ~ (cast(char*)outbuffer).fromStringz ~ "\"");
}
解决方案
您的代码有几个错误。
首先,您似乎将密码短语与密钥混淆了。假设您AES_set_encrypt_key()
使用 128 位的密钥大小(第二个参数)调用,用于密钥的实际字节将是第一个参数指向的 128 位 = 16 个字节。由于您的第一个参数指向一个以 0 结尾的 string "foo!"
,因此第五个字节之外的所有内容都将是不可预测的,并且每次运行此代码时使用的实际密钥可能会有所不同。
然后您想使用该AES_encrypt()
功能“加密您的数据”,您的数据是 0-terminated string "bar"
。但该函数实际上对 128 位 = 16 字节的固定大小的块执行操作,与使用的密钥大小无关。关于 AES 的维基百科页面详细解释了它。因此,该函数的输入和输出缓冲区都应该是 16 字节的缓冲区。您正在提供指向错误大小的缓冲区的函数参数。
同样的问题也适用于代码的“解密”部分。
看看这个正确使用这些函数的简洁 C 示例。这可能会帮助您正确编写代码(并重新设置您对实现这些功能的期望)。要以正确的方式实现您真正想要的,请参阅 OpenSSL wiki 页面EVP Symmetric Encryption and Decryption。我没有D
编程经验,但乍一看,Deimos openssl 绑定似乎提供了所需的所有功能。
推荐阅读
- javascript - How to wait on async .then
- spring-boot - 从 Spring Cloud Configuration 加载属性数组
- flutter - 由于 cloud_firestore,无法安装 permission_handler 和 file_picker
- r - plot.window(…) 中的错误:需要有限的“xlim”值,但看起来一切都很好
- python - 从 psycopg2 在 Postgres 中插入 dict 列表作为 json 数组
- python - 在 Heroku 中上传烧瓶应用程序并且工作正常但在我的终端中出现错误,(拉取函数中的错误)
- php - 从某个日期到 12 月计算月份,然后从次年 1 月到同年 12 月计算月份,然后从 1 月到结束日期
- git - 每当我们使用 dotnet 格式运行 git commit 时,如何格式化代码?
- javascript - 需要根据javascript中的特定要求修改数组
- rxjs - 如何在 Svelte 中使用 RXJs 主题之类的存储变量