65 lines
1.9 KiB
JavaScript
65 lines
1.9 KiB
JavaScript
/**
|
|
* Persistent HyperDHT keypair management.
|
|
* SERVER_SEED (32-byte hex) is the secret seed.
|
|
* Clients connect using the derived public key.
|
|
*/
|
|
import fs from 'fs'
|
|
import path from 'path'
|
|
import DHT from 'hyperdht'
|
|
import b4a from 'b4a'
|
|
import crypto from 'hypercore-crypto'
|
|
import dotenv from 'dotenv'
|
|
import logger from '../utils/logger.js'
|
|
|
|
dotenv.config()
|
|
|
|
const log = logger.child('keys')
|
|
|
|
/**
|
|
* @param {string} [envPath]
|
|
*/
|
|
export function loadOrCreateKeyPair(envPath = '.env') {
|
|
let seedHex = process.env.SERVER_SEED || process.env.SERVER_KEY
|
|
|
|
if (!seedHex) {
|
|
const seed = crypto.randomBytes(32)
|
|
seedHex = b4a.toString(seed, 'hex')
|
|
const publicKeyHex = b4a.toString(DHT.keyPair(seed).publicKey, 'hex')
|
|
const line = `\nSERVER_SEED=${seedHex}\nSERVER_PUBLIC_KEY=${publicKeyHex}\n`
|
|
fs.appendFileSync(envPath, line, { flag: 'a' })
|
|
log.info('Generated new SERVER_SEED and SERVER_PUBLIC_KEY', {
|
|
path: path.resolve(envPath),
|
|
})
|
|
}
|
|
|
|
if (!/^[0-9a-fA-F]{64}$/.test(seedHex)) {
|
|
throw new Error('SERVER_SEED must be 64 hex characters (32 bytes)')
|
|
}
|
|
|
|
const seed = b4a.from(seedHex, 'hex')
|
|
const keyPair = DHT.keyPair(seed)
|
|
const publicKeyHex = b4a.toString(keyPair.publicKey, 'hex')
|
|
|
|
if (process.env.SERVER_PUBLIC_KEY !== publicKeyHex) {
|
|
try {
|
|
let env = fs.existsSync(envPath) ? fs.readFileSync(envPath, 'utf8') : ''
|
|
if (env.includes('SERVER_PUBLIC_KEY=')) {
|
|
env = env.replace(/SERVER_PUBLIC_KEY=.*/g, `SERVER_PUBLIC_KEY=${publicKeyHex}`)
|
|
} else {
|
|
env += `\nSERVER_PUBLIC_KEY=${publicKeyHex}\n`
|
|
}
|
|
if (!env.includes('SERVER_SEED=')) {
|
|
env += `SERVER_SEED=${seedHex}\n`
|
|
}
|
|
fs.writeFileSync(envPath, env)
|
|
} catch (err) {
|
|
log.warn('Could not update .env with SERVER_PUBLIC_KEY', { error: err.message })
|
|
}
|
|
}
|
|
|
|
process.env.SERVER_SEED = seedHex
|
|
process.env.SERVER_PUBLIC_KEY = publicKeyHex
|
|
|
|
return { seed, keyPair, publicKeyHex, seedHex }
|
|
}
|