使用window.crypto.subtle解密RSA密文时出现未捕获错误求助
问题原因
解密失败的核心是在线工具使用的加密填充方式与Web Crypto API的配置不匹配:
- 你的JS代码采用
RSA-OAEP填充算法(搭配SHA-256哈希) - 你使用的在线工具默认大概率用的是
RSA-PKCS#1 v1.5填充,两种填充标准不兼容,导致解密失败 - 你用代码内公钥加密的密文能正常解密,也验证了填充方式不匹配的问题
解决方案
优先采用方案1,操作简单且符合Web Crypto的规范:
方案1:调整在线工具参数匹配代码
- 在在线工具的加密配置中,将填充方式改为 OAEP Padding
- 将哈希算法设置为 SHA-256
- 重新加密
Hello World生成新密文,替换代码中的ciphertext变量,即可正常解密
方案2:手动实现PKCS#1 v1.5解密(仅当无法修改在线工具时使用)
Web Crypto API不直接支持RSA-PKCS#1 v1.5的解密,需要手动实现RSA运算和填充去除逻辑(注意:该方式需解析PKCS#8私钥提取核心参数,逻辑较繁琐):
// Base64转BigInt function base64ToBigInt(base64) { const binary = atob(base64); const hex = Array.from(binary).map(c => c.charCodeAt(0).toString(16).padStart(2, '0')).join(''); return BigInt('0x' + hex); } // BigInt转Uint8Array function bigIntToUint8Array(bigInt) { let hex = bigInt.toString(16); if (hex.length % 2 !== 0) hex = '0' + hex; const bytes = []; for (let i = 0; i < hex.length; i += 2) { bytes.push(parseInt(hex.substr(i, 2), 16)); } return new Uint8Array(bytes); } // 手动解析PKCS#8私钥提取模数n和私钥指数d(示例简化,实际需处理ASN.1编码) // 注意:Web Crypto API不允许导出私钥敏感参数,此方法仅用于演示 async function extractPrivateKeyParams(privateKeyBase64) { // 此处需补充ASN.1解析逻辑,提取私钥的n和d值 // 实际实现可参考ASN.1 DER编码规范 return { n: BigInt('...'), d: BigInt('...') }; } // RSA-PKCS#1 v1.5解密 async function decryptPKCS1(privateKeyBase64, ciphertextBase64) { const { n, d } = await extractPrivateKeyParams(privateKeyBase64); const ciphertext = base64ToBigInt(ciphertextBase64); // 执行RSA解密运算 const decryptedBigInt = ciphertext ** d % n; const decryptedBytes = bigIntToUint8Array(decryptedBigInt); // 去除PKCS#1 v1.5填充:找到第一个0x00后的有效内容 const zeroIndex = decryptedBytes.indexOf(0x00); if (zeroIndex === -1) throw new Error('无效的PKCS#1填充'); return decryptedBytes.slice(zeroIndex + 1); }
额外验证
你的fromBase64函数转换Uint8Array的方式完全正确,编码环节不存在问题,无需修改。
内容的提问来源于stack exchange,提问作者mkc210593
相关产品推荐
相关产品推荐

