From b0a1f3fc058d669e73708cf1c887d77fa8c25482 Mon Sep 17 00:00:00 2001 From: HDegroote <75906619+HDegroote@users.noreply.github.com> Date: Mon, 26 Feb 2024 00:18:29 +0100 Subject: [PATCH 1/6] Add key-file opt (temp secure-key dependency) --- client.js | 200 ++++++++++++++++++++++--------------- package.json | 4 +- server.js | 208 +++++++++++++++++++++++---------------- test/end-to-end-tests.js | 79 +++++++++++++-- 4 files changed, 317 insertions(+), 174 deletions(-) diff --git a/client.js b/client.js index cad54fa..208879b 100644 --- a/client.js +++ b/client.js @@ -8,112 +8,148 @@ const libUtils = require('@hyper-cmd/lib-utils') const libKeys = require('@hyper-cmd/lib-keys') const goodbye = require('graceful-goodbye') const connPiper = libNet.connPiper +const SecureKey = require('secure-key') -const helpMsg = 'Usage:\nhypertele -p port_listen -u unix_socket ?--address service_address ?-c conf.json ?-i identity.json ?-s peer_key ?--private' +async function main () { + const helpMsg = 'Usage:\nhypertele -p port_listen -u unix_socket ?--address service_address ?-c conf.json ?-i identity.json ?-s peer_key ?--private ?--key-file ?--key-file-password' -if (argv.help) { - console.log(helpMsg) - process.exit(-1) -} + if (argv.help) { + console.log(helpMsg) + process.exit(-1) + } -if (!argv.u && argv.p == null) { - console.error('Error: proxy port invalid') - process.exit(-1) -} + if (!argv.u && argv.p == null) { + console.error('Error: proxy port invalid') + process.exit(-1) + } -if (argv.u && argv.p) { - console.error('Error: cannot listen to both a port and a Unix domain socket') - process.exit(-1) -} -const conf = {} + if (argv.u && argv.p) { + console.error('Error: cannot listen to both a port and a Unix domain socket') + process.exit(-1) + } + const conf = {} + conf.private = argv.private != null + + const target = argv.u ? argv.u : +argv.p + + const keyPair = await getKeyPair(argv, conf) -const target = argv.u ? argv.u : +argv.p + // Unofficial opt, only used for tests + let bootstrap = null + if (argv.bootstrap) { + bootstrap = [{ host: '127.0.0.1', port: argv.bootstrap }] + } + + if (argv['key-file']) { + conf.peer = keyPair.publicKey + } + if (argv.s) { + conf.peer = conf.private + ? keyPair.publicKey + : libUtils.resolveHostToKey([], argv.s) + } -let keyPair = null -if (argv.i) { - keyPair = libUtils.resolveIdentity([], argv.i) + if (argv.c) { + libUtils.readConf(conf, argv.c) + } - if (!keyPair) { - console.error('Error: identity file invalid') + if (!conf.keepAlive) { + conf.keepAlive = 5000 + } + + if (argv.compress) { + conf.compress = true + } + + const peer = conf.peer + if (!peer) { + console.error('Error: peer is invalid') process.exit(-1) } - keyPair = libKeys.parseKeyPair(keyPair) -} + const debug = argv.debug -conf.private = argv.private != null -if (conf.private) { - if (keyPair != null) throw new Error('The --private flag is not compatible with the -i(dentity) flag, since the identity is derived from the peer key') - const seed = argv.s - keyPair = HyperDHT.keyPair(b4a.from(seed, 'hex')) -} + const stats = {} -// Unofficial opt, only used for tests -let bootstrap = null -if (argv.bootstrap) { - bootstrap = [{ host: '127.0.0.1', port: argv.bootstrap }] -} + const dht = new HyperDHT({ + bootstrap, + keyPair + }) -if (argv.s) { - conf.peer = conf.private - ? keyPair.publicKey - : libUtils.resolveHostToKey([], argv.s) -} + const proxy = net.createServer({ allowHalfOpen: true }, c => { + return connPiper(c, () => { + const stream = dht.connect(Buffer.from(peer, 'hex'), { reusableSocket: true }) + stream.setKeepAlive(conf.keepAlive) -if (argv.c) { - libUtils.readConf(conf, argv.c) -} + return stream + }, { compress: conf.comgetKeyPairpress }, stats) + }) -if (!conf.keepAlive) { - conf.keepAlive = 5000 -} + if (debug) { + setInterval(() => { + console.log('connection stats', stats) + }, 5000) + } -if (argv.compress) { - conf.compress = true -} + if (argv.u) { + proxy.listen(target, () => { + console.log(`Server ready @${target}`) + }) + } else { + const targetHost = argv.address || '127.0.0.1' + proxy.listen(target, targetHost, () => { + const { address, port } = proxy.address() + console.log(`Server ready @${address}:${port}`) + }) + } -const peer = conf.peer -if (!peer) { - console.error('Error: peer is invalid') - process.exit(-1) + goodbye(async () => { + await dht.destroy() + }) } -const debug = argv.debug +async function getKeyPair (argv, conf) { + if (argv['key-file']) { + const password = argv['key-file-password'] + ? b4a.from(argv['key-file-password']) + : null // read from stdin if not specified -const stats = {} + const secureKeyPair = await SecureKey.open(argv['key-file'], { password }) -const dht = new HyperDHT({ - bootstrap, - keyPair -}) + secureKeyPair.unlock() + const keyPair = { + publicKey: b4a.from(secureKeyPair.publicKey), + secretKey: b4a.from(secureKeyPair.secretKey) + } + secureKeyPair.lock() + secureKeyPair.clear() -const proxy = net.createServer({ allowHalfOpen: true }, c => { - return connPiper(c, () => { - const stream = dht.connect(Buffer.from(peer, 'hex'), { reusableSocket: true }) - stream.setKeepAlive(conf.keepAlive) + return keyPair + } - return stream - }, { compress: conf.compress }, stats) -}) + if (argv.i && conf.private) { + throw new Error('The --private flag is not compatible with the -i(dentity) flag, since the identity is derived from the peer key') + } -if (debug) { - setInterval(() => { - console.log('connection stats', stats) - }, 5000) -} + let keyPair = null -if (argv.u) { - proxy.listen(target, () => { - console.log(`Server ready @${target}`) - }) -} else { - const targetHost = argv.address || '127.0.0.1' - proxy.listen(target, targetHost, () => { - const { address, port } = proxy.address() - console.log(`Server ready @${address}:${port}`) - }) + if (argv.i) { + keyPair = libUtils.resolveIdentity([], argv.i) + + if (!keyPair) { + console.error('Error: identity file invalid') + process.exit(-1) + } + + keyPair = libKeys.parseKeyPair(keyPair) + } + + if (conf.private) { + const seed = argv.s + keyPair = HyperDHT.keyPair(b4a.from(seed, 'hex')) + } + + return keyPair } -goodbye(async () => { - await dht.destroy() -}) +main() diff --git a/package.json b/package.json index 865eea2..a705535 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "@hyper-cmd/lib-keys": "https://github.com/holepunchto/hyper-cmd-lib-keys#v0.0.2", "@hyper-cmd/lib-net": "https://github.com/holepunchto/hyper-cmd-lib-net#v0.0.8", "@hyper-cmd/lib-utils": "https://github.com/holepunchto/hyper-cmd-lib-utils#v0.0.2", + "secure-key": "https://github.com/holepunchto/secure-key", "b4a": "^1.6.4", "graceful-goodbye": "^1.3.0", "hyperdht": "^6.11.0", @@ -28,7 +29,8 @@ "homepage": "https://github.com/bitfinexcom/hypertele", "devDependencies": { "brittle": "^3.3.2", - "standard": "^17.1.0" + "standard": "^17.1.0", + "test-tmp": "^1.2.0" }, "scripts": { "test": "standard && brittle test/end-to-end-tests.js" diff --git a/server.js b/server.js index fe6914b..1a18930 100644 --- a/server.js +++ b/server.js @@ -8,115 +8,153 @@ const libUtils = require('@hyper-cmd/lib-utils') const libKeys = require('@hyper-cmd/lib-keys') const goodbye = require('graceful-goodbye') const connPiper = libNet.connPiper +const SecureKey = require('secure-key') -const helpMsg = 'Usage:\nhypertele-server -l service_port -u unix_socket ?--address service_address ?-c conf.json ?--seed seed ?--cert-skip ?--private' +async function main () { + const helpMsg = 'Usage:\nhypertele-server -l service_port -u unix_socket ?--address service_address ?-c conf.json ?--seed seed ?--cert-skip ?--private ?--key-file ?--key-file-password' -if (argv.help) { - console.log(helpMsg) - process.exit(-1) -} + if (argv.help) { + console.log(helpMsg) + process.exit(-1) + } -if (!argv.u && !+argv.l) { - console.error('Error: proxy port invalid') - process.exit(-1) -} + if (!argv.u && !+argv.l) { + console.error('Error: proxy port invalid') + process.exit(-1) + } -if (argv.u && argv.l) { - console.error('Error: cannot listen to both a port and a Unix domain socket') - process.exit(-1) -} + if (argv.u && argv.l) { + console.error('Error: cannot listen to both a port and a Unix domain socket') + process.exit(-1) + } -const conf = {} + const conf = {} -if (argv.seed) { - conf.seed = argv.seed -} + if (argv.seed) { + conf.seed = argv.seed + } -if (argv.c) { - libUtils.readConf(conf, argv.c) -} + if (argv.c) { + libUtils.readConf(conf, argv.c) + } -if (argv.compress) { - conf.compress = true -} + if (argv.compress) { + conf.compress = true + } -if (argv['cert-skip']) { - process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0 -} + if (argv['cert-skip']) { + process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0 + } -if (!conf.seed) { - console.error('Error: conf.seed invalid') - process.exit(-1) -} + if (!conf.seed && !argv['key-file']) { + console.error('Error: conf.seed invalid') + process.exit(-1) + } -if (conf.allow) { - conf.allow = libKeys.prepKeyList(conf.allow) -} + if (conf.allow) { + conf.allow = libKeys.prepKeyList(conf.allow) + } -conf.private = false -if (argv.private) { - if (conf.allow) throw new Error('--private flag is not compatible with an allow list, as the private key derived from the seed is the capability') - conf.private = true -} + conf.private = false + if (argv.private) { + if (conf.allow) throw new Error('--private flag is not compatible with an allow list, as the private key derived from the seed is the capability') + conf.private = true + } -// Unofficial opt, only used for tests -let bootstrap = null -if (argv.bootstrap) { - bootstrap = [{ host: '127.0.0.1', port: argv.bootstrap }] + await setupServer(argv, conf) } -const debug = argv.debug +async function setupServer (argv, conf) { + // Unofficial opt, only used for tests + let bootstrap = null + if (argv.bootstrap) { + bootstrap = [{ host: '127.0.0.1', port: argv.bootstrap }] + } -const seed = Buffer.from(conf.seed, 'hex') + const debug = argv.debug -const dht = new HyperDHT({ bootstrap }) -const keyPair = HyperDHT.keyPair(seed) + const keyPair = await getKeyPair(conf, argv) -const stats = {} + const dht = new HyperDHT({ bootstrap }) -const destIp = argv.address || '127.0.0.1' + const stats = {} -const privateFirewall = (remotePublicKey) => { - return !b4a.equals(remotePublicKey, keyPair.publicKey) -} + const destIp = argv.address || '127.0.0.1' + + const privateFirewall = (remotePublicKey) => { + return !b4a.equals(remotePublicKey, keyPair.publicKey) + } + + const allowListFirewall = (remotePublicKey, remoteHandshakePayload) => { + if (conf.allow && !libKeys.checkAllowList(conf.allow, remotePublicKey)) { + return true + } + + return false + } -const allowListFirewall = (remotePublicKey, remoteHandshakePayload) => { - if (conf.allow && !libKeys.checkAllowList(conf.allow, remotePublicKey)) { - return true + const firewall = conf.private ? privateFirewall : allowListFirewall + + const server = dht.createServer({ + firewall, + reusableSocket: true + }, c => { + connPiper(c, () => { + return net.connect( + argv.u + ? { path: argv.u } + : { port: +argv.l, host: destIp, allowHalfOpen: true } + ) + }, { debug, isServer: true, compress: conf.compress }, stats) + }) + + server.listen(keyPair).then(() => { + if (conf.private) { + if (argv['key-file']) { + console.log(`hypertele (private, encrypted keypair): use the --key-file option with the same keypair to connect (listening on ${b4a.toString(keyPair.publicKey, 'hex')})`) + } else { + console.log(`hypertele (private): connect with seed ${conf.seed} (listening on ${b4a.toString(keyPair.publicKey, 'hex')})`) + } + } else { + console.log('hypertele:', keyPair.publicKey.toString('hex')) + } + }) + + if (debug) { + setInterval(() => { + console.log('connection stats', stats) + }, 5000) } - return false + goodbye(async () => { + await dht.destroy() + }) } -const firewall = conf.private ? privateFirewall : allowListFirewall - -const server = dht.createServer({ - firewall, - reusableSocket: true -}, c => { - connPiper(c, () => { - return net.connect( - argv.u - ? { path: argv.u } - : { port: +argv.l, host: destIp, allowHalfOpen: true } - ) - }, { debug, isServer: true, compress: conf.compress }, stats) -}) - -server.listen(keyPair).then(() => { - if (conf.private) { - console.log(`hypertele (private): connect with seed ${b4a.toString(seed, 'hex')} (listening on ${b4a.toString(keyPair.publicKey, 'hex')})`) - } else { - console.log('hypertele:', keyPair.publicKey.toString('hex')) - } -}) - -if (debug) { - setInterval(() => { - console.log('connection stats', stats) - }, 5000) +async function getKeyPair (conf, argv) { + if (conf.seed) { + return HyperDHT.keyPair(Buffer.from(conf.seed, 'hex')) + } + + if (!argv['key-file']) { + throw new Error('--seed or --key-file must be specified') + } + + const password = argv['key-file-password'] + ? b4a.from(argv['key-file-password']) + : null // read from stdin if not specified + + const secureKeyPair = await SecureKey.open(argv['key-file'], { password }) + + secureKeyPair.unlock() + const keyPair = { + publicKey: b4a.from(secureKeyPair.publicKey), + secretKey: b4a.from(secureKeyPair.secretKey) + } + secureKeyPair.lock() + secureKeyPair.clear() + + return keyPair } -goodbye(async () => { - await dht.destroy() -}) +main() diff --git a/test/end-to-end-tests.js b/test/end-to-end-tests.js index 9e79f99..1265747 100644 --- a/test/end-to-end-tests.js +++ b/test/end-to-end-tests.js @@ -6,11 +6,15 @@ const createTestnet = require('hyperdht/testnet') const test = require('brittle') const HyperDHT = require('hyperdht') const b4a = require('b4a') +const tmp = require('test-tmp') +const SecureKey = require('secure-key') const MAIN_DIR = path.dirname(__dirname) const SERVER_EXECUTABLE = path.join(MAIN_DIR, 'server.js') const CLIENT_EXECUTABLE = path.join(MAIN_DIR, 'client.js') +const DEBUG_LOG = false + test('Can proxy in private mode', async t => { const { bootstrap } = await createTestnet(3, t.teardown) const portToProxy = await setupDummyServer(t.teardown) @@ -51,6 +55,33 @@ test('Can proxy in non-private mode', async t => { t.is(res.data, 'You got served', 'Proxy works') }) +test('Can proxy with key-file (private mode)', async t => { + const { bootstrap } = await createTestnet(3, t.teardown) + const portToProxy = await setupDummyServer(t.teardown) + const { password, keyFile } = await setupKeyPairFile(t) + + console.log('setting up server') + await setupHyperteleServer( + portToProxy, + null, + bootstrap, + t, + { isPrivate: true, keyFile, password } + ) + console.log('setup server') + const clientPort = await setupHyperteleClient( + null, + bootstrap, + t, + { isPrivate: true, keyFile, password } + ) + console.log('setup client') + const res = await request(clientPort) + t.is(res.data, 'You got served', 'Proxy works') + console.log('password:', password) + console.log('keyFile:', keyFile) +}) + async function setupDummyServer (teardown) { const server = http.createServer(async (req, res) => { res.setHeader('Content-Type', 'text/html; charset=utf-8') @@ -63,16 +94,24 @@ async function setupDummyServer (teardown) { return server.address().port } -async function setupHyperteleServer (portToProxy, seed, bootstrap, t, { isPrivate = false } = {}) { +async function setupHyperteleServer (portToProxy, seed, bootstrap, t, { isPrivate = false, keyFile, password } = {}) { const args = [ SERVER_EXECUTABLE, '-l', portToProxy, - '--seed', - seed, '--bootstrap', bootstrap[0].port ] + if (seed) { + args.push('--seed') + args.push(seed) + } + if (keyFile) { + args.push('--key-file') + args.push(keyFile) + args.push('--key-file-password') + args.push(password) + } if (isPrivate) args.push('--private') const setupServer = spawn('node', args) @@ -83,6 +122,10 @@ async function setupHyperteleServer (portToProxy, seed, bootstrap, t, { isPrivat t.fail('Failed to setup hypertele server') }) + setupServer.stdout.on('data', (data) => { + if (DEBUG_LOG) console.debug(console.debug(data.toString())) + }) + await new Promise(resolve => { setupServer.stdout.on('data', (data) => { if (data.includes('hypertele')) { @@ -92,16 +135,24 @@ async function setupHyperteleServer (portToProxy, seed, bootstrap, t, { isPrivat }) } -async function setupHyperteleClient (seed, bootstrap, t, { isPrivate = false } = {}) { +async function setupHyperteleClient (seed, bootstrap, t, { isPrivate = false, keyFile, password } = {}) { const args = [ CLIENT_EXECUTABLE, '-p', 0, // random - '-s', - seed, '--bootstrap', bootstrap[0].port ] + if (seed) { + args.push('-s') + args.push(seed) + } + if (keyFile) { + args.push('--key-file') + args.push(keyFile) + args.push('--key-file-password') + args.push(password) + } if (isPrivate) args.push('--private') const setupClient = spawn('node', args) @@ -112,6 +163,10 @@ async function setupHyperteleClient (seed, bootstrap, t, { isPrivate = false } = t.fail('Failed to setup hypertele client') }) + setupClient.stdout.on('data', (data) => { + if (DEBUG_LOG) console.debug(data.toString()) + }) + const clientPort = await new Promise(resolve => { setupClient.stdout.on('data', (data) => { const msg = data.toString() @@ -158,3 +213,15 @@ async function request (port, { msTimeout = 500 } = {}) { }) }) } + +async function setupKeyPairFile (t) { + const password = `dummy-pass-${Math.random().toString().slice(2)}` + + const keysDir = await tmp(t) + const keyFile = path.join(keysDir, 'test-key') + await SecureKey.generate(keyFile, { password: b4a.from(password) }) + return { + keyFile, + password + } +} From 7c4f0efd11fabea51404e876ad3295b8b5b1f815 Mon Sep 17 00:00:00 2001 From: HDegroote <75906619+HDegroote@users.noreply.github.com> Date: Mon, 26 Feb 2024 11:42:42 +0100 Subject: [PATCH 2/6] Handle and test non-private mode --- client.js | 9 +++------ test/end-to-end-tests.js | 39 ++++++++++++++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/client.js b/client.js index 208879b..e79efdb 100644 --- a/client.js +++ b/client.js @@ -40,13 +40,10 @@ async function main () { bootstrap = [{ host: '127.0.0.1', port: argv.bootstrap }] } - if (argv['key-file']) { + if (conf.private) { conf.peer = keyPair.publicKey - } - if (argv.s) { - conf.peer = conf.private - ? keyPair.publicKey - : libUtils.resolveHostToKey([], argv.s) + } else if (argv.s) { + conf.peer = libUtils.resolveHostToKey([], argv.s) } if (argv.c) { diff --git a/test/end-to-end-tests.js b/test/end-to-end-tests.js index 1265747..cbd88fd 100644 --- a/test/end-to-end-tests.js +++ b/test/end-to-end-tests.js @@ -8,6 +8,7 @@ const HyperDHT = require('hyperdht') const b4a = require('b4a') const tmp = require('test-tmp') const SecureKey = require('secure-key') +const fsProm = require('fs/promises') const MAIN_DIR = path.dirname(__dirname) const SERVER_EXECUTABLE = path.join(MAIN_DIR, 'server.js') @@ -60,7 +61,6 @@ test('Can proxy with key-file (private mode)', async t => { const portToProxy = await setupDummyServer(t.teardown) const { password, keyFile } = await setupKeyPairFile(t) - console.log('setting up server') await setupHyperteleServer( portToProxy, null, @@ -68,18 +68,47 @@ test('Can proxy with key-file (private mode)', async t => { t, { isPrivate: true, keyFile, password } ) - console.log('setup server') + const clientPort = await setupHyperteleClient( null, bootstrap, t, { isPrivate: true, keyFile, password } ) - console.log('setup client') + + const res = await request(clientPort) + t.is(res.data, 'You got served', 'Proxy works') +}) + +test('Can proxy with key-file (non-private server)', async t => { + const { bootstrap } = await createTestnet(3, t.teardown) + const portToProxy = await setupDummyServer(t.teardown) + const keyFileInfos = await Promise.all([ + setupKeyPairFile(t), + setupKeyPairFile(t) + ]) + const { password: passwordServer, keyFile: keyFileServer } = keyFileInfos[0] + const { password: passwordClient, keyFile: keyFileClient } = keyFileInfos[1] + + const pubKey = await fsProm.readFile(`${keyFileServer}.public`, 'hex') + + await setupHyperteleServer( + portToProxy, + null, + bootstrap, + t, + { isPrivate: false, keyFile: keyFileServer, password: passwordServer } + ) + + const clientPort = await setupHyperteleClient( + pubKey, + bootstrap, + t, + { isPrivate: false, keyFile: keyFileClient, password: passwordClient } + ) + const res = await request(clientPort) t.is(res.data, 'You got served', 'Proxy works') - console.log('password:', password) - console.log('keyFile:', keyFile) }) async function setupDummyServer (teardown) { From 75eb4225e9c4da8c663ab444d03e54ec62edda24 Mon Sep 17 00:00:00 2001 From: HDegroote <75906619+HDegroote@users.noreply.github.com> Date: Mon, 26 Feb 2024 13:05:02 +0100 Subject: [PATCH 3/6] Early exit on private + key-file + seed options in client --- client.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client.js b/client.js index e79efdb..42ec35d 100644 --- a/client.js +++ b/client.js @@ -107,6 +107,8 @@ async function main () { async function getKeyPair (argv, conf) { if (argv['key-file']) { + if (argv.s && conf.private) throw new Error('key-file is not compatible with -s(eed) in private mode, since it uses the keys in the key-file instead of the seed') + const password = argv['key-file-password'] ? b4a.from(argv['key-file-password']) : null // read from stdin if not specified From 99e9bb57b0de785258fa2bfdb6498578a4cc8a2b Mon Sep 17 00:00:00 2001 From: HDegroote <75906619+HDegroote@users.noreply.github.com> Date: Mon, 26 Feb 2024 13:39:58 +0100 Subject: [PATCH 4/6] Use published secure-key --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a705535..38f297e 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "@hyper-cmd/lib-keys": "https://github.com/holepunchto/hyper-cmd-lib-keys#v0.0.2", "@hyper-cmd/lib-net": "https://github.com/holepunchto/hyper-cmd-lib-net#v0.0.8", "@hyper-cmd/lib-utils": "https://github.com/holepunchto/hyper-cmd-lib-utils#v0.0.2", - "secure-key": "https://github.com/holepunchto/secure-key", + "secure-key": "^1.0.0", "b4a": "^1.6.4", "graceful-goodbye": "^1.3.0", "hyperdht": "^6.11.0", From 22d00b9bf4228fe1a1e048e221fa78ad9e20402f Mon Sep 17 00:00:00 2001 From: HDegroote <75906619+HDegroote@users.noreply.github.com> Date: Mon, 26 Feb 2024 13:55:24 +0100 Subject: [PATCH 5/6] Cleaner error logs --- client.js | 2 +- server.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client.js b/client.js index 42ec35d..3f6c995 100644 --- a/client.js +++ b/client.js @@ -151,4 +151,4 @@ async function getKeyPair (argv, conf) { return keyPair } -main() +main().catch(console.error) diff --git a/server.js b/server.js index 1a18930..7de31c4 100644 --- a/server.js +++ b/server.js @@ -157,4 +157,4 @@ async function getKeyPair (conf, argv) { return keyPair } -main() +main().catch(console.error) From 351408f36b91ff18ba66701301357d191fbbc7d0 Mon Sep 17 00:00:00 2001 From: HDegroote <75906619+HDegroote@users.noreply.github.com> Date: Mon, 26 Feb 2024 15:55:53 +0100 Subject: [PATCH 6/6] Document --key-file and --key-file-password --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 8e5d5ec..e14eb9d 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,9 @@ options: --seed SEED : seed (command-line) --compress : enable chunk compression --private : make the proxy private (do not leak the access capability to the DHT) +--key-file : load the key pair from the secure-key file at the specified location (https://github.com/holepunchto/secure-key) +--key-file-password : pass in the secure-key password (the default is to read it from stdin) + ``` ```sh @@ -106,6 +109,8 @@ options: -i keypair.json : keypair file --compress : enable chunk compression --private : access a private hypertele server (expects -s to contain the server's seed instead of the public key) +--key-file : load the key pair from the secure-key file at the specified location (https://github.com/holepunchto/secure-key). In private mode, this should be the same file as used to launch the server. +--key-file-password : pass in the secure-key password (the default is to read it from stdin) ``` Read more about using identities here: https://github.com/prdn/hyper-cmd-docs/blob/main/identity.md