React项目中用jose库将RSA公钥转CryptoKey加密JWE存localStorage
解决RSA公钥转CryptoKey并实现JWE加密的问题
问题分析
你直接将PEM格式的公钥字符串传给encrypt方法,但jose库要求必须传入CryptoKey类型的密钥,因此触发类型错误。核心解决点是把PEM格式的RSA公钥转换成符合要求的CryptoKey对象。
解决方案
jose库内置了importSPKI方法,专门用于导入SPKI格式的RSA公钥(即你当前使用的-----BEGIN PUBLIC KEY-----包裹的格式),按以下步骤修改代码即可:
1. 引入jose的必要方法
确保已安装jose库,在代码中导入所需方法:
import { CompactEncrypt, importSPKI } from 'jose'
2. 实现公钥转CryptoKey
替换原代码中const cryptoKey = publicKey这一行,用importSPKI处理公钥:
const cryptoKey = await importSPKI(publicKey, 'RSA-OAEP-256')
- 第一个参数是PEM格式的公钥字符串
- 第二个参数指定加密算法,必须和后续加密时
setProtectedHeader里的alg保持一致(此处为RSA-OAEP-256)
3. 修正存储逻辑
你当前存储的是未加密的serializedSession,应替换为加密后的JWE字符串:
localStorage.setItem('deluxeSession', jwe)
4. 恢复错误捕获
启用注释掉的try/catch块,方便调试异常:
完整修改后的代码
import { CompactEncrypt, importSPKI } from 'jose' export const createDeluxeSession = async (session) => { try { // 序列化session并base64编码 const serializedSession = btoa(JSON.stringify(session)) console.log('createDeluxeSession---1', serializedSession) // 从API获取的RSA公钥(示例) const publicKey = `-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCP7pn0NTKW3u8d6kNZ10x20F+E Ir8PQ0jkyZSi7ze6c+w+THhGHkwuLEBfuEjwdo9zcXpweiRc2mQgLsVFnqSMm978 z1dRxZPYT3z3ynpK9mw9jNfndH3ogpJlYlXV64IcWRoCP0Bz+uOx0lXHItuiPHQn b8oBtw2LTVevN8KO0wIDAQAB -----END PUBLIC KEY-----` // 将PEM公钥转换为CryptoKey const cryptoKey = await importSPKI(publicKey, 'RSA-OAEP-256') // 加密生成JWE const jwe = await new CompactEncrypt( new TextEncoder().encode(serializedSession) ) .setProtectedHeader({ alg: 'RSA-OAEP-256', enc: 'A256GCM' }) .encrypt(cryptoKey) // 存储加密后的JWE localStorage.setItem('deluxeSession', jwe) } catch (e) { console.error('加密或存储失败:', e) } }
关键说明
importSPKI会自动处理PEM格式的头部和尾部,无需手动去除字符串标识。- 算法参数必须全程一致:导入密钥、加密头部的算法要匹配,否则会导致加密失败。
- 存储JWE到localStorage是安全的,因为JWE是加密后的内容,只有持有对应私钥的服务端才能解密还原原始session数据。
内容的提问来源于stack exchange,提问作者Carey
相关产品推荐
相关产品推荐

