赞
踩
我在公司折腾了很久,php加密,java端解密不成功,翻墙后找到了解决问题的关键。
使用 AES GCM 模式的 PHP 和 Java 之间的跨平台加密正在运行。有一些细节可能会阻止你成功。
首先:在 PHP 端,openssl_encrypt 返回一个 base64 编码的密文,当将密文与版本、iv 和标签连接时,该密文再次被 base64 编码。为了避免这种情况,我将 OPENSSL 选项设置为“OPENSSL_RAW_DATA”。
第二:在Java端,标签被附加到密文中,因此“密文|标签”可以直接被使用。
请注意:我的示例只是展示了 PHP 端的加密和 Java 端的解密将如何工作,但可能与您的源代码无关(Java 端特别) - 我懒得采用我的例子: -)
这是 PHP 端的输出:
- AES GCM in PHP/Java
- ciphertext: djAx/kMbxfJI5Zx7lTWeDbw601cD2wkjBvuKeVBbKOZHll98GstPNfi1xHvyRlBwJDQ6YWvpymsk76kwbBbD0cBsOzzK/tH8UpA=
将密文复制到Java程序并让它运行:
- AES GCM in PHP/Java
- decryptedtext: The quick brown fox jumps over the lazy dog
您可以在下面找到这两个程序的源代码。安全警告:代码使用固定和硬编码的密钥 - 不要这样做。这些程序没有任何异常处理,仅用于教育目的。
该代码在 PHP > 7.2 和 Java 11+ 上运行。
PHP代码:
- <?php
- function encrypt($key, $textToEncrypt){
- $cipher = 'aes-256-gcm';
- $iv_len = 12;
- $tag_length = 16;
- $version_length = 3;
- $version = "v01";
- $iv = openssl_random_pseudo_bytes($iv_len);
- $tag = ""; // will be filled by openssl_encrypt
- $ciphertext = openssl_encrypt($textToEncrypt, $cipher, $key, OPENSSL_RAW_DATA, $iv, $tag, "", $tag_length);
- $encrypted = base64_encode($version.$iv.$ciphertext.$tag);
- return $encrypted;
- }
-
- echo 'AES GCM in PHP/Java' . PHP_EOL;
- // ### security warning: never use hardcoded keys in source ###
- $key = '12345678901234567890123456789012';
- $plaintext = 'The quick brown fox jumps over the lazy dog';
- $ciphertext = encrypt($key, $plaintext);
- echo 'ciphertext: ' . $ciphertext . PHP_EOL;
- ?>
Java代码:
- import javax.crypto.BadPaddingException;
- import javax.crypto.Cipher;
- import javax.crypto.IllegalBlockSizeException;
- import javax.crypto.NoSuchPaddingException;
- import javax.crypto.spec.GCMParameterSpec;
- import javax.crypto.spec.SecretKeySpec;
- import java.nio.charset.StandardCharsets;
- import java.security.InvalidAlgorithmParameterException;
- import java.security.InvalidKeyException;
- import java.security.NoSuchAlgorithmException;
- import java.util.Arrays;
- import java.util.Base64;
-
- public class SO_final {
- public static void main(String[] args) throws NoSuchPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException {
- System.out.println("AES GCM in PHP/Java");
- // https://stackoverflow.com/questions/65001817/aes-gcm-in-php-java
- String ciphertext = "djAx/kMbxfJI5Zx7lTWeDbw601cD2wkjBvuKeVBbKOZHll98GstPNfi1xHvyRlBwJDQ6YWvpymsk76kwbBbD0cBsOzzK/tH8UpA=";
- // ### security warning: never use hardcoded keys in source ###
- byte[] key = "12345678901234567890123456789012".getBytes(StandardCharsets.UTF_8);
- String decryptedtext = decryptGcmBase64(key, ciphertext);
- System.out.println("decryptedtext: " + decryptedtext);
- }
-
- public static String decryptGcmBase64(byte[] key, String ciphertextBase64) throws
- NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException,
- InvalidAlgorithmParameterException, BadPaddingException, IllegalBlockSizeException {
- byte[] ciphertextComplete = Base64.getDecoder().decode(ciphertextBase64);
- // split data
- // base64 encoding $encrypted = base64_encode($version.$iv.$ciphertext.$tag);
- byte[] version = Arrays.copyOfRange(ciphertextComplete, 0, 3); // 3 bytes
- byte[] iv = Arrays.copyOfRange(ciphertextComplete, 3, 15); // 12 bytes
- byte[] ciphertextWithTag = Arrays.copyOfRange(ciphertextComplete, 15, ciphertextComplete.length);
- SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
- GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(16 * 8, iv);
- Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5Padding");//NOPadding
- cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, gcmParameterSpec);
- return new String(cipher.doFinal(ciphertextWithTag), StandardCharsets.UTF_8);
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。