【问题标题】:32-character PHP AES Key for mcrypt_encrypt用于 mcrypt_encrypt 的 32 个字符的 PHP AES 密钥
【发布时间】:2015-08-24 22:35:22
【问题描述】:

考虑以下 PHP 代码:

<?php
$key = "1234567812345678";
$iv = "1234567812345678";
$data = "Test string";

$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128,
                            $key,
                            $data,
                            MCRYPT_MODE_CBC,
                            $iv);

print "Encoded1: " . base64_encode($encrypted) . "\n";

$key = "12345678123456781234567812345678";

$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128,
                            $key,
                            $data,
                            MCRYPT_MODE_CBC,
                            $iv);

print "Encoded2: " . base64_encode($encrypted) . "\n";

运行时,会产生输出:

Encoded1: iz1qFlQJfs6Ycp+gcc2z4w==
Encoded2: n3D26h/m8CSH0CE+z6okkw==

请注意,我从PHP Java AES CBC Encryption Different Results 窃取了第一段代码

现在 - 这是问题:

在第一种情况下,传入的密钥是一个 16 个字符的字符串。如果每个单独的字符都被解释为一个 8 位的数量,这将给出预期的 128 位密钥大小。事实上,我在上面引用的 StackOverflow 页面上的 Java 代码正是这样做的,并获得了与 PHP 相同的结果。

在上面对mcrypt_encrypt 的第二次调用中,我将密钥的长度增加了一倍。 mcrypt_encrypt 很高兴地接受了这一点,但产生的加密输出与第一种情况不同。因此,很明显,它认为这是一个不同的密钥 - 例如,它不会只取前 128 位并丢弃任何过去的位。

那么,mcrypt_encrypt 如何处理输入的密钥字符串以得出MCRYPT_RIJNDAEL_128 算法所需的 128 位密钥?

如果有什么不同,我特别感兴趣的情况是像我的第二个示例一样传入 32 个字符的字符串 - 我必须创建一个匹配的解密例程(在 Java 中),所以我需要弄清楚在这种情况下如何实际生成密钥。我引用的页面有非常好的 Java 代码(适用于我所有的测试用例)——我只是缺少正确的关键字节集。

【问题讨论】:

    标签: php encryption aes rijndael symmetric-key


    【解决方案1】:

    Rijndael 算法有两个重要参数。有密钥大小(128位、192位和256位),然后有块大小(128位、192位和256-少量)。 MCRYPT_RIJNDAEL_128 中的 128 指的是块大小。密钥大小是可变的。

    当你将不同长度的密钥传递给 MCrypt 时,它会自动选择合适的密钥大小,所以你不能也不能设置它。 MCRYPT_RIJNDAEL_128 是 AES(AES-128、AES-192、AES-256)。 MCRYPT_RIJNDAEL_192 和 MCRYPT_RIJNDAEL_256 不再是 AES。

    如果 Java 代码生成了 128 位密钥的匹配结果,那么它也会生成 256 位密钥的匹配结果。

    MCrypt 有点奇怪。在 PHP 5.6.0 版本之前,它可以采用任何密钥长度,而不仅仅是 128 位、192 位或 256 位。密钥将被填充 0x00 字节,直到下一个有效密钥长度。


    由于 Java 不支持开箱即用的 ZeroPadding,因此您应该使用适当的填充方案,例如 PHP 中的 PKCS#5/PKCS#7 填充。 This answer 有一个很好的实现。

    【讨论】:

    • 灯泡时刻!我假设 MCRYPT_RIJNDAEL_128 = AES-128、MCRYPT_RIJNDAEL_192 = AES-192 和 MCRYPT_RIJNDAEL_256 = AES-256(即数字后缀指定 key 大小)。正如您所建议的,只要我正确处理了密钥,Java 解决方案就会完美运行。我正在使用 PHP 5.5 并没有帮助,因此在我摆弄(有时是随机的)密钥大小时没有遇到任何错误。非常感谢!
    猜你喜欢
    • 2015-03-13
    • 2021-01-27
    • 1970-01-01
    • 2021-09-23
    • 1970-01-01
    • 2017-05-04
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    相关资源
    最近更新 更多