OverviewFilesCommitsIssuesDocsReleasesPeers

autobase-doctor / node_modules / noise-curve-ed / index.js

72 lines · javascript ref:
/* eslint-disable camelcase */
const sodium = require('sodium-universal')
const assert = require('nanoassert')
const b4a = require('b4a')

const DHLEN = sodium.crypto_scalarmult_ed25519_BYTES
const PKLEN = sodium.crypto_scalarmult_ed25519_BYTES
const SCALARLEN = sodium.crypto_scalarmult_ed25519_BYTES
const SKLEN = sodium.crypto_sign_SECRETKEYBYTES
const ALG = 'Ed25519'

module.exports = {
  DHLEN,
  PKLEN,
  SCALARLEN,
  SKLEN,
  ALG,
  name: ALG,
  generateKeyPair,
  dh
}

function generateKeyPair (privKey) {
  if (privKey) return generateSeedKeyPair(privKey.subarray(0, 32))

  const keyPair = {}
  keyPair.secretKey = b4a.alloc(SKLEN)
  keyPair.publicKey = b4a.alloc(PKLEN)

  sodium.crypto_sign_keypair(keyPair.publicKey, keyPair.secretKey)
  return keyPair
}

function generateSeedKeyPair (seed) {
  const keyPair = {}
  keyPair.secretKey = b4a.alloc(SKLEN)
  keyPair.publicKey = b4a.alloc(PKLEN)

  sodium.crypto_sign_seed_keypair(keyPair.publicKey, keyPair.secretKey, seed)
  return keyPair
}

function dh (publicKey, { scalar, secretKey }) {
  // tweaked keys expose scalar directly
  if (!scalar) {
    assert(secretKey.byteLength === SKLEN)

    // libsodium stores seed not actual scalar
    const sk = b4a.alloc(64)
    sodium.crypto_hash_sha512(sk, secretKey.subarray(0, 32))
    sk[0] &= 248
    sk[31] &= 127
    sk[31] |= 64

    scalar = sk.subarray(0, 32)
  }

  assert(scalar.byteLength === SCALARLEN)
  assert(publicKey.byteLength === PKLEN)

  const output = b4a.alloc(DHLEN)

  // we clamp if necessary above
  sodium.crypto_scalarmult_ed25519_noclamp(
    output,
    scalar,
    publicKey
  )

  return output
}