我需要在 IndexedDB 数据库中存储一个 ECDH P-384 密钥对。这是生成密钥对的代码:
async function generateKeys() {
// generate client's ECDH asymmetric keypair (privateKey, publicKey)
return await window.crypto.subtle.generateKey(
{
name: "ECDH",
namedCurve: "P-384",
},
true,
["deriveKey", "deriveBits"]
);
}
这是打开数据库的代码,如果它不存在则创建“非对称”对象存储,然后生成并存储密钥对:
var request = window.indexedDB.open("main", 3);
request.onerror = function (event) {
console.error("Database error: " + event.target.errorCode);
};
request.onupgradeneeded = function (event) {
db = event.target.result;
if (!db.objectStoreNames.contains('asymmetric')) {
console.log('creating OS');
var objectStore = db.createObjectStore("asymmetric", { keyPath: "owner" });
objectStore.transaction.oncomplete = function (event) {
intialKeySetup = true;
};
}
};
request.onsuccess = function (event) {
db = event.target.result;
if (intialKeySetup) { // first time running
setupNewKeys();
} else {
console.log('loading keys...');
loadKeys();
}
};
function setupNewKeys() {
// Generates ECDH keypair, then saves them to the 'asymmetric' object store with key '#this#'
return generateKeys().then((kp) => {
clientKeys = kp;
var asymOS = db.transaction("asymmetric", "readwrite").objectStore("asymmetric");
// Error occurs here:
asymOS.add({ owner: '#this#', keys: kp }); // kp = { publicKey: CryptoKey object, privateKey: CryptoKey object }
console.log('Done. Wrote keys to DB: ');
console.log(kp);
startComm();
});
}
function loadKeys() {
// Loads the client's keypair into memory from the 'asymmetric' object store at key '#this#'
console.log('Attempting to access client keys...');
var transaction = db.transaction(["asymmetric"]);
var objectStore = transaction.objectStore("asymmetric");
var request = objectStore.get("#this#");
request.onerror = function (event) {
console.error(event.target.errorCode);
};
request.onsuccess = function (event) {
if (!request.result) {
setupNewKeys();
} else {
console.log(request.result);
clientKeys = request.result.keys;
console.log('Retrieved Keys');
console.log('Starting Comm...');
startComm(); // connect to WebSocket server
}
};
}
此代码在 Chrome、Chromium Edge、macOS Safari、iOS Safari 和 Android 上的 Chrome 上运行良好,但在 Firefox 上不起作用。它不允许它将两个 CryptoKey 对象存储在对象存储中,并生成错误:
Uncaught (in promise) DOMException: The object could not be cloned.
当我尝试存储字符串而不是 CryptoKey 对象时,错误消失了,我可以看到存储在“存储" 开发者工具的标签。为什么不让我将 CryptoKey 存储在 Firefox 的对象存储中?除了导出密钥之外,还有其他解决方法吗?