diff --git a/src/lib/hooks/callApi.ts b/src/lib/hooks/callApi.ts index 7189735..c36b59a 100644 --- a/src/lib/hooks/callApi.ts +++ b/src/lib/hooks/callApi.ts @@ -1,4 +1,4 @@ -import { signRequest } from "$lib/modules/crypto"; +import { signRequestBody } from "$lib/modules/crypto"; export const refreshToken = async () => { return await fetch("/api/auth/refreshToken", { method: "POST" }); @@ -36,6 +36,6 @@ export const callSignedPostApi = async (input: RequestInfo, payload: T, signK headers: { "Content-Type": "application/json", }, - body: await signRequest(payload, signKey), + body: await signRequestBody(payload, signKey), }); }; diff --git a/src/lib/hooks/gotoStateful.ts b/src/lib/hooks/gotoStateful.ts index 2d168a7..fffc95f 100644 --- a/src/lib/hooks/gotoStateful.ts +++ b/src/lib/hooks/gotoStateful.ts @@ -10,7 +10,7 @@ interface KeyExportState { signKeyBase64: string; verifyKeyBase64: string; - masterKeyWrapped: ArrayBuffer; + masterKeyWrapped: string; } const useAutoNull = (value: T | null) => { diff --git a/src/lib/modules/crypto.ts b/src/lib/modules/crypto.ts deleted file mode 100644 index 563ae49..0000000 --- a/src/lib/modules/crypto.ts +++ /dev/null @@ -1,227 +0,0 @@ -export type RSAKeyPurpose = "encryption" | "signature"; -export type RSAKeyType = "public" | "private"; - -export const encodeToBase64 = (data: ArrayBuffer) => { - return btoa(String.fromCharCode(...new Uint8Array(data))); -}; - -export const decodeFromBase64 = (data: string) => { - return Uint8Array.from(atob(data), (c) => c.charCodeAt(0)).buffer; -}; - -export const generateRSAKeyPair = async (purpose: RSAKeyPurpose) => { - return await window.crypto.subtle.generateKey( - { - name: purpose === "encryption" ? "RSA-OAEP" : "RSA-PSS", - modulusLength: 4096, - publicExponent: new Uint8Array([1, 0, 1]), - hash: "SHA-256", - } satisfies RsaHashedKeyGenParams, - true, - purpose === "encryption" ? ["encrypt", "decrypt", "wrapKey", "unwrapKey"] : ["sign", "verify"], - ); -}; - -export const makeRSAKeyNonextractable = async (key: CryptoKey) => { - const { format, key: exportedKey } = await exportRSAKey(key); - return await window.crypto.subtle.importKey( - format, - exportedKey, - key.algorithm, - false, - key.usages, - ); -}; - -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) => { - return encodeToBase64((await exportRSAKey(key)).key); -}; - -export const encryptRSAPlaintext = async (plaintext: BufferSource, publicKey: CryptoKey) => { - return await window.crypto.subtle.encrypt( - { - name: "RSA-OAEP", - } satisfies RsaOaepParams, - publicKey, - plaintext, - ); -}; - -export const decryptRSACiphertext = async (ciphertext: BufferSource, privateKey: CryptoKey) => { - return await window.crypto.subtle.decrypt( - { - name: "RSA-OAEP", - } satisfies RsaOaepParams, - privateKey, - ciphertext, - ); -}; - -export const signRSAMessage = async (message: BufferSource, privateKey: CryptoKey) => { - return await window.crypto.subtle.sign( - { - name: "RSA-PSS", - saltLength: 32, - } satisfies RsaPssParams, - privateKey, - message, - ); -}; - -export const verifyRSASignature = async ( - message: BufferSource, - signature: BufferSource, - publicKey: CryptoKey, -) => { - return await window.crypto.subtle.verify( - { - name: "RSA-PSS", - saltLength: 32, - } satisfies RsaPssParams, - publicKey, - signature, - message, - ); -}; - -export const generateAESMasterKey = async () => { - return await window.crypto.subtle.generateKey( - { - name: "AES-KW", - length: 256, - } satisfies AesKeyGenParams, - true, - ["wrapKey", "unwrapKey"], - ); -}; - -export const generateAESDataKey = async () => { - return await window.crypto.subtle.generateKey( - { - name: "AES-GCM", - length: 256, - } satisfies AesKeyGenParams, - true, - ["encrypt", "decrypt"], - ); -}; - -export const makeAESKeyNonextractable = async (key: CryptoKey) => { - return await window.crypto.subtle.importKey( - "raw", - await exportAESKey(key), - key.algorithm, - false, - key.usages, - ); -}; - -export const exportAESKey = async (key: CryptoKey) => { - return await window.crypto.subtle.exportKey("raw", key); -}; - -export const encryptAESPlaintext = async (plaintext: BufferSource, aesKey: CryptoKey) => { - const iv = window.crypto.getRandomValues(new Uint8Array(12)); - const ciphertext = await window.crypto.subtle.encrypt( - { - name: "AES-GCM", - iv, - } satisfies AesGcmParams, - aesKey, - plaintext, - ); - return { ciphertext, iv }; -}; - -export const decryptAESCiphertext = async ( - ciphertext: BufferSource, - iv: BufferSource, - aesKey: CryptoKey, -) => { - return await window.crypto.subtle.decrypt( - { - name: "AES-GCM", - iv, - } satisfies AesGcmParams, - aesKey, - ciphertext, - ); -}; - -export const wrapAESMasterKey = async (aesKey: CryptoKey, rsaPublicKey: CryptoKey) => { - return await window.crypto.subtle.wrapKey("raw", aesKey, rsaPublicKey, { - name: "RSA-OAEP", - } satisfies RsaOaepParams); -}; - -export const wrapAESDataKey = async (aesKey: CryptoKey, aesWrapKey: CryptoKey) => { - return await window.crypto.subtle.wrapKey("raw", aesKey, aesWrapKey, "AES-KW"); -}; - -export const unwrapAESMasterKey = async (wrappedKey: BufferSource, rsaPrivateKey: CryptoKey) => { - return await window.crypto.subtle.unwrapKey( - "raw", - wrappedKey, - rsaPrivateKey, - { - name: "RSA-OAEP", - } satisfies RsaOaepParams, - "AES-KW", - true, - ["wrapKey", "unwrapKey"], - ); -}; - -export const unwrapAESDataKey = async (wrappedKey: BufferSource, aesMasterKey: CryptoKey) => { - return await window.crypto.subtle.unwrapKey( - "raw", - wrappedKey, - aesMasterKey, - "AES-KW", - "AES-GCM", - false, - ["encrypt", "decrypt"], - ); -}; - -export const digestSHA256 = async (data: BufferSource) => { - return await window.crypto.subtle.digest("SHA-256", data); -}; - -export const signRequest = async (data: T, privateKey: CryptoKey) => { - const dataBuffer = new TextEncoder().encode(JSON.stringify(data)); - const signature = await signRSAMessage(dataBuffer, privateKey); - return JSON.stringify({ - data, - signature: encodeToBase64(signature), - }); -}; - -export const signMasterKeyWrapped = async ( - version: number, - masterKeyWrapped: ArrayBuffer, - privateKey: CryptoKey, -) => { - const data = JSON.stringify({ version, key: encodeToBase64(masterKeyWrapped) }); - const dataBuffer = new TextEncoder().encode(data); - return encodeToBase64(await signRSAMessage(dataBuffer, privateKey)); -}; - -export const verifyMasterKeyWrappedSig = async ( - version: number, - masterKeyWrappedBase64: string, - masterKeyWrappedSig: string, - publicKey: CryptoKey, -) => { - const data = JSON.stringify({ version, key: masterKeyWrappedBase64 }); - const dataBuffer = new TextEncoder().encode(data); - return await verifyRSASignature(dataBuffer, decodeFromBase64(masterKeyWrappedSig), publicKey); -}; diff --git a/src/lib/modules/crypto/aes.ts b/src/lib/modules/crypto/aes.ts new file mode 100644 index 0000000..e1e917a --- /dev/null +++ b/src/lib/modules/crypto/aes.ts @@ -0,0 +1,83 @@ +import { encodeToBase64, decodeFromBase64 } from "./util"; + +export const generateMasterKey = async () => { + return { + masterKey: await window.crypto.subtle.generateKey( + { + name: "AES-KW", + length: 256, + } satisfies AesKeyGenParams, + true, + ["wrapKey", "unwrapKey"], + ), + }; +}; + +export const generateDataKey = async () => { + return { + dataKey: await window.crypto.subtle.generateKey( + { + name: "AES-GCM", + length: 256, + } satisfies AesKeyGenParams, + true, + ["encrypt", "decrypt"], + ), + }; +}; + +const exportAESKey = async (key: CryptoKey) => { + return await window.crypto.subtle.exportKey("raw", key); +}; + +export const makeAESKeyNonextractable = async (key: CryptoKey) => { + return await window.crypto.subtle.importKey( + "raw", + await exportAESKey(key), + key.algorithm, + false, + key.usages, + ); +}; + +export const wrapDataKey = async (dataKey: CryptoKey, masterKey: CryptoKey) => { + return encodeToBase64(await window.crypto.subtle.wrapKey("raw", dataKey, masterKey, "AES-KW")); +}; + +export const unwrapDataKey = async (dataKeyWrapped: string, masterKey: CryptoKey) => { + return { + dataKey: await window.crypto.subtle.unwrapKey( + "raw", + decodeFromBase64(dataKeyWrapped), + masterKey, + "AES-KW", + "AES-GCM", + false, // Non-extractable + ["encrypt", "decrypt"], + ), + }; +}; + +export const encryptData = async (data: BufferSource, dataKey: CryptoKey) => { + const iv = window.crypto.getRandomValues(new Uint8Array(12)); + const ciphertext = await window.crypto.subtle.encrypt( + { + name: "AES-GCM", + iv, + } satisfies AesGcmParams, + dataKey, + data, + ); + return { ciphertext, iv: encodeToBase64(iv.buffer) }; +}; + +export const decryptData = async (ciphertext: BufferSource, iv: string, dataKey: CryptoKey) => { + return await window.crypto.subtle.decrypt( + { + name: "AES-GCM", + iv: decodeFromBase64(iv), + } satisfies AesGcmParams, + dataKey, + ciphertext, + ); +}; diff --git a/src/lib/modules/crypto/index.ts b/src/lib/modules/crypto/index.ts new file mode 100644 index 0000000..e6972ba --- /dev/null +++ b/src/lib/modules/crypto/index.ts @@ -0,0 +1,4 @@ +export * from "./aes"; +export * from "./rsa"; +export * from "./sha"; +export * from "./util"; diff --git a/src/lib/modules/crypto/rsa.ts b/src/lib/modules/crypto/rsa.ts new file mode 100644 index 0000000..a82abee --- /dev/null +++ b/src/lib/modules/crypto/rsa.ts @@ -0,0 +1,159 @@ +import { encodeToBase64, decodeFromBase64 } from "./util"; + +export const generateEncryptionKeyPair = async () => { + const keyPair = await window.crypto.subtle.generateKey( + { + name: "RSA-OAEP", + modulusLength: 4096, + publicExponent: new Uint8Array([1, 0, 1]), + hash: "SHA-256", + } satisfies RsaHashedKeyGenParams, + true, + ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + ); + return { + encryptKey: keyPair.publicKey, + decryptKey: keyPair.privateKey, + }; +}; + +export const generateSigningKeyPair = 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 { + signKey: keyPair.privateKey, + verifyKey: keyPair.publicKey, + }; +}; + +export const exportRSAKey = async (key: CryptoKey) => { + const format = key.type === "public" ? ("spki" as const) : ("pkcs8" as const); + return { + key: await window.crypto.subtle.exportKey(format, key), + format, + }; +}; + +export const exportRSAKeyToBase64 = async (key: CryptoKey) => { + return encodeToBase64((await exportRSAKey(key)).key); +}; + +export const makeRSAKeyNonextractable = async (key: CryptoKey) => { + const { key: exportedKey, format } = await exportRSAKey(key); + return await window.crypto.subtle.importKey( + format, + exportedKey, + key.algorithm, + false, + key.usages, + ); +}; + +export const decryptChallenge = async (challenge: string, decryptKey: CryptoKey) => { + return await window.crypto.subtle.decrypt( + { + name: "RSA-OAEP", + } satisfies RsaOaepParams, + decryptKey, + decodeFromBase64(challenge), + ); +}; + +export const wrapMasterKey = async (masterKey: CryptoKey, encryptKey: CryptoKey) => { + return encodeToBase64( + await window.crypto.subtle.wrapKey("raw", masterKey, encryptKey, { + name: "RSA-OAEP", + } satisfies RsaOaepParams), + ); +}; + +export const unwrapMasterKey = async ( + masterKeyWrapped: string, + decryptKey: CryptoKey, + extractable = false, +) => { + return { + masterKey: await window.crypto.subtle.unwrapKey( + "raw", + decodeFromBase64(masterKeyWrapped), + decryptKey, + { + name: "RSA-OAEP", + } satisfies RsaOaepParams, + "AES-KW", + extractable, + ["wrapKey", "unwrapKey"], + ), + }; +}; + +export const signMessage = async (message: BufferSource, signKey: CryptoKey) => { + return await window.crypto.subtle.sign( + { + name: "RSA-PSS", + saltLength: 32, // SHA-256 + } satisfies RsaPssParams, + signKey, + message, + ); +}; + +export const verifySignature = async ( + message: BufferSource, + signature: BufferSource, + verifyKey: CryptoKey, +) => { + return await window.crypto.subtle.verify( + { + name: "RSA-PSS", + saltLength: 32, // SHA-256 + } satisfies RsaPssParams, + verifyKey, + signature, + message, + ); +}; + +export const signRequestBody = async (requestBody: T, signKey: CryptoKey) => { + const dataBuffer = new TextEncoder().encode(JSON.stringify(requestBody)); + const signature = await signMessage(dataBuffer, signKey); + return JSON.stringify({ + data: requestBody, + signature: encodeToBase64(signature), + }); +}; + +export const signMasterKeyWrapped = async ( + masterKeyVersion: number, + masterKeyWrapped: string, + signKey: CryptoKey, +) => { + const serialized = JSON.stringify({ + version: masterKeyVersion, + key: masterKeyWrapped, + }); + const serializedBuffer = new TextEncoder().encode(serialized); + return encodeToBase64(await signMessage(serializedBuffer, signKey)); +}; + +export const verifyMasterKeyWrapped = async ( + masterKeyVersion: number, + masterKeyWrapped: string, + masterKeyWrappedSig: string, + verifyKey: CryptoKey, +) => { + const serialized = JSON.stringify({ + version: masterKeyVersion, + key: masterKeyWrapped, + }); + const serializedBuffer = new TextEncoder().encode(serialized); + return await verifySignature(serializedBuffer, decodeFromBase64(masterKeyWrappedSig), verifyKey); +}; diff --git a/src/lib/modules/crypto/sha.ts b/src/lib/modules/crypto/sha.ts new file mode 100644 index 0000000..e79f706 --- /dev/null +++ b/src/lib/modules/crypto/sha.ts @@ -0,0 +1,3 @@ +export const digestMessage = async (message: BufferSource) => { + return await window.crypto.subtle.digest("SHA-256", message); +}; diff --git a/src/lib/modules/crypto/util.ts b/src/lib/modules/crypto/util.ts new file mode 100644 index 0000000..9aeeb9d --- /dev/null +++ b/src/lib/modules/crypto/util.ts @@ -0,0 +1,19 @@ +export const encodeToBase64 = (data: ArrayBuffer) => { + return btoa(String.fromCharCode(...new Uint8Array(data))); +}; + +export const decodeFromBase64 = (data: string) => { + return Uint8Array.from(atob(data), (c) => c.charCodeAt(0)).buffer; +}; + +export const concatenateBuffers = (...buffers: ArrayBuffer[]) => { + const arrays = buffers.map((buffer) => new Uint8Array(buffer)); + const totalLength = arrays.reduce((acc, array) => acc + array.length, 0); + const result = new Uint8Array(totalLength); + + arrays.reduce((offset, array) => { + result.set(array, offset); + return offset + array.length; + }, 0); + return result; +}; diff --git a/src/lib/services/auth.ts b/src/lib/services/auth.ts index 7a0936b..d796d28 100644 --- a/src/lib/services/auth.ts +++ b/src/lib/services/auth.ts @@ -1,9 +1,4 @@ -import { - encodeToBase64, - decodeFromBase64, - decryptRSACiphertext, - signRSAMessage, -} from "$lib/modules/crypto"; +import { encodeToBase64, decryptChallenge, signMessage } from "$lib/modules/crypto"; import type { TokenUpgradeRequest, TokenUpgradeResponse, @@ -29,8 +24,8 @@ export const requestTokenUpgrade = async ( if (!res.ok) return false; const { challenge }: TokenUpgradeResponse = await res.json(); - const answer = await decryptRSACiphertext(decodeFromBase64(challenge), decryptKey); - const sigAnswer = await signRSAMessage(answer, signKey); + const answer = await decryptChallenge(challenge, decryptKey); + const sigAnswer = await signMessage(answer, signKey); res = await fetch("/api/auth/upgradeToken/verify", { method: "POST", diff --git a/src/lib/services/key.ts b/src/lib/services/key.ts index 0d4b7a1..a430eb1 100644 --- a/src/lib/services/key.ts +++ b/src/lib/services/key.ts @@ -2,12 +2,10 @@ import { callGetApi, callPostApi } from "$lib/hooks"; import { storeMasterKeys } from "$lib/indexedDB"; import { encodeToBase64, - decodeFromBase64, - decryptRSACiphertext, - signRSAMessage, - makeAESKeyNonextractable, - unwrapAESMasterKey, - verifyMasterKeyWrappedSig, + decryptChallenge, + signMessage, + unwrapMasterKey, + verifyMasterKeyWrapped, } from "$lib/modules/crypto"; import type { ClientRegisterRequest, @@ -30,8 +28,8 @@ export const requestClientRegistration = async ( if (!res.ok) return false; const { challenge }: ClientRegisterResponse = await res.json(); - const answer = await decryptRSACiphertext(decodeFromBase64(challenge), decryptKey); - const sigAnswer = await signRSAMessage(answer, signKey); + const answer = await decryptChallenge(challenge, decryptKey); + const sigAnswer = await signMessage(answer, signKey); res = await callPostApi("/api/client/register/verify", { answer: encodeToBase64(answer), @@ -47,19 +45,20 @@ export const requestMasterKeyDownload = async (decryptKey: CryptoKey, verfiyKey: const { meks: masterKeysWrapped }: MasterKeyListResponse = await res.json(); const masterKeys = await Promise.all( masterKeysWrapped.map( - async ({ version, state, mek: masterKeyWrapped, mekSig: masterKeyWrappedSig }) => ({ - version, - state, - masterKey: await makeAESKeyNonextractable( - await unwrapAESMasterKey(decodeFromBase64(masterKeyWrapped), decryptKey), - ), - isValid: await verifyMasterKeyWrappedSig( + async ({ version, state, mek: masterKeyWrapped, mekSig: masterKeyWrappedSig }) => { + const { masterKey } = await unwrapMasterKey(masterKeyWrapped, decryptKey); + return { version, - masterKeyWrapped, - masterKeyWrappedSig, - verfiyKey, - ), - }), + state, + masterKey, + isValid: await verifyMasterKeyWrapped( + version, + masterKeyWrapped, + masterKeyWrappedSig, + verfiyKey, + ), + }; + }, ), ); if (!masterKeys.every(({ isValid }) => isValid)) return false; diff --git a/src/routes/(fullscreen)/client/pending/+page.svelte b/src/routes/(fullscreen)/client/pending/+page.svelte index ae5696d..e009529 100644 --- a/src/routes/(fullscreen)/client/pending/+page.svelte +++ b/src/routes/(fullscreen)/client/pending/+page.svelte @@ -9,7 +9,9 @@ let { data } = $props(); const fingerprint = $derived( - $clientKeyStore ? generateEncryptKeyFingerprint($clientKeyStore.encryptKey) : undefined, + $clientKeyStore + ? generateEncryptKeyFingerprint($clientKeyStore.encryptKey, $clientKeyStore.verifyKey) + : undefined, ); $effect(() => { diff --git a/src/routes/(fullscreen)/client/pending/service.ts b/src/routes/(fullscreen)/client/pending/service.ts index 5a1a06d..df634d9 100644 --- a/src/routes/(fullscreen)/client/pending/service.ts +++ b/src/routes/(fullscreen)/client/pending/service.ts @@ -1,10 +1,14 @@ -import { exportRSAKey, digestSHA256 } from "$lib/modules/crypto"; +import { concatenateBuffers, exportRSAKey, digestMessage } from "$lib/modules/crypto"; export { requestMasterKeyDownload } from "$lib/services/key"; -export const generateEncryptKeyFingerprint = async (encryptKey: CryptoKey) => { - const { key } = await exportRSAKey(encryptKey); - const digest = await digestSHA256(key); +export const generateEncryptKeyFingerprint = async ( + encryptKey: CryptoKey, + verifyKey: CryptoKey, +) => { + const { key: encryptKeyBuffer } = await exportRSAKey(encryptKey); + const { key: verifyKeyBuffer } = await exportRSAKey(verifyKey); + const digest = await digestMessage(concatenateBuffers(encryptKeyBuffer, verifyKeyBuffer)); return Array.from(new Uint8Array(digest)) .map((byte) => byte.toString(16).padStart(2, "0")) .join("") diff --git a/src/routes/(fullscreen)/key/export/service.ts b/src/routes/(fullscreen)/key/export/service.ts index fd1fadd..415eb77 100644 --- a/src/routes/(fullscreen)/key/export/service.ts +++ b/src/routes/(fullscreen)/key/export/service.ts @@ -1,6 +1,6 @@ import { callSignedPostApi } from "$lib/hooks"; import { storeClientKey } from "$lib/indexedDB"; -import { encodeToBase64, signMasterKeyWrapped } from "$lib/modules/crypto"; +import { signMasterKeyWrapped } from "$lib/modules/crypto"; import type { InitialMasterKeyRegisterRequest } from "$lib/server/schemas"; import type { ClientKeys } from "$lib/stores"; @@ -43,13 +43,13 @@ export const storeClientKeys = async (clientKeys: ClientKeys) => { }; export const requestInitialMasterKeyRegistration = async ( - masterKeyWrapped: ArrayBuffer, + masterKeyWrapped: string, signKey: CryptoKey, ) => { const res = await callSignedPostApi( "/api/mek/register/initial", { - mek: encodeToBase64(masterKeyWrapped), + mek: masterKeyWrapped, mekSig: await signMasterKeyWrapped(1, masterKeyWrapped, signKey), }, signKey, diff --git a/src/routes/(fullscreen)/key/generate/service.ts b/src/routes/(fullscreen)/key/generate/service.ts index b8a4a9f..b63da21 100644 --- a/src/routes/(fullscreen)/key/generate/service.ts +++ b/src/routes/(fullscreen)/key/generate/service.ts @@ -1,35 +1,36 @@ import { - generateRSAKeyPair, - makeRSAKeyNonextractable, + generateEncryptionKeyPair, + generateSigningKeyPair, exportRSAKeyToBase64, - generateAESMasterKey, - wrapAESMasterKey, + makeRSAKeyNonextractable, + generateMasterKey, + wrapMasterKey, } from "$lib/modules/crypto"; import { clientKeyStore } from "$lib/stores"; export const generateClientKeys = async () => { - const encKeyPair = await generateRSAKeyPair("encryption"); - const sigKeyPair = await generateRSAKeyPair("signature"); + const { encryptKey, decryptKey } = await generateEncryptionKeyPair(); + const { signKey, verifyKey } = await generateSigningKeyPair(); clientKeyStore.set({ - encryptKey: encKeyPair.publicKey, - decryptKey: await makeRSAKeyNonextractable(encKeyPair.privateKey), - signKey: await makeRSAKeyNonextractable(sigKeyPair.privateKey), - verifyKey: sigKeyPair.publicKey, + encryptKey, + decryptKey: await makeRSAKeyNonextractable(decryptKey), + signKey: await makeRSAKeyNonextractable(signKey), + verifyKey, }); return { - encryptKey: encKeyPair.publicKey, - encryptKeyBase64: await exportRSAKeyToBase64(encKeyPair.publicKey), - decryptKeyBase64: await exportRSAKeyToBase64(encKeyPair.privateKey), - signKeyBase64: await exportRSAKeyToBase64(sigKeyPair.privateKey), - verifyKeyBase64: await exportRSAKeyToBase64(sigKeyPair.publicKey), + encryptKey, + encryptKeyBase64: await exportRSAKeyToBase64(encryptKey), + decryptKeyBase64: await exportRSAKeyToBase64(decryptKey), + signKeyBase64: await exportRSAKeyToBase64(signKey), + verifyKeyBase64: await exportRSAKeyToBase64(verifyKey), }; }; export const generateInitialMasterKey = async (encryptKey: CryptoKey) => { - const masterKey = await generateAESMasterKey(); + const { masterKey } = await generateMasterKey(); return { - masterKeyWrapped: await wrapAESMasterKey(masterKey, encryptKey), + masterKeyWrapped: await wrapMasterKey(masterKey, encryptKey), }; }; diff --git a/src/routes/(main)/directory/[[id]]/service.ts b/src/routes/(main)/directory/[[id]]/service.ts index 782197e..f90477f 100644 --- a/src/routes/(main)/directory/[[id]]/service.ts +++ b/src/routes/(main)/directory/[[id]]/service.ts @@ -2,11 +2,11 @@ import { callSignedPostApi } from "$lib/hooks"; import { encodeToBase64, decodeFromBase64, - generateAESDataKey, - encryptAESPlaintext, - decryptAESCiphertext, - wrapAESDataKey, - unwrapAESDataKey, + generateDataKey, + wrapDataKey, + unwrapDataKey, + encryptData, + decryptData, } from "$lib/modules/crypto"; import type { DirectroyInfoResponse, DirectoryCreateRequest } from "$lib/server/schemas"; import type { MasterKey } from "$lib/stores"; @@ -15,14 +15,10 @@ export const decryptDirectroyMetadata = async ( metadata: NonNullable, masterKey: CryptoKey, ) => { - const dataDecryptKey = await unwrapAESDataKey(decodeFromBase64(metadata.dek), masterKey); + const { dataKey } = await unwrapDataKey(metadata.dek, masterKey); return { name: new TextDecoder().decode( - await decryptAESCiphertext( - decodeFromBase64(metadata.name), - decodeFromBase64(metadata.nameIv), - dataDecryptKey, - ), + await decryptData(decodeFromBase64(metadata.name), metadata.nameIv, dataKey), ), }; }; @@ -33,16 +29,16 @@ export const requestDirectroyCreation = async ( masterKey: MasterKey, signKey: CryptoKey, ) => { - const dataKey = await generateAESDataKey(); - const nameEncrypted = await encryptAESPlaintext(new TextEncoder().encode(name), dataKey); + const { dataKey } = await generateDataKey(); + const nameEncrypted = await encryptData(new TextEncoder().encode(name), dataKey); return await callSignedPostApi( "/api/directory/create", { parentId, mekVersion: masterKey.version, - dek: encodeToBase64(await wrapAESDataKey(dataKey, masterKey.key)), + dek: await wrapDataKey(dataKey, masterKey.key), name: encodeToBase64(nameEncrypted.ciphertext), - nameIv: encodeToBase64(nameEncrypted.iv.buffer), + nameIv: nameEncrypted.iv, }, signKey, );