使用Web Crypto API导入PEM公钥时出现未捕获Promise错误
解决PEM公钥导入时的Promise未捕获错误
以下是几个核心问题及修复方案:
1. PEM格式不兼容
你当前使用的-----BEGIN RSA PUBLIC KEY-----是PKCS#1格式,但Web Crypto API的spki导入格式要求的是SubjectPublicKeyInfo(PKCS#8衍生格式),也就是以-----BEGIN PUBLIC KEY-----开头的公钥。
如果无法更换公钥格式,可以通过代码将PKCS#1格式转换为SPKI格式:
function pkcs1ToSpki(pkcs1PublicKey) { const pemHeader = '-----BEGIN RSA PUBLIC KEY-----'; const pemFooter = '-----END RSA PUBLIC KEY-----'; // 去除头尾标签及所有空白字符 const pemContents = pkcs1PublicKey.replace(pemHeader, '').replace(pemFooter, '').replace(/\s/g, ''); const der = Uint8Array.from(atob(pemContents), c => c.charCodeAt(0)); // 构建SPKI标准DER结构 const spkiHeader = new Uint8Array([ 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00 ]); const spki = new Uint8Array(spkiHeader.length + der.length); spki.set(spkiHeader); spki.set(der, spkiHeader.length); return spki; }
在导入函数中替换为转换后的SPKI:
async function importPEM(pemKey) { try { const spkiBuffer = pkcs1ToSpki(pemKey); const importAlgorithm = { name: 'RSA-OAEP', hash: { name: 'SHA-256' }, }; return await window.crypto.subtle.importKey( 'spki', spkiBuffer, importAlgorithm, true, ['encrypt'], ); } catch (err) { console.error('导入公钥失败:', err); throw err; // 可选:重新抛出错误让上层逻辑处理 } }
2. PEM内容处理不严谨
原代码直接通过substring截取头尾,未考虑PEM中可能存在的换行、空格或缩进,会导致atob解码失败。修改后的处理方式应先清除所有非Base64字符:
const pemContents = pemKey .replace(pemHeader, '') .replace(pemFooter, '') .replace(/[\n\r\s]/g, ''); // 移除所有换行、空格
3. 未捕获错误
原代码没有错误捕获逻辑,导致错误直接抛出为未捕获的Promise异常。必须在async函数中添加try-catch块,才能查看具体错误信息(比如格式错误、不支持的算法等)。
内容的提问来源于stack exchange,提问作者Vinno
相关产品推荐
相关产品推荐

