phpseclib AES-GCM加密能否与JavaScript WebCrypto兼容互通?
PHP phpseclib 与 WebCrypto AES-GCM 互通问题解决
二者完全兼容,你的问题出在PHP端对密钥和IV的处理上——未正确解码Base64字符串,导致加密使用了错误的密钥/IV字节,最终WebCrypto解密时验证失败抛出OperationError。
问题核心
PHP代码中$TEST_AES_KEY和$TEST_AES_IV是Base64编码字符串,但AES->setKey()和AES->setNonce()需要的是原始字节数据,而非Base64字符串。直接传入Base64会导致实际使用的密钥/IV与WebCrypto端完全不一致,解密自然失败。
修正后的PHP加密代码
<?php require_once($_SERVER['DOCUMENT_ROOT'] . '/../vendor/autoload.php'); use phpseclib3\Crypt\AES; $TEST_AES_KEY = "TWw4QCkeZEnXoCDkI1GEHQ=="; $TEST_AES_IV = "CRKTyQoWdWB2n56f"; $message = "123&abc"; $aes = new AES('gcm'); // 关键:对密钥和IV做Base64解码,获取原始字节 $aes->setKey(base64_decode($TEST_AES_KEY)); $aes->setNonce(base64_decode($TEST_AES_IV)); $ciphertext = $aes->encrypt($message); $tag = $aes->getTag(); // 密文拼接标签后Base64编码的逻辑是正确的 $ciphertextBase64 = base64_encode($ciphertext . $tag); echo $ciphertextBase64;
验证WebCrypto解密
用修正后的PHP代码生成新的密文,替换前端的messageEncrypted字段,即可正常解密。你的WebCrypto代码逻辑完全正确,无需修改。
互通关键注意事项
- 密钥/IV字节对齐:确保两端使用的是相同原始字节的密钥和IV,Base64编码仅用于传输存储,使用前必须解码。
- Tag长度一致:phpseclib默认GCM Tag长度为128位,与WebCrypto指定的
tagLength:128匹配,无需额外调整。 - 数据格式统一:PHP端密文+标签拼接后Base64编码,WebCrypto端解码后直接传入
decrypt方法即可,WebCrypto会自动从数据末尾提取16字节(128位)的Tag完成验证。
内容的提问来源于stack exchange,提问作者stk
相关产品推荐
相关产品推荐

