This commit is contained in:
Theron Spiegl 2020-12-16 18:59:49 -06:00
parent 7a4e676717
commit eaaaca98ff
2 changed files with 11 additions and 20 deletions

View File

@ -15,9 +15,6 @@ function ROTL32 (x, b) {
return (x << b) | (x >>> (64 - b)) return (x << b) | (x >>> (64 - b))
} }
// In C, we know how the uint32 is laid out in memory, so on LE systems, it makes sense to memcpy the 4 bytes, and on BE to reconstruct with bitshifts.
// In JS, we're assuming a LE array as input into this function, and we want the user-facing representation of the number, and JS numbers are 64-bit Frankensteins,
// so we bitshift, even though that looks like the BE thing to do in the C code.
function LOAD32_LE (src, offset) { function LOAD32_LE (src, offset) {
assert(src instanceof Uint8Array, 'src not byte array') assert(src instanceof Uint8Array, 'src not byte array')
let w = src[offset] let w = src[offset]
@ -46,12 +43,10 @@ function QUARTERROUND (l, A, B, C, D) {
l[D] = ROTL32(l[D] ^ l[A], 8) l[D] = ROTL32(l[D] ^ l[A], 8)
l[C] += l[D] l[C] += l[D]
l[B] = ROTL32(l[B] ^ l[C], 7) l[B] = ROTL32(l[B] ^ l[C], 7)
return [l[A], l[B], l[C], l[D]]
} }
function crypto_core_hchacha20 (out, _in, k, c) { function crypto_core_hchacha20 (out, _in, k, c) {
assert(out instanceof Uint8Array && out.length === 32, 'out is not an array of 32 bytes') assert(out instanceof Uint8Array && out.length === 32, 'out is not an array of 32 bytes')
// assert(_in instanceof Uint8Array && _in.length === 16, '_in is not an array of 16 bytes')
assert(k instanceof Uint8Array && k.length === 32, 'k 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') assert(c === null || (c instanceof Uint8Array && c.length === 16), 'c is not null or an array of 16 bytes')
@ -174,6 +169,7 @@ function tv_hchacha20 () {
} }
} }
assert(outs_equal, 'hchacha20 test with constant failed') assert(outs_equal, 'hchacha20 test with constant failed')
console.log('hchacha20 test OK')
} }
tv_hchacha20() tv_hchacha20()

View File

@ -34,17 +34,17 @@ const crypto_secretstream_xchacha20poly1305_TAG_FINAL = crypto_secretstream_xcha
// #define STATE_INONCE(STATE) ((STATE)->nonce + \ // #define STATE_INONCE(STATE) ((STATE)->nonce + \
// crypto_secretstream_xchacha20poly1305_COUNTERBYTES) // crypto_secretstream_xchacha20poly1305_COUNTERBYTES)
const _pad0 = new Uint8Array(16).fill(0) const _pad0 = new Uint8Array(16)
class Crypto_secretstream_xchacha20poly1305_state { class Crypto_secretstream_xchacha20poly1305_state {
constructor () { constructor () {
this.k = new Uint8Array(crypto_stream_chacha20_ietf_KEYBYTES).fill(0) this.k = new Uint8Array(crypto_stream_chacha20_ietf_KEYBYTES)
this.nonce = new Uint8Array(crypto_stream_chacha20_ietf_NONCEBYTES).fill(0) this.nonce = new Uint8Array(crypto_stream_chacha20_ietf_NONCEBYTES)
this.pad = new Uint8Array(8).fill(0) this.pad = new Uint8Array(8)
} }
} }
function _crypto_secretstream_xchacha20poly1305_counter_reset (state) { function crypto_secretstream_xchacha20poly1305_counter_reset (state) {
assert(state instanceof Crypto_secretstream_xchacha20poly1305_state, 'state is not an instance of Crypto_secretstream_xchacha20poly1305_state') assert(state instanceof Crypto_secretstream_xchacha20poly1305_state, 'state is not an instance of Crypto_secretstream_xchacha20poly1305_state')
for (let i = 0; i < crypto_secretstream_xchacha20poly1305_COUNTERBYTES; i++) { for (let i = 0; i < crypto_secretstream_xchacha20poly1305_COUNTERBYTES; i++) {
state.nonce[i] = 0 state.nonce[i] = 0
@ -67,7 +67,7 @@ function crypto_secretstream_xchacha20poly1305_init_push (state, out, k) {
randombytes_buf(out, crypto_secretstream_xchacha20poly1305_HEADERBYTES) randombytes_buf(out, crypto_secretstream_xchacha20poly1305_HEADERBYTES)
crypto_core_hchacha20(state.k, out, k, null) crypto_core_hchacha20(state.k, out, k, null)
_crypto_secretstream_xchacha20poly1305_counter_reset(state) crypto_secretstream_xchacha20poly1305_counter_reset(state)
for (let i = 0; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) { for (let i = 0; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
state.nonce[i + crypto_secretstream_xchacha20poly1305_COUNTERBYTES] = out[i + crypto_core_hchacha20_INPUTBYTES] state.nonce[i + crypto_secretstream_xchacha20poly1305_COUNTERBYTES] = out[i + crypto_core_hchacha20_INPUTBYTES]
} }
@ -83,7 +83,7 @@ function crypto_secretstream_xchacha20poly1305_init_pull (state, _in, k) {
assert(k instanceof Uint8Array && k.length === crypto_secretstream_xchacha20poly1305_KEYBYTES, assert(k instanceof Uint8Array && k.length === crypto_secretstream_xchacha20poly1305_KEYBYTES,
'k not byte array of length crypto_secretstream_xchacha20poly1305_KEYBYTES') 'k not byte array of length crypto_secretstream_xchacha20poly1305_KEYBYTES')
crypto_core_hchacha20(state.k, _in, k, null) crypto_core_hchacha20(state.k, _in, k, null)
_crypto_secretstream_xchacha20poly1305_counter_reset(state) crypto_secretstream_xchacha20poly1305_counter_reset(state)
for (let i = 0; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) { for (let i = 0; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
state.nonce[i + crypto_secretstream_xchacha20poly1305_COUNTERBYTES] = _in[i + crypto_core_hchacha20_INPUTBYTES] state.nonce[i + crypto_secretstream_xchacha20poly1305_COUNTERBYTES] = _in[i + crypto_core_hchacha20_INPUTBYTES]
@ -113,7 +113,7 @@ function crypto_secretstream_xchacha20poly1305_rekey (state) {
state.nonce[crypto_secretstream_xchacha20poly1305_COUNTERBYTES + i] = state.nonce[crypto_secretstream_xchacha20poly1305_COUNTERBYTES + i] =
new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i] new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i]
} }
_crypto_secretstream_xchacha20poly1305_counter_reset(state) crypto_secretstream_xchacha20poly1305_counter_reset(state)
} }
function crypto_secretstream_xchacha20poly1305_push (state, out, m, ad, adlen, tag, outputs) { function crypto_secretstream_xchacha20poly1305_push (state, out, m, ad, adlen, tag, outputs) {
@ -161,9 +161,7 @@ function crypto_secretstream_xchacha20poly1305_push (state, out, m, ad, adlen, t
sodium_is_zero(state.nonce.subarray(0, crypto_secretstream_xchacha20poly1305_COUNTERBYTES))) { sodium_is_zero(state.nonce.subarray(0, crypto_secretstream_xchacha20poly1305_COUNTERBYTES))) {
crypto_secretstream_xchacha20poly1305_rekey(state) crypto_secretstream_xchacha20poly1305_rekey(state)
} }
// if (outlen_p != NULL) {
// *outlen_p = crypto_secretstream_xchacha20poly1305_ABYTES + mlen;
// }
outputs.res_len = crypto_secretstream_xchacha20poly1305_ABYTES + m.byteLength outputs.res_len = crypto_secretstream_xchacha20poly1305_ABYTES + m.byteLength
return 0 return 0
} }
@ -178,9 +176,6 @@ function crypto_secretstream_xchacha20poly1305_pull (state, m, _in, ad, adlen, o
} }
const mlen = _in.byteLength - crypto_secretstream_xchacha20poly1305_ABYTES const mlen = _in.byteLength - crypto_secretstream_xchacha20poly1305_ABYTES
// if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) {
// sodium_misuse()
// }
crypto_stream_chacha20_ietf(block, state.nonce, state.k) crypto_stream_chacha20_ietf(block, state.nonce, state.k)
const poly = new Poly1305(block) const poly = new Poly1305(block)
block.fill(0) // sodium_memzero(block, sizeof block); block.fill(0) // sodium_memzero(block, sizeof block);
@ -549,7 +544,7 @@ function test_secretstream () {
assert(crypto_secretstream_xchacha20poly1305_tag_final() === assert(crypto_secretstream_xchacha20poly1305_tag_final() ===
crypto_secretstream_xchacha20poly1305_TAG_FINAL) crypto_secretstream_xchacha20poly1305_TAG_FINAL)
console.log('OK') console.log('secretstream test OK')
} }
test_secretstream() test_secretstream()