mirror of
https://github.com/kmc7468/arkvault.git
synced 2025-12-16 23:18:48 +00:00
암호 키 생성 및 등록시 HSK도 함께 생성 및 등록하도록 변경
This commit is contained in:
@@ -11,6 +11,7 @@ interface KeyExportState {
|
||||
verifyKeyBase64: string;
|
||||
|
||||
masterKeyWrapped: string;
|
||||
hmacSecretWrapped: string;
|
||||
}
|
||||
|
||||
const useAutoNull = <T>(value: T | null) => {
|
||||
|
||||
@@ -7,22 +7,28 @@ interface ClientKey {
|
||||
key: CryptoKey;
|
||||
}
|
||||
|
||||
type MasterKeyState = "active" | "retired";
|
||||
|
||||
interface MasterKey {
|
||||
version: number;
|
||||
state: MasterKeyState;
|
||||
state: "active" | "retired";
|
||||
key: CryptoKey;
|
||||
}
|
||||
|
||||
interface HmacSecret {
|
||||
version: number;
|
||||
state: "active";
|
||||
secret: CryptoKey;
|
||||
}
|
||||
|
||||
const keyStore = new Dexie("keyStore") as Dexie & {
|
||||
clientKey: EntityTable<ClientKey, "usage">;
|
||||
masterKey: EntityTable<MasterKey, "version">;
|
||||
hmacSecret: EntityTable<HmacSecret, "version">;
|
||||
};
|
||||
|
||||
keyStore.version(1).stores({
|
||||
clientKey: "usage",
|
||||
masterKey: "version",
|
||||
hmacSecret: "version",
|
||||
});
|
||||
|
||||
export const getClientKey = async (usage: ClientKeyUsage) => {
|
||||
@@ -62,3 +68,14 @@ export const storeMasterKeys = async (keys: MasterKey[]) => {
|
||||
}
|
||||
await keyStore.masterKey.bulkPut(keys);
|
||||
};
|
||||
|
||||
export const getHmacSecrets = async () => {
|
||||
return await keyStore.hmacSecret.toArray();
|
||||
};
|
||||
|
||||
export const storeHmacSecrets = async (secrets: HmacSecret[]) => {
|
||||
if (secrets.some(({ secret }) => secret.extractable)) {
|
||||
throw new Error("Hmac secrets must be nonextractable");
|
||||
}
|
||||
await keyStore.hmacSecret.bulkPut(secrets);
|
||||
};
|
||||
|
||||
@@ -55,6 +55,27 @@ export const unwrapDataKey = async (dataKeyWrapped: string, masterKey: CryptoKey
|
||||
};
|
||||
};
|
||||
|
||||
export const wrapHmacSecret = async (hmacSecret: CryptoKey, masterKey: CryptoKey) => {
|
||||
return encodeToBase64(await window.crypto.subtle.wrapKey("raw", hmacSecret, masterKey, "AES-KW"));
|
||||
};
|
||||
|
||||
export const unwrapHmacSecret = async (hmacSecretWrapped: string, masterKey: CryptoKey) => {
|
||||
return {
|
||||
hmacSecret: await window.crypto.subtle.unwrapKey(
|
||||
"raw",
|
||||
decodeFromBase64(hmacSecretWrapped),
|
||||
masterKey,
|
||||
"AES-KW",
|
||||
{
|
||||
name: "HMAC",
|
||||
hash: "SHA-256",
|
||||
} satisfies HmacImportParams,
|
||||
false, // Nonextractable
|
||||
["sign", "verify"],
|
||||
),
|
||||
};
|
||||
};
|
||||
|
||||
export const encryptData = async (data: BufferSource, dataKey: CryptoKey) => {
|
||||
const iv = window.crypto.getRandomValues(new Uint8Array(12));
|
||||
const ciphertext = await window.crypto.subtle.encrypt(
|
||||
|
||||
@@ -95,7 +95,7 @@ export const unwrapMasterKey = async (
|
||||
};
|
||||
};
|
||||
|
||||
export const signMessage = async (message: BufferSource, signKey: CryptoKey) => {
|
||||
export const signMessageRSA = async (message: BufferSource, signKey: CryptoKey) => {
|
||||
return await window.crypto.subtle.sign(
|
||||
{
|
||||
name: "RSA-PSS",
|
||||
@@ -106,7 +106,7 @@ export const signMessage = async (message: BufferSource, signKey: CryptoKey) =>
|
||||
);
|
||||
};
|
||||
|
||||
export const verifySignature = async (
|
||||
export const verifySignatureRSA = async (
|
||||
message: BufferSource,
|
||||
signature: BufferSource,
|
||||
verifyKey: CryptoKey,
|
||||
@@ -131,7 +131,7 @@ export const signMasterKeyWrapped = async (
|
||||
version: masterKeyVersion,
|
||||
key: masterKeyWrapped,
|
||||
});
|
||||
return encodeToBase64(await signMessage(encodeString(serialized), signKey));
|
||||
return encodeToBase64(await signMessageRSA(encodeString(serialized), signKey));
|
||||
};
|
||||
|
||||
export const verifyMasterKeyWrapped = async (
|
||||
@@ -144,7 +144,7 @@ export const verifyMasterKeyWrapped = async (
|
||||
version: masterKeyVersion,
|
||||
key: masterKeyWrapped,
|
||||
});
|
||||
return await verifySignature(
|
||||
return await verifySignatureRSA(
|
||||
encodeString(serialized),
|
||||
decodeFromBase64(masterKeyWrappedSig),
|
||||
verifyKey,
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
export const digestMessage = async (message: BufferSource) => {
|
||||
return await window.crypto.subtle.digest("SHA-256", message);
|
||||
};
|
||||
|
||||
export const generateHmacSecret = async () => {
|
||||
return {
|
||||
hmacSecret: await window.crypto.subtle.generateKey(
|
||||
{
|
||||
name: "HMAC",
|
||||
hash: "SHA-256",
|
||||
} satisfies HmacKeyGenParams,
|
||||
true,
|
||||
["sign", "verify"],
|
||||
),
|
||||
};
|
||||
};
|
||||
|
||||
export const signMessageHmac = async (message: BufferSource, hmacSecret: CryptoKey) => {
|
||||
return await window.crypto.subtle.sign("HMAC", hmacSecret, message);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { callPostApi } from "$lib/hooks";
|
||||
import { encodeToBase64, decryptChallenge, signMessage } from "$lib/modules/crypto";
|
||||
import { encodeToBase64, decryptChallenge, signMessageRSA } from "$lib/modules/crypto";
|
||||
import type {
|
||||
SessionUpgradeRequest,
|
||||
SessionUpgradeResponse,
|
||||
@@ -20,7 +20,7 @@ export const requestSessionUpgrade = async (
|
||||
|
||||
const { challenge }: SessionUpgradeResponse = await res.json();
|
||||
const answer = await decryptChallenge(challenge, decryptKey);
|
||||
const answerSig = await signMessage(answer, signKey);
|
||||
const answerSig = await signMessageRSA(answer, signKey);
|
||||
|
||||
res = await callPostApi<SessionUpgradeVerifyRequest>("/api/auth/upgradeSession/verify", {
|
||||
answer: encodeToBase64(answer),
|
||||
|
||||
@@ -3,7 +3,7 @@ import { storeMasterKeys } from "$lib/indexedDB";
|
||||
import {
|
||||
encodeToBase64,
|
||||
decryptChallenge,
|
||||
signMessage,
|
||||
signMessageRSA,
|
||||
unwrapMasterKey,
|
||||
verifyMasterKeyWrapped,
|
||||
} from "$lib/modules/crypto";
|
||||
@@ -29,7 +29,7 @@ export const requestClientRegistration = async (
|
||||
|
||||
const { challenge }: ClientRegisterResponse = await res.json();
|
||||
const answer = await decryptChallenge(challenge, decryptKey);
|
||||
const answerSig = await signMessage(answer, signKey);
|
||||
const answerSig = await signMessageRSA(answer, signKey);
|
||||
|
||||
res = await callPostApi<ClientRegisterVerifyRequest>("/api/client/register/verify", {
|
||||
answer: encodeToBase64(answer),
|
||||
|
||||
@@ -13,6 +13,14 @@ export interface MasterKey {
|
||||
key: CryptoKey;
|
||||
}
|
||||
|
||||
export interface HmacSecret {
|
||||
version: number;
|
||||
state: "active";
|
||||
secret: CryptoKey;
|
||||
}
|
||||
|
||||
export const clientKeyStore = writable<ClientKeys | null>(null);
|
||||
|
||||
export const masterKeyStore = writable<Map<number, MasterKey> | null>(null);
|
||||
|
||||
export const hmacSecretStore = writable<Map<number, HmacSecret> | null>(null);
|
||||
|
||||
Reference in New Issue
Block a user