From 400438c395712362531e81e8cc83fa01194be60f Mon Sep 17 00:00:00 2001 From: static Date: Fri, 27 Dec 2024 21:23:47 +0900 Subject: [PATCH] =?UTF-8?q?=EC=95=94=ED=98=B8=20=ED=82=A4=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=ED=9B=84=20=EB=82=B4=EB=B3=B4=EB=82=B4=EA=B8=B0=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/hooks/goto.ts | 21 +++++++++ src/lib/hooks/index.ts | 1 + src/lib/stores/key.ts | 4 ++ .../auth/generateKey/done/+page.svelte | 29 ------------- .../(fullscreen)/key/export/+page.svelte | 43 +++++++++++++++++++ src/routes/(fullscreen)/key/export/+page.ts | 14 ++++++ .../generateKey => key/generate}/+page.svelte | 8 +++- .../generateKey => key/generate}/Order.svelte | 0 .../generateKey => key/generate}/service.ts | 35 ++++++++------- 9 files changed, 107 insertions(+), 48 deletions(-) create mode 100644 src/lib/hooks/goto.ts create mode 100644 src/lib/stores/key.ts delete mode 100644 src/routes/(fullscreen)/auth/generateKey/done/+page.svelte create mode 100644 src/routes/(fullscreen)/key/export/+page.svelte create mode 100644 src/routes/(fullscreen)/key/export/+page.ts rename src/routes/(fullscreen)/{auth/generateKey => key/generate}/+page.svelte (88%) rename src/routes/(fullscreen)/{auth/generateKey => key/generate}/Order.svelte (100%) rename src/routes/(fullscreen)/{auth/generateKey => key/generate}/service.ts (69%) diff --git a/src/lib/hooks/goto.ts b/src/lib/hooks/goto.ts new file mode 100644 index 0000000..c2cef9c --- /dev/null +++ b/src/lib/hooks/goto.ts @@ -0,0 +1,21 @@ +import { writable } from "svelte/store"; +import { goto as svelteGoto } from "$app/navigation"; + +type Path = "/key/export"; + +interface KeyExportState { + pubKeyBase64: string; + privKeyBase64: string; +} + +export const keyExportState = writable(null); + +export function goto(path: "/key/export", state: KeyExportState): Promise; + +export function goto(path: Path, state: unknown) { + switch (path) { + case "/key/export": + keyExportState.set(state as KeyExportState); + return svelteGoto(path); + } +} diff --git a/src/lib/hooks/index.ts b/src/lib/hooks/index.ts index 54f1be9..48c19b9 100644 --- a/src/lib/hooks/index.ts +++ b/src/lib/hooks/index.ts @@ -1 +1,2 @@ export { default as callAPI } from "./callAPI"; +export { goto } from "./goto"; diff --git a/src/lib/stores/key.ts b/src/lib/stores/key.ts new file mode 100644 index 0000000..e11209c --- /dev/null +++ b/src/lib/stores/key.ts @@ -0,0 +1,4 @@ +import { writable } from "svelte/store"; + +export const pubKey = writable(null); +export const privKey = writable(null); diff --git a/src/routes/(fullscreen)/auth/generateKey/done/+page.svelte b/src/routes/(fullscreen)/auth/generateKey/done/+page.svelte deleted file mode 100644 index fd84277..0000000 --- a/src/routes/(fullscreen)/auth/generateKey/done/+page.svelte +++ /dev/null @@ -1,29 +0,0 @@ - - - - 암호 키 생성하기 - - -
-
- -

암호 키가 생성되었어요!

-
-

모든 디바이스의 암호 키가 유실되면 서버에 저장된 데이터를 영원히 복호화할 수 없게 돼요.

-

복원을 위해 암호 키를 파일로 내보낼 수 있어요.

-
-
- -
- -
-
- 내보내지 않을래요 -
-
-
diff --git a/src/routes/(fullscreen)/key/export/+page.svelte b/src/routes/(fullscreen)/key/export/+page.svelte new file mode 100644 index 0000000..ca53016 --- /dev/null +++ b/src/routes/(fullscreen)/key/export/+page.svelte @@ -0,0 +1,43 @@ + + + + 암호 키 생성하기 + + +
+
+ +
+
+
+

암호 키를 파일로 내보낼까요?

+
+

+ 모든 디바이스의 암호 키가 유실되면, 서버에 저장된 데이터를 영원히 복호화할 수 없게 돼요. +

+

만약의 상황을 위해 암호 키를 파일로 내보낼 수 있어요.

+
+
+ +
+ +
+
+ 내보내지 않을래요 +
+
+
+
diff --git a/src/routes/(fullscreen)/key/export/+page.ts b/src/routes/(fullscreen)/key/export/+page.ts new file mode 100644 index 0000000..994640b --- /dev/null +++ b/src/routes/(fullscreen)/key/export/+page.ts @@ -0,0 +1,14 @@ +import { error } from "@sveltejs/kit"; +import { get } from "svelte/store"; +import { keyExportState } from "$lib/hooks/goto"; +import type { PageLoad } from "./$types"; + +export const load: PageLoad = async () => { + const state = get(keyExportState); + if (!state) { + error(403, "Forbidden"); + } + + keyExportState.set(null); + return state; +}; diff --git a/src/routes/(fullscreen)/auth/generateKey/+page.svelte b/src/routes/(fullscreen)/key/generate/+page.svelte similarity index 88% rename from src/routes/(fullscreen)/auth/generateKey/+page.svelte rename to src/routes/(fullscreen)/key/generate/+page.svelte index 29bb56c..eddcf85 100644 --- a/src/routes/(fullscreen)/auth/generateKey/+page.svelte +++ b/src/routes/(fullscreen)/key/generate/+page.svelte @@ -1,7 +1,9 @@ @@ -49,7 +55,7 @@
- +
키를 갖고 있어요 diff --git a/src/routes/(fullscreen)/auth/generateKey/Order.svelte b/src/routes/(fullscreen)/key/generate/Order.svelte similarity index 100% rename from src/routes/(fullscreen)/auth/generateKey/Order.svelte rename to src/routes/(fullscreen)/key/generate/Order.svelte diff --git a/src/routes/(fullscreen)/auth/generateKey/service.ts b/src/routes/(fullscreen)/key/generate/service.ts similarity index 69% rename from src/routes/(fullscreen)/auth/generateKey/service.ts rename to src/routes/(fullscreen)/key/generate/service.ts index 5653703..aa46c87 100644 --- a/src/routes/(fullscreen)/auth/generateKey/service.ts +++ b/src/routes/(fullscreen)/key/generate/service.ts @@ -1,4 +1,5 @@ import { storeKeyPairIntoIndexedDB } from "$lib/indexedDB"; +import { pubKey, privKey } from "$lib/stores/key"; type KeyType = "public" | "private"; @@ -16,20 +17,6 @@ const generateRSAKeyPair = async () => { return keyPair; }; -const exportKeyAsPem = async (key: CryptoKey, type: KeyType) => { - const exportedKey = await window.crypto.subtle.exportKey( - type === "public" ? "spki" : "pkcs8", - key, - ); - const exportedKeyBase64 = btoa(String.fromCharCode(...new Uint8Array(exportedKey))) - .match(/.{1,64}/g)! - .join("\n"); - - const pemHeader = type === "public" ? "PUBLIC" : "PRIVATE"; - const pem = `-----BEGIN ${pemHeader} KEY-----\n${exportedKeyBase64}\n-----END ${pemHeader} KEY-----\n`; - return pem; -}; - const makeRSAKeyNonextractable = async (key: CryptoKey, type: KeyType) => { const format = type === "public" ? "spki" : "pkcs8"; const keyUsage = type === "public" ? "encrypt" : "decrypt"; @@ -45,13 +32,25 @@ const makeRSAKeyNonextractable = async (key: CryptoKey, type: KeyType) => { ); }; +const exportKeyToBase64 = async (key: CryptoKey, type: KeyType) => { + const exportedKey = await window.crypto.subtle.exportKey( + type === "public" ? "spki" : "pkcs8", + key, + ); + return btoa(String.fromCharCode(...new Uint8Array(exportedKey))); +}; + export const generateKeyPair = async () => { const keyPair = await generateRSAKeyPair(); - const privKeySecure = await makeRSAKeyNonextractable(keyPair.privateKey, "private"); + + pubKey.set(keyPair.publicKey); + privKey.set(privKeySecure); + await storeKeyPairIntoIndexedDB(keyPair.publicKey, privKeySecure); - const pubKeyPem = await exportKeyAsPem(keyPair.publicKey, "public"); - const privKeyPem = await exportKeyAsPem(keyPair.privateKey, "private"); - return { pubKeyPem, privKeyPem }; + return { + pubKeyBase64: await exportKeyToBase64(keyPair.publicKey, "public"), + privKeyBase64: await exportKeyToBase64(keyPair.privateKey, "private"), + }; };