在PHP中如何解密Java中加密的字符串?
P粉083785014
P粉083785014 2023-08-30 12:12:13
[PHP讨论组]

我尝试使用以下代码在JAVA中解密一个加密的字符串。

SecretKey secretKey = new SecretKeySpec(build3DesKey(key), "DESede");
Cipher cipher = Cipher.getInstance("DESede");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] b = cipher.doFinal(str2ByteArray(dest));
String decoder = new String(b, "utf-8");
private static byte[] build3DesKey(String keyStr) throws Exception {
    byte[] key = new byte[24];
    byte[] temp = keyStr.getBytes("utf-8");
    if (key.length > temp.length) {
        System.arraycopy(temp, 0, key, 0, temp.length);
    } else {
        System.arraycopy(temp, 0, key, 0, key.length);
    }
    return key;
}

我如何在PHP版本中获得相同的结果?我尝试用PHP写,但输出的结果是错误的。

$data = '69C16E8142F2BDDE7569842BB0D68A3176624264E...';
$key = 'rpwdvbppnrvr56m123+#';
function decrypt($data, $secret)
{
    //从哈希生成密钥
    $key = md5(utf8_encode($secret), true);
    //将$key的前8个字节附加到$key的末尾。
    $key .= substr($key, 0, 8);
    $data = base64_decode($data);
    $data = mcrypt_decrypt('tripledes', $key, $data, 'ecb');
    $block = mcrypt_get_block_size('tripledes', 'ecb');
    $len = strlen($data);
    $pad = ord($data[$len-1]);
    return substr($data, 0, strlen($data) - $pad);
}

var_dump(utf8_encode(Decrypt($data, $key)));

P粉083785014
P粉083785014

全部回复(1)
P粉014218124

函数 build3DesKey() 将一个太短的3DES密钥扩展到24个字节,通过在末尾填充0x00值,对于太长的密钥,末尾会被简单地截断。在PHP中,可以如下实现 build3DesKey()

$key = substr(str_pad($key, 24, "\0"), 0, 24);

尽管缺少函数 str2ByteArray(),但其功能可以推断出来。由于在您的示例中,密文是十六进制编码的,所以这个函数似乎只是执行十六进制解码。在PHP中,与 str2ByteArray() 相对应的是 hex2bin()

因此,解密的可能实现方式是(使用PHP/OpenSSL):

$key = "12345";
$ciphertext = "84b24172c57752385251d142abadbed1d9945301a3aee429ce00c1e291a605c30ad18c5e00007f6db394fc6138a2ee4c";
$key = substr(str_pad($key, 24, "\0"), 0, 24);
$plaintext = openssl_decrypt(hex2bin($ciphertext), "des-ede3", $key, OPENSSL_RAW_DATA);
print($plaintext. PHP_EOL); // The quick brown fox jumps over the lazy dog

这些输入数据在Java代码中返回相同的明文!


与您的代码的差异:
您的代码使用了已弃用的 mcrypt。出于安全原因,现在不应该使用它。一个更好的替代方案是PHP/OpenSSL,如上面的代码所示。此外,实现的密钥派生是错误的,例如它应用了MD5摘要,在Java代码中根本没有使用。


安全性:
尽管这可能是一个旧的应用程序,但还是有几点关于安全性的说明:

  • 密钥派生 build3DesKey() 是不安全的。如果密钥材料是一个字符串,它通常不是一个密钥,而是一个密码。因此,应该使用可靠的密钥派生函数,例如Argon2或PBKDF2。
  • des-ede3 应用了ECB模式,这也是不安全的。现在应该使用认证加密,例如AES-GCM。
  • 3DES/TripleDES 已经过时,而唯一尚未弃用的变体,即三倍长度密钥或3TDEA,很快也会被弃用,并且相对较慢。今天的标准是应用AES。
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号