#include "noise_stream.h"
#include <cstring>
NoiseStream::NoiseStream()
: _tx_init(false), _rx_init(false) {
memset(&_tx_state, 0, sizeof(_tx_state));
memset(&_rx_state, 0, sizeof(_rx_state));
memset(_tx_header, 0, HEADER_BYTES);
}
NoiseStream::~NoiseStream() {
sodium_memzero(&_tx_state, sizeof(_tx_state));
sodium_memzero(&_rx_state, sizeof(_rx_state));
sodium_memzero(_tx_header, HEADER_BYTES);
}
void NoiseStream::init_tx(const uint8_t *key) {
crypto_secretstream_xchacha20poly1305_init_push(&_tx_state, _tx_header, key);
_tx_init = true;
}
bool NoiseStream::init_rx(const uint8_t *key, const uint8_t *header) {
int ret = crypto_secretstream_xchacha20poly1305_init_pull(&_rx_state, header, key);
_rx_init = (ret == 0);
return _rx_init;
}
std::vector<uint8_t> NoiseStream::encrypt(const uint8_t *data, size_t len) {
std::vector<uint8_t> ct(len + TAG_BYTES);
unsigned long long ct_len;
crypto_secretstream_xchacha20poly1305_push(
&_tx_state,
ct.data(), &ct_len,
data, len,
nullptr, 0, // no additional data
0 // tag: MESSAGE (not FINAL)
);
ct.resize(static_cast<size_t>(ct_len));
return ct;
}
bool NoiseStream::decrypt(const uint8_t *data, size_t len, std::vector<uint8_t> &out) {
out.clear();
if (len < TAG_BYTES) return false;
std::vector<uint8_t> pt(len - TAG_BYTES);
unsigned long long pt_len;
unsigned char tag;
int ret = crypto_secretstream_xchacha20poly1305_pull(
&_rx_state,
pt.data(), &pt_len, &tag,
data, len,
nullptr, 0 // no additional data
);
if (ret != 0) return false; // Authentication failure.
pt.resize(static_cast<size_t>(pt_len));
out.swap(pt);
return true;
}
std::vector<uint8_t> NoiseStream::decrypt(const uint8_t *data, size_t len) {
if (len < TAG_BYTES) return {};
std::vector<uint8_t> pt(len - TAG_BYTES);
unsigned long long pt_len;
unsigned char tag;
int ret = crypto_secretstream_xchacha20poly1305_pull(
&_rx_state,
pt.data(), &pt_len, &tag,
data, len,
nullptr, 0 // no additional data
);
if (ret != 0) return {}; // Authentication failure.
pt.resize(static_cast<size_t>(pt_len));
return pt;
}