b44f83f0a8
* crypto_stream: signature change needed to modularise * move ed25519 arithmetic to separate module * module: poly1305 * module: crypto_scalarmult * module: crypto_hash * module: crypto_sign * module: crypto_secretbox * move verify functions to crypto_verify module * leftover crypto_stream functions * module: crypto_onetimeauth * module: crypto_box * tidy up * require ed25519.js * update: crypto_hash * add chacha20; align API with PR#21 * update sha512 to wasm module * fix bugs in crypto_sign * be standard * add: crypto_box_seed_keypair; alias crypto_kx methods to crypto_box * scalarmult: import curve methods; be standard * correction: crypto_kx is not actually an alias of crypto_box * export _9 constant field element * add: crypto_box_seed_keypair * removed duplicate module.exports declaraion * declare constants about exports * rename memzero -> sodium-memzero * update sodium_memzero function to arr.fill(0) * tidy: remove legacy functions * added: crypto_aead_chacha20poly1305_ietf methods * listen to linter * add assertions * chacha: readUint32Le generalised for uint8array; aead: standard fix * add null check on ad param * added: sodium_memcmp * export sodium_memcmp * export crypto_verify module * sodium_memcmp returns boolean * added: sodium_is_zero * catch syntax error * throw if crypto_aead cannot validate, fix typo in crypto_verify * move chacha20 alg to external module * use Uint8Arrays instead of buffers * change checks to assertions * bump to chacha 1.0.3 - remove Buffer dependency * reduce code branching, align return values with sodium-native * add sha-wasm deps to package.json * standard fixes * bump chacha20 to 1.0.4: remove Buffer dep * move crypto_hash_sha256 to module to uncouple wasm dependencies * add endian check: all other modules require members of this set * correct filename: crypto_hash_sha256 * export constant: crypto_hash_sha512_BYTES
106 lines
3.2 KiB
JavaScript
106 lines
3.2 KiB
JavaScript
const { crypto_hash_sha512 } = require('./crypto_hash')
|
|
const { crypto_scalarmult, crypto_scalarmult_base } = require('./crypto_scalarmult')
|
|
const { randombytes } = require('./randombytes')
|
|
const { crypto_generichash_batch } = require('./crypto_generichash')
|
|
const { crypto_secretbox_open_easy, crypto_secretbox_easy } = require('./crypto_secretbox')
|
|
const xsalsa20 = require('xsalsa20')
|
|
const assert = require('nanoassert')
|
|
|
|
var crypto_box_PUBLICKEYBYTES = 32,
|
|
crypto_box_SECRETKEYBYTES = 32,
|
|
crypto_box_BEFORENMBYTES = 32,
|
|
crypto_box_NONCEBYTES = 24,
|
|
crypto_box_ZEROBYTES = 32,
|
|
crypto_box_BOXZEROBYTES = 16,
|
|
crypto_box_SEALBYTES = 48,
|
|
crypto_box_SEEDBYTES = 32,
|
|
crypto_box_BEFORENMBYTES = 32
|
|
|
|
module.exports = {
|
|
crypto_box_keypair,
|
|
crypto_box_seed_keypair,
|
|
crypto_box_seal,
|
|
crypto_box_seal_open,
|
|
crypto_box_PUBLICKEYBYTES,
|
|
crypto_box_SECRETKEYBYTES,
|
|
crypto_box_BEFORENMBYTES,
|
|
crypto_box_NONCEBYTES,
|
|
crypto_box_ZEROBYTES,
|
|
crypto_box_BOXZEROBYTES,
|
|
crypto_box_SEALBYTES,
|
|
crypto_box_SEEDBYTES,
|
|
crypto_box_BEFORENMBYTES
|
|
}
|
|
|
|
function crypto_box_keypair(pk, sk) {
|
|
check(pk, crypto_box_PUBLICKEYBYTES)
|
|
check(sk, crypto_box_SECRETKEYBYTES)
|
|
randombytes(sk, 32)
|
|
return crypto_scalarmult_base(pk, sk)
|
|
}
|
|
|
|
function crypto_box_seed_keypair(pk, sk, seed) {
|
|
assert(pk.byteLength === crypto_box_PUBLICKEYBYTES, "pk should be 'crypto_box_PUBLICKEYBYTES' bytes")
|
|
assert(sk.byteLength === crypto_box_SECRETKEYBYTES, "sk should be 'crypto_box_SECRETKEYBYTES' bytes")
|
|
assert(sk.byteLength === crypto_box_SEEDBYTES, "sk should be 'crypto_box_SEEDBYTES' bytes")
|
|
|
|
const hash = new Uint8Array(64)
|
|
crypto_hash_sha512(hash, seed, 32)
|
|
sk.set(hash.subarray(0, 32))
|
|
hash.fill(0)
|
|
|
|
return crypto_scalarmult_base(pk, sk)
|
|
}
|
|
|
|
function crypto_box_seal(c, m, pk) {
|
|
check(c, crypto_box_SEALBYTES + m.length)
|
|
check(pk, crypto_box_PUBLICKEYBYTES)
|
|
|
|
var epk = c.subarray(0, crypto_box_PUBLICKEYBYTES)
|
|
var esk = new Uint8Array(crypto_box_SECRETKEYBYTES)
|
|
crypto_box_keypair(epk, esk)
|
|
|
|
var n = new Uint8Array(crypto_box_NONCEBYTES)
|
|
crypto_generichash_batch(n, [ epk, pk ])
|
|
|
|
var s = new Uint8Array(crypto_box_PUBLICKEYBYTES)
|
|
crypto_scalarmult(s, esk, pk)
|
|
|
|
var k = new Uint8Array(crypto_box_BEFORENMBYTES)
|
|
var zero = new Uint8Array(16)
|
|
xsalsa20.core_hsalsa20(k, zero, s, xsalsa20.SIGMA)
|
|
|
|
crypto_secretbox_easy(c.subarray(epk.length), m, n, k)
|
|
|
|
cleanup(esk)
|
|
}
|
|
|
|
function crypto_box_seal_open(m, c, pk, sk) {
|
|
check(c, crypto_box_SEALBYTES)
|
|
check(m, c.length - crypto_box_SEALBYTES)
|
|
check(pk, crypto_box_PUBLICKEYBYTES)
|
|
check(sk, crypto_box_SECRETKEYBYTES)
|
|
|
|
var epk = c.subarray(0, crypto_box_PUBLICKEYBYTES)
|
|
|
|
var n = new Uint8Array(crypto_box_NONCEBYTES)
|
|
crypto_generichash_batch(n, [ epk, pk ])
|
|
|
|
var s = new Uint8Array(crypto_box_PUBLICKEYBYTES)
|
|
crypto_scalarmult(s, sk, epk)
|
|
|
|
var k = new Uint8Array(crypto_box_BEFORENMBYTES)
|
|
var zero = new Uint8Array(16)
|
|
xsalsa20.core_hsalsa20(k, zero, s, xsalsa20.SIGMA)
|
|
|
|
return crypto_secretbox_open_easy(m, c.subarray(epk.length), n, k)
|
|
}
|
|
|
|
function check (buf, len) {
|
|
if (!buf || (len && buf.length < len)) throw new Error('Argument must be a buffer' + (len ? ' of length ' + len : ''))
|
|
}
|
|
|
|
function cleanup(arr) {
|
|
for (var i = 0; i < arr.length; i++) arr[i] = 0;
|
|
}
|