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

使用PHP JWT Framework v2.2加密Payload时触发RangeException错误

问题解决:JWT Framework v2.2加密时Base64解码错误

问题重现

使用JWT Framework v2.2构建JWE时,触发以下致命错误:

RangeException: Base64::decode() only expects characters in the correct base64 alphabet in ...\jwt-framework-2.2.x\vendor\paragonie\constant_time_encoding\src\Base64.php on line 229

经排查,错误发生在解码包含斜杠字符(如fbf/)的公钥4字符块时。

根本原因

JWK标准中,RSA类型的n(公钥模数值)要求使用**Base64URL编码(无填充)**格式,而你传入的$public_key_plain大概率是普通Base64编码(含/、+和=填充),甚至是完整的PEM格式公钥,不符合JWK的编码规范,导致解码时识别到非法字符。

解决方案

1. 正确提取并编码RSA公钥的核心参数

不能直接把PEM公钥或普通Base64公钥传入JWK的n字段,需要先解析PEM公钥,提取模(n)和指数(e),再转成Base64URL无填充格式:

// 假设你的公钥是PEM格式字符串
$pem_public_key = "-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----";

// 解析PEM公钥
$pkey = openssl_pkey_get_public($pem_public_key);
$key_details = openssl_pkey_get_details($pkey);
if (!$key_details || !isset($key_details['rsa'])) {
    throw new Exception("无效的RSA公钥");
}

// 对n和e进行Base64URL无填充编码
use ParagonIE\ConstantTime\Base64UrlSafe;
$jwk_n = Base64UrlSafe::encodeUnpadded($key_details['rsa']['n']);
$jwk_e = Base64UrlSafe::encodeUnpadded($key_details['rsa']['e']);

2. 修正JWK实例创建

使用编码后的参数创建JWK,注意JWK必须包含e字段(公钥指数):

$jwk = new JWK([
    'kty' => 'RSA',
    'n' => $jwk_n,
    'e' => $jwk_e,
    'kid' => $kid
]);

3. 修复代码中的其他疏漏

  • 删除重复创建的$keyEncryptionAlgorithmManager实例;
  • 补充初始化$contentEncryptionAlgorithmManager(原代码未定义):
$contentEncryptionAlgorithmManager = new AlgorithmManager([
    new A256GCM(),
]);

最终修正后的核心代码片段

$jws_payload = "sdvsd.....";
$kid = "AH1111";
$aad = "你的AAD内容";

// 初始化算法管理器
$keyEncryptionAlgorithmManager = new AlgorithmManager([
    new RSAOAEP256(),
]);
$contentEncryptionAlgorithmManager = new AlgorithmManager([
    new A256GCM(),
]);
$compressionMethodManager = new CompressionMethodManager([]);

$jweBuilder = new JWEBuilder(
    $keyEncryptionAlgorithmManager,
    $contentEncryptionAlgorithmManager,
    $compressionMethodManager
);

// 处理公钥并创建JWK
$pem_public_key = "-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----";
$pkey = openssl_pkey_get_public($pem_public_key);
$key_details = openssl_pkey_get_details($pkey);
use ParagonIE\ConstantTime\Base64UrlSafe;
$jwk_n = Base64UrlSafe::encodeUnpadded($key_details['rsa']['n']);
$jwk_e = Base64UrlSafe::encodeUnpadded($key_details['rsa']['e']);

$jwk = new JWK([
    'kty' => 'RSA',
    'n' => $jwk_n,
    'e' => $jwk_e,
    'kid' => $kid
]);

// 构建JWE
$jwe = $jweBuilder
    ->create()
    ->withPayload($jws_payload)
    ->withSharedProtectedHeader([
        'alg' => 'RSA-OAEP-256',
        'enc' => 'A256GCM',
        'kid' => $kid
    ])
    ->addRecipient($jwk)
    ->withAAD($aad)
    ->build();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 03:20:08