为什么 openssl AES 产生的结果与我尝试的每个在线工具都不同?

Why is openssl AES producing a different result than every online tool I try?

我正在尝试使用 AES 加密字符串。

在我的 Macbook 上,我输入命令

echo -n "hello" | openssl enc -e -aes-128-cbc

并输入密钥 123456.

结果:U2FsdGVkX1+FBre1MZ1YDfgZRmRyt/hMogfMhYeiq8Q=

然而,当我尝试任何在线加密工具时,我得到了不同的结果。

例如,对于这个站点,encode-decode 使用相同的加密方案,我得到

NrjrStoGrmkLAvWaJuKtvg==

为什么不同?我缺少什么配置?

我无法重现您的任何一个结果(我不在 Mac)。这个问题可能与 CBC 是块密码这一事实有关,这意味着每个加密周期它需要固定长度为 16 字节的块(与流密码不同)。当您的数据少于 16 个字节时,它将使用填充。

为什么不同? AES 标准没有定义(.. 我知道,这对我们不是很有帮助)需要使用什么样的填充,因此在 PKCS #5 或 PKCS #7 之间的实现可能有所不同。

在我的例子中,我什至被提示使用这个而不是你选择的操作 *** WARNING : deprecated key derivation used. Using -iter or -pbkdf2 would be better. openssl 中的 -pbkdf2 选项对应于 PKCS #5。 我们真的没有关于在线工具使用哪个库进行相同操作的信息。 关于结果:

U2FsdGVkX1+FBre1MZ1YDfgZRmRyt/hMogfMhYeiq8Q= and 
NrjrStoGrmkLAvWaJuKtvg==

Base64解码后分别为:

Salted__1XFdrL̅
6Ji&⭾

所以从这里可以看出,openssl加密的输出也是加了salt,但是内容还是完全不一样

我缺少什么配置? 不过,您可以尝试以下操作:

 openssl enc -e -aes-128-cbc -pbkdf2 -nosalt

盐的存在是为了防止与所用私钥有关的暴力攻击,例如,如果收集了多个加密文档,并且在解密过程中它们无关紧要。它只是一个解密的独特提示,在解密过程中会被消除,但会消除一些攻击。

问题是,你将如何使用加密方案 - 只要你始终如一地使用 openssl,你就可以放心它会起作用,尽管快速谷歌搜索显示不同的版本 can change 甚至影响,这就是为什么我可能无法解密 OpenSSL 1.1.1 2018 年 9 月 11 日提供的数据的原因。 此外,这里有一个 article,其中包含一些很好的示例和解释。

首先:要在默认设置 AES-128-CBC 和明文 hello 上重现发布的密文 NrjrStoGrmkLAvWaJuKtvg==,密钥 [=14] =](并且不是123456必须应用。

该网站使用 PKCS7 填充。密钥使用 UTF8 编码,并用 0x00 值填充到所需长度(AES 128 为 16 字节)。在 CBC 模式中,零向量用作 IV。由于没有描述(至少我没有找到文档),这只能通过与参考实现或网站进行比较来推断。

在 OpenSSL 中,密钥是使用 -K 选项(十六进制数字)指定的,请参阅 here。如果应用 IV,则必须使用 -iv 选项指定此 IV(也是十六进制数字)。所以要得到和网站一样的结果,需要在OpenSSL语句中加入:

-K 31323334353637380000000000000000 -iv 00000000000000000000000000000000

如果没有传递密钥,OpenSSL 会要求输入密码,生成一个随机的 8 字节盐,并使用 OpenSSL 函数 EVP_BytesToKey 从盐和密码中派生密钥和 IV。默认情况下,使用摘要 SHA256(从版本 1.1.0 开始,在 MD5 之前)和迭代计数为 1。输出格式是 Salted__ 的 ASCII 编码,后跟 8 字节盐和实际密文,全部Base64编码。因此密文总是以U2FsdGVkX1开头。由于盐是针对每次加密 随机 确定的,因此每次都会产生不同的密钥和 IV,从而产生不同的密文。 Key 和 IV 可以用 -p 选项显示。

使用密码 123456(如发布的那样)和摘要 MD5,发布的 OpenSSL 密文 U2FsdGVkX1+FBre1MZ1YDfgZRmRyt/hMogfMhYeiq8Q= 可以解密为明文 hello-p 选项也可用于解密并显示:

Key: F1A16DEEFFEE4AB705BB72C21C1F1CA2 
IV:  000A7A05E99BF90C025EFE40B534E836 

反之亦然,这个密钥和IV可以用来直接加密明文hello,得到密文F819466472B7F84CA207CC8587A2ABC4。如果发布的 OpenSSL 密文 U2FsdGVkX1+FBre1MZ1YDfgZRmRyt/hMogfMhYeiq8Q= 是 Base64 解码的,并且前 16 个字节(前缀和盐)被丢弃,那么会产生与预期相同的密文。

需要注意的是,OpenSSL 使用的密钥推导不是很安全,here。从 1.1.1 版本开始,OpenSSL 支持 PBKDF2,但这必须明确指定。