RSA公钥能否存.env?多行存储及importKey报错排查
问题解答
1. RSA公钥能否存储到.env文件及多行存储方法
完全可以将RSA公钥存储到.env文件中,针对多行格式的公钥,有两种兼容性较强的存储方案:
方案一:转义换行符
在.env文件里,给公钥每一行末尾添加反斜杠,将多行内容转为单行转义字符串:PUBLIC_KEY='-----BEGIN PUBLIC KEY-----\ MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRixgfjY2/zdJ18OnwSiVzmBKCh5GYzfvX2jYlLC3DHfGstnbL0fxnHxizg68ZG4oQPfmKJQGF2hbQ+vQ+zaYfC33mKZGF+ln+NlxQk+D742pj5GYenIPjKHshV3P1GHubAw9nW71WAd0yyjL7BHV3nWbewR+AAce8V6YLt54mVwIDAQAB\ -----END PUBLIC KEY-----'方案二:转为单行格式
直接删除公钥里所有换行符,把整个PEM格式公钥写成一行:PUBLIC_KEY='-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRixgfjY2/zdJ18OnwSiVzmBKCh5GYzfvX2jYlLC3DHfGstnbL0fxnHxizg68ZG4oQPfmKJQGF2hbQ+vQ+zaYfC33mKZGF+ln+NlxQk+D742pj5GYenIPjKHshV3P1GHubAw9nW71WAd0yyjL7BHV3nWbewR+AAce8V6YLt54mVwIDAQAB-----END PUBLIC KEY-----'
注意:不同.env解析工具对字符串处理有细微差异,上述两种是通用适配方案。
2. 解决crypto.subtle.importKey报错问题
你的代码存在3个核心问题,结合公钥存储的正确方式,修正如下:
问题1:换行符处理错误
formatToDER函数中,你用replace(/\\r\\n/g, '')移除换行,但实际从.env读取的公钥换行符是\n或\r,而非转义后的\\r\\n,需改为匹配所有换行符:
const pemContents = pemCertificate.replace(pemHeader, '').replace(pemFooter, '').replace(/[\r\n]/g, '')
问题2:importKey参数错误
- 公钥的
modulusLength和publicExponent已经包含在SPKI格式里,手动指定会和公钥实际信息不匹配,导致报错,直接删除这两个参数。 - RSA公钥只能用于加密,不能指定
decrypt权限,不符合公钥使用逻辑。
修正后的importKey代码:
crypto.subtle.importKey( "spki", pubKeySelfOwnedDER, { name: algorithm, hash: 'SHA-256', }, true, ['encrypt'] // 仅保留加密权限 )
问题3:异步操作未等待
自定义公钥分支中,你用.then()赋值key,但后续encrypt操作不会等待这个异步任务完成,导致key为undefined,需改用await等待:
修正后的自定义公钥分支:
if (selfOwnedPubKey) { const pubKeySelfOwnedPEM = selfOwnedPubKey const pubKeySelfOwnedDER = formatToDER(pubKeySelfOwnedPEM, 'PUBLIC KEY') try { key = await crypto.subtle.importKey( "spki", pubKeySelfOwnedDER, { name: algorithm, hash: 'SHA-256', }, true, ['encrypt'] ) } catch(error) { console.group(error) console.log('code: ', error.code) console.log('message: ', error.message) console.log('name: ', error.name) console.groupEnd() throw error // 抛出错误让外层catch处理 } console.group('---SELF_OWNED_KEY---') console.log('pubKeySelfOwnedPEM:\n', pubKeySelfOwnedPEM); console.log(`%c${pubKeySelfOwnedPEM}`,'color:green;font-weight:bold') console.log('pubKeySelfOwnedDER: ', pubKeySelfOwnedDER) console.groupEnd(); }
完整修正后的关键代码片段
function formatToDER(pemCertificate, type) { const pemHeader=`-----BEGIN ${type || ""}-----` const pemFooter=`-----END ${type || ""}-----` const pemContents=pemCertificate.replace(pemHeader, '').replace(pemFooter, '').replace(/[\r\n]/g, '') const contentDecoded = atob(pemContents) const derArray = new Uint8Array(contentDecoded.length) for (let i = 0; i < contentDecoded.length; i++) derArray[i] = contentDecoded.charCodeAt(i) return derArray } async function encrypt(algorithm, data, selfOwnedPubKey) { let key if (selfOwnedPubKey) { const pubKeySelfOwnedPEM = selfOwnedPubKey const pubKeySelfOwnedDER = formatToDER(pubKeySelfOwnedPEM, 'PUBLIC KEY') try { key = await crypto.subtle.importKey( "spki", pubKeySelfOwnedDER, { name: algorithm, hash: 'SHA-256', }, true, ['encrypt'] ) } catch(error){ console.group(error) console.log('code: ', error.code) console.log('message: ', error.message) console.log('name: ', error.name) console.groupEnd() throw error } console.group('---SELF_OWNED_KEY---') console.log('pubKeySelfOwnedPEM:\n', pubKeySelfOwnedPEM); console.log(`%c${pubKeySelfOwnedPEM}`,'color:green;font-weight:bold') console.log('pubKeySelfOwnedDER: ', pubKeySelfOwnedDER) console.groupEnd(); } else { let keyPair = await crypto.subtle.generateKey( { name: algorithm, modulusLength: 1024, publicExponent: new Uint8Array([1,0,1]), hash: 'SHA-256', }, true, ['encrypt', 'decrypt'] ); let pubKeyGeneratedExportedDER = new Uint8Array(await crypto.subtle.exportKey('spki',keyPair.publicKey)) const pubKeyGeneratedPEM = formatToPEM(pubKeyGeneratedExportedDER, 'PUBLIC KEY') key = keyPair.publicKey; console.group('---GENERATED_KEY---') console.log('pubKeyGeneratedOriginal:',keyPair.publicKey); console.log('pubKeyGeneratedExportedDER:',pubKeyGeneratedExportedDER); console.log('pubKeyGeneratedPEM:\n'); console.log(`%c${pubKeyGeneratedPEM}`,'color:green;font-weight:bold'); console.groupEnd() } const cipher = await crypto.subtle.encrypt( { name: algorithm }, key, data ); return cipher };
验证步骤
- 按前面的方案将公钥存入.env文件
- 确保代码正确读取
process.env.PUBLIC_KEY(根据运行环境调整) - 运行修正后的代码,即可正常执行加密操作
内容的提问来源于stack exchange,提问作者Fateh Ali Sulthoni
相关产品推荐
相关产品推荐

