키 가져오기 기능 추가

This commit is contained in:
static
2025-07-12 01:28:44 +09:00
parent c47885d571
commit eac81abe5a
10 changed files with 304 additions and 118 deletions

View File

@@ -46,6 +46,56 @@ export const exportRSAKeyToBase64 = async (key: CryptoKey) => {
return encodeToBase64((await exportRSAKey(key)).key);
};
export const importEncryptionKeyPairFromBase64 = async (
encryptKeyBase64: string,
decryptKeyBase64: string,
) => {
const algorithm: RsaHashedImportParams = {
name: "RSA-OAEP",
hash: "SHA-256",
};
const encryptKey = await window.crypto.subtle.importKey(
"spki",
decodeFromBase64(encryptKeyBase64),
algorithm,
true,
["encrypt", "wrapKey"],
);
const decryptKey = await window.crypto.subtle.importKey(
"pkcs8",
decodeFromBase64(decryptKeyBase64),
algorithm,
true,
["decrypt", "unwrapKey"],
);
return { encryptKey, decryptKey };
};
export const importSigningKeyPairFromBase64 = async (
signKeyBase64: string,
verifyKeyBase64: string,
) => {
const algorithm: RsaHashedImportParams = {
name: "RSA-PSS",
hash: "SHA-256",
};
const signKey = await window.crypto.subtle.importKey(
"pkcs8",
decodeFromBase64(signKeyBase64),
algorithm,
true,
["sign"],
);
const verifyKey = await window.crypto.subtle.importKey(
"spki",
decodeFromBase64(verifyKeyBase64),
algorithm,
true,
["verify"],
);
return { signKey, verifyKey };
};
export const makeRSAKeyNonextractable = async (key: CryptoKey) => {
const { key: exportedKey, format } = await exportRSAKey(key);
return await window.crypto.subtle.importKey(

65
src/lib/modules/key.ts Normal file
View File

@@ -0,0 +1,65 @@
import { z } from "zod";
import { storeClientKey } from "$lib/indexedDB";
import type { ClientKeys } from "$lib/stores";
const serializedClientKeysSchema = z.intersection(
z.object({
generator: z.literal("ArkVault"),
exportedAt: z.string().datetime(),
}),
z.object({
version: z.literal(1),
encryptKey: z.string().base64().nonempty(),
decryptKey: z.string().base64().nonempty(),
signKey: z.string().base64().nonempty(),
verifyKey: z.string().base64().nonempty(),
}),
);
type SerializedClientKeys = z.infer<typeof serializedClientKeysSchema>;
type DeserializedClientKeys = {
encryptKeyBase64: string;
decryptKeyBase64: string;
signKeyBase64: string;
verifyKeyBase64: string;
};
export const serializeClientKeys = ({
encryptKeyBase64,
decryptKeyBase64,
signKeyBase64,
verifyKeyBase64,
}: DeserializedClientKeys) => {
return JSON.stringify({
version: 1,
generator: "ArkVault",
exportedAt: new Date().toISOString(),
encryptKey: encryptKeyBase64,
decryptKey: decryptKeyBase64,
signKey: signKeyBase64,
verifyKey: verifyKeyBase64,
} satisfies SerializedClientKeys);
};
export const deserializeClientKeys = (serialized: string) => {
const zodRes = serializedClientKeysSchema.safeParse(JSON.parse(serialized));
if (zodRes.success) {
return {
encryptKeyBase64: zodRes.data.encryptKey,
decryptKeyBase64: zodRes.data.decryptKey,
signKeyBase64: zodRes.data.signKey,
verifyKeyBase64: zodRes.data.verifyKey,
} satisfies DeserializedClientKeys;
}
return undefined;
};
export const storeClientKeys = async (clientKeys: ClientKeys) => {
await Promise.all([
storeClientKey(clientKeys.encryptKey, "encrypt"),
storeClientKey(clientKeys.decryptKey, "decrypt"),
storeClientKey(clientKeys.signKey, "sign"),
storeClientKey(clientKeys.verifyKey, "verify"),
]);
};