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

如何修改PHP JWE代码适配A256CBC-HS512与RSA-OAEP-256算法

PHP JWE 实现:切换至 A256CBC-HS512/RSA-OAEP-256

上周对接某服务商新API,要求在HTTPS请求头中使用JWE进行身份认证。此前无JWE开发经验,查阅资料后用PHP实现,经测试调试得到以下可用代码。现需将加密算法enc改为A256CBC-HS512,密钥加密算法alg改为RSA-OAEP-256,以下是修改方案:


原可用代码

require_once("auth/key.php");
include 'vendor/autoload.php';
use phpseclib3\Crypt\PublicKeyLoader;  

function jwe (){
    global $payloadAuth; //此处填入所需的payload

    /**************************************************/
    /********************HEADER************************/
    /**************************************************/
    // 对header json进行base64编码
    $arr = array('enc' => 'A256GCM', 'alg' => 'RSA-OAEP');
    $arr2 = json_encode($arr);
    $encoded_header=base64url_encode($arr2);     

    /**************************************************/
    /********************JWE KEY***********************/
    /**************************************************/
    $CEK=openssl_random_pseudo_bytes(32);    
    $encoded_EncCEK = base64url_encode(rsaEncryptionOaepSha256($publicKey, $CEK));

    /**************************************************/
    /********************VECTOR************************/
    /**************************************************/
    $iv = openssl_random_pseudo_bytes(12);
    $encoded_iv = base64url_encode($iv);
    
    /**************************************************/
    /********************CYPHERTEXT********************/
    $cipher = "aes-256-gcm";
    $option=1;    
    $aad=$encoded_header;

    $ciphertext=openssl_encrypt($payloadAuth, $cipher, $CEK, $option, $iv, $tag, $aad);
    $encoded_ciphertext=base64url_encode($ciphertext);
    
    /**************************************************/
    /********************TAG***************************/
    /**************************************************/
    $encoded_tag=base64url_encode($tag);

    /**************************************************/
    /********************FIN***************************/
    /**************************************************/

    return $encoded_header . '.' . $encoded_EncCEK . '.' . $encoded_iv . '.' . $encoded_ciphertext . '.' . $encoded_tag;

} 
  
function base64url_encode($data) {
    return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
  }

function rsaEncryptionOaepSha256($publicKey, $plaintext) {
    global $publicKey;       

    $rsa = PublicKeyLoader::load($publicKey)->withHash('sha1')->withMGFHash('sha1');
    return $rsa->encrypt($plaintext);
}    

?>

修改方案与完整代码

要切换到A256CBC-HS512和RSA-OAEP-256,需要修改以下核心点:

关键修改说明

  • Header更新:修改alg为RSA-OAEP-256,enc为A256CBC-HS512
  • CEK生成:A256CBC-HS512需要64字节的复合密钥(前32字节用于AES-256-CBC加密,后32字节用于HMAC-SHA512签名)
  • RSA加密配置:RSA-OAEP-256要求使用SHA-256哈希及MGF1-SHA256掩码生成函数
  • 加密逻辑调整:改用AES-256-CBC加密,手动处理PKCS#7填充,IV长度改为16字节,同时基于AAD、IV、密文生成HMAC标签

修改后的完整代码

require_once("auth/key.php");
include 'vendor/autoload.php';
use phpseclib3\Crypt\PublicKeyLoader;  

function jwe (){
    global $payloadAuth; // 填入所需的payload
    global $publicKey;   // 从auth/key.php引入的公钥

    /**************************************************/
    /********************HEADER************************/
    /**************************************************/
    // 更新为目标算法标识
    $arr = array('enc' => 'A256CBC-HS512', 'alg' => 'RSA-OAEP-256');
    $arr2 = json_encode($arr);
    $encoded_header=base64url_encode($arr2);     

    /**************************************************/
    /********************JWE KEY***********************/
    /**************************************************/
    // A256CBC-HS512需要64字节复合密钥:前32字节AES密钥,后32字节HMAC密钥
    $CEK=openssl_random_pseudo_bytes(64);    
    $encoded_EncCEK = base64url_encode(rsaEncryptionOaep256($publicKey, $CEK));

    /**************************************************/
    /********************VECTOR************************/
    /**************************************************/
    // AES-CBC要求IV长度等于块大小(16字节)
    $iv = openssl_random_pseudo_bytes(16);
    $encoded_iv = base64url_encode($iv);
    
    /**************************************************/
    /********************CYPHERTEXT********************/
    $cipher = "aes-256-cbc";
    // 配置为返回原始数据,手动处理填充
    $option = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING;    
    $aad = $encoded_header;

    // 对payload添加PKCS#7填充,确保长度为16字节的倍数
    $blockSize = openssl_cipher_iv_length($cipher);
    $padding = $blockSize - (strlen($payloadAuth) % $blockSize);
    $payloadPadded = $payloadAuth . str_repeat(chr($padding), $padding);

    // 使用CEK前32字节进行AES-256-CBC加密
    $ciphertext = openssl_encrypt($payloadPadded, $cipher, substr($CEK, 0, 32), $option, $iv);
    $encoded_ciphertext = base64url_encode($ciphertext);
    
    /**************************************************/
    /********************TAG***************************/
    /**************************************************/
    // 生成HMAC-SHA512标签:AAD、IV、密文的base64url编码拼接后计算
    $hmacInput = $aad . '.' . $encoded_iv . '.' . $encoded_ciphertext;
    // 使用CEK后32字节作为HMAC密钥
    $tag = hash_hmac('sha512', $hmacInput, substr($CEK, 32), true);
    $encoded_tag = base64url_encode($tag);

    /**************************************************/
    /********************FIN***************************/
    /**************************************************/

    return $encoded_header . '.' . $encoded_EncCEK . '.' . $encoded_iv . '.' . $encoded_ciphertext . '.' . $encoded_tag;

} 
  
function base64url_encode($data) {
    return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
  }

function rsaEncryptionOaep256($publicKey, $plaintext) {
    // RSA-OAEP-256对应SHA-256哈希和MGF1-SHA256掩码函数
    $rsa = PublicKeyLoader::load($publicKey)->withHash('sha256')->withMGFHash('sha256');
    return $rsa->encrypt($plaintext);
}    

?>

额外说明

  • PKCS#7填充:AES-CBC要求明文长度必须是块大小(16字节)的整数倍,因此手动实现了标准的PKCS#7填充逻辑
  • HMAC计算逻辑:A256CBC-HS512的标签由AAD、IV、密文的base64url编码拼接后,用CEK的后32字节计算HMAC-SHA512得到
  • CEK拆分规则:64字节的CEK严格分为两部分,分别用于加密和签名,完全符合JWE对该算法的规范

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 23:10:31