72 lines
1.6 KiB
JavaScript
72 lines
1.6 KiB
JavaScript
/* 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
|
|
}
|