working on secretstream

This commit is contained in:
Theron Spiegl 2020-11-22 14:48:59 -06:00
parent 173a9c6a08
commit 58216d8ca6
3 changed files with 399 additions and 0 deletions

View File

@ -179,6 +179,7 @@ function tv_hchacha20 () {
tv_hchacha20()
module.exports = {
crypto_core_hchacha20_INPUTBYTES,
LOAD32_LE,
STORE32_LE,
QUARTERROUND,

397
crypto_secretstream.js Normal file
View File

@ -0,0 +1,397 @@
/* eslint-disable camelcase */
const { assert } = require('nanoassert')
const { randombytes_buf } = require('./randombytes')
const { crypto_stream_chacha20_ietf_KEYBYTES, crypto_stream_chacha20_ietf_NONCEBYTES, crypto_stream_chacha20_ietf_xor } = require('./crypto_stream_chacha20')
const { crypto_core_hchacha20, crypto_core_hchacha20_INPUTBYTES } = require('./crypto_core_hchacha20')
const crypto_secretstream_xchacha20poly1305_COUNTERBYTES = 4
const crypto_secretstream_xchacha20poly1305_INONCEBYTES = 8
const crypto_aead_xchacha20poly1305_ietf_KEYBYTES = 32
const crypto_secretstream_xchacha20poly1305_KEYBYTES = crypto_aead_xchacha20poly1305_ietf_KEYBYTES
// #define crypto_secretstream_xchacha20poly1305_HEADERBYTES \
// crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
const crypto_aead_xchacha20poly1305_ietf_NPUBBYTES = 24
const crypto_secretstream_xchacha20poly1305_HEADERBYTES = crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
// #define STATE_COUNTER(STATE) ((STATE)->nonce)
// #define STATE_INONCE(STATE) ((STATE)->nonce + \
// crypto_secretstream_xchacha20poly1305_COUNTERBYTES)
// const _pad0 = new Uint8Array(16).fill(0)
class crypto_secretstream_xchacha20poly1305_state {
constructor (k, nonce, pad) {
this.k = Uint8Array(crypto_stream_chacha20_ietf_KEYBYTES).fill(0)
this.nonce = Uint8Array(crypto_stream_chacha20_ietf_NONCEBYTES).fill(0)
this.pad = Uint8Array(8).fill(0)
}
}
// static inline void
// _crypto_secretstream_xchacha20poly1305_counter_reset
// (crypto_secretstream_xchacha20poly1305_state *state)
// {
// memset(STATE_COUNTER(state), 0,
// crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
// STATE_COUNTER(state)[0] = 1;
// }
function _crypto_secretstream_xchacha20poly1305_counter_reset (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++) {
state[i] = 0
}
state[0] = 1
}
// void
// crypto_secretstream_xchacha20poly1305_keygen
// (unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
// {
// randombytes_buf(k, crypto_secretstream_xchacha20poly1305_KEYBYTES);
// }
function crypto_secretstream_xchacha20poly1305_keygen (k) {
assert(k.length === crypto_secretstream_xchacha20poly1305_KEYBYTES)
randombytes_buf(k)
}
// int
// crypto_secretstream_xchacha20poly1305_init_push
// (crypto_secretstream_xchacha20poly1305_state *state,
// unsigned char out[crypto_secretstream_xchacha20poly1305_HEADERBYTES],
// const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
// {
// COMPILER_ASSERT(crypto_secretstream_xchacha20poly1305_HEADERBYTES ==
// crypto_core_hchacha20_INPUTBYTES +
// crypto_secretstream_xchacha20poly1305_INONCEBYTES);
// COMPILER_ASSERT(crypto_secretstream_xchacha20poly1305_HEADERBYTES ==
// crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
// COMPILER_ASSERT(sizeof state->nonce ==
// crypto_secretstream_xchacha20poly1305_INONCEBYTES +
// crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
// randombytes_buf(out, crypto_secretstream_xchacha20poly1305_HEADERBYTES);
// crypto_core_hchacha20(state->k, out, k, NULL);
// _crypto_secretstream_xchacha20poly1305_counter_reset(state);
// memcpy(STATE_INONCE(state), out + crypto_core_hchacha20_INPUTBYTES,
// crypto_secretstream_xchacha20poly1305_INONCEBYTES);
// memset(state->_pad, 0, sizeof state->_pad);
// return 0;
// }
function crypto_secretstream_xchacha20poly1305_init_push (state, out, k) {
assert(state instanceof crypto_secretstream_xchacha20poly1305_state, 'state not instance of crypto_secretstream_xchacha20poly1305_state')
assert(out instanceof Uint8Array && out.length === crypto_secretstream_xchacha20poly1305_HEADERBYTES, 'out not byte array of length crypto_secretstream_xchacha20poly1305_HEADERBYTES')
assert(k instanceof Uint8Array && k.length === crypto_secretstream_xchacha20poly1305_KEYBYTES, 'k not byte array of length crypto_secretstream_xchacha20poly1305_KEYBYTES')
assert(crypto_secretstream_xchacha20poly1305_HEADERBYTES === crypto_core_hchacha20_INPUTBYTES + crypto_secretstream_xchacha20poly1305_INONCEBYTES)
assert(crypto_secretstream_xchacha20poly1305_HEADERBYTES === crypto_aead_xchacha20poly1305_ietf_NPUBBYTES)
assert(state.nonce.length === crypto_secretstream_xchacha20poly1305_INONCEBYTES + crypto_secretstream_xchacha20poly1305_COUNTERBYTES)
randombytes_buf(out, crypto_secretstream_xchacha20poly1305_HEADERBYTES)
crypto_core_hchacha20(state.k, out, k, null)
_crypto_secretstream_xchacha20poly1305_counter_reset(state)
for (let i = 0; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
state.nonce[i + crypto_secretstream_xchacha20poly1305_COUNTERBYTES] = out[i + crypto_core_hchacha20_INPUTBYTES]
}
state.pad.fill(0)
return 0
}
// int
// crypto_secretstream_xchacha20poly1305_init_pull
// (crypto_secretstream_xchacha20poly1305_state *state,
// const unsigned char in[crypto_secretstream_xchacha20poly1305_HEADERBYTES],
// const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
// {
// crypto_core_hchacha20(state->k, in, k, NULL);
// _crypto_secretstream_xchacha20poly1305_counter_reset(state);
// memcpy(STATE_INONCE(state), in + crypto_core_hchacha20_INPUTBYTES,
// crypto_secretstream_xchacha20poly1305_INONCEBYTES);
// memset(state->_pad, 0, sizeof state->_pad);
// return 0;
// }
function crypto_secretstream_xchacha20poly1305_init_pull(state, _in, k) {
assert(state instanceof crypto_secretstream_xchacha20poly1305_state,
'state not instance of crypto_secretstream_xchacha20poly1305_state')
assert(_in instanceof Uint8Array && out.length === crypto_secretstream_xchacha20poly1305_HEADERBYTES,
'_in not byte array of length crypto_secretstream_xchacha20poly1305_HEADERBYTES')
assert(k instanceof Uint8Array && k.length === crypto_secretstream_xchacha20poly1305_KEYBYTES,
'k not byte array of length crypto_secretstream_xchacha20poly1305_KEYBYTES')
crypto_core_hchacha20(state.k, _in, k, null);
_crypto_secretstream_xchacha20poly1305_counter_reset(state);
for (let i = 0; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
state.nonce[i + crypto_secretstream_xchacha20poly1305_COUNTERBYTES] = _in[i + crypto_core_hchacha20_INPUTBYTES]
}
state.pad.fill(0)
return 0
}
// void
// crypto_secretstream_xchacha20poly1305_rekey
// (crypto_secretstream_xchacha20poly1305_state *state)
// {
// unsigned char new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES +
// crypto_secretstream_xchacha20poly1305_INONCEBYTES];
// size_t i;
// for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) {
// new_key_and_inonce[i] = state->k[i];
// }
// for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
// new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i] =
// STATE_INONCE(state)[i];
// }
// crypto_stream_chacha20_ietf_xor(new_key_and_inonce, new_key_and_inonce,
// sizeof new_key_and_inonce,
// state->nonce, state->k);
// for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) {
// state->k[i] = new_key_and_inonce[i];
// }
// for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
// STATE_INONCE(state)[i] =
// new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i];
// }
// _crypto_secretstream_xchacha20poly1305_counter_reset(state);
// }
function crypto_secretstream_xchacha20poly1305_rekey(state) {
assert(state instanceof crypto_secretstream_xchacha20poly1305_state,
'state not instance of crypto_secretstream_xchacha20poly1305_state')
const new_key_and_inonce = new Uint8Array(
crypto_stream_chacha20_ietf_KEYBYTES + crypto_secretstream_xchacha20poly1305_INONCEBYTES)
let i
for (i = 0; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) {
new_key_and_inonce[i] = state.k[i]
}
for (i = 0; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i] =
state.nonce[crypto_secretstream_xchacha20poly1305_COUNTERBYTES + i]
}
crypto_stream_chacha20_ietf_xor(new_key_and_inonce, new_key_and_inonce, state.nonce, state.k)
for (i = 0; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) {
state.k[i] = new_key_and_inonce[i];
}
for (i = 0; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
state.nonce[crypto_secretstream_xchacha20poly1305_COUNTERBYTES + i] =
new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i]
}
_crypto_secretstream_xchacha20poly1305_counter_reset(state)
}
// int
// crypto_secretstream_xchacha20poly1305_push
// (crypto_secretstream_xchacha20poly1305_state *state,
// unsigned char *out, unsigned long long *outlen_p,
// const unsigned char *m, unsigned long long mlen,
// const unsigned char *ad, unsigned long long adlen, unsigned char tag)
// {
// crypto_onetimeauth_poly1305_state poly1305_state;
// unsigned char block[64U];
// unsigned char slen[8U];
// unsigned char *c;
// unsigned char *mac;
// if (outlen_p != NULL) {
// *outlen_p = 0U;
// }
// COMPILER_ASSERT(crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX
// <= crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX);
// if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) {
// sodium_misuse();
// }
// crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k);
// crypto_onetimeauth_poly1305_init(&poly1305_state, block);
// sodium_memzero(block, sizeof block);
// crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen);
// crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0,
// (0x10 - adlen) & 0xf);
// memset(block, 0, sizeof block);
// block[0] = tag;
// crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block,
// state->nonce, 1U, state->k);
// crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block);
// out[0] = block[0];
// c = out + (sizeof tag);
// crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, state->nonce, 2U, state->k);
// crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen);
// crypto_onetimeauth_poly1305_update
// (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf);
// /* should have been (0x10 - (sizeof block + mlen)) & 0xf to keep input blocks aligned */
// STORE64_LE(slen, (uint64_t) adlen);
// crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
// STORE64_LE(slen, (sizeof block) + mlen);
// crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
// mac = c + mlen;
// crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
// sodium_memzero(&poly1305_state, sizeof poly1305_state);
// COMPILER_ASSERT(crypto_onetimeauth_poly1305_BYTES >=
// crypto_secretstream_xchacha20poly1305_INONCEBYTES);
// XOR_BUF(STATE_INONCE(state), mac,
// crypto_secretstream_xchacha20poly1305_INONCEBYTES);
// sodium_increment(STATE_COUNTER(state),
// crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
// if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||
// sodium_is_zero(STATE_COUNTER(state),
// crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {
// crypto_secretstream_xchacha20poly1305_rekey(state);
// }
// if (outlen_p != NULL) {
// *outlen_p = crypto_secretstream_xchacha20poly1305_ABYTES + mlen;
// }
// return 0;
// }
// int
// crypto_secretstream_xchacha20poly1305_pull
// (crypto_secretstream_xchacha20poly1305_state *state,
// unsigned char *m, unsigned long long *mlen_p, unsigned char *tag_p,
// const unsigned char *in, unsigned long long inlen,
// const unsigned char *ad, unsigned long long adlen)
// {
// crypto_onetimeauth_poly1305_state poly1305_state;
// unsigned char block[64U];
// unsigned char slen[8U];
// unsigned char mac[crypto_onetimeauth_poly1305_BYTES];
// const unsigned char *c;
// const unsigned char *stored_mac;
// unsigned long long mlen;
// unsigned char tag;
// if (mlen_p != NULL) {
// *mlen_p = 0U;
// }
// if (tag_p != NULL) {
// *tag_p = 0xff;
// }
// if (inlen < crypto_secretstream_xchacha20poly1305_ABYTES) {
// return -1;
// }
// mlen = inlen - crypto_secretstream_xchacha20poly1305_ABYTES;
// if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) {
// sodium_misuse();
// }
// crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k);
// crypto_onetimeauth_poly1305_init(&poly1305_state, block);
// sodium_memzero(block, sizeof block);
// crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen);
// crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0,
// (0x10 - adlen) & 0xf);
// memset(block, 0, sizeof block);
// block[0] = in[0];
// crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block,
// state->nonce, 1U, state->k);
// tag = block[0];
// block[0] = in[0];
// crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block);
// c = in + (sizeof tag);
// crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen);
// crypto_onetimeauth_poly1305_update
// (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf);
// /* should have been (0x10 - (sizeof block + mlen)) & 0xf to keep input blocks aligned */
// STORE64_LE(slen, (uint64_t) adlen);
// crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
// STORE64_LE(slen, (sizeof block) + mlen);
// crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
// crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
// sodium_memzero(&poly1305_state, sizeof poly1305_state);
// stored_mac = c + mlen;
// if (sodium_memcmp(mac, stored_mac, sizeof mac) != 0) {
// sodium_memzero(mac, sizeof mac);
// return -1;
// }
// crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, state->nonce, 2U, state->k);
// XOR_BUF(STATE_INONCE(state), mac,
// crypto_secretstream_xchacha20poly1305_INONCEBYTES);
// sodium_increment(STATE_COUNTER(state),
// crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
// if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||
// sodium_is_zero(STATE_COUNTER(state),
// crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {
// crypto_secretstream_xchacha20poly1305_rekey(state);
// }
// if (mlen_p != NULL) {
// *mlen_p = mlen;
// }
// if (tag_p != NULL) {
// *tag_p = tag;
// }
// return 0;
// }
// size_t
// crypto_secretstream_xchacha20poly1305_statebytes(void)
// {
// return sizeof(crypto_secretstream_xchacha20poly1305_state);
// }
// size_t
// crypto_secretstream_xchacha20poly1305_abytes(void)
// {
// return crypto_secretstream_xchacha20poly1305_ABYTES;
// }
// size_t
// crypto_secretstream_xchacha20poly1305_headerbytes(void)
// {
// return crypto_secretstream_xchacha20poly1305_HEADERBYTES;
// }
// size_t
// crypto_secretstream_xchacha20poly1305_keybytes(void)
// {
// return crypto_secretstream_xchacha20poly1305_KEYBYTES;
// }
// size_t
// crypto_secretstream_xchacha20poly1305_messagebytes_max(void)
// {
// return crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX;
// }
// unsigned char
// crypto_secretstream_xchacha20poly1305_tag_message(void)
// {
// return crypto_secretstream_xchacha20poly1305_TAG_MESSAGE;
// }
// unsigned char
// crypto_secretstream_xchacha20poly1305_tag_push(void)
// {
// return crypto_secretstream_xchacha20poly1305_TAG_PUSH;
// }
// unsigned char
// crypto_secretstream_xchacha20poly1305_tag_rekey(void)
// {
// return crypto_secretstream_xchacha20poly1305_TAG_REKEY;
// }
// unsigned char
// crypto_secretstream_xchacha20poly1305_tag_final(void)
// {
// return crypto_secretstream_xchacha20poly1305_TAG_FINAL;
// }
module.exports = {
crypto_secretstream_xchacha20poly1305_keygen,
crypto_secretstream_xchacha20poly1305_init_push,
crypto_secretstream_xchacha20poly1305_init_pull,
crypto_secretstream_xchacha20poly1305_rekey,
}

View File

@ -23,6 +23,7 @@ forward(require('./crypto_aead'))
forward(require('./crypto_onetimeauth'))
forward(require('./crypto_scalarmult'))
forward(require('./crypto_secretbox'))
forward(require('./crypto_secretstream'))
forward(require('./crypto_shorthash'))
forward(require('./crypto_sign'))
forward(require('./crypto_stream'))