You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 18:13:18