我使用Dim的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 ~ "\"");
}
Run Code Online (Sandbox Code Playgroud)
代码有几个错误.
首先,您似乎将密码与密钥混淆.假设您AES_set_encrypt_key()使用128位密钥大小(第二个参数)调用,则用于密钥的实际字节将是您的第一个参数指向的128位= 16个字节.由于您的第一个参数指向以0结尾的字符串"foo!",因此超出第五个字节的所有内容都将是不可预测的,并且每次运行此代码时使用的实际密钥可能会有所不同.
然后,您希望使用该AES_encrypt()功能"加密您的数据",您的数据是以0结尾的字符串"bar".但该函数实际上对128位= 16字节的固定大小的块执行操作,与所使用的密钥大小无关.关于AES的维基百科页面详细解释了它.因此,该函数的输入和输出缓冲区都应该是16字节的缓冲区.您将提供指向错误大小的缓冲区的函数参数.
代码的"解密"部分也存在同样的问题.
看看这个正确使用这些函数的简洁C示例.这可能有助于您正确地获得代码(并重置您对这些功能实现的期望).要以正确的方式实现您真正想要的内容,请参阅OpenSSL Wiki页面EVP对称加密和解密.我没有D编程经验,但初看起来,Deimos openssl绑定似乎提供了所需的所有功能.