From b077271d465a7e674fefb0e549aa09d6c9adf2b1 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Mon, 4 Jan 2021 14:15:27 -0300 Subject: [PATCH] initial commit. --- .gitignore | 1 + event.js | 39 +++++++++++++++++++++++++++++++++++++++ index.js | 4 ++++ package.json | 13 +++++++++++++ relay.js | 27 +++++++++++++++++++++++++++ schnorr.js | 10 ++++++++++ utils.js | 5 +++++ 7 files changed, 99 insertions(+) create mode 100644 .gitignore create mode 100644 event.js create mode 100644 index.js create mode 100644 package.json create mode 100644 relay.js create mode 100644 schnorr.js create mode 100644 utils.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/event.js b/event.js new file mode 100644 index 0000000..c866703 --- /dev/null +++ b/event.js @@ -0,0 +1,39 @@ +import shajs from 'sha.js' +import BigInteger from 'bigi' +import schnorr from 'bip-schnorr' + +export function serializeEvent(evt) { + return JSON.stringify([ + 0, + evt.pubkey, + evt.created_at, + evt.kind, + evt.tags, + evt.content + ]) +} + +export function getEventID(event) { + let hash = shajs('sha256').update(serializeEvent(event)).digest() + return hash.toString('hex') +} + +export function verifySignature(event) { + try { + schnorr.verify( + Buffer.from(event.pubkey, 'hex'), + Buffer.from(getEventID(event), 'hex'), + Buffer.from(event.sig, 'hex') + ) + return true + } catch (err) { + return false + } +} + +export function signEvent(event, key) { + let eventHash = shajs('sha256').update(serializeEvent(event)).digest() + schnorr + .sign(new BigInteger(key, 16), eventHash, makeRandom32()) + .toString('hex') +} diff --git a/index.js b/index.js new file mode 100644 index 0000000..63c9c4f --- /dev/null +++ b/index.js @@ -0,0 +1,4 @@ +export {relayConnect} from './relay' +export {signEvent, verifySignature, serializeEvent, getEventID} from './event' +export {pubkeyFromPrivate} from './schnorr' +export {makeRandom32} from './utils' diff --git a/package.json b/package.json new file mode 100644 index 0000000..3eeef7d --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "name": "nostr-tools", + "version": "0.0.1", + "dependencies": { + "assert": "^2.0.0", + "bigi": "^1.4.2", + "bip-schnorr": "^0.6.2", + "buffer": "^6.0.3", + "ecurve": "^1.0.6", + "pws": "^5.0.2", + "sha.js": "^2.4.11" + } +} diff --git a/relay.js b/relay.js new file mode 100644 index 0000000..5dd20fe --- /dev/null +++ b/relay.js @@ -0,0 +1,27 @@ +import PersistentWebSocket from 'pws' + +export function relayConnect(url, onEventCallback) { + if (url.length && url[url.length - 1] === '/') url = url.slice(0, -1) + + const ws = new PersistentWebSocket(url + '/ws?session=' + Math.random(), { + pingTimeout: 30 * 1000 + }) + + ws.onopen = () => console.log('connected to ', url) + ws.onerror = err => console.log('error connecting', url, err) + + ws.onmessage = e => { + let event = JSON.parse(e.data) + event.context + } + + return { + url, + subscribe() {}, + request() {}, + publish() {}, + close() { + ws.close() + } + } +} diff --git a/schnorr.js b/schnorr.js new file mode 100644 index 0000000..a233171 --- /dev/null +++ b/schnorr.js @@ -0,0 +1,10 @@ +import BigInteger from 'bigi' +import ecurve from 'ecurve' + +const curve = ecurve.getCurveByName('secp256k1') +const G = curve.G + +export function pubkeyFromPrivate(privateHex) { + const privKey = BigInteger.fromHex(privateHex) + return G.multiply(privKey).getEncoded(true).slice(1).toString('hex') +} diff --git a/utils.js b/utils.js new file mode 100644 index 0000000..8046146 --- /dev/null +++ b/utils.js @@ -0,0 +1,5 @@ +export function makeRandom32() { + var array = new Uint32Array(32) + window.crypto.getRandomValues(array) + return Buffer.from(array) +}