129 lines
3.2 KiB
JavaScript
129 lines
3.2 KiB
JavaScript
|
/* eslint-disable camelcase */
|
||
|
const { sodium_malloc } = require('../memory')
|
||
|
const assert = require('nanoassert')
|
||
|
|
||
|
if (new Uint16Array([1])[0] !== 1) throw new Error('Big endian architecture is not supported.')
|
||
|
|
||
|
const crypto_core_hchacha20_OUTPUTBYTES = 32
|
||
|
const crypto_core_hchacha20_INPUTBYTES = 16
|
||
|
const crypto_core_hchacha20_KEYBYTES = 32
|
||
|
const crypto_core_hchacha20_CONSTBYTES = 16
|
||
|
|
||
|
function ROTL32 (x, b) {
|
||
|
x &= 0xFFFFFFFF
|
||
|
b &= 0xFFFFFFFF
|
||
|
return (x << b) | (x >>> (32 - b))
|
||
|
}
|
||
|
|
||
|
function LOAD32_LE (src, offset) {
|
||
|
assert(src instanceof Uint8Array, 'src not byte array')
|
||
|
let w = src[offset]
|
||
|
w |= src[offset + 1] << 8
|
||
|
w |= src[offset + 2] << 16
|
||
|
w |= src[offset + 3] << 24
|
||
|
return w
|
||
|
}
|
||
|
|
||
|
function STORE32_LE (dest, int, offset) {
|
||
|
assert(dest instanceof Uint8Array, 'dest not byte array')
|
||
|
var mul = 1
|
||
|
var i = 0
|
||
|
dest[offset] = int & 0xFF // grab bottom byte
|
||
|
while (++i < 4 && (mul *= 0x100)) {
|
||
|
dest[offset + i] = (int / mul) & 0xFF
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function QUARTERROUND (l, A, B, C, D) {
|
||
|
l[A] += l[B]
|
||
|
l[D] = ROTL32(l[D] ^ l[A], 16)
|
||
|
l[C] += l[D]
|
||
|
l[B] = ROTL32(l[B] ^ l[C], 12)
|
||
|
l[A] += l[B]
|
||
|
l[D] = ROTL32(l[D] ^ l[A], 8)
|
||
|
l[C] += l[D]
|
||
|
l[B] = ROTL32(l[B] ^ l[C], 7)
|
||
|
}
|
||
|
|
||
|
function crypto_core_hchacha20 (out, _in, k, c) {
|
||
|
assert(out instanceof Uint8Array && out.length === 32, 'out is not an array of 32 bytes')
|
||
|
assert(k instanceof Uint8Array && k.length === 32, 'k is not an array of 32 bytes')
|
||
|
assert(c === null || (c instanceof Uint8Array && c.length === 16), 'c is not null or an array of 16 bytes')
|
||
|
|
||
|
let i = 0
|
||
|
const x = new Uint32Array(16)
|
||
|
if (!c) {
|
||
|
x[0] = 0x61707865
|
||
|
x[1] = 0x3320646E
|
||
|
x[2] = 0x79622D32
|
||
|
x[3] = 0x6B206574
|
||
|
} else {
|
||
|
x[0] = LOAD32_LE(c, 0)
|
||
|
x[1] = LOAD32_LE(c, 4)
|
||
|
x[2] = LOAD32_LE(c, 8)
|
||
|
x[3] = LOAD32_LE(c, 12)
|
||
|
}
|
||
|
x[4] = LOAD32_LE(k, 0)
|
||
|
x[5] = LOAD32_LE(k, 4)
|
||
|
x[6] = LOAD32_LE(k, 8)
|
||
|
x[7] = LOAD32_LE(k, 12)
|
||
|
x[8] = LOAD32_LE(k, 16)
|
||
|
x[9] = LOAD32_LE(k, 20)
|
||
|
x[10] = LOAD32_LE(k, 24)
|
||
|
x[11] = LOAD32_LE(k, 28)
|
||
|
x[12] = LOAD32_LE(_in, 0)
|
||
|
x[13] = LOAD32_LE(_in, 4)
|
||
|
x[14] = LOAD32_LE(_in, 8)
|
||
|
x[15] = LOAD32_LE(_in, 12)
|
||
|
|
||
|
for (i = 0; i < 10; i++) {
|
||
|
QUARTERROUND(x, 0, 4, 8, 12)
|
||
|
QUARTERROUND(x, 1, 5, 9, 13)
|
||
|
QUARTERROUND(x, 2, 6, 10, 14)
|
||
|
QUARTERROUND(x, 3, 7, 11, 15)
|
||
|
QUARTERROUND(x, 0, 5, 10, 15)
|
||
|
QUARTERROUND(x, 1, 6, 11, 12)
|
||
|
QUARTERROUND(x, 2, 7, 8, 13)
|
||
|
QUARTERROUND(x, 3, 4, 9, 14)
|
||
|
}
|
||
|
|
||
|
STORE32_LE(out, x[0], 0)
|
||
|
STORE32_LE(out, x[1], 4)
|
||
|
STORE32_LE(out, x[2], 8)
|
||
|
STORE32_LE(out, x[3], 12)
|
||
|
STORE32_LE(out, x[12], 16)
|
||
|
STORE32_LE(out, x[13], 20)
|
||
|
STORE32_LE(out, x[14], 24)
|
||
|
STORE32_LE(out, x[15], 28)
|
||
|
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
function crypto_core_hchacha20_outputbytes () {
|
||
|
return crypto_core_hchacha20_OUTPUTBYTES
|
||
|
}
|
||
|
|
||
|
function crypto_core_hchacha20_inputbytes () {
|
||
|
return crypto_core_hchacha20_INPUTBYTES
|
||
|
}
|
||
|
|
||
|
function crypto_core_hchacha20_keybytes () {
|
||
|
return crypto_core_hchacha20_KEYBYTES
|
||
|
}
|
||
|
|
||
|
function crypto_core_hchacha20_constbytes () {
|
||
|
return crypto_core_hchacha20_CONSTBYTES
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
crypto_core_hchacha20_INPUTBYTES,
|
||
|
LOAD32_LE,
|
||
|
STORE32_LE,
|
||
|
QUARTERROUND,
|
||
|
crypto_core_hchacha20,
|
||
|
crypto_core_hchacha20_outputbytes,
|
||
|
crypto_core_hchacha20_inputbytes,
|
||
|
crypto_core_hchacha20_keybytes,
|
||
|
crypto_core_hchacha20_constbytes
|
||
|
}
|