diff --git a/src/lib/modules/crypto.ts b/src/lib/modules/crypto.ts index b188ca8..0d82085 100644 --- a/src/lib/modules/crypto.ts +++ b/src/lib/modules/crypto.ts @@ -1,3 +1,4 @@ +export type RSAKeyPurpose = "encryption" | "signature"; export type RSAKeyType = "public" | "private"; export const encodeToBase64 = (data: ArrayBuffer) => { @@ -8,72 +9,40 @@ export const decodeFromBase64 = (data: string) => { return Uint8Array.from(atob(data), (c) => c.charCodeAt(0)).buffer; }; -export const generateRSAEncKeyPair = async () => { - const keyPair = await window.crypto.subtle.generateKey( +export const generateRSAKeyPair = async (purpose: RSAKeyPurpose) => { + return await window.crypto.subtle.generateKey( { - name: "RSA-OAEP", + name: purpose === "encryption" ? "RSA-OAEP" : "RSA-PSS", modulusLength: 4096, publicExponent: new Uint8Array([1, 0, 1]), hash: "SHA-256", } satisfies RsaHashedKeyGenParams, true, - ["encrypt", "decrypt"], + purpose === "encryption" ? ["encrypt", "decrypt"] : ["sign", "verify"], ); - return keyPair; }; -export const generateRSASigKeyPair = async () => { - const keyPair = await window.crypto.subtle.generateKey( - { - name: "RSA-PSS", - modulusLength: 4096, - publicExponent: new Uint8Array([1, 0, 1]), - hash: "SHA-256", - } satisfies RsaHashedKeyGenParams, - true, - ["sign", "verify"], - ); - return keyPair; -}; - -export const makeRSAEncKeyNonextractable = async (key: CryptoKey, type: RSAKeyType) => { - const { format, key: exportedKey } = await exportRSAKey(key, type); +export const makeRSAKeyNonextractable = async (key: CryptoKey) => { + const { format, key: exportedKey } = await exportRSAKey(key); return await window.crypto.subtle.importKey( format, exportedKey, - { - name: "RSA-OAEP", - hash: "SHA-256", - } satisfies RsaHashedImportParams, + key.algorithm, false, - [type === "public" ? "encrypt" : "decrypt"], + key.usages, ); }; -export const makeRSASigKeyNonextractable = async (key: CryptoKey, type: RSAKeyType) => { - const { format, key: exportedKey } = await exportRSAKey(key, type); - return await window.crypto.subtle.importKey( - format, - exportedKey, - { - name: "RSA-PSS", - hash: "SHA-256", - } satisfies RsaHashedImportParams, - false, - [type === "public" ? "verify" : "sign"], - ); -}; - -const exportRSAKey = async (key: CryptoKey, type: RSAKeyType) => { - const format = type === "public" ? ("spki" as const) : ("pkcs8" as const); +export const exportRSAKey = async (key: CryptoKey) => { + const format = key.type === "public" ? ("spki" as const) : ("pkcs8" as const); return { format, key: await window.crypto.subtle.exportKey(format, key), }; }; -export const exportRSAKeyToBase64 = async (key: CryptoKey, type: RSAKeyType) => { - return encodeToBase64((await exportRSAKey(key, type)).key); +export const exportRSAKeyToBase64 = async (key: CryptoKey) => { + return encodeToBase64((await exportRSAKey(key)).key); }; export const encryptRSAPlaintext = async (plaintext: ArrayBuffer, publicKey: CryptoKey) => { @@ -122,12 +91,9 @@ export const makeAESKeyNonextractable = async (key: CryptoKey) => { return await window.crypto.subtle.importKey( "raw", await exportAESKey(key), - { - name: "AES-GCM", - length: 256, - } satisfies AesKeyAlgorithm, + key.algorithm, false, - ["encrypt", "decrypt"], + key.usages, ); }; diff --git a/src/routes/(fullscreen)/auth/login/service.ts b/src/routes/(fullscreen)/auth/login/service.ts index 091ebc8..77c4620 100644 --- a/src/routes/(fullscreen)/auth/login/service.ts +++ b/src/routes/(fullscreen)/auth/login/service.ts @@ -20,8 +20,8 @@ export const requestTokenUpgrade = async ({ signKey, verifyKey, }: ClientKeys) => { - const encryptKeyBase64 = await exportRSAKeyToBase64(encryptKey, "public"); - const verifyKeyBase64 = await exportRSAKeyToBase64(verifyKey, "public"); + const encryptKeyBase64 = await exportRSAKeyToBase64(encryptKey); + const verifyKeyBase64 = await exportRSAKeyToBase64(verifyKey); if (await requestTokenUpgradeInternal(encryptKeyBase64, decryptKey, verifyKeyBase64, signKey)) { return true; } diff --git a/src/routes/(fullscreen)/key/generate/service.ts b/src/routes/(fullscreen)/key/generate/service.ts index d7c4ce9..4e16e63 100644 --- a/src/routes/(fullscreen)/key/generate/service.ts +++ b/src/routes/(fullscreen)/key/generate/service.ts @@ -1,8 +1,6 @@ import { - generateRSAEncKeyPair, - generateRSASigKeyPair, - makeRSAEncKeyNonextractable, - makeRSASigKeyNonextractable, + generateRSAKeyPair, + makeRSAKeyNonextractable, exportRSAKeyToBase64, generateAESKey, makeAESKeyNonextractable, @@ -11,21 +9,21 @@ import { import { clientKeyStore, mekStore } from "$lib/stores"; export const generateClientKeys = async () => { - const encKeyPair = await generateRSAEncKeyPair(); - const sigKeyPair = await generateRSASigKeyPair(); + const encKeyPair = await generateRSAKeyPair("encryption"); + const sigKeyPair = await generateRSAKeyPair("signature"); clientKeyStore.set({ encryptKey: encKeyPair.publicKey, - decryptKey: await makeRSAEncKeyNonextractable(encKeyPair.privateKey, "private"), - signKey: await makeRSASigKeyNonextractable(sigKeyPair.privateKey, "private"), + decryptKey: await makeRSAKeyNonextractable(encKeyPair.privateKey), + signKey: await makeRSAKeyNonextractable(sigKeyPair.privateKey), verifyKey: sigKeyPair.publicKey, }); return { - encryptKeyBase64: await exportRSAKeyToBase64(encKeyPair.publicKey, "public"), - decryptKeyBase64: await exportRSAKeyToBase64(encKeyPair.privateKey, "private"), - signKeyBase64: await exportRSAKeyToBase64(sigKeyPair.privateKey, "private"), - verifyKeyBase64: await exportRSAKeyToBase64(sigKeyPair.publicKey, "public"), + encryptKeyBase64: await exportRSAKeyToBase64(encKeyPair.publicKey), + decryptKeyBase64: await exportRSAKeyToBase64(encKeyPair.privateKey), + signKeyBase64: await exportRSAKeyToBase64(sigKeyPair.privateKey), + verifyKeyBase64: await exportRSAKeyToBase64(sigKeyPair.publicKey), }; };