在 JavaScript 中,公私钥的保存位置取决于生成方式和用途。
1. 使用 Web Crypto API 生成密钥
const keyPair = await crypto.subtle.generateKey(
{
name: "RSA-PSS",
modulusLength: 2048,
publicExponent: new Uint8Array([1, 0, 1]),
hash: "SHA-256"
},
false, // 私钥不可导出
["sign", "verify"]
);
默认情况
privateKey:只存在于当前页面内存中的CryptoKey对象里publicKey:也存在内存中,可导出后发送给服务器页面刷新或关闭后:内存中的密钥会丢失
const { privateKey, publicKey } = keyPair;
2. 持久化保存到 IndexedDB
CryptoKey 可以保存到 IndexedDB:
const dbRequest = indexedDB.open("keyDB", 1);
dbRequest.onupgradeneeded = () => {
dbRequest.result.createObjectStore("keys");
};
dbRequest.onsuccess = () => {
const db = dbRequest.result;
const tx = db.transaction("keys", "readwrite");
tx.objectStore("keys").put(keyPair.privateKey, "privateKey");
tx.objectStore("keys").put(keyPair.publicKey, "publicKey");
};
一般建议:
私钥保存为不可导出密钥:
extractable: false私钥可保存到 IndexedDB,但只能被同源页面使用
不要把私钥直接转成字符串放进
localStorage不要把私钥放进 Cookie、URL 或发送到服务器
3. 导出为 JWK 或 PEM
如果生成密钥时允许导出:
const jwk = await crypto.subtle.exportKey("jwk", privateKey);
此时私钥可能被保存到:
localStoragesessionStorageIndexedDB
浏览器扩展存储
服务器端
但不建议把私钥保存到 localStorage,因为一旦发生 XSS,脚本可能直接读取它。
4. 如果使用 WebAuthn / Passkey
WebAuthn 的私钥通常保存在:
手机或电脑的安全硬件
操作系统凭据管理器
浏览器关联的 Passkey 存储
外部安全密钥
JavaScript 无法直接读取 WebAuthn 私钥。JS 只能调用:
navigator.credentials.create()
navigator.credentials.get()
服务器保存的是公钥和凭据 ID。
总结
场景 | 私钥保存位置 |
|---|---|
JS 变量 | 当前页面内存 |
Web Crypto + IndexedDB | 浏览器 IndexedDB |
WebAuthn / Passkey | 系统或硬件安全存储,JS 不可读取 |
导出为 JWK/PEM | 由应用自行保存,风险较高 |
公钥 | 通常发送并保存到服务器 |
如果是浏览器端登录认证,优先考虑 WebAuthn/Passkey,不要在前端自行保存可导出的私钥。