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

Java转PHP实现AES/GCM/NoPadding加解密遇Tag报错求助

解决PHP AES-GCM加解密兼容Java实现的问题

首先,你遇到的错误是因为GCM属于AEAD(认证加密带关联数据)模式,PHP的openssl_encrypt在使用该模式时需要单独处理认证标签(Tag),同时你的代码还有两个关键问题需要修正:

关键修正点

  • Java代码使用的是AES-256(密钥长度32字节),但你PHP里写的是aes-128-gcm,需改为aes-256-gcm
  • Java的Cipher.doFinal()会自动将密文和16字节的认证标签拼接在一起,而PHP默认会把密文和标签分开,需要手动拼接来对齐Java的输出格式

正确的PHP兼容实现代码

<?php
$data = "private-key";

// 生成256位AES密钥(和Java的AES-256对应)
$skey = random_bytes(32);
// 生成12字节IV(GCM推荐标准长度,与Java保持一致)
$biv = random_bytes(12);

// 加密:第6个参数用于接收生成的认证标签
$tag = '';
// OPENSSL_RAW_DATA表示输出原始字节,不自动做Base64编码
$ciphertext = openssl_encrypt(
    $data,
    'aes-256-gcm',
    $skey,
    OPENSSL_RAW_DATA | OPENSSL_NO_PADDING,
    $biv,
    $tag
);

// 拼接密文和标签(对齐Java的输出结构:密文 + 16字节Tag)
$encrypted = $ciphertext . $tag;
// Base64编码后输出,和Java的输出格式统一
echo "encryption: " . base64_encode($encrypted) . "<br>";

// 解密:拆分密文和标签
$ciphertextDecrypt = substr($encrypted, 0, -16);
$tagDecrypt = substr($encrypted, -16);

$origin = openssl_decrypt(
    $ciphertextDecrypt,
    'aes-256-gcm',
    $skey,
    OPENSSL_RAW_DATA | OPENSSL_NO_PADDING,
    $biv,
    $tagDecrypt
);

echo "origin: " . $origin;
?>

代码说明

  1. 密钥与IV:完全对齐Java的参数,密钥为32字节(AES-256),IV为12字节(GCM标准推荐长度)
  2. 加密流程:
    • 使用OPENSSL_RAW_DATA让openssl_encrypt输出原始字节,避免自动Base64干扰
    • 通过第6个参数$tag获取GCM模式生成的认证标签
    • 将密文和标签拼接,和JavadoFinal()的输出结构完全一致
  3. 解密流程:
    • 从拼接后的字节串中拆分出前N-16字节作为密文,最后16字节作为认证标签
    • 将标签传入openssl_decrypt完成解密验证和明文还原

修改后的代码可实现PHP与Java之间的AES-GCM加解密互通。

内容的提问来源于stack exchange,提问作者KunLun

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 19:35:22