如何在Web端解密携带自定义标签的RSA-OAEP加密消息
RSA-OAEP带自定义标签WebCrypto解密实现
现有代码核心问题
你当前的实现存在两个致命错误直接导致解密失败:
- 使用
crypto.subtle.generateKey生成了全新的RSA密钥对,完全没有导入Go代码中使用的目标私钥,不同密钥加密的内容不可能解密成功 - 缺失PEM格式私钥的解析导入逻辑,WebCrypto无法直接识别PEM格式的密钥文本
完整可运行实现
// 工具函数:base64转ArrayBuffer function base64ToArrayBuffer(base64Text) { base64Text = base64Text.replace(/[\n\r\t\s]/g, ""); const binary = atob(base64Text); const bytes = new Uint8Array(binary.length); for (let i = 0; i < binary.length; i++) { bytes[i] = binary.charCodeAt(i); } return bytes.buffer; } // 工具函数:字符串转Uint8Array function stringToUint8Array(str) { return new TextEncoder().encode(str); } // 工具函数:ArrayBuffer转字符串 function arrayBufferToString(buf) { return new TextDecoder().decode(buf); } // 导入RSA私钥 async function importPrivateKey(pemText) { // 去除PEM头尾标识和空白字符 const pemContent = pemText .replace("-----BEGIN RSA PRIVATE KEY-----", "") .replace("-----END RSA PRIVATE KEY-----", "") .replace(/[\n\r\t\s]/g, ""); const keyDer = base64ToArrayBuffer(pemContent); return crypto.subtle.importKey( "pkcs8", keyDer, { name: "RSA-OAEP", hash: "SHA-256" }, false, ["decrypt"] ); } // 解密方法,参数和Go端decryptOAEP完全对应 async function decryptOAEP(cipherTextBase64, label, hashName, privateKeyPem) { const privateKey = await importPrivateKey(privateKeyPem); const cipherBuf = base64ToArrayBuffer(cipherTextBase64); const labelBuf = stringToUint8Array(label); const plainBuf = await crypto.subtle.decrypt( { name: "RSA-OAEP", label: labelBuf }, privateKey, cipherBuf ); return arrayBufferToString(plainBuf); } // 调用示例 const cipherTextOAEP = "你的Go代码中对应的密文字符串"; const privateKeyPem = "你的Go代码中对应的私钥字符串"; decryptOAEP(cipherTextOAEP, "MyCustomLabel", "sha256", privateKeyPem) .then(res => console.log("解密结果:", res)) .catch(err => console.error("解密失败:", err));
常见问题排查
如果仍然解密失败,按以下顺序排查:
- 私钥格式问题:如果导入私钥阶段报错,说明你的PEM是PKCS#1格式,需要先转换成PKCS#8格式,可使用openssl命令
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in 原私钥路径 -out 导出路径转换 - 哈希算法不匹配:加密和解密使用的哈希算法必须完全一致,Go端用sha256对应WebCrypto的
SHA-256 - 标签内容不一致:标签不要有多余空格、换行,统一使用UTF-8编码
- 密文损坏:确认密文没有被截断、修改,base64解码后的长度要和私钥模数长度匹配,比如2048位密钥对应256字节密文
内容的提问来源于stack exchange,提问作者k4rli
相关产品推荐
相关产品推荐

