d openssl aes加密的字节数组在两次执行之间不是常数

时间:2018-07-26 20:18:44

标签: openssl aes d ldc

我正在使用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 ~ "\"");
}

1 个答案:

答案 0 :(得分:5)

您的代码中有几个错误。

首先,您似乎将密码短语和密钥混淆了。假设您以128位(第二个参数)的密钥大小调用AES_set_encrypt_key(),则用于该密钥的实际字节将是第一个参数指向的128位= 16个字节。由于您的第一个参数指向以0结尾的字符串"foo!",因此第五个字节之后的所有内容都是不可预测的,并且每次运行此代码时,实际使用的键可能会有所不同。

然后,您要使用AES_encrypt()函数来“加密您的数据”,并且您的数据是以0结尾的字符串"bar"。但是该函数实际上在固定大小为128位= 16字节的块上执行操作,与所使用的密钥大小无关。 wikipedia page about AES对其进行了详细说明。因此,该函数的输入和输出缓冲区都应为16个字节的缓冲区。您正在提供指向错误大小缓冲区的函数参数。

您的代码“解密”部分也会遇到同样的问题。

看看this concise C example正确使用了这些功能。这可能有助于您正确编写代码(并重新设置对实现这些功能的期望)。要以正确的方式实现您实际上的要求,请参见OpenSSL Wiki页面EVP Symmetric Encryption and Decryption。我没有D编程经验,但是乍一看,Deimos openssl绑定似乎可以提供所需的所有功能。