在PHP中如何解密Java中加密的字串?
P粉083785014
2023-08-30 12:12:13
<p>我嘗試使用以下程式碼在JAVA中解密一個加密的字串。 </p>
<pre class="lang-java prettyprint-override"><code>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");
</code></pre>
<pre class="lang-java prettyprint-override"><code>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;
}
</code></pre>
<p>我如何在PHP版本中得到相同的結果?我嘗試用PHP寫,但輸出的結果是錯的。 </p>
<pre class="brush:php;toolbar:false;">$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)));</pre></p>
函數
build3DesKey()
將一個太短的3DES密鑰擴展到24個字節,透過在末尾填充0x00值,對於太長的密鑰,末尾會被簡單地截斷。在PHP中,可以如下實作build3DesKey()
:儘管缺少函數
str2ByteArray()
,但其功能可以推斷出來。由於在您的範例中,密文是十六進位編碼的,所以這個函數似乎只是執行十六進位解碼。在PHP中,與str2ByteArray()
相對應的是hex2bin()
。因此,解密的可能實作方式是(使用PHP/OpenSSL):
rrreee這些輸入資料在Java程式碼中傳回相同的明文!
與您的程式碼的差異:
您的程式碼使用了已棄用的
mcrypt
。出於安全原因,現在不應該使用它。一個更好的替代方案是PHP/OpenSSL,如上面的程式碼所示。此外,實現的金鑰派生是錯誤的,例如它應用了MD5摘要,在Java程式碼中根本沒有使用。安全性:
儘管這可能是舊的應用程序,但還是有幾點關於安全性的說明:
build3DesKey()
是不安全的。如果密鑰材料是一個字串,它通常不是一個密鑰,而是一個密碼。因此,應該使用可靠的金鑰衍生函數,例如Argon2或PBKDF2。