Skip to content

Instantly share code, notes, and snippets.

@pinheadmz
Last active June 14, 2022 00:01
Show Gist options
  • Save pinheadmz/680809e633467c56a3b3de33855bee38 to your computer and use it in GitHub Desktop.
Save pinheadmz/680809e633467c56a3b3de33855bee38 to your computer and use it in GitHub Desktop.
'use strict';
const assert = require('assert');
const path = require('path');
const fs = require('fs');
const os = require('os');
const {Chain, Pool} = require('hsd');
const NetAddress = require('hsd/lib/net/netaddress');
const Logger =require('hsd/node_modules/blgr');
const IP =require('hsd/node_modules/binet');
const secp256k1 = require('hsd/node_modules/bcrypto/lib/secp256k1');
const blake2b = require('hsd/node_modules/bcrypto/lib/blake2b');
const base32 = require('hsd/node_modules/bcrypto/lib/encoding/base32');
const MAGIC_STRING = 'HNS-PROVE-NODE';
const argv = process.argv;
if ( argv.length < 4
|| argv.length > 6
|| (argv[2] !== 'sign' && argv[2] !== 'verify'))
throw new Error(
'\nUSAGE: ' +
'node prove-node.js <sign|verify> <message> <signature> <key@ip:port>\n'
);
const action = argv[2];
const msg = argv[3];
const sig = argv[4];
let host = argv[5];
if (action === 'verify')
if (!sig || !host)
throw new Error('\nVerification requires signature and host\n');
if (sig || host) {
if (action !== 'verify')
throw new Error('\nSignature and hostname only needed for verification\n');
const ip = IP.fromHostname(host);
host = NetAddress.fromHost(ip.host, ip.port, ip.key);
}
(async () => {
switch (action) {
case 'sign':
return sign(msg);
case 'verify':
return await verify(msg, sig, host);
default:
throw new Error('unknown verb');
}
})().catch((err) => {
console.error(err.stack);
process.exit(1);
});
function sign(msg) {
const file = path.join(os.homedir(), '.hsd', 'key');
const data = fs.readFileSync(file, 'utf-8');
const key = Buffer.from(data.trim(), 'hex');
assert(secp256k1.privateKeyVerify(key));
const salted = Buffer.from(MAGIC_STRING + msg, 'utf8');
const hash = blake2b.digest(salted);
const sig = secp256k1.sign(hash, key);
console.log({
publicKey: base32.encode(secp256k1.publicKeyCreate(key)),
message: msg,
signature: sig.toString('hex')
});
}
async function verify(msg, sig, host) {
// First verify the signature
const salted = Buffer.from(MAGIC_STRING + msg, 'utf8');
const hash = blake2b.digest(salted);
if (!secp256k1.verify(hash, Buffer.from(sig, 'hex'), host.key))
throw new Error('Bad signature');
else
console.log('Good signature!');
console.log('Attempting p2p connection...');
const logger = new Logger();
logger.set({
console: true,
filename: null,
level: 'spam'
});
const chain = new Chain();
const pool = new Pool({
chain,
logger: logger.context('hns-prove-node'),
agent: 'HNS-PROVE-NODE',
only: [host.hostname]
});
const timeout = setTimeout(
async () => {
await pool.close();
await logger.close();
console.log('Timeout: could not connect to peer in 30s');
}, 30000);
pool.once('peer connect', async (peer) => {
clearTimeout(timeout);
await pool.close();
await logger.close();
console.log('Peer reachable!');
console.log(peer.hostname());
});
await logger.open();
await pool.open();
await pool.connect();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment