MCrypt rijndael-128 到 OpenSSL aes-128-ecb 转换
MCrypt rijndael-128 to OpenSSL aes-128-ecb conversion
由于 Mcrypt 已被弃用,我想在我的代码中使用 OpenSSL,因为我们已经在我们的服务器中使用 php 7.0.17 并且不知道什么时候它们升级它。
一些第三方 API(可能托管在 PHP 5.x 上并使用 mcrypt ), 正在获取加密数据。他们提供了用于 encrypt/decrypt 字符串的方法。
这是他们
$secret = 'a0a7e7997b6d5fcd55f4b5c32611b87c' ;
public function encrypt128($str)
{
$block = mcrypt_get_block_size("rijndael_128", "ecb");
$pad = $block - (strlen($str) % $block);
$str .= str_repeat(chr($pad), $pad);
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $secret, $str, MCRYPT_MODE_ECB));
}
public function decrypt128($str)
{
$str = base64_decode($str);
$str = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $secret, $str, MCRYPT_MODE_ECB);
$len = strlen($str);
$pad = ord($str[$len - 1]);
return substr($str, 0, strlen($str) - $pad);
}
使用这些方法字符串 small1
如果加密变为 v7IXp5vVaFVXXlt/MN8BVw==
我们想在我们这边使用 openssl_encrypt
这样,如果我们使用 OpenSSL 加密相同的字符串,它必须给出与 Mcrypt 相同的结果。我研究过使用 rijndael-128 模式 ecb 的 mcrypt 应该与 OpenSSL aes-128-ecb
.
兼容
在过去的几个小时里,我一直在尝试使用 OpenSSL 创建自己的方法来加密提供相同结果的字符串。到目前为止,我已经来到这里
public function sslEncrypt128($str)
{
$secret = 'a0a7e7997b6d5fcd55f4b5c32611b87c';
return base64_encode(openssl_encrypt($str, 'aes-128-ecb', $secret, OPENSSL_RAW_DATA));
}
但它会为与上述输入相同的内容生成不同的字符串 SxJ3+EdaeItZx3/EwGTUbw==
。不知道是flag的问题还是padding的问题,欢迎指点
我在这里添加了代码来在线测试https://3v4l.org/v2J2N
提前致谢。
很可能密钥被用作十六进制(它已经是十六进制格式)而不是要转换为十六进制的字符串。
mcrypt:
mcrypt
不支持标准 PKCS#7(née PKCS#5)填充,仅支持非标准空填充 但填充是在 mcrypt[=57= 之前显式添加的].
加密 v7IXp5vVaFVXXlt/MN8BVw==
是基于 PKCS#7 填充的正确加密。 ECB 模式和密钥作为字符串。
在十六进制中,注意数据填充清晰可见:
key: 6130613765373939376236643566636435356634623563333236313162383763
data: 736D616C6C310A0A0A0A0A0A0A0A0A0A
encrypted: BFB217A79BD56855575E5B7F30DF0157
在 Base64 中:
encrypted: v7IXp5vVaFVXXlt/MN8BVw==
OpenSSL:
请注意密钥是 256 位,但使用 "aes-128-ecb" 的 OpenSSL 调用似乎暗示了 128 位密钥。所以键不匹配。
在十六进制中,注意数据填充清晰可见:
key: 61306137653739393762366435666364
data: 736D616C6C310A0A0A0A0A0A0A0A0A0A
encrypted: 4B1277F8475A788B59C77FC4C064D46F
在 Base64 中:
encrypted: SxJ3+EdaeItZx3/EwGTUbw==
在您的具体示例中,我发现通过将 aes-128-ecb
更改为 aes-256-ecb
,它会产生与遗留 mcrypt_encrypt
.
相同的输出
以下是对我有用的方法:
<?php
$str = 'Content';
if (strlen($str) % 16) {
$str = str_pad($str, strlen($str) + 16 - strlen($str) % 16, "[=10=]");
}
$key = 'KEY';
if (strlen($key) % 16) {
$key = str_pad($key, strlen($key) + 16 - strlen($key) % 16, "[=10=]");
}
$res1 = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_ECB);
echo strToHex($res1) . ' | mcrypt_encrypt';
echo "<hr>";
echo strToHex(openssl_decrypt($res1, "aes-128-ecb", $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING)) . ' | openssl_decrypt';
echo "<hr>";
$res2 = openssl_encrypt($str, "aes-128-ecb", $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING);
echo strToHex($res2) . ' | openssl_encrypt';
echo "<hr>";
echo strToHex(openssl_decrypt($res2, "aes-128-ecb", $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING)) . ' | openssl_decrypt';
function strToHex($string) {
$hex = '';
for ($i = 0; $i < strlen($string); $i++) {
$ord = ord($string[$i]);
$hexCode = dechex($ord);
$hex .= substr('0' . $hexCode, -2);
}
return strToUpper($hex);
}
由于 Mcrypt 已被弃用,我想在我的代码中使用 OpenSSL,因为我们已经在我们的服务器中使用 php 7.0.17 并且不知道什么时候它们升级它。
一些第三方 API(可能托管在 PHP 5.x 上并使用 mcrypt ), 正在获取加密数据。他们提供了用于 encrypt/decrypt 字符串的方法。
这是他们
$secret = 'a0a7e7997b6d5fcd55f4b5c32611b87c' ;
public function encrypt128($str)
{
$block = mcrypt_get_block_size("rijndael_128", "ecb");
$pad = $block - (strlen($str) % $block);
$str .= str_repeat(chr($pad), $pad);
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $secret, $str, MCRYPT_MODE_ECB));
}
public function decrypt128($str)
{
$str = base64_decode($str);
$str = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $secret, $str, MCRYPT_MODE_ECB);
$len = strlen($str);
$pad = ord($str[$len - 1]);
return substr($str, 0, strlen($str) - $pad);
}
使用这些方法字符串 small1
如果加密变为 v7IXp5vVaFVXXlt/MN8BVw==
我们想在我们这边使用 openssl_encrypt
这样,如果我们使用 OpenSSL 加密相同的字符串,它必须给出与 Mcrypt 相同的结果。我研究过使用 rijndael-128 模式 ecb 的 mcrypt 应该与 OpenSSL aes-128-ecb
.
在过去的几个小时里,我一直在尝试使用 OpenSSL 创建自己的方法来加密提供相同结果的字符串。到目前为止,我已经来到这里
public function sslEncrypt128($str)
{
$secret = 'a0a7e7997b6d5fcd55f4b5c32611b87c';
return base64_encode(openssl_encrypt($str, 'aes-128-ecb', $secret, OPENSSL_RAW_DATA));
}
但它会为与上述输入相同的内容生成不同的字符串 SxJ3+EdaeItZx3/EwGTUbw==
。不知道是flag的问题还是padding的问题,欢迎指点
我在这里添加了代码来在线测试https://3v4l.org/v2J2N
提前致谢。
很可能密钥被用作十六进制(它已经是十六进制格式)而不是要转换为十六进制的字符串。
mcrypt:
mcrypt
不支持标准 PKCS#7(née PKCS#5)填充,仅支持非标准空填充 但填充是在 mcrypt[=57= 之前显式添加的].
加密 v7IXp5vVaFVXXlt/MN8BVw==
是基于 PKCS#7 填充的正确加密。 ECB 模式和密钥作为字符串。
在十六进制中,注意数据填充清晰可见:
key: 6130613765373939376236643566636435356634623563333236313162383763
data: 736D616C6C310A0A0A0A0A0A0A0A0A0A
encrypted: BFB217A79BD56855575E5B7F30DF0157
在 Base64 中:
encrypted: v7IXp5vVaFVXXlt/MN8BVw==
OpenSSL:
请注意密钥是 256 位,但使用 "aes-128-ecb" 的 OpenSSL 调用似乎暗示了 128 位密钥。所以键不匹配。
在十六进制中,注意数据填充清晰可见:
key: 61306137653739393762366435666364
data: 736D616C6C310A0A0A0A0A0A0A0A0A0A
encrypted: 4B1277F8475A788B59C77FC4C064D46F
在 Base64 中:
encrypted: SxJ3+EdaeItZx3/EwGTUbw==
在您的具体示例中,我发现通过将 aes-128-ecb
更改为 aes-256-ecb
,它会产生与遗留 mcrypt_encrypt
.
以下是对我有用的方法:
<?php
$str = 'Content';
if (strlen($str) % 16) {
$str = str_pad($str, strlen($str) + 16 - strlen($str) % 16, "[=10=]");
}
$key = 'KEY';
if (strlen($key) % 16) {
$key = str_pad($key, strlen($key) + 16 - strlen($key) % 16, "[=10=]");
}
$res1 = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $str, MCRYPT_MODE_ECB);
echo strToHex($res1) . ' | mcrypt_encrypt';
echo "<hr>";
echo strToHex(openssl_decrypt($res1, "aes-128-ecb", $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING)) . ' | openssl_decrypt';
echo "<hr>";
$res2 = openssl_encrypt($str, "aes-128-ecb", $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING);
echo strToHex($res2) . ' | openssl_encrypt';
echo "<hr>";
echo strToHex(openssl_decrypt($res2, "aes-128-ecb", $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING)) . ' | openssl_decrypt';
function strToHex($string) {
$hex = '';
for ($i = 0; $i < strlen($string); $i++) {
$ord = ord($string[$i]);
$hexCode = dechex($ord);
$hex .= substr('0' . $hexCode, -2);
}
return strToUpper($hex);
}