mirror of
https://github.com/kmc7468/arkvault.git
synced 2025-12-15 06:18:48 +00:00
MEK 관련 DB 스키마 생성
This commit is contained in:
@@ -47,7 +47,7 @@ export const setUserClientStateToPending = async (userId: number, clientId: numb
|
|||||||
export const createUserClientChallenge = async (
|
export const createUserClientChallenge = async (
|
||||||
userId: number,
|
userId: number,
|
||||||
clientId: number,
|
clientId: number,
|
||||||
challenge: string,
|
answer: string,
|
||||||
allowedIp: string,
|
allowedIp: string,
|
||||||
expiresAt: Date,
|
expiresAt: Date,
|
||||||
) => {
|
) => {
|
||||||
@@ -56,20 +56,20 @@ export const createUserClientChallenge = async (
|
|||||||
.values({
|
.values({
|
||||||
userId,
|
userId,
|
||||||
clientId,
|
clientId,
|
||||||
challenge,
|
answer,
|
||||||
allowedIp,
|
allowedIp,
|
||||||
expiresAt,
|
expiresAt,
|
||||||
})
|
})
|
||||||
.execute();
|
.execute();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getUserClientChallenge = async (challenge: string, ip: string) => {
|
export const getUserClientChallenge = async (answer: string, ip: string) => {
|
||||||
const challenges = await db
|
const challenges = await db
|
||||||
.select()
|
.select()
|
||||||
.from(userClientChallenge)
|
.from(userClientChallenge)
|
||||||
.where(
|
.where(
|
||||||
and(
|
and(
|
||||||
eq(userClientChallenge.challenge, challenge),
|
eq(userClientChallenge.answer, answer),
|
||||||
eq(userClientChallenge.allowedIp, ip),
|
eq(userClientChallenge.allowedIp, ip),
|
||||||
gt(userClientChallenge.expiresAt, new Date()),
|
gt(userClientChallenge.expiresAt, new Date()),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ export const userClient = sqliteTable(
|
|||||||
state: text("state", { enum: ["challenging", "pending", "active"] })
|
state: text("state", { enum: ["challenging", "pending", "active"] })
|
||||||
.notNull()
|
.notNull()
|
||||||
.default("challenging"),
|
.default("challenging"),
|
||||||
encKey: text("encrypted_key"),
|
|
||||||
},
|
},
|
||||||
(t) => ({
|
(t) => ({
|
||||||
pk: primaryKey({ columns: [t.userId, t.clientId] }),
|
pk: primaryKey({ columns: [t.userId, t.clientId] }),
|
||||||
@@ -33,7 +32,7 @@ export const userClientChallenge = sqliteTable("user_client_challenge", {
|
|||||||
clientId: integer("client_id")
|
clientId: integer("client_id")
|
||||||
.notNull()
|
.notNull()
|
||||||
.references(() => client.id),
|
.references(() => client.id),
|
||||||
challenge: text("challenge").notNull().unique(), // Base64
|
answer: text("challenge").notNull().unique(), // Base64
|
||||||
allowedIp: text("allowed_ip").notNull(),
|
allowedIp: text("allowed_ip").notNull(),
|
||||||
expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
|
expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
export * from "./client";
|
export * from "./client";
|
||||||
|
export * from "./mek";
|
||||||
export * from "./token";
|
export * from "./token";
|
||||||
export * from "./user";
|
export * from "./user";
|
||||||
|
|||||||
65
src/lib/server/db/schema/mek.ts
Normal file
65
src/lib/server/db/schema/mek.ts
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import { sqliteTable, text, integer, primaryKey, foreignKey } from "drizzle-orm/sqlite-core";
|
||||||
|
import { client } from "./client";
|
||||||
|
import { user } from "./user";
|
||||||
|
|
||||||
|
export const mek = sqliteTable(
|
||||||
|
"master_encryption_key",
|
||||||
|
{
|
||||||
|
userId: integer("user_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => user.id),
|
||||||
|
version: integer("version").notNull(),
|
||||||
|
createdBy: integer("created_by")
|
||||||
|
.notNull()
|
||||||
|
.references(() => client.id),
|
||||||
|
createdAt: integer("created_at", { mode: "timestamp_ms" }).notNull(),
|
||||||
|
state: text("state", { enum: ["pending", "active", "retired", "dead"] })
|
||||||
|
.notNull()
|
||||||
|
.default("pending"),
|
||||||
|
},
|
||||||
|
(t) => ({
|
||||||
|
pk: primaryKey({ columns: [t.userId, t.version] }),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const clientMek = sqliteTable(
|
||||||
|
"client_master_encryption_key",
|
||||||
|
{
|
||||||
|
userId: integer("user_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => user.id),
|
||||||
|
clientId: integer("client_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => client.id),
|
||||||
|
mekVersion: integer("master_encryption_key_version").notNull(),
|
||||||
|
encMek: text("encrypted_master_encryption_key").notNull(),
|
||||||
|
},
|
||||||
|
(t) => ({
|
||||||
|
pk: primaryKey({ columns: [t.userId, t.clientId, t.mekVersion] }),
|
||||||
|
ref: foreignKey({
|
||||||
|
columns: [t.userId, t.mekVersion],
|
||||||
|
foreignColumns: [mek.userId, mek.version],
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const mekChallenge = sqliteTable(
|
||||||
|
"master_encryption_key_challenge",
|
||||||
|
{
|
||||||
|
userId: integer("user_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => user.id),
|
||||||
|
mekVersion: integer("master_encryption_key_version").notNull(),
|
||||||
|
answer: text("answer").notNull().unique(), // Base64
|
||||||
|
challenge: text("challenge").unique(), // Base64
|
||||||
|
allowedIp: text("allowed_ip").notNull(),
|
||||||
|
expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
|
||||||
|
},
|
||||||
|
(t) => ({
|
||||||
|
pk: primaryKey({ columns: [t.userId, t.mekVersion] }),
|
||||||
|
ref: foreignKey({
|
||||||
|
columns: [t.userId, t.mekVersion],
|
||||||
|
foreignColumns: [mek.userId, mek.version],
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
);
|
||||||
@@ -17,13 +17,13 @@ const expiresIn = ms(env.challenge.pubKeyExp);
|
|||||||
const expiresAt = () => new Date(Date.now() + expiresIn);
|
const expiresAt = () => new Date(Date.now() + expiresIn);
|
||||||
|
|
||||||
const generateChallenge = async (userId: number, ip: string, clientId: number, pubKey: string) => {
|
const generateChallenge = async (userId: number, ip: string, clientId: number, pubKey: string) => {
|
||||||
const challenge = await promisify(randomBytes)(32);
|
const answer = await promisify(randomBytes)(32);
|
||||||
const challengeBase64 = challenge.toString("base64");
|
const answerBase64 = answer.toString("base64");
|
||||||
await createUserClientChallenge(userId, clientId, challengeBase64, ip, expiresAt());
|
await createUserClientChallenge(userId, clientId, answerBase64, ip, expiresAt());
|
||||||
|
|
||||||
const pubKeyPem = `-----BEGIN PUBLIC KEY-----\n${pubKey}\n-----END PUBLIC KEY-----`;
|
const pubKeyPem = `-----BEGIN PUBLIC KEY-----\n${pubKey}\n-----END PUBLIC KEY-----`;
|
||||||
const challengeEncrypted = publicEncrypt({ key: pubKeyPem, oaepHash: "sha256" }, challenge);
|
const challenge = publicEncrypt({ key: pubKeyPem, oaepHash: "sha256" }, answer);
|
||||||
return challengeEncrypted.toString("base64");
|
return challenge.toString("base64");
|
||||||
};
|
};
|
||||||
|
|
||||||
export const registerPubKey = async (userId: number, ip: string, pubKey: string) => {
|
export const registerPubKey = async (userId: number, ip: string, pubKey: string) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user