Files
peardata/client/identity.js
T
Raven Scott f7e26d1aac
Release rolling / release (push) Successful in 25s
CI / test (push) Successful in 28s
Testing
2026-07-18 16:33:43 -04:00

89 lines
2.1 KiB
JavaScript

/**
* Persistent client DHT identity for stable peerId across reconnects.
* Stored at ~/.config/peardata/identity.json (mode 0600).
*
* Uses fs/path/os/crypto via package.json import maps → bare-* under Bare/Pear.
*/
import fs from 'fs'
import path from 'path'
import os from 'os'
import crypto from 'crypto'
import DHT from 'hyperdht'
import b4a from 'b4a'
const IDENTITY_VERSION = 1
function envGet(name) {
try {
return typeof process !== 'undefined' ? process.env?.[name] : undefined
} catch {
return undefined
}
}
export function getIdentityPath() {
const home =
envGet('PEARDATA_HOME') ||
envGet('HOME') ||
envGet('USERPROFILE') ||
(typeof os.homedir === 'function' ? os.homedir() : '') ||
''
return path.join(home, '.config', 'peardata', 'identity.json')
}
export function loadOrCreateClientIdentity() {
const filePath = getIdentityPath()
let seedHex = null
try {
if (fs.existsSync(filePath)) {
const raw = JSON.parse(fs.readFileSync(filePath, 'utf8'))
if (raw?.seedHex && /^[0-9a-fA-F]{64}$/.test(raw.seedHex)) {
seedHex = String(raw.seedHex).toLowerCase()
}
}
} catch {
// regenerate
}
if (!seedHex) {
seedHex = b4a.toString(crypto.randomBytes(32), 'hex')
try {
const dir = path.dirname(filePath)
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true, mode: 0o700 })
fs.writeFileSync(
filePath,
JSON.stringify(
{
version: IDENTITY_VERSION,
seedHex,
createdAt: new Date().toISOString(),
},
null,
2
),
{ mode: 0o600 }
)
try {
fs.chmodSync(filePath, 0o600)
} catch {
// ignore
}
} catch {
// In-memory only if FS unavailable
}
}
const seed = b4a.from(seedHex, 'hex')
const keyPair = DHT.keyPair(seed)
const publicKeyHex = b4a.toString(keyPair.publicKey, 'hex')
return { seed, keyPair, publicKeyHex, seedHex }
}
let cached = null
export function getClientIdentity() {
if (!cached) cached = loadOrCreateClientIdentity()
return cached
}