PHP无法解密Java AES GCM加密文本问题排查与解决
AES GCM跨语言加解密问题解决
问题现象
同端进行AES GCM加解密可正常工作,但使用PHP解密方法无法解密Java AES GCM加密的文本,始终返回false。
Java加密代码
public static String encrypt(String stringToEncrypt, String encryptionKey) throws Exception { byte[] encryptionKeyBytes = encryptionKey.getBytes(); SecureRandom secureRandom = new SecureRandom(); byte[] iv = new byte[12]; secureRandom.nextBytes(iv); Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); SecretKey secretKey = new SecretKeySpec(encryptionKeyBytes, "AES"); GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv); cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec); byte[] encryptedMessageBytes = cipher.doFinal(stringToEncrypt.getBytes()); byte[] encryptedMessageAndIVBytes = ByteBuffer.allocate(iv.length + encryptedMessageBytes.length) .put(iv) .put(encryptedMessageBytes) .array(); return Base64.getEncoder().encodeToString(encryptedMessageAndIVBytes); }
PHP解密代码
function decode(string $ciphertext, string $encryptionKey): false|string { $ciphertext = base64_decode($ciphertext); $iv = substr($ciphertext, 0, 12); $tag = substr($ciphertext, -16); $ciphertext = substr($ciphertext, 12, -16); //Also doesn't work! //$tag = ''; //$ciphertext = substr($ciphertext, 12); return openssl_decrypt($ciphertext, 'aes-128-gcm', $encryptionKey, OPENSSL_RAW_DATA, $iv, $tag); }
问题原因及解决方向
可能的原因是使用的密钥不是16字节,比如32字节。Java代码中AES变体由密钥长度决定(如AES-256),而PHP侧由指定的算法(如AES-128)决定,密钥会被静默截断,导致两端密钥不一致。
解决思路:确保两端使用匹配的AES变体与密钥长度。例如Java侧用32字节密钥对应AES-256时,PHP侧需将解密算法改为aes-256-gcm;若要统一使用AES-128,则两端密钥都需设置为16字节。
内容的提问来源于stack exchange,提问作者AHHP
相关产品推荐
相关产品推荐

