From 24261666760fd1c0352628f9109a49ccb8c78086 Mon Sep 17 00:00:00 2001 From: charlesgauthereau Date: Thu, 12 Feb 2026 18:46:11 +0100 Subject: [PATCH] fix: working on AEA-GCM encryption. --- .../(admin)/agents/[agentId]/page.tsx | 2 +- src/features/keys/keys.action.ts | 16 ++++++++++ src/utils/edge_key.ts | 10 +++--- src/utils/init.ts | 5 +-- src/utils/rsa-keys.ts | 31 +++++++++++++++++++ 5 files changed, 56 insertions(+), 8 deletions(-) diff --git a/app/(customer)/dashboard/(admin)/agents/[agentId]/page.tsx b/app/(customer)/dashboard/(admin)/agents/[agentId]/page.tsx index 4959e901..29dcd6e2 100644 --- a/app/(customer)/dashboard/(admin)/agents/[agentId]/page.tsx +++ b/app/(customer)/dashboard/(admin)/agents/[agentId]/page.tsx @@ -28,7 +28,7 @@ export default async function RoutePage(props: PageParams<{ agentId: string }>) } const edgeKey = await generateEdgeKey(getServerUrl(), agent.id); - + return (
diff --git a/src/features/keys/keys.action.ts b/src/features/keys/keys.action.ts index 1cd6251a..894595fe 100644 --- a/src/features/keys/keys.action.ts +++ b/src/features/keys/keys.action.ts @@ -15,3 +15,19 @@ export function getPublicServerKeyContent() { }; } } + + +/** + * Get Master server key + */ +export function getMasterServerKeyContent() { + try { + return fs.readFileSync("private/keys/master_key.bin"); + } catch (error: any) { + console.error("Error :", error); + return { + success: false, + message: `An error occurred while getting master server key`, + }; + } +} diff --git a/src/utils/edge_key.ts b/src/utils/edge_key.ts index 71810957..7be159c6 100644 --- a/src/utils/edge_key.ts +++ b/src/utils/edge_key.ts @@ -1,16 +1,16 @@ "use server" -import {getPublicServerKeyContent} from "@/features/keys/keys.action"; +import {getMasterServerKeyContent} from "@/features/keys/keys.action"; export async function generateEdgeKey(serverUrl: string, agentId: string): Promise { - const publicKey = getPublicServerKeyContent() + const masterKey = getMasterServerKeyContent() + console.log("Master server key: ", masterKey) const edgeKeyData = { serverUrl, agentId, - publicKey + masterKeyB64: masterKey.toString('base64') }; const edgeKeyJson = JSON.stringify(edgeKeyData); - const edgeKeyBuffer = Buffer.from(edgeKeyJson, 'utf-8'); - return edgeKeyBuffer.toString('base64').replace(/=+$/, '').replace(/\+/g, '-').replace(/\//g, '_'); + return Buffer.from(edgeKeyJson, 'utf-8').toString('base64'); } function decodeEdgeKey(edgeKey: string): object { diff --git a/src/utils/init.ts b/src/utils/init.ts index d6a9b340..9344b763 100644 --- a/src/utils/init.ts +++ b/src/utils/init.ts @@ -3,13 +3,14 @@ import {db, makeMigration} from "@/db"; import {eq} from "drizzle-orm"; import * as drizzleDb from "@/db"; import {retentionJob} from "@/lib/tasks"; -import {generateRSAKeys} from "@/utils/rsa-keys"; +import {generateRSAKeys, getOrCreateMasterKey} from "@/utils/rsa-keys"; import {StorageProviderKind} from "@/features/storages/types"; export async function init() { consoleAscii(); console.log("====Init Functions===="); + await getOrCreateMasterKey(); await generateRSAKeys(); await makeMigration(); await createDefaultOrganization(); @@ -82,7 +83,7 @@ async function createSettingsIfNotExist() { if (!finalSystemSetting.defaultStorageChannelId) { await tx .update(drizzleDb.schemas.setting) - .set({ defaultStorageChannelId: localStorage.id }) + .set({defaultStorageChannelId: localStorage.id}) .where(eq(drizzleDb.schemas.setting.id, finalSystemSetting.id)); } }); diff --git a/src/utils/rsa-keys.ts b/src/utils/rsa-keys.ts index e6f5df9a..4f51effc 100644 --- a/src/utils/rsa-keys.ts +++ b/src/utils/rsa-keys.ts @@ -2,6 +2,7 @@ import {promises as fs} from 'fs'; import path from 'path'; import {generateKeyPair} from 'crypto'; import {promisify} from 'util'; +import {randomBytes} from 'crypto'; const generateKeyPairAsync = promisify(generateKeyPair); @@ -37,3 +38,33 @@ export async function generateRSAKeys(dir = path.join(process.cwd(), 'private/ke return {privateKeyPath, publicKeyPath}; } + + +/** + * Generate a 256-bit AES master key for AES-256-GCM. + * - Skips generation if the file already exists. + * - File mode 0o600 for private key. + * @param {string} [filePath] Path to store the key + * @returns {Promise} The master key + */ +export async function getOrCreateMasterKey(filePath = path.join(process.cwd(), 'private/keys', 'master_key.bin')) { + + await fs.mkdir(path.dirname(filePath), {recursive: true}); + + try { + const existing = await fs.readFile(filePath); + console.log('Master key already exists. Skipping generation.'); + return existing; + } catch { + // File does not exist, generate + } + + const key = randomBytes(32); // 256-bit key + + console.log(key) + + await fs.writeFile(filePath, key, {mode: 0o600}); + console.log(`Master key generated at ${filePath}`); + + return key; +} \ No newline at end of file