From 023c2f640b0a8c5cd8018adf718b32680d680aab Mon Sep 17 00:00:00 2001 From: Jerko Steiner Date: Tue, 7 Jan 2020 18:08:56 +0100 Subject: [PATCH] Make private key extractable too. Main reason: https://bugzilla.mozilla.org/show_bug.cgi?id=1133698 Unfortunately, because of this bug Firefox cannot save non-exportable keys to IndexedDB. As a workaround, we call exportKey before saving and store JsonWebKey instead. We use importKey again while reading the key from the database. Extra reason for this change - during testing isomorphic-webcrypto complains about keys read from IndexedDB. While being less secure, this could also help users export their keys if they want to migrate their identities to another computer... --- src/client/crypto/index.test.ts | 8 ++++---- src/client/crypto/index.ts | 15 +++++---------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/client/crypto/index.test.ts b/src/client/crypto/index.test.ts index 610164d..5b026b7 100644 --- a/src/client/crypto/index.test.ts +++ b/src/client/crypto/index.test.ts @@ -1,4 +1,4 @@ -import { exportPublicKey, encrypt, decrypt, generateECDHKeyPair, deriveECDHKey, hasWebCryptoAPI, importPublicKey } from './index' +import { exportKey, encrypt, decrypt, generateECDHKeyPair, deriveECDHKey, hasWebCryptoAPI, importKey } from './index' describe('crypto', () => { @@ -27,11 +27,11 @@ describe('crypto', () => { }) }) - describe('exportPublicKey and importPublicKey', () => { + describe('exportKey and importKey', () => { it('exports public key', async () => { - const value = await exportPublicKey(keypair1.publicKey) + const value = await exportKey(keypair1.publicKey) console.log(value) - const key = await importPublicKey(value) + const key = await importKey(value) expect(key).toBeTruthy() expect(key).toEqual(keypair1.publicKey) }) diff --git a/src/client/crypto/index.ts b/src/client/crypto/index.ts index d87e99f..de9bcc8 100644 --- a/src/client/crypto/index.ts +++ b/src/client/crypto/index.ts @@ -13,7 +13,7 @@ export async function generateECDHKeyPair() { name: 'ECDH', namedCurve: 'P-256', }, - /* extractable */ false, + /* extractable */ true, ['deriveKey'], ) return key @@ -34,7 +34,7 @@ export async function deriveECDHKey(params: { name: 'AES-CTR', length: 256, }, - /* extractable */ false, + /* extractable */ true, ['encrypt', 'decrypt'], ) @@ -68,13 +68,8 @@ export async function decrypt(key: CryptoKey, data: string): Promise { return ab2str(decrypted) } -export async function exportPublicKey(key: CryptoKey) { +export async function exportKey(key: CryptoKey) { return await window.crypto.subtle.exportKey('jwk', key) - // const pkcs8 = await window.crypto.subtle.exportKey('pkcs8', key) - // const base64 = window.btoa(ab2str(pkcs8, Uint8Array)) - // const value = - // `-----BEGIN PUBLIC KEY-----\n${base64}\n-----END PUBLIC KEY-----` - // return value } function ab2str( @@ -85,7 +80,7 @@ function ab2str( null, new ArrayType(buf) as unknown as number[]) } -export async function importPublicKey(keyData: JsonWebKey) { +export async function importKey(keyData: JsonWebKey) { if (keyData.kty !== 'EC' || keyData.crv !== 'P-256') { throw new Error(`Unsupported key type: ${keyData.kty}, crv: ${keyData.crv}`) } @@ -97,7 +92,7 @@ export async function importPublicKey(keyData: JsonWebKey) { namedCurve: keyData.crv, }, /* extractable */ true, - [], + keyData.key_ops || [], ) return key }