/* eslint-disable camelcase */ const assert = require('nanoassert') const { crypto_stream, crypto_stream_xor } = require('./crypto_stream') const { crypto_onetimeauth, crypto_onetimeauth_verify, crypto_onetimeauth_BYTES, crypto_onetimeauth_KEYBYTES } = require('./crypto_onetimeauth') const crypto_secretbox_KEYBYTES = 32 const crypto_secretbox_NONCEBYTES = 24 const crypto_secretbox_ZEROBYTES = 32 const crypto_secretbox_BOXZEROBYTES = 16 const crypto_secretbox_MACBYTES = 16 module.exports = { crypto_secretbox, crypto_secretbox_open, crypto_secretbox_detached, crypto_secretbox_open_detached, crypto_secretbox_easy, crypto_secretbox_open_easy, crypto_secretbox_KEYBYTES, crypto_secretbox_NONCEBYTES, crypto_secretbox_ZEROBYTES, crypto_secretbox_BOXZEROBYTES, crypto_secretbox_MACBYTES } function crypto_secretbox (c, m, n, k) { assert(c.byteLength === m.byteLength, 'c must be \'m.byteLength\' bytes') const mlen = m.byteLength assert(mlen >= crypto_secretbox_ZEROBYTES, 'mlen must be at least \'crypto_secretbox_ZEROBYTES\'') assert(n.byteLength === crypto_secretbox_NONCEBYTES, 'n must be \'crypto_secretbox_NONCEBYTES\' bytes') assert(k.byteLength === crypto_secretbox_KEYBYTES, 'k must be \'crypto_secretbox_KEYBYTES\' bytes') crypto_stream_xor(c, m, n, k) crypto_onetimeauth( c.subarray(crypto_secretbox_BOXZEROBYTES, crypto_secretbox_BOXZEROBYTES + crypto_onetimeauth_BYTES), c.subarray(crypto_secretbox_BOXZEROBYTES + crypto_onetimeauth_BYTES, c.byteLength), c.subarray(0, crypto_onetimeauth_KEYBYTES) ) c.fill(0, 0, crypto_secretbox_BOXZEROBYTES) return 0 } function crypto_secretbox_open (m, c, n, k) { assert(c.byteLength === m.byteLength, 'c must be \'m.byteLength\' bytes') const mlen = m.byteLength assert(mlen >= crypto_secretbox_ZEROBYTES, 'mlen must be at least \'crypto_secretbox_ZEROBYTES\'') assert(n.byteLength === crypto_secretbox_NONCEBYTES, 'n must be \'crypto_secretbox_NONCEBYTES\' bytes') assert(k.byteLength === crypto_secretbox_KEYBYTES, 'k must be \'crypto_secretbox_KEYBYTES\' bytes') const x = new Uint8Array(crypto_onetimeauth_KEYBYTES) crypto_stream(x, n, k) const validMac = crypto_onetimeauth_verify( c.subarray(crypto_secretbox_BOXZEROBYTES, crypto_secretbox_BOXZEROBYTES + crypto_onetimeauth_BYTES), c.subarray(crypto_secretbox_BOXZEROBYTES + crypto_onetimeauth_BYTES, c.byteLength), x ) if (validMac === false) return false crypto_stream_xor(m, c, n, k) m.fill(0, 0, 32) return true } function crypto_secretbox_detached (o, mac, msg, n, k) { assert(o.byteLength === msg.byteLength, 'o must be \'msg.byteLength\' bytes') assert(mac.byteLength === crypto_secretbox_MACBYTES, 'mac must be \'crypto_secretbox_MACBYTES\' bytes') assert(n.byteLength === crypto_secretbox_NONCEBYTES, 'n must be \'crypto_secretbox_NONCEBYTES\' bytes') assert(k.byteLength === crypto_secretbox_KEYBYTES, 'k must be \'crypto_secretbox_KEYBYTES\' bytes') const tmp = new Uint8Array(msg.byteLength + mac.byteLength) crypto_secretbox_easy(tmp, msg, n, k) o.set(tmp.subarray(0, msg.byteLength)) mac.set(tmp.subarray(msg.byteLength)) return true } function crypto_secretbox_open_detached (msg, o, mac, n, k) { assert(o.byteLength === msg.byteLength, 'o must be \'msg.byteLength\' bytes') assert(mac.byteLength === crypto_secretbox_MACBYTES, 'mac must be \'crypto_secretbox_MACBYTES\' bytes') assert(n.byteLength === crypto_secretbox_NONCEBYTES, 'n must be \'crypto_secretbox_NONCEBYTES\' bytes') assert(k.byteLength === crypto_secretbox_KEYBYTES, 'k must be \'crypto_secretbox_KEYBYTES\' bytes') const tmp = new Uint8Array(o.byteLength + mac.byteLength) tmp.set(o) tmp.set(mac, msg.byteLength) return crypto_secretbox_open_easy(msg, tmp, n, k) } function crypto_secretbox_easy (o, msg, n, k) { assert(o.byteLength === msg.byteLength + crypto_secretbox_MACBYTES, 'o must be \'msg.byteLength + crypto_secretbox_MACBYTES\' bytes') assert(n.byteLength === crypto_secretbox_NONCEBYTES, 'n must be \'crypto_secretbox_NONCEBYTES\' bytes') assert(k.byteLength === crypto_secretbox_KEYBYTES, 'k must be \'crypto_secretbox_KEYBYTES\' bytes') const m = new Uint8Array(crypto_secretbox_ZEROBYTES + msg.byteLength) const c = new Uint8Array(m.byteLength) m.set(msg, crypto_secretbox_ZEROBYTES) if (crypto_secretbox(c, m, n, k) === false) return false o.set(c.subarray(crypto_secretbox_BOXZEROBYTES)) return true } function crypto_secretbox_open_easy (msg, box, n, k) { assert(box.byteLength === msg.byteLength + crypto_secretbox_MACBYTES, 'box must be \'msg.byteLength + crypto_secretbox_MACBYTES\' bytes') assert(n.byteLength === crypto_secretbox_NONCEBYTES, 'n must be \'crypto_secretbox_NONCEBYTES\' bytes') assert(k.byteLength === crypto_secretbox_KEYBYTES, 'k must be \'crypto_secretbox_KEYBYTES\' bytes') const c = new Uint8Array(crypto_secretbox_BOXZEROBYTES + box.byteLength) const m = new Uint8Array(c.byteLength) c.set(box, crypto_secretbox_BOXZEROBYTES) if (crypto_secretbox_open(m, c, n, k) === false) return false msg.set(m.subarray(crypto_secretbox_ZEROBYTES)) return true }