browser-crypto-secure-store
Version:
Securely store Crypto Keys in the browser
140 lines (138 loc) • 3.95 kB
JavaScript
// src/IndexedDbCryptoKeyPairStore.ts
var IndexedDbCryptoKeyPairStore = class {
constructor(dbName, storeName) {
this._dbName = "secure";
this._storeName = "store";
if (dbName) {
this._dbName = dbName;
}
if (storeName) {
this._storeName = storeName;
}
}
async set(key, value) {
const store = await this.createStore(this._dbName, this._storeName);
await store("readwrite", (str) => {
str.put(value, key);
return this.promisifyRequest(str.transaction);
});
}
async get(key) {
const store = await this.createStore(this._dbName, this._storeName);
return await store("readonly", (str) => {
return this.promisifyRequest(str.get(key));
});
}
async remove(key) {
const store = await this.createStore(this._dbName, this._storeName);
await store("readwrite", (str) => {
return this.promisifyRequest(str.delete(key));
});
}
async getAllKeys() {
const store = await this.createStore(this._dbName, this._storeName);
return await store("readonly", (str) => {
return this.promisifyRequest(str.getAllKeys());
});
}
promisifyRequest(request) {
return new Promise((resolve, reject) => {
request.oncomplete = request.onsuccess = () => resolve(request.result);
request.onabort = request.onerror = () => reject(request.error);
});
}
async createStore(dbName, storeName) {
const request = indexedDB.open(dbName);
request.onupgradeneeded = () => request.result.createObjectStore(storeName);
const db = await this.promisifyRequest(request);
return async (txMode, callback) => {
const tx = db.transaction(storeName, txMode);
const store = tx.objectStore(storeName);
return await callback(store);
};
}
};
// src/SecureStore.ts
var SecureStore = class {
/**
* Creates a new instance of SecureStore using indexedDb as the storage mechanism.
*
* @param args - An object containing optional arguments.
*/
constructor({
cryptoKeyPairStore,
dbName,
storeName
} = {}) {
this.cryptoKeyPairStore = cryptoKeyPairStore || new IndexedDbCryptoKeyPairStore(dbName, storeName);
}
/**
* Generates a new CryptoKeyPair and stores it in the SecureStore.
*
* @param args - A SeyKeyOptions object containing the key name and optional arguments.
* @returns - A CryptoKeyPair or CryptoKey.
*/
async setKey({
key,
options = {
algorithm: {
name: "ECDSA",
namedCurve: "P-256"
},
extractable: false,
keyUsages: ["sign", "verify"]
},
ttl
}) {
const { algorithm, extractable, keyUsages } = options;
const keyPair = await window.crypto.subtle.generateKey(
algorithm,
extractable,
keyUsages
);
try {
await this.cryptoKeyPairStore.set(key, keyPair);
if (ttl) {
await this.setTtl(key, ttl);
}
return keyPair;
} catch (err) {
throw new Error(`Error storing key pair: ${err.message}`);
}
}
/**
* Retrieves a CryptoKeyPair from the SecureStore.
* @param key - the name of the key to retrieve.
*/
async getKey(key) {
const keyPair = await this.cryptoKeyPairStore.get(key);
if (!keyPair) {
throw new Error(`Key not found: ${key}`);
}
return keyPair;
}
/**
* Removes a CryptoKeyPair from the SecureStore.
* @param key - the name of the key to remove.
*/
async removeKey(key) {
await this.cryptoKeyPairStore.remove(key);
}
/**
* Retrieves all the names of all keys stored in the SecureStore.
* @returns An array of key names.
*/
async getAllKeys() {
return await this.cryptoKeyPairStore.getAllKeys();
}
async setTtl(key, ttl) {
window.setTimeout(async () => {
await this.removeKey(key);
console.log("Removed key: ", key);
}, ttl);
}
};
export {
SecureStore
};
//# sourceMappingURL=browser-crypto-secure-store.js.map