import fs from 'node:fs'; import path from 'node:path'; import { x25519, b64 } from './crypto.js'; export interface ChannelKeys { pub: string; priv: string; } /** Fresh channel x25519 keypair — generated by the channel's first user. */ export function newChannelKeypair(): ChannelKeys { const priv = x25519.utils.randomPrivateKey(); return { pub: b64(x25519.getPublicKey(priv)), priv: b64(priv) }; } /** Channels file: { "": { "pub": "", "priv": "" } }. * Missing or invalid file = no channels. */ export function loadChannelKeys(file: string): Record { try { const raw = JSON.parse(fs.readFileSync(file, 'utf8')) as Record>; const out: Record = {}; for (const [name, keys] of Object.entries(raw)) { if (typeof keys?.pub === 'string' && typeof keys?.priv === 'string') { out[name] = { pub: keys.pub, priv: keys.priv }; } } return out; } catch { return {}; } } /** Read-modify-write: keeps the other channels; creates the parent dir * (e.g. ~/.dap) on demand. */ export function persistChannelKeys(file: string, name: string, keys: ChannelKeys): void { const all = loadChannelKeys(file); all[name] = keys; fs.mkdirSync(path.dirname(file), { recursive: true }); fs.writeFileSync(file, JSON.stringify(all, null, 2) + '\n'); }