diff --git a/web/database/utils/worker-crypto-utils.js b/web/database/utils/worker-crypto-utils.js --- a/web/database/utils/worker-crypto-utils.js +++ b/web/database/utils/worker-crypto-utils.js @@ -1,6 +1,10 @@ // @flow const ENCRYPTION_ALGORITHM = 'AES-GCM'; +const ENCRYPTION_KEY_USAGES: $ReadOnlyArray = [ + 'encrypt', + 'decrypt', +]; type EncryptedData = { +iv: BufferSource, @@ -18,7 +22,7 @@ length: 256, }, extractable, - ['encrypt', 'decrypt'], + ENCRYPTION_KEY_USAGES, ); } @@ -61,4 +65,28 @@ return new Uint8Array(decrypted); } -export { generateDatabaseCryptoKey, encryptDatabaseFile, decryptDatabaseFile }; +async function exportKeyToJWK( + key: CryptoKey, +): Promise { + return await crypto.subtle.exportKey('jwk', key); +} + +async function importJWKKey( + jwkKey: SubtleCrypto$JsonWebKey, +): Promise { + return await crypto.subtle.importKey( + 'jwk', + jwkKey, + ENCRYPTION_ALGORITHM, + true, + ENCRYPTION_KEY_USAGES, + ); +} + +export { + generateDatabaseCryptoKey, + encryptDatabaseFile, + decryptDatabaseFile, + exportKeyToJWK, + importJWKKey, +}; diff --git a/web/database/utils/worker-crypto-utlis.test.js b/web/database/utils/worker-crypto-utlis.test.js --- a/web/database/utils/worker-crypto-utlis.test.js +++ b/web/database/utils/worker-crypto-utlis.test.js @@ -5,7 +5,9 @@ import { decryptDatabaseFile, encryptDatabaseFile, + exportKeyToJWK, generateDatabaseCryptoKey, + importJWKKey, } from './worker-crypto-utils.js'; import { getSQLiteDBVersion } from '../queries/db-queries.js'; @@ -84,4 +86,22 @@ const newDatabase = new SQL.Database(decrypted); expect(getSQLiteDBVersion(newDatabase)).toBe(TEST_DB_VERSION); }); + + it('should export and import key in JWK format', async () => { + // creating new key + const key = await generateDatabaseCryptoKey({ extractable: true }); + const dbContent: Uint8Array = database.export(); + const encryptedData = await encryptDatabaseFile(dbContent, key); + + // exporting and importing key + const exportedKey = await exportKeyToJWK(key); + const importedKey = await importJWKKey(exportedKey); + + // decrypt using re-created on import key + const decrypted = await decryptDatabaseFile(encryptedData, importedKey); + + const SQL = await initSqlJs(); + const newDatabase = new SQL.Database(decrypted); + expect(getSQLiteDBVersion(newDatabase)).toBe(TEST_DB_VERSION); + }); });