首頁  >  問答  >  主體

在PHP中如何解密Java中加密的字串?

<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>
P粉083785014P粉083785014437 天前543

全部回覆(1)我來回復

  • P粉014218124

    P粉0142181242023-08-31 10:27:11

    函數 build3DesKey() 將一個太短的3DES密鑰擴展到24個字節,透過在末尾填充0x00值,對於太長的密鑰,末尾會被簡單地截斷。在PHP中,可以如下實作 build3DesKey()

    $key = substr(str_pad($key, 24, "
    $key = "12345";
    $ciphertext = "84b24172c57752385251d142abadbed1d9945301a3aee429ce00c1e291a605c30ad18c5e00007f6db394fc6138a2ee4c";
    $key = substr(str_pad($key, 24, "rrreee"), 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
    
    "), 0, 24);

    儘管缺少函數 str2ByteArray(),但其功能可以推斷出來。由於在您的範例中,密文是十六進位編碼的,所以這個函數似乎只是執行十六進位解碼。在PHP中,與 str2ByteArray() 相對應的是 hex2bin()

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

    rrreee

    這些輸入資料在Java程式碼中傳回相同的明文!


    與您的程式碼的差異:
    您的程式碼使用了已棄用的 mcrypt。出於安全原因,現在不應該使用它。一個更好的替代方案是PHP/OpenSSL,如上面的程式碼所示。此外,實現的金鑰派生是錯誤的,例如它應用了MD5摘要,在Java程式碼中根本沒有使用。


    安全性:
    儘管這可能是舊的應用程序,但還是有幾點關於安全性的說明:

    • 金鑰派生 build3DesKey() 是不安全的。如果密鑰材料是一個字串,它通常不是一個密鑰,而是一個密碼。因此,應該使用可靠的金鑰衍生函數,例如Argon2或PBKDF2。
    • des-ede3 應用了ECB模式,這也是不安全的。現在應該使用認證加密,例如AES-GCM。
    • 3DES/TripleDES 已經過時,而唯一尚未棄用的變體,即三倍長度密鑰或3TDEA,很快也會被棄用,並且相對較慢。今天的標準是應用AES。

    回覆
    0
  • 取消回覆