mirror of
https://github.com/kmc7468/arkvault.git
synced 2025-12-12 21:08:46 +00:00
/api/mek/register, /api/mek/share Endpoint 삭제 및 MEK 서명 매커니즘 구현
2025년 첫 커밋! Happy New Year~
This commit is contained in:
@@ -76,6 +76,22 @@ export const signRSAMessage = async (message: BufferSource, privateKey: CryptoKe
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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 generateAESKey = async () => {
|
export const generateAESKey = async () => {
|
||||||
return await window.crypto.subtle.generateKey(
|
return await window.crypto.subtle.generateKey(
|
||||||
{
|
{
|
||||||
@@ -136,3 +152,24 @@ export const signRequest = async <T>(data: T, privateKey: CryptoKey) => {
|
|||||||
signature: encodeToBase64(signature),
|
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);
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
import { and, or, eq, lt, desc } from "drizzle-orm";
|
import { and, or, eq } from "drizzle-orm";
|
||||||
import db from "./drizzle";
|
import db from "./drizzle";
|
||||||
import { mek, clientMek, userClient } from "./schema";
|
import { mek, clientMek } from "./schema";
|
||||||
|
|
||||||
export const registerInitialMek = async (userId: number, createdBy: number, encMek: string) => {
|
export const registerInitialMek = async (
|
||||||
|
userId: number,
|
||||||
|
createdBy: number,
|
||||||
|
encMek: string,
|
||||||
|
encMekSig: string,
|
||||||
|
) => {
|
||||||
await db.transaction(async (tx) => {
|
await db.transaction(async (tx) => {
|
||||||
await tx.insert(mek).values({
|
await tx.insert(mek).values({
|
||||||
userId,
|
userId,
|
||||||
@@ -16,70 +21,11 @@ export const registerInitialMek = async (userId: number, createdBy: number, encM
|
|||||||
clientId: createdBy,
|
clientId: createdBy,
|
||||||
mekVersion: 1,
|
mekVersion: 1,
|
||||||
encMek,
|
encMek,
|
||||||
|
encMekSig,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const registerActiveMek = async (
|
|
||||||
userId: number,
|
|
||||||
version: number,
|
|
||||||
createdBy: number,
|
|
||||||
clientMeks: {
|
|
||||||
clientId: number;
|
|
||||||
encMek: string;
|
|
||||||
}[],
|
|
||||||
) => {
|
|
||||||
await db.transaction(async (tx) => {
|
|
||||||
// 1. Check if the clientMeks are valid
|
|
||||||
const userClients = await tx
|
|
||||||
.select()
|
|
||||||
.from(userClient)
|
|
||||||
.where(and(eq(userClient.userId, userId), eq(userClient.state, "active")));
|
|
||||||
if (
|
|
||||||
clientMeks.length !== userClients.length ||
|
|
||||||
!clientMeks.every((clientMek) =>
|
|
||||||
userClients.some((userClient) => userClient.clientId === clientMek.clientId),
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
throw new Error("Invalid key list");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Retire the old active MEK and insert the new one
|
|
||||||
await tx
|
|
||||||
.update(mek)
|
|
||||||
.set({
|
|
||||||
state: "retired",
|
|
||||||
retiredAt: new Date(),
|
|
||||||
})
|
|
||||||
.where(and(eq(mek.userId, userId), lt(mek.version, version), eq(mek.state, "active")));
|
|
||||||
await tx.insert(mek).values({
|
|
||||||
userId,
|
|
||||||
version,
|
|
||||||
createdBy,
|
|
||||||
createdAt: new Date(),
|
|
||||||
state: "active",
|
|
||||||
});
|
|
||||||
|
|
||||||
// 3. Insert the new client MEKs
|
|
||||||
await tx.insert(clientMek).values(
|
|
||||||
clientMeks.map(({ clientId, encMek }) => ({
|
|
||||||
userId,
|
|
||||||
clientId,
|
|
||||||
mekVersion: version,
|
|
||||||
encMek,
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getAllValidMeks = async (userId: number) => {
|
|
||||||
return await db
|
|
||||||
.select()
|
|
||||||
.from(mek)
|
|
||||||
.where(and(eq(mek.userId, userId), or(eq(mek.state, "active"), eq(mek.state, "retired"))))
|
|
||||||
.execute();
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getInitialMek = async (userId: number) => {
|
export const getInitialMek = async (userId: number) => {
|
||||||
const meks = await db
|
const meks = await db
|
||||||
.select()
|
.select()
|
||||||
@@ -89,68 +35,6 @@ export const getInitialMek = async (userId: number) => {
|
|||||||
return meks[0] ?? null;
|
return meks[0] ?? null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getNextActiveMekVersion = async (userId: number) => {
|
|
||||||
const meks = await db
|
|
||||||
.select({ version: mek.version })
|
|
||||||
.from(mek)
|
|
||||||
.where(eq(mek.userId, userId))
|
|
||||||
.orderBy(desc(mek.version))
|
|
||||||
.limit(1)
|
|
||||||
.execute();
|
|
||||||
if (!meks[0]) {
|
|
||||||
throw new Error("No MEK found");
|
|
||||||
}
|
|
||||||
return meks[0].version + 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const registerClientMeks = async (
|
|
||||||
userId: number,
|
|
||||||
clientId: number,
|
|
||||||
clientMeks: {
|
|
||||||
version: number;
|
|
||||||
encMek: string;
|
|
||||||
}[],
|
|
||||||
) => {
|
|
||||||
await db.transaction(async (tx) => {
|
|
||||||
// 1. Check if the client is valid
|
|
||||||
const userClients = await tx
|
|
||||||
.select()
|
|
||||||
.from(userClient)
|
|
||||||
.where(
|
|
||||||
and(
|
|
||||||
eq(userClient.userId, userId),
|
|
||||||
eq(userClient.clientId, clientId),
|
|
||||||
eq(userClient.state, "active"),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
if (userClients.length === 0) {
|
|
||||||
throw new Error("Invalid client");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Check if the clientMeks are valid
|
|
||||||
const meks = await tx
|
|
||||||
.select()
|
|
||||||
.from(mek)
|
|
||||||
.where(and(eq(mek.userId, userId), or(eq(mek.state, "active"), eq(mek.state, "retired"))));
|
|
||||||
if (
|
|
||||||
clientMeks.length !== meks.length ||
|
|
||||||
!clientMeks.every((clientMek) => meks.some((mek) => mek.version === clientMek.version))
|
|
||||||
) {
|
|
||||||
throw new Error("Invalid key list");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Insert the client MEKs
|
|
||||||
await tx.insert(clientMek).values(
|
|
||||||
clientMeks.map(({ version, encMek }) => ({
|
|
||||||
userId,
|
|
||||||
clientId,
|
|
||||||
mekVersion: version,
|
|
||||||
encMek,
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getAllValidClientMeks = async (userId: number, clientId: number) => {
|
export const getAllValidClientMeks = async (userId: number, clientId: number) => {
|
||||||
return await db
|
return await db
|
||||||
.select()
|
.select()
|
||||||
|
|||||||
@@ -30,8 +30,9 @@ export const clientMek = sqliteTable(
|
|||||||
clientId: integer("client_id")
|
clientId: integer("client_id")
|
||||||
.notNull()
|
.notNull()
|
||||||
.references(() => client.id),
|
.references(() => client.id),
|
||||||
mekVersion: integer("master_encryption_key_version").notNull(),
|
mekVersion: integer("version").notNull(),
|
||||||
encMek: text("encrypted_master_encryption_key").notNull(),
|
encMek: text("encrypted_key").notNull(), // Base64
|
||||||
|
encMekSig: text("encrypted_key_signature").notNull(), // Base64
|
||||||
},
|
},
|
||||||
(t) => ({
|
(t) => ({
|
||||||
pk: primaryKey({ columns: [t.userId, t.clientId, t.mekVersion] }),
|
pk: primaryKey({ columns: [t.userId, t.clientId, t.mekVersion] }),
|
||||||
|
|||||||
@@ -1,6 +1,25 @@
|
|||||||
|
import { error } from "@sveltejs/kit";
|
||||||
|
import { getUserClientWithDetails } from "$lib/server/db/client";
|
||||||
import { getInitialMek } from "$lib/server/db/mek";
|
import { getInitialMek } from "$lib/server/db/mek";
|
||||||
|
import { verifySignature } from "$lib/server/modules/crypto";
|
||||||
|
|
||||||
export const isInitialMekNeeded = async (userId: number) => {
|
export const isInitialMekNeeded = async (userId: number) => {
|
||||||
const initialMek = await getInitialMek(userId);
|
const initialMek = await getInitialMek(userId);
|
||||||
return !initialMek;
|
return !initialMek;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const verifyClientEncMekSig = async (
|
||||||
|
userId: number,
|
||||||
|
clientId: number,
|
||||||
|
version: number,
|
||||||
|
encMek: string,
|
||||||
|
encMekSig: string,
|
||||||
|
) => {
|
||||||
|
const userClient = await getUserClientWithDetails(userId, clientId);
|
||||||
|
if (!userClient) {
|
||||||
|
error(500, "Invalid access token");
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = JSON.stringify({ version, key: encMek });
|
||||||
|
return verifySignature(Buffer.from(data), encMekSig, userClient.client.sigPubKey);
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,14 +1,7 @@
|
|||||||
import { error } from "@sveltejs/kit";
|
import { error } from "@sveltejs/kit";
|
||||||
import { getAllUserClients, setUserClientStateToActive } from "$lib/server/db/client";
|
import { setUserClientStateToActive } from "$lib/server/db/client";
|
||||||
import {
|
import { registerInitialMek, getAllValidClientMeks } from "$lib/server/db/mek";
|
||||||
registerInitialMek,
|
import { isInitialMekNeeded, verifyClientEncMekSig } from "$lib/server/modules/mek";
|
||||||
registerActiveMek,
|
|
||||||
getAllValidMeks,
|
|
||||||
getNextActiveMekVersion,
|
|
||||||
registerClientMeks,
|
|
||||||
getAllValidClientMeks,
|
|
||||||
} from "$lib/server/db/mek";
|
|
||||||
import { isInitialMekNeeded } from "$lib/server/modules/mek";
|
|
||||||
|
|
||||||
export const getClientMekList = async (userId: number, clientId: number) => {
|
export const getClientMekList = async (userId: number, clientId: number) => {
|
||||||
const clientMeks = await getAllValidClientMeks(userId, clientId);
|
const clientMeks = await getAllValidClientMeks(userId, clientId);
|
||||||
@@ -17,6 +10,7 @@ export const getClientMekList = async (userId: number, clientId: number) => {
|
|||||||
version: clientMek.master_encryption_key.version,
|
version: clientMek.master_encryption_key.version,
|
||||||
state: clientMek.master_encryption_key.state,
|
state: clientMek.master_encryption_key.state,
|
||||||
mek: clientMek.client_master_encryption_key.encMek,
|
mek: clientMek.client_master_encryption_key.encMek,
|
||||||
|
mekSig: clientMek.client_master_encryption_key.encMekSig,
|
||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -25,53 +19,14 @@ export const registerInitialActiveMek = async (
|
|||||||
userId: number,
|
userId: number,
|
||||||
createdBy: number,
|
createdBy: number,
|
||||||
encMek: string,
|
encMek: string,
|
||||||
|
encMekSig: string,
|
||||||
) => {
|
) => {
|
||||||
if (!(await isInitialMekNeeded(userId))) {
|
if (!(await isInitialMekNeeded(userId))) {
|
||||||
error(409, "Initial MEK already registered");
|
error(409, "Initial MEK already registered");
|
||||||
|
} else if (!(await verifyClientEncMekSig(userId, createdBy, 1, encMek, encMekSig))) {
|
||||||
|
error(400, "Invalid signature");
|
||||||
}
|
}
|
||||||
|
|
||||||
await registerInitialMek(userId, createdBy, encMek);
|
await registerInitialMek(userId, createdBy, encMek, encMekSig);
|
||||||
await setUserClientStateToActive(userId, createdBy);
|
await setUserClientStateToActive(userId, createdBy);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const registerNewActiveMek = async (
|
|
||||||
userId: number,
|
|
||||||
createdBy: number,
|
|
||||||
clientMeks: {
|
|
||||||
clientId: number;
|
|
||||||
encMek: string;
|
|
||||||
}[],
|
|
||||||
) => {
|
|
||||||
const userClients = await getAllUserClients(userId);
|
|
||||||
const activeUserClients = userClients.filter(({ state }) => state === "active");
|
|
||||||
if (
|
|
||||||
clientMeks.length !== activeUserClients.length ||
|
|
||||||
!clientMeks.every((clientMek) =>
|
|
||||||
activeUserClients.some((userClient) => userClient.clientId === clientMek.clientId),
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
error(400, "Invalid key list");
|
|
||||||
}
|
|
||||||
|
|
||||||
const newMekVersion = await getNextActiveMekVersion(userId);
|
|
||||||
await registerActiveMek(userId, newMekVersion, createdBy, clientMeks);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const shareMeksForNewClient = async (
|
|
||||||
userId: number,
|
|
||||||
targetClientId: number,
|
|
||||||
clientMeks: {
|
|
||||||
version: number;
|
|
||||||
encMek: string;
|
|
||||||
}[],
|
|
||||||
) => {
|
|
||||||
const meks = await getAllValidMeks(userId);
|
|
||||||
if (
|
|
||||||
clientMeks.length !== meks.length ||
|
|
||||||
!clientMeks.every((clientMek) => meks.some((mek) => mek.version === clientMek.version))
|
|
||||||
) {
|
|
||||||
error(400, "Invalid key list");
|
|
||||||
}
|
|
||||||
|
|
||||||
await registerClientMeks(userId, targetClientId, clientMeks);
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
signRSAMessage,
|
signRSAMessage,
|
||||||
makeAESKeyNonextractable,
|
makeAESKeyNonextractable,
|
||||||
unwrapAESKeyUsingRSA,
|
unwrapAESKeyUsingRSA,
|
||||||
|
verifyMasterKeyWrappedSig,
|
||||||
} from "$lib/modules/crypto";
|
} from "$lib/modules/crypto";
|
||||||
import { masterKeyStore } from "$lib/stores";
|
import { masterKeyStore } from "$lib/stores";
|
||||||
|
|
||||||
@@ -45,7 +46,7 @@ export const requestClientRegistration = async (
|
|||||||
return res.ok;
|
return res.ok;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const requestMasterKeyDownload = async (decryptKey: CryptoKey) => {
|
export const requestMasterKeyDownload = async (decryptKey: CryptoKey, verfiyKey: CryptoKey) => {
|
||||||
const res = await callAPI("/api/mek/list", { method: "GET" });
|
const res = await callAPI("/api/mek/list", { method: "GET" });
|
||||||
if (!res.ok) return false;
|
if (!res.ok) return false;
|
||||||
|
|
||||||
@@ -55,17 +56,28 @@ export const requestMasterKeyDownload = async (decryptKey: CryptoKey) => {
|
|||||||
version: number;
|
version: number;
|
||||||
state: "active" | "retired";
|
state: "active" | "retired";
|
||||||
mek: string;
|
mek: string;
|
||||||
|
mekSig: string;
|
||||||
}[];
|
}[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const masterKeys = await Promise.all(
|
const masterKeys = await Promise.all(
|
||||||
masterKeysWrapped.map(async ({ version, state, mek: masterKeyWrapped }) => ({
|
masterKeysWrapped.map(
|
||||||
version,
|
async ({ version, state, mek: masterKeyWrapped, mekSig: masterKeyWrappedSig }) => ({
|
||||||
state,
|
version,
|
||||||
masterKey: await makeAESKeyNonextractable(
|
state,
|
||||||
await unwrapAESKeyUsingRSA(decodeFromBase64(masterKeyWrapped), decryptKey),
|
masterKey: await makeAESKeyNonextractable(
|
||||||
),
|
await unwrapAESKeyUsingRSA(decodeFromBase64(masterKeyWrapped), decryptKey),
|
||||||
})),
|
),
|
||||||
|
isValid: await verifyMasterKeyWrappedSig(
|
||||||
|
version,
|
||||||
|
masterKeyWrapped,
|
||||||
|
masterKeyWrappedSig,
|
||||||
|
verfiyKey,
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
if (!masterKeys.every(({ isValid }) => isValid)) return false;
|
||||||
|
|
||||||
await storeMasterKeys(
|
await storeMasterKeys(
|
||||||
masterKeys.map(({ version, state, masterKey }) => ({ version, state, key: masterKey })),
|
masterKeys.map(({ version, state, masterKey }) => ({ version, state, key: masterKey })),
|
||||||
|
|||||||
@@ -29,7 +29,10 @@
|
|||||||
|
|
||||||
// TODO: Multi-user support
|
// TODO: Multi-user support
|
||||||
|
|
||||||
if ($masterKeyStore || (await requestMasterKeyDownload($clientKeyStore.decryptKey))) {
|
if (
|
||||||
|
$masterKeyStore ||
|
||||||
|
(await requestMasterKeyDownload($clientKeyStore.decryptKey, $clientKeyStore.verifyKey))
|
||||||
|
) {
|
||||||
await goto(data.redirectPath);
|
await goto(data.redirectPath);
|
||||||
} else {
|
} else {
|
||||||
await redirect("/client/pending");
|
await redirect("/client/pending");
|
||||||
|
|||||||
@@ -16,11 +16,13 @@
|
|||||||
if ($masterKeyStore) {
|
if ($masterKeyStore) {
|
||||||
goto(data.redirectPath);
|
goto(data.redirectPath);
|
||||||
} else if ($clientKeyStore) {
|
} else if ($clientKeyStore) {
|
||||||
requestMasterKeyDownload($clientKeyStore.decryptKey).then(async (ok) => {
|
requestMasterKeyDownload($clientKeyStore.decryptKey, $clientKeyStore.verifyKey).then(
|
||||||
if (ok) {
|
async (ok) => {
|
||||||
return await goto(data.redirectPath);
|
if (ok) {
|
||||||
}
|
return await goto(data.redirectPath);
|
||||||
});
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { callAPI } from "$lib/hooks";
|
import { callAPI } from "$lib/hooks";
|
||||||
import { storeClientKey } from "$lib/indexedDB";
|
import { storeClientKey } from "$lib/indexedDB";
|
||||||
import { encodeToBase64, signRequest } from "$lib/modules/crypto";
|
import { encodeToBase64, signRequest, signMasterKeyWrapped } from "$lib/modules/crypto";
|
||||||
import type { ClientKeys } from "$lib/stores";
|
import type { ClientKeys } from "$lib/stores";
|
||||||
|
|
||||||
export { requestTokenUpgrade } from "$lib/services/auth";
|
export { requestTokenUpgrade } from "$lib/services/auth";
|
||||||
@@ -53,6 +53,7 @@ export const requestInitialMasterKeyRegistration = async (
|
|||||||
body: await signRequest(
|
body: await signRequest(
|
||||||
{
|
{
|
||||||
mek: encodeToBase64(masterKeyWrapped),
|
mek: encodeToBase64(masterKeyWrapped),
|
||||||
|
mekSig: await signMasterKeyWrapped(1, masterKeyWrapped, signKey),
|
||||||
},
|
},
|
||||||
signKey,
|
signKey,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
import { text } from "@sveltejs/kit";
|
|
||||||
import { z } from "zod";
|
|
||||||
import { authorize } from "$lib/server/modules/auth";
|
|
||||||
import { parseSignedRequest } from "$lib/server/modules/crypto";
|
|
||||||
import { registerNewActiveMek } from "$lib/server/services/mek";
|
|
||||||
import type { RequestHandler } from "@sveltejs/kit";
|
|
||||||
|
|
||||||
export const POST: RequestHandler = async ({ request, cookies }) => {
|
|
||||||
const { userId, clientId } = await authorize(cookies, "activeClient");
|
|
||||||
const { meks } = await parseSignedRequest(
|
|
||||||
clientId,
|
|
||||||
await request.json(),
|
|
||||||
z.object({
|
|
||||||
meks: z.array(
|
|
||||||
z.object({
|
|
||||||
clientId: z.number().int().positive(),
|
|
||||||
mek: z.string().base64().nonempty(),
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
await registerNewActiveMek(
|
|
||||||
userId,
|
|
||||||
clientId,
|
|
||||||
meks.map(({ clientId, mek }) => ({
|
|
||||||
clientId,
|
|
||||||
encMek: mek,
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
return text("MEK registered", { headers: { "Content-Type": "text/plain" } });
|
|
||||||
};
|
|
||||||
@@ -11,14 +11,15 @@ export const POST: RequestHandler = async ({ request, cookies }) => {
|
|||||||
error(403, "Forbidden");
|
error(403, "Forbidden");
|
||||||
}
|
}
|
||||||
|
|
||||||
const { mek } = await parseSignedRequest(
|
const { mek, mekSig } = await parseSignedRequest(
|
||||||
clientId,
|
clientId,
|
||||||
await request.json(),
|
await request.json(),
|
||||||
z.object({
|
z.object({
|
||||||
mek: z.string().base64().nonempty(),
|
mek: z.string().base64().nonempty(),
|
||||||
|
mekSig: z.string().base64().nonempty(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
await registerInitialActiveMek(userId, clientId, mek);
|
await registerInitialActiveMek(userId, clientId, mek, mekSig);
|
||||||
return text("MEK registered", { headers: { "Content-Type": "text/plain" } });
|
return text("MEK registered", { headers: { "Content-Type": "text/plain" } });
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
import { text } from "@sveltejs/kit";
|
|
||||||
import { z } from "zod";
|
|
||||||
import { authorize } from "$lib/server/modules/auth";
|
|
||||||
import { parseSignedRequest } from "$lib/server/modules/crypto";
|
|
||||||
import { shareMeksForNewClient } from "$lib/server/services/mek";
|
|
||||||
import type { RequestHandler } from "./$types";
|
|
||||||
|
|
||||||
export const POST: RequestHandler = async ({ request, cookies }) => {
|
|
||||||
const { userId, clientId } = await authorize(cookies, "activeClient");
|
|
||||||
const { targetId, meks } = await parseSignedRequest(
|
|
||||||
clientId,
|
|
||||||
await request.json(),
|
|
||||||
z.object({
|
|
||||||
targetId: z.number().int().positive(),
|
|
||||||
meks: z.array(
|
|
||||||
z.object({
|
|
||||||
version: z.number().int().positive(),
|
|
||||||
mek: z.string().base64().nonempty(),
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
await shareMeksForNewClient(
|
|
||||||
userId,
|
|
||||||
targetId,
|
|
||||||
meks.map(({ version, mek }) => ({ version, encMek: mek })),
|
|
||||||
);
|
|
||||||
return text("MEK shared", { headers: { "Content-Type": "text/plain" } });
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user