OverviewFilesCommitsIssuesDocsReleasesPeers

mirall-cli / node_modules / hyperdht / lib / noise-wrap.js

53 lines · javascript ref:
const NoiseSecretStream = require('@hyperswarm/secret-stream')
const NoiseHandshake = require('noise-handshake')
const curve = require('noise-curve-ed')
const c = require('compact-encoding')
const b4a = require('b4a')
const sodium = require('sodium-universal')
const m = require('./messages')
const { NS } = require('./constants')
const { HANDSHAKE_UNFINISHED } = require('./errors')

const NOISE_PROLOUGE = NS.PEER_HANDSHAKE

module.exports = class NoiseWrap {
  constructor(keyPair, remotePublicKey) {
    this.isInitiator = !!remotePublicKey
    this.remotePublicKey = remotePublicKey
    this.keyPair = keyPair
    this.handshake = new NoiseHandshake('IK', this.isInitiator, keyPair, { curve })
    this.handshake.initialise(NOISE_PROLOUGE, remotePublicKey)
  }

  send(payload) {
    const buf = c.encode(m.noisePayload, payload)
    return this.handshake.send(buf)
  }

  recv(buf) {
    const payload = c.decode(m.noisePayload, this.handshake.recv(buf))
    this.remotePublicKey = b4a.toBuffer(this.handshake.rs)
    return payload
  }

  final() {
    if (!this.handshake.complete) throw HANDSHAKE_UNFINISHED()

    const holepunchSecret = b4a.allocUnsafe(32)

    sodium.crypto_generichash(holepunchSecret, NS.PEER_HOLEPUNCH, this.handshake.hash)

    return {
      isInitiator: this.isInitiator,
      publicKey: this.keyPair.publicKey,
      streamId: this.streamId,
      remotePublicKey: this.remotePublicKey,
      remoteId: NoiseSecretStream.id(this.handshake.hash, !this.isInitiator),
      holepunchSecret,
      hash: b4a.toBuffer(this.handshake.hash),
      rx: b4a.toBuffer(this.handshake.rx),
      tx: b4a.toBuffer(this.handshake.tx)
    }
  }
}