【问题标题】:Why is openssl AES producing a different result than every online tool I try?为什么 openssl AES 产生的结果与我尝试的每个在线工具都不同?
【发布时间】:2020-04-17 23:38:57
【问题描述】:

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

在我的 Macbook 上,我输入命令

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

并输入密钥123456。

结果:U2FsdGVkX1+FBre1MZ1YDfgZRmRyt/hMogfMhYeiq8Q=

但是,当我尝试任何在线加密工具时,我会得到不同的结果。

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

NrjrStoGrmkLAvWaJuKtvg==

为什么不一样?我缺少什么配置?

【问题讨论】:

    标签: encryption openssl aes


    【解决方案1】:

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

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

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

    -K 31323334353637380000000000000000 -iv 00000000000000000000000000000000
    

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

    使用密码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,但必须明确指定。

    【讨论】:

    • 感谢您的有趣解释!
    【解决方案2】:

    我无法重现您的任何结果(我不在 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,里面有一些很好的例子和解释。

    【讨论】:

      猜你喜欢
      • 2019-08-12
      • 2018-12-31
      • 2012-06-09
      • 2018-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-25
      • 2023-03-14
      相关资源
      最近更新 更多