sodium-javascript/crypto_secretbox.js

114 lines
5.0 KiB
JavaScript

/* 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
}