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

PHP用JS生成的RSA-OAEP公钥加密后JS解密失败求助

RSA-OAEP解密失败:DOMException排查与修复

问题根源

你遇到的解密错误,核心原因是加密和解密两端的RSA-OAEP哈希算法不匹配:

  • 前端生成密钥及解密时,明确指定了SHA-256作为哈希算法
  • PHP端使用openssl_public_encrypt搭配OPENSSL_PKCS1_OAEP_PADDING时,默认采用SHA-1哈希算法

这种不一致会导致解密过程验证失败,抛出DOMException。

解决方案

1. 修正PHP端加密逻辑,指定SHA-256哈希

PHP的openssl_public_encrypt无法直接指定OAEP的哈希算法,需要改用更灵活的openssl_pkey_encrypt函数,并通过配置项明确指定SHA-256:

$pbkey = "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA52N7Q/kQxNrVaGCLOlD0IgrSROPWt029GTqRKMdFQSFMAZPD0V5TZPLDylbtmvLhDajKugYpjHfDGD44cXiYy1jZeVCiFas09gAGBKmgFY4Ixsl/+opF2hlPjvnugn2aPKpSLgoX9f1DpXBDEpuHJ+AVSTxL+C3uE1PgQPYy2ots15Km4W2AnV+p81UfLdafStQ40gbkUOHvzFkwizazm4q1Scjh2Fc+RR6FXy+ySp54yuRqHuMS8QTdXVMBChqs5lNwuu6V+BEryXMFbDx2fW9qCWShVTc2lq4KzvXRE/65L0sttMA7oP/WzsVW3zeNFgla8g4dxvCftwrwGviMay9N+vsa902TClR2xj7/JSzQXSW0E4Am4ZB4bCJh04f08M0nMBY6yWWV3+QpBG+9CeXHfwPrdqT2OR5N7Jq+xslCfbf4D/9itjDdvaBZP5Z6BYiOF3QzeTk+V2rfAWZdOUcuWAdP3gczQKdJM11bTxOKNCiYmBu773aDXCNFpaHDatqUgnNrVp7guOP1owOdd7qxWsplzylQUcWuhuWczs7/X/UPwT7vBTkg0pb8Ujrr+KyNmsxsJTefg1z4xcbxtgqgoDRxXu92V9iVl1HVssAM8IZdc+naEIyOjt+3OPZkaCwts38U7nYUDd96ovHjMs0hFlTxqsltwyfPFAVygLUCAwEAAQ==\n-----END PUBLIC KEY-----";

// 解析公钥
$publicKey = openssl_pkey_get_public($pbkey);
if (!$publicKey) {
    die("公钥解析失败: " . openssl_error_string());
}

// 配置OAEP参数,指定SHA-256哈希
$encryptOptions = [
    'oaep' => [
        'digest' => 'sha256'
    ]
];

$plaintext = "secret";
$encrypted = '';

// 执行加密
if (!openssl_pkey_encrypt($plaintext, $encrypted, $publicKey, $encryptOptions)) {
    die("加密失败: " . openssl_error_string());
}

echo base64_encode($encrypted);
// 释放资源
openssl_pkey_free($publicKey);

2. 确保前端辅助函数正确性

你的代码中用到了ab2str和str2ab但未给出实现,这两个函数的错误会导致编码/解码异常,正确实现如下:

// ArrayBuffer转字符串
function ab2str(buffer) {
    return new TextDecoder().decode(buffer);
}

// 字符串转ArrayBuffer
function str2ab(str) {
    return new TextEncoder().encode(str);
}

3. 优化前端解密函数(可选)

解密后返回的是ArrayBuffer,需要转换为字符串才能得到原始明文,修改Decrypt函数:

async function Decrypt(message) {
    const keys = GetKeys();
    let pemPvKey = keys[0];

    const pvkey = await window.crypto.subtle.importKey(
        "pkcs8",
        str2ab(window.atob(FormatPrivateKey(pemPvKey))),
        {
            name: "RSA-OAEP",
            hash: {name: "SHA-256"}
        },
        false,
        ["decrypt"]
    );

    const decryptedBuffer = await window.crypto.subtle.decrypt(
        {
            name: "RSA-OAEP"
        },
        pvkey,
        str2ab(window.atob(message))
    );

    // 转换为明文字符串
    return ab2str(decryptedBuffer);
}

关键注意事项

  • RSA-OAEP的哈希算法、密钥长度必须在加密/解密两端完全一致
  • 避免使用openssl_public_encrypt的默认OAEP配置,始终显式指定哈希算法
  • 确保密钥的导出、存储、导入过程中没有出现编码或格式错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 09:25:40