002969f78d
Missing dependent apis and tests
80 lines
3.1 KiB
JavaScript
80 lines
3.1 KiB
JavaScript
var assert = require('nanoassert')
|
|
var randombytes_buf = require('./randombytes').randombytes_buf
|
|
var generichash = require('./crypto_generichash')
|
|
var crypto_scalarmult_base = require('./crypto_scalarmult').crypto_scalarmult_base
|
|
|
|
exports.crypto_kx_PUBLICKEYBYTES = 32
|
|
exports.crypto_kx_SECRETKEYBYTES = 32
|
|
exports.crypto_kx_SEEDBYTES = 32
|
|
exports.crypto_kx_SESSIONKEYBYTES = 32
|
|
exports.crypto_kx_PRIMITIVE = ''
|
|
|
|
exports.crypto_kx_keypair = function (pk, sk) {
|
|
assert(sk.byteLength >= exports.crypto_kx_SECRETKEYBYTES, 'sk must be at least crypto_kx_SECRETKEYBYTES')
|
|
assert(pk.byteLength >= exports.crypto_kx_PUBLICKEYBYTES, 'pk must be at least crypto_kx_PUBLICKEYBYTES')
|
|
|
|
randombytes_buf(sk.subarray(0, exports.crypto_kx_SECRETKEYBYTES))
|
|
|
|
crypto_scalarmult_base(
|
|
pk.subarray(0, exports.crypto_kx_PUBLICKEYBYTES),
|
|
sk.subarray(0, exports.crypto_kx_SECRETKEYBYTES)
|
|
)
|
|
}
|
|
|
|
exports.crypto_kx_seed_keypair = function (pk, sk, seed) {
|
|
assert(sk.byteLength >= exports.crypto_kx_SECRETKEYBYTES, 'sk must be at least crypto_kx_SECRETKEYBYTES')
|
|
assert(pk.byteLength >= exports.crypto_kx_PUBLICKEYBYTES, 'pk must be at least crypto_kx_PUBLICKEYBYTES')
|
|
assert(seed.byteLength >= exports.crypto_kx_SEEDBYTES, 'seed must be at least crypto_kx_SEEDBYTES')
|
|
|
|
generichash.crypto_generichash(
|
|
sk.subarray(0, exports.crypto_kx_SECRETKEYBYTES),
|
|
seed.subarray(0, exports.crypto_kx_SEEDBYTES)
|
|
)
|
|
|
|
crypto_scalarmult_base(
|
|
pk.subarray(0, exports.crypto_kx_PUBLICKEYBYTES),
|
|
sk.subarray(0, exports.crypto_kx_SECRETKEYBYTES)
|
|
)
|
|
}
|
|
|
|
exports.crypto_kx_client_session_keys = calc.bind(null, false)
|
|
|
|
exports.crypto_kx_server_session_keys = calc.bind(null, true)
|
|
|
|
|
|
function calc (server, rx, tx, pk, sk, remote_pk) {
|
|
if (rx == null) rx = tx
|
|
if (tx == null) tx = rx
|
|
|
|
assert(rx >= exports.crypto_kx_SESSIONKEYBYTES, 'rx must be at least crypto_kx_SESSIONKEYBYTES')
|
|
assert(tx >= exports.crypto_kx_SESSIONKEYBYTES, 'tx should be at least crypto_kx_SESSIONKEYBYTES')
|
|
assert(sk.byteLength >= exports.crypto_kx_SECRETKEYBYTES, 'sk must be at least crypto_kx_SECRETKEYBYTES')
|
|
assert(pk.byteLength >= exports.crypto_kx_PUBLICKEYBYTES, 'pk must be at least crypto_kx_PUBLICKEYBYTES')
|
|
assert(remote_pk.byteLength >= exports.crypto_kx_PUBLICKEYBYTES, 'remote_pk must be at least crypto_kx_PUBLICKEYBYTES')
|
|
|
|
rx = rx.subarray(0, exports.crypto_kx_SESSIONKEYBYTES)
|
|
tx = tx.subarray(0, exports.crypto_kx_SESSIONKEYBYTES)
|
|
|
|
sk = sk.subarray(0, exports.crypto_kx_SECRETKEYBYTES)
|
|
pk = pk.subarray(0, exports.crypto_kx_PUBLICKEYBYTES)
|
|
remote_pk = remote_pk.subarray(0, exports.crypto_kx_PUBLICKEYBYTES)
|
|
|
|
var keys = new Uint8Array(2 * exports.crypto_kx_SESSIONKEYBYTES)
|
|
var hash = generichash.crypto_generichash_instance(null, keys.byteLength)
|
|
var q = new Uint8Array(scalarmult.crypto_scalarmult_BYTES)
|
|
|
|
scalarmult.crypto_scalamult(q, sk, remote_pk)
|
|
|
|
hash.update(q)
|
|
q.fill(0)
|
|
// if server, then remote_pk == client_pk
|
|
hash.update(server ? remote_pk : pk)
|
|
hash.update(server ? pk : remote_pk)
|
|
hash.final(keys)
|
|
|
|
// TODO clear out hash
|
|
|
|
rx.set(keys.subarray(0, exports.crypto_kx_SESSIONKEYBYTES))
|
|
tx.set(keys.subarray(exports.crypto_kx_SESSIONKEYBYTES))
|
|
}
|