This commit is contained in:
Theron Spiegl 2020-11-24 17:08:48 -06:00
parent f6dc03f84a
commit 468a9d82a9

View File

@ -18,6 +18,7 @@ const crypto_aead_xchacha20poly1305_ietf_ABYTES = 16
const crypto_secretstream_xchacha20poly1305_ABYTES = 1 + crypto_aead_xchacha20poly1305_ietf_ABYTES const crypto_secretstream_xchacha20poly1305_ABYTES = 1 + crypto_aead_xchacha20poly1305_ietf_ABYTES
const crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX = Number.MAX_SAFE_INTEGER const crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX = Number.MAX_SAFE_INTEGER
const crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX = Number.MAX_SAFE_INTEGER const crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX = Number.MAX_SAFE_INTEGER
const crypto_secretstream_xchacha20poly1305_TAG_MESSAGE = 0
// #define STATE_COUNTER(STATE) ((STATE)->nonce) // #define STATE_COUNTER(STATE) ((STATE)->nonce)
// #define STATE_INONCE(STATE) ((STATE)->nonce + \ // #define STATE_INONCE(STATE) ((STATE)->nonce + \
@ -33,14 +34,6 @@ class crypto_secretstream_xchacha20poly1305_state {
} }
} }
// 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) { 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++) {
@ -49,41 +42,11 @@ function _crypto_secretstream_xchacha20poly1305_counter_reset (state) {
state.nonce[0] = 1 state.nonce[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) { function crypto_secretstream_xchacha20poly1305_keygen (k) {
assert(k.length === crypto_secretstream_xchacha20poly1305_KEYBYTES) assert(k.length === crypto_secretstream_xchacha20poly1305_KEYBYTES)
randombytes_buf(k) 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) { 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(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(out instanceof Uint8Array && out.length === crypto_secretstream_xchacha20poly1305_HEADERBYTES, 'out not byte array of length crypto_secretstream_xchacha20poly1305_HEADERBYTES')
@ -102,20 +65,6 @@ function crypto_secretstream_xchacha20poly1305_init_push (state, out, k) {
return 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) { function crypto_secretstream_xchacha20poly1305_init_pull (state, _in, k) {
assert(state instanceof crypto_secretstream_xchacha20poly1305_state, assert(state instanceof crypto_secretstream_xchacha20poly1305_state,
'state not instance of crypto_secretstream_xchacha20poly1305_state') 'state not instance of crypto_secretstream_xchacha20poly1305_state')
@ -133,33 +82,6 @@ function crypto_secretstream_xchacha20poly1305_init_pull (state, _in, k) {
return 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) { function crypto_secretstream_xchacha20poly1305_rekey (state) {
assert(state instanceof crypto_secretstream_xchacha20poly1305_state, assert(state instanceof crypto_secretstream_xchacha20poly1305_state,
'state not instance of crypto_secretstream_xchacha20poly1305_state') 'state not instance of crypto_secretstream_xchacha20poly1305_state')
@ -184,74 +106,6 @@ function crypto_secretstream_xchacha20poly1305_rekey (state) {
_crypto_secretstream_xchacha20poly1305_counter_reset(state) _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;
// }
function crypto_secretstream_xchacha20poly1305_push (state, out, m, ad, tag) { function crypto_secretstream_xchacha20poly1305_push (state, out, m, ad, tag) {
const block = new Uint8Array(64) const block = new Uint8Array(64)
const slen = new Uint8Array(8) const slen = new Uint8Array(8)
@ -267,7 +121,7 @@ function crypto_secretstream_xchacha20poly1305_push (state, out, m, ad, tag) {
poly.update(_pad0, 0, (0x10 - ad.byteLength) & 0xf) poly.update(_pad0, 0, (0x10 - ad.byteLength) & 0xf)
block[0] = tag block[0] = tag
crypto_stream_chacha20_ietf_xor_ic(block, state.nonce, 1, state.k) crypto_stream_chacha20_ietf_xor_ic(block, block, state.nonce, 1, state.k)
poly.update(block, 0, block.byteLength) poly.update(block, 0, block.byteLength)
out[0] = block[0] out[0] = block[0]
@ -275,7 +129,7 @@ function crypto_secretstream_xchacha20poly1305_push (state, out, m, ad, tag) {
// block is 64 bytes. sizeof tag is 1, as it's a byte, so c is the subarray starting at out[1] // block is 64 bytes. sizeof tag is 1, as it's a byte, so c is the subarray starting at out[1]
// c = out + (sizeof tag); // c = out + (sizeof tag);
const c = out.subarray(1, out.byteLength) const c = out.subarray(1, out.byteLength)
crypto_stream_chacha20_ietf_xor_ic(c, m, state.nonce, 2, state.key) crypto_stream_chacha20_ietf_xor_ic(c, m, state.nonce, 2, state.k)
poly.update(c, 0, m.byteLength) poly.update(c, 0, m.byteLength)
poly.update(_pad0, (0x10 - block.byteLength + m.byteLength) & 0xf) poly.update(_pad0, (0x10 - block.byteLength + m.byteLength) & 0xf)
@ -303,148 +157,100 @@ function crypto_secretstream_xchacha20poly1305_push (state, out, m, ad, tag) {
return 0 return 0
} }
// int function crypto_secretstream_xchacha20poly1305_pull (state, m, _in, ad) {
// 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;
// }
function crypto_secretstream_xchacha20poly1305_pull (state, m, tag, _in, ad) {
const block = new Uint8Array(64) const block = new Uint8Array(64)
const slen = new Uint8Array(8) const slen = new Uint8Array(8)
const mac = new Uint8Array(crypto_onetimeauth_poly1305_BYTES) const mac = new Uint8Array(crypto_onetimeauth_poly1305_BYTES)
if (_in.byteLength < crypto_secretstream_xchacha20poly1305_ABYTES) {
return -1
}
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)
const poly = new Poly1305(block)
block.fill(0) // sodium_memzero(block, sizeof block);
poly.update(ad, 0, ad.byteLength)
poly.update(_pad0, 0, (0x10 - ad.byteLength) & 0xf)
block.fill(0) // memset(block, 0, sizeof block);
block[0] = _in[0]
crypto_stream_chacha20_ietf_xor_ic(block, block, nonce, 1, state.k)
const tag = block[0]
block[0] = _in[0]
poly.update(block, 0, block.byteLength)
c = _in.subarray(1, _in.length)
poly.update(c, 0, mlen)
// poly.update(_in, 1, mlen)
poly.update(_pad0, (0x10 - block.byteLength + mlen) & 0xf)
STORE64_LE(slen, ad.byteLength)
poly.update(slen, slen.byteLength)
STORE64_LE(slen, block.byteLength + m.byteLength)
poly.update(slen, slen.byteLength)
poly.finish(mac, 0)
const stored_mac = _in.subarray(c + mlen, _in.length)
for (let i = 0; i < mac.length; i++) {
if (mac[i] !== stored_mac[i]) {
mac.fill(0)
return -1
}
}
crypto_stream_chacha20_ietf_xor_ic(m, c, state.nonce, 2, state.k)
xor_buf(state.nonce.subarray(crypto_secretstream_xchacha20poly1305_COUNTERBYTES, state.nonce.length),
mac, crypto_secretstream_xchacha20poly1305_INONCEBYTES)
sodium_increment(state.nonce)
if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||
sodium_is_zero(STATE_COUNTER(state), crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {
crypto_secretstream_xchacha20poly1305_rekey(state)
}
return tag
} }
// size_t function crypto_secretstream_xchacha20poly1305_statebytes () {
// crypto_secretstream_xchacha20poly1305_statebytes(void) return crypto_stream_chacha20_ietf_KEYBYTES + crypto_stream_chacha20_ietf_NONCEBYTES + 8
// { }
// return sizeof(crypto_secretstream_xchacha20poly1305_state);
// }
// size_t function crypto_secretstream_xchacha20poly1305_abytes() {
// crypto_secretstream_xchacha20poly1305_abytes(void) return crypto_secretstream_xchacha20poly1305_ABYTES
// { }
// return crypto_secretstream_xchacha20poly1305_ABYTES;
// }
// size_t function crypto_secretstream_xchacha20poly1305_headerbytes () {
// crypto_secretstream_xchacha20poly1305_headerbytes(void) return crypto_secretstream_xchacha20poly1305_HEADERBYTES
// { }
// return crypto_secretstream_xchacha20poly1305_HEADERBYTES;
// }
// size_t function crypto_secretstream_xchacha20poly1305_keybytes () {
// crypto_secretstream_xchacha20poly1305_keybytes(void) return crypto_secretstream_xchacha20poly1305_KEYBYTES
// { }
// return crypto_secretstream_xchacha20poly1305_KEYBYTES;
// }
// size_t function crypto_secretstream_xchacha20poly1305_messagebytes_max () {
// crypto_secretstream_xchacha20poly1305_messagebytes_max(void) return crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX
// { }
// return crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX;
// }
// unsigned char function crypto_secretstream_xchacha20poly1305_tag_message () {
// crypto_secretstream_xchacha20poly1305_tag_message(void) return crypto_secretstream_xchacha20poly1305_TAG_MESSAGE
// { }
// return crypto_secretstream_xchacha20poly1305_TAG_MESSAGE;
// }
// unsigned char function crypto_secretstream_xchacha20poly1305_tag_push () {
// crypto_secretstream_xchacha20poly1305_tag_push(void) return crypto_secretstream_xchacha20poly1305_TAG_PUSH
// { }
// return crypto_secretstream_xchacha20poly1305_TAG_PUSH;
// }
// unsigned char function crypto_secretstream_xchacha20poly1305_tag_rekey () {
// crypto_secretstream_xchacha20poly1305_tag_rekey(void) return crypto_secretstream_xchacha20poly1305_TAG_REKEY
// { }
// return crypto_secretstream_xchacha20poly1305_TAG_REKEY;
// }
// unsigned char function crypto_secretstream_xchacha20poly1305_tag_final () {
// crypto_secretstream_xchacha20poly1305_tag_final(void) return crypto_secretstream_xchacha20poly1305_TAG_FINAL
// { }
// return crypto_secretstream_xchacha20poly1305_TAG_FINAL;
// }
function xor_buf (out, _in, n) { function xor_buf (out, _in, n) {
for (let i = 0; i < n; i++) { for (let i = 0; i < n; i++) {
@ -460,5 +266,14 @@ module.exports = {
crypto_secretstream_xchacha20poly1305_init_pull, crypto_secretstream_xchacha20poly1305_init_pull,
crypto_secretstream_xchacha20poly1305_rekey, crypto_secretstream_xchacha20poly1305_rekey,
crypto_secretstream_xchacha20poly1305_push, crypto_secretstream_xchacha20poly1305_push,
crypto_secretstream_xchacha20poly1305_pull crypto_secretstream_xchacha20poly1305_pull,
crypto_secretstream_xchacha20poly1305_statebytes,
crypto_secretstream_xchacha20poly1305_abytes,
crypto_secretstream_xchacha20poly1305_headerbytes,
crypto_secretstream_xchacha20poly1305_keybytes,
crypto_secretstream_xchacha20poly1305_messagebytes_max,
crypto_secretstream_xchacha20poly1305_tag_message,
crypto_secretstream_xchacha20poly1305_tag_push,
crypto_secretstream_xchacha20poly1305_tag_rekey,
crypto_secretstream_xchacha20poly1305_tag_final
} }