From e8e4022bc28446dfc1725d3e8ebf583621b519bd Mon Sep 17 00:00:00 2001 From: static Date: Tue, 31 Dec 2024 22:32:24 +0900 Subject: [PATCH] =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=B0=8F=20?= =?UTF-8?q?=EC=95=94=ED=98=B8=20=ED=82=A4=20=EB=93=B1=EB=A1=9D=20=EC=9D=B4?= =?UTF-8?q?=ED=9B=84=20=ED=81=B4=EB=9D=BC=EC=9D=B4=EC=96=B8=ED=8A=B8=20?= =?UTF-8?q?=EC=8A=B9=EC=9D=B8=20=EB=8C=80=EA=B8=B0=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=EB=A1=9C=EC=9D=98=20=EC=9E=90=EB=8F=99=20=EB=A6=AC?= =?UTF-8?q?=EB=8B=A4=EC=9D=B4=EB=A0=89=EC=85=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/services/key.ts | 36 +++++++++++++++ .../(fullscreen)/auth/login/+page.svelte | 25 +++++++---- src/routes/(fullscreen)/auth/login/service.ts | 2 + .../(fullscreen)/client/pending/service.ts | 45 ++----------------- .../(fullscreen)/key/export/+page.svelte | 2 +- 5 files changed, 58 insertions(+), 52 deletions(-) diff --git a/src/lib/services/key.ts b/src/lib/services/key.ts index 4d7b97a..d55cb93 100644 --- a/src/lib/services/key.ts +++ b/src/lib/services/key.ts @@ -1,10 +1,14 @@ import { callAPI } from "$lib/hooks"; +import { storeMasterKeys } from "$lib/indexedDB"; import { encodeToBase64, decodeFromBase64, decryptRSACiphertext, signRSAMessage, + makeAESKeyNonextractable, + unwrapAESKeyUsingRSA, } from "$lib/modules/crypto"; +import { masterKeyStore } from "$lib/stores"; export const requestClientRegistration = async ( encryptKeyBase64: string, @@ -40,3 +44,35 @@ export const requestClientRegistration = async ( }); return res.ok; }; + +export const requestMasterKeyDownload = async (decryptKey: CryptoKey) => { + const res = await callAPI("/api/mek/list", { method: "GET" }); + if (!res.ok) return false; + + const data = await res.json(); + const { meks: masterKeysWrapped } = data as { + meks: { + version: number; + state: "active" | "retired"; + mek: string; + }[]; + }; + const masterKeys = await Promise.all( + masterKeysWrapped.map(async ({ version, state, mek: masterKeyWrapped }) => ({ + version, + state, + masterKey: await makeAESKeyNonextractable( + await unwrapAESKeyUsingRSA(decodeFromBase64(masterKeyWrapped), decryptKey), + ), + })), + ); + + await storeMasterKeys( + masterKeys.map(({ version, state, masterKey }) => ({ version, state, key: masterKey })), + ); + masterKeyStore.set( + new Map(masterKeys.map(({ version, state, masterKey }) => [version, { state, masterKey }])), + ); + + return true; +}; diff --git a/src/routes/(fullscreen)/auth/login/+page.svelte b/src/routes/(fullscreen)/auth/login/+page.svelte index 556911f..776bb6d 100644 --- a/src/routes/(fullscreen)/auth/login/+page.svelte +++ b/src/routes/(fullscreen)/auth/login/+page.svelte @@ -5,28 +5,35 @@ import { TitleDiv, BottomDiv } from "$lib/components/divs"; import { TextInput } from "$lib/components/inputs"; import { refreshToken } from "$lib/hooks/callAPI"; - import { clientKeyStore } from "$lib/stores"; - import { requestLogin, requestTokenUpgrade } from "./service"; + import { clientKeyStore, masterKeyStore } from "$lib/stores"; + import { requestLogin, requestTokenUpgrade, requestMasterKeyDownload } from "./service"; let { data } = $props(); let email = $state(""); let password = $state(""); + const redirect = async (url: string) => { + return await goto(`${url}?redirect=${encodeURIComponent(data.redirectPath)}`); + }; + const login = async () => { // TODO: Validation try { if (!(await requestLogin(email, password))) throw new Error("Failed to login"); - if ($clientKeyStore && !(await requestTokenUpgrade($clientKeyStore))) - throw new Error("Failed to upgrade token"); + if (!$clientKeyStore) return await redirect("/key/generate"); - await goto( - $clientKeyStore - ? data.redirectPath - : "/key/generate?redirect=" + encodeURIComponent(data.redirectPath), - ); + if (!(await requestTokenUpgrade($clientKeyStore))) throw new Error("Failed to upgrade token"); + + // TODO: Multi-user support + + if ($masterKeyStore || (await requestMasterKeyDownload($clientKeyStore.decryptKey))) { + await goto(data.redirectPath); + } else { + await redirect("/client/pending"); + } } catch (e) { // TODO: Alert throw e; diff --git a/src/routes/(fullscreen)/auth/login/service.ts b/src/routes/(fullscreen)/auth/login/service.ts index 77c4620..e9002af 100644 --- a/src/routes/(fullscreen)/auth/login/service.ts +++ b/src/routes/(fullscreen)/auth/login/service.ts @@ -3,6 +3,8 @@ import { requestTokenUpgrade as requestTokenUpgradeInternal } from "$lib/service import { requestClientRegistration } from "$lib/services/key"; import type { ClientKeys } from "$lib/stores"; +export { requestMasterKeyDownload } from "$lib/services/key"; + export const requestLogin = async (email: string, password: string) => { const res = await fetch("/api/auth/login", { method: "POST", diff --git a/src/routes/(fullscreen)/client/pending/service.ts b/src/routes/(fullscreen)/client/pending/service.ts index 51037b5..5a1a06d 100644 --- a/src/routes/(fullscreen)/client/pending/service.ts +++ b/src/routes/(fullscreen)/client/pending/service.ts @@ -1,13 +1,6 @@ -import { callAPI } from "$lib/hooks"; -import { storeMasterKeys } from "$lib/indexedDB"; -import { - decodeFromBase64, - exportRSAKey, - makeAESKeyNonextractable, - unwrapAESKeyUsingRSA, - digestSHA256, -} from "$lib/modules/crypto"; -import { masterKeyStore } from "$lib/stores"; +import { exportRSAKey, digestSHA256 } from "$lib/modules/crypto"; + +export { requestMasterKeyDownload } from "$lib/services/key"; export const generateEncryptKeyFingerprint = async (encryptKey: CryptoKey) => { const { key } = await exportRSAKey(encryptKey); @@ -19,35 +12,3 @@ export const generateEncryptKeyFingerprint = async (encryptKey: CryptoKey) => { .match(/.{1,4}/g)! .join(" "); }; - -export const requestMasterKeyDownload = async (decryptKey: CryptoKey) => { - const res = await callAPI("/api/mek/list", { method: "GET" }); - if (!res.ok) return false; - - const data = await res.json(); - const { meks: masterKeysWrapped } = data as { - meks: { - version: number; - state: "active" | "retired"; - mek: string; - }[]; - }; - const masterKeys = await Promise.all( - masterKeysWrapped.map(async ({ version, state, mek: masterKeyWrapped }) => ({ - version, - state, - masterKey: await makeAESKeyNonextractable( - await unwrapAESKeyUsingRSA(decodeFromBase64(masterKeyWrapped), decryptKey), - ), - })), - ); - - await storeMasterKeys( - masterKeys.map(({ version, state, masterKey }) => ({ version, state, key: masterKey })), - ); - masterKeyStore.set( - new Map(masterKeys.map(({ version, state, masterKey }) => [version, { state, masterKey }])), - ); - - return true; -}; diff --git a/src/routes/(fullscreen)/key/export/+page.svelte b/src/routes/(fullscreen)/key/export/+page.svelte index 31d7384..b45747c 100644 --- a/src/routes/(fullscreen)/key/export/+page.svelte +++ b/src/routes/(fullscreen)/key/export/+page.svelte @@ -76,7 +76,7 @@ ) throw new Error("Failed to register initial MEK"); - await goto(data.redirectPath); + await goto("/client/pending?redirect=" + encodeURIComponent(data.redirectPath)); } catch (e) { // TODO: Error handling throw e;