librats 0.5.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +1 -1
  2. package/binding.gyp +1 -0
  3. package/lib/index.d.ts +2 -1
  4. package/native-src/3rdparty/android/ifaddrs-android.c +600 -0
  5. package/native-src/3rdparty/android/ifaddrs-android.h +54 -0
  6. package/native-src/CMakeLists.txt +360 -0
  7. package/native-src/LICENSE +21 -0
  8. package/native-src/src/bencode.cpp +485 -0
  9. package/native-src/src/bencode.h +145 -0
  10. package/native-src/src/bittorrent.cpp +3682 -0
  11. package/native-src/src/bittorrent.h +731 -0
  12. package/native-src/src/dht.cpp +2460 -0
  13. package/native-src/src/dht.h +508 -0
  14. package/native-src/src/encrypted_socket.cpp +817 -0
  15. package/native-src/src/encrypted_socket.h +239 -0
  16. package/native-src/src/file_transfer.cpp +1808 -0
  17. package/native-src/src/file_transfer.h +567 -0
  18. package/native-src/src/fs.cpp +639 -0
  19. package/native-src/src/fs.h +108 -0
  20. package/native-src/src/gossipsub.cpp +1137 -0
  21. package/native-src/src/gossipsub.h +403 -0
  22. package/native-src/src/ice.cpp +1386 -0
  23. package/native-src/src/ice.h +328 -0
  24. package/native-src/src/json.hpp +25526 -0
  25. package/native-src/src/krpc.cpp +558 -0
  26. package/native-src/src/krpc.h +145 -0
  27. package/native-src/src/librats.cpp +2735 -0
  28. package/native-src/src/librats.h +1732 -0
  29. package/native-src/src/librats_bittorrent.cpp +167 -0
  30. package/native-src/src/librats_c.cpp +1333 -0
  31. package/native-src/src/librats_c.h +239 -0
  32. package/native-src/src/librats_encryption.cpp +123 -0
  33. package/native-src/src/librats_file_transfer.cpp +226 -0
  34. package/native-src/src/librats_gossipsub.cpp +293 -0
  35. package/native-src/src/librats_ice.cpp +515 -0
  36. package/native-src/src/librats_logging.cpp +158 -0
  37. package/native-src/src/librats_mdns.cpp +171 -0
  38. package/native-src/src/librats_nat.cpp +571 -0
  39. package/native-src/src/librats_persistence.cpp +815 -0
  40. package/native-src/src/logger.h +412 -0
  41. package/native-src/src/mdns.cpp +1178 -0
  42. package/native-src/src/mdns.h +253 -0
  43. package/native-src/src/network_utils.cpp +598 -0
  44. package/native-src/src/network_utils.h +162 -0
  45. package/native-src/src/noise.cpp +981 -0
  46. package/native-src/src/noise.h +227 -0
  47. package/native-src/src/os.cpp +371 -0
  48. package/native-src/src/os.h +40 -0
  49. package/native-src/src/rats_export.h +17 -0
  50. package/native-src/src/sha1.cpp +163 -0
  51. package/native-src/src/sha1.h +42 -0
  52. package/native-src/src/socket.cpp +1376 -0
  53. package/native-src/src/socket.h +309 -0
  54. package/native-src/src/stun.cpp +484 -0
  55. package/native-src/src/stun.h +349 -0
  56. package/native-src/src/threadmanager.cpp +105 -0
  57. package/native-src/src/threadmanager.h +53 -0
  58. package/native-src/src/tracker.cpp +1110 -0
  59. package/native-src/src/tracker.h +268 -0
  60. package/native-src/src/version.cpp +24 -0
  61. package/native-src/src/version.h.in +45 -0
  62. package/native-src/version.rc.in +31 -0
  63. package/package.json +2 -8
  64. package/scripts/build-librats.js +59 -12
  65. package/scripts/prepare-package.js +133 -37
  66. package/src/librats_node.cpp +46 -1
@@ -0,0 +1,981 @@
1
+ #include "noise.h"
2
+ #include "logger.h"
3
+ #include <cstring>
4
+ #include <random>
5
+ #include <iomanip>
6
+ #include <sstream>
7
+ #include <stdexcept>
8
+
9
+ // Include platform-specific headers for cryptographic operations
10
+ #ifdef _WIN32
11
+ #include <windows.h>
12
+ #include <bcrypt.h>
13
+ #pragma comment(lib, "bcrypt.lib")
14
+ #else
15
+ #include <fcntl.h>
16
+ #include <unistd.h>
17
+ #ifndef __IPHONE_OS_VERSION_MIN_REQUIRED
18
+ #include <sys/random.h>
19
+ #endif
20
+ #endif
21
+
22
+ #define LOG_NOISE_DEBUG(message) LOG_DEBUG("noise", message)
23
+ #define LOG_NOISE_INFO(message) LOG_INFO("noise", message)
24
+ #define LOG_NOISE_WARN(message) LOG_WARN("noise", message)
25
+ #define LOG_NOISE_ERROR(message) LOG_ERROR("noise", message)
26
+
27
+ namespace librats {
28
+
29
+ // Noise Protocol constants
30
+ constexpr char NOISE_PROTOCOL_NAME[] = "Noise_XX_25519_ChaChaPoly_SHA256";
31
+
32
+ // Simple implementation of cryptographic primitives
33
+ // NOTE: This is a basic implementation for demonstration purposes.
34
+ // In production, you should use a well-tested cryptographic library like libsodium.
35
+
36
+ namespace {
37
+
38
+ // Simple ChaCha20 implementation
39
+ class ChaCha20 {
40
+ public:
41
+ static void chacha20_block(uint32_t out[16], const uint32_t in[16]) {
42
+ uint32_t x[16];
43
+ for (int i = 0; i < 16; ++i) x[i] = in[i];
44
+
45
+ for (int i = 0; i < 10; ++i) {
46
+ // Column rounds
47
+ quarter_round(x[0], x[4], x[8], x[12]);
48
+ quarter_round(x[1], x[5], x[9], x[13]);
49
+ quarter_round(x[2], x[6], x[10], x[14]);
50
+ quarter_round(x[3], x[7], x[11], x[15]);
51
+ // Diagonal rounds
52
+ quarter_round(x[0], x[5], x[10], x[15]);
53
+ quarter_round(x[1], x[6], x[11], x[12]);
54
+ quarter_round(x[2], x[7], x[8], x[13]);
55
+ quarter_round(x[3], x[4], x[9], x[14]);
56
+ }
57
+
58
+ for (int i = 0; i < 16; ++i) out[i] = x[i] + in[i];
59
+ }
60
+
61
+ private:
62
+ static uint32_t rotl(uint32_t x, int n) {
63
+ return (x << n) | (x >> (32 - n));
64
+ }
65
+
66
+ static void quarter_round(uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d) {
67
+ a += b; d ^= a; d = rotl(d, 16);
68
+ c += d; b ^= c; b = rotl(b, 12);
69
+ a += b; d ^= a; d = rotl(d, 8);
70
+ c += d; b ^= c; b = rotl(b, 7);
71
+ }
72
+ };
73
+
74
+ // Simple Poly1305 implementation
75
+ class Poly1305 {
76
+ public:
77
+ static void poly1305_mac(uint8_t out[16], const uint8_t* m, size_t inlen, const uint8_t key[32]) {
78
+ uint32_t r0, r1, r2, r3, r4;
79
+ uint32_t s1, s2, s3, s4;
80
+ uint32_t h0, h1, h2, h3, h4;
81
+ uint64_t d0, d1, d2, d3, d4;
82
+ uint32_t c;
83
+
84
+ // r &= 0xffffffc0ffffffc0ffffffc0fffffff
85
+ r0 = (get_u32le(key + 0)) & 0x3ffffff;
86
+ r1 = (get_u32le(key + 3) >> 2) & 0x3ffff03;
87
+ r2 = (get_u32le(key + 6) >> 4) & 0x3ffc0ff;
88
+ r3 = (get_u32le(key + 9) >> 6) & 0x3f03fff;
89
+ r4 = (get_u32le(key + 12) >> 8) & 0x00fffff;
90
+
91
+ s1 = r1 * 5;
92
+ s2 = r2 * 5;
93
+ s3 = r3 * 5;
94
+ s4 = r4 * 5;
95
+
96
+ h0 = h1 = h2 = h3 = h4 = 0;
97
+
98
+ while (inlen > 0) {
99
+ // h += m[i]
100
+ if (inlen >= 16) {
101
+ h0 += (get_u32le(m + 0)) & 0x3ffffff;
102
+ h1 += (get_u32le(m + 3) >> 2) & 0x3ffffff;
103
+ h2 += (get_u32le(m + 6) >> 4) & 0x3ffffff;
104
+ h3 += (get_u32le(m + 9) >> 6) & 0x3ffffff;
105
+ h4 += (get_u32le(m + 12) >> 8) | (1 << 24);
106
+ m += 16;
107
+ inlen -= 16;
108
+ } else {
109
+ uint8_t mp[16];
110
+ size_t i;
111
+ for (i = 0; i < inlen; i++) mp[i] = m[i];
112
+ mp[i++] = 1;
113
+ for (; i < 16; i++) mp[i] = 0;
114
+ inlen = 0;
115
+ h0 += (get_u32le(mp + 0)) & 0x3ffffff;
116
+ h1 += (get_u32le(mp + 3) >> 2) & 0x3ffffff;
117
+ h2 += (get_u32le(mp + 6) >> 4) & 0x3ffffff;
118
+ h3 += (get_u32le(mp + 9) >> 6) & 0x3ffffff;
119
+ h4 += (get_u32le(mp + 12) >> 8);
120
+ }
121
+
122
+ // h *= r
123
+ d0 = ((uint64_t)h0 * r0) + ((uint64_t)h1 * s4) + ((uint64_t)h2 * s3) + ((uint64_t)h3 * s2) + ((uint64_t)h4 * s1);
124
+ d1 = ((uint64_t)h0 * r1) + ((uint64_t)h1 * r0) + ((uint64_t)h2 * s4) + ((uint64_t)h3 * s3) + ((uint64_t)h4 * s2);
125
+ d2 = ((uint64_t)h0 * r2) + ((uint64_t)h1 * r1) + ((uint64_t)h2 * r0) + ((uint64_t)h3 * s4) + ((uint64_t)h4 * s3);
126
+ d3 = ((uint64_t)h0 * r3) + ((uint64_t)h1 * r2) + ((uint64_t)h2 * r1) + ((uint64_t)h3 * r0) + ((uint64_t)h4 * s4);
127
+ d4 = ((uint64_t)h0 * r4) + ((uint64_t)h1 * r3) + ((uint64_t)h2 * r2) + ((uint64_t)h3 * r1) + ((uint64_t)h4 * r0);
128
+
129
+ // (partial) h %= p
130
+ c = (uint32_t)(d0 >> 26); h0 = (uint32_t)d0 & 0x3ffffff;
131
+ d1 += c; c = (uint32_t)(d1 >> 26); h1 = (uint32_t)d1 & 0x3ffffff;
132
+ d2 += c; c = (uint32_t)(d2 >> 26); h2 = (uint32_t)d2 & 0x3ffffff;
133
+ d3 += c; c = (uint32_t)(d3 >> 26); h3 = (uint32_t)d3 & 0x3ffffff;
134
+ d4 += c; c = (uint32_t)(d4 >> 26); h4 = (uint32_t)d4 & 0x3ffffff;
135
+ h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
136
+ h1 += c;
137
+ }
138
+
139
+ // fully carry h
140
+ c = h1 >> 26; h1 = h1 & 0x3ffffff;
141
+ h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
142
+ h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
143
+ h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
144
+ h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
145
+ h1 += c;
146
+
147
+ // compute h + -p
148
+ uint32_t g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff;
149
+ uint32_t g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff;
150
+ uint32_t g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff;
151
+ uint32_t g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff;
152
+ uint32_t g4 = h4 + c - (1 << 26);
153
+
154
+ // select h if h < p, or h + -p if h >= p
155
+ uint32_t mask = (g4 >> ((sizeof(uint32_t) * 8) - 1)) - 1;
156
+ g0 &= mask;
157
+ g1 &= mask;
158
+ g2 &= mask;
159
+ g3 &= mask;
160
+ g4 &= mask;
161
+ mask = ~mask;
162
+ h0 = (h0 & mask) | g0;
163
+ h1 = (h1 & mask) | g1;
164
+ h2 = (h2 & mask) | g2;
165
+ h3 = (h3 & mask) | g3;
166
+ h4 = (h4 & mask) | g4;
167
+
168
+ // h = h % (2^128)
169
+ h0 = ((h0) | (h1 << 26)) & 0xffffffff;
170
+ h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff;
171
+ h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
172
+ h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff;
173
+
174
+ // mac = (h + s) % (2^128)
175
+ d0 = (uint64_t)h0 + get_u32le(key + 16); h0 = (uint32_t)d0;
176
+ d1 = (uint64_t)h1 + get_u32le(key + 20) + (d0 >> 32); h1 = (uint32_t)d1;
177
+ d2 = (uint64_t)h2 + get_u32le(key + 24) + (d1 >> 32); h2 = (uint32_t)d2;
178
+ d3 = (uint64_t)h3 + get_u32le(key + 28) + (d2 >> 32); h3 = (uint32_t)d3;
179
+
180
+ put_u32le(out + 0, h0);
181
+ put_u32le(out + 4, h1);
182
+ put_u32le(out + 8, h2);
183
+ put_u32le(out + 12, h3);
184
+ }
185
+
186
+ private:
187
+ static uint32_t get_u32le(const uint8_t* p) {
188
+ return (uint32_t)p[0] | ((uint32_t)p[1] << 8) | ((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24);
189
+ }
190
+
191
+ static void put_u32le(uint8_t* p, uint32_t v) {
192
+ p[0] = (uint8_t)(v);
193
+ p[1] = (uint8_t)(v >> 8);
194
+ p[2] = (uint8_t)(v >> 16);
195
+ p[3] = (uint8_t)(v >> 24);
196
+ }
197
+ };
198
+
199
+ // Simple Curve25519 implementation
200
+ class Curve25519 {
201
+ public:
202
+ static void scalarmult(uint8_t out[32], const uint8_t scalar[32], const uint8_t point[32]) {
203
+ // This is a simplified implementation for demonstration
204
+ // In production, use a proper curve25519 implementation
205
+ std::memcpy(out, point, 32);
206
+ for (int i = 0; i < 32; ++i) {
207
+ out[i] ^= scalar[i]; // Simplified operation - NOT cryptographically secure
208
+ }
209
+ }
210
+
211
+ static void scalarmult_base(uint8_t out[32], const uint8_t scalar[32]) {
212
+ uint8_t basepoint[32] = {9}; // Standard base point
213
+ scalarmult(out, scalar, basepoint);
214
+ }
215
+ };
216
+
217
+ // Simple SHA256 implementation
218
+ class SHA256 {
219
+ public:
220
+ static void hash(uint8_t out[32], const uint8_t* data, size_t len) {
221
+ // This is a placeholder implementation
222
+ // In production, use a proper SHA256 implementation
223
+ std::memset(out, 0, 32);
224
+ for (size_t i = 0; i < len && i < 32; ++i) {
225
+ out[i] = data[i] ^ (uint8_t)(len & 0xFF);
226
+ }
227
+ }
228
+ };
229
+
230
+ } // anonymous namespace
231
+
232
+ //=============================================================================
233
+ // NoiseCrypto Implementation
234
+ //=============================================================================
235
+
236
+ NoiseKey NoiseCrypto::generate_keypair(NoiseKey& private_key) {
237
+ random_bytes(private_key.data(), NOISE_KEY_SIZE);
238
+
239
+ NoiseKey public_key;
240
+ Curve25519::scalarmult_base(public_key.data(), private_key.data());
241
+
242
+ return public_key;
243
+ }
244
+
245
+ NoiseKey NoiseCrypto::dh(const NoiseKey& private_key, const NoiseKey& public_key) {
246
+ NoiseKey shared_secret;
247
+ Curve25519::scalarmult(shared_secret.data(), private_key.data(), public_key.data());
248
+ return shared_secret;
249
+ }
250
+
251
+ std::vector<uint8_t> NoiseCrypto::encrypt(const NoiseKey& key, uint64_t nonce,
252
+ const std::vector<uint8_t>& plaintext,
253
+ const std::vector<uint8_t>& ad) {
254
+ std::vector<uint8_t> ciphertext(plaintext.size() + NOISE_TAG_SIZE);
255
+
256
+ // Setup ChaCha20 state
257
+ uint32_t state[16];
258
+ std::memcpy(state, "expand 32-byte k", 16);
259
+ std::memcpy(state + 4, key.data(), 32);
260
+ state[12] = 0; // Counter
261
+ state[13] = (uint32_t)nonce;
262
+ state[14] = (uint32_t)(nonce >> 32);
263
+ state[15] = 0;
264
+
265
+ // Generate Poly1305 key (use counter 0)
266
+ uint32_t poly_key[16];
267
+ ChaCha20::chacha20_block(poly_key, state);
268
+
269
+ // Generate keystream and encrypt (start from counter 1)
270
+ state[12] = 1;
271
+ for (size_t i = 0; i < plaintext.size(); i += 64) {
272
+ uint32_t keystream[16];
273
+ ChaCha20::chacha20_block(keystream, state);
274
+ state[12]++;
275
+
276
+ size_t chunk_size = (std::min)(size_t(64), plaintext.size() - i);
277
+ for (size_t j = 0; j < chunk_size; ++j) {
278
+ ciphertext[i + j] = plaintext[i + j] ^ ((uint8_t*)keystream)[j];
279
+ }
280
+ }
281
+
282
+ // Calculate MAC
283
+ std::vector<uint8_t> mac_data;
284
+ mac_data.insert(mac_data.end(), ad.begin(), ad.end());
285
+ mac_data.insert(mac_data.end(), ciphertext.begin(), ciphertext.begin() + plaintext.size());
286
+
287
+ uint8_t mac[16];
288
+ Poly1305::poly1305_mac(mac, mac_data.data(), mac_data.size(), (uint8_t*)poly_key);
289
+
290
+ // Append MAC
291
+ std::memcpy(ciphertext.data() + plaintext.size(), mac, 16);
292
+
293
+ return ciphertext;
294
+ }
295
+
296
+ std::vector<uint8_t> NoiseCrypto::decrypt(const NoiseKey& key, uint64_t nonce,
297
+ const std::vector<uint8_t>& ciphertext,
298
+ const std::vector<uint8_t>& ad) {
299
+ if (ciphertext.size() < NOISE_TAG_SIZE) {
300
+ return {};
301
+ }
302
+
303
+ size_t plaintext_size = ciphertext.size() - NOISE_TAG_SIZE;
304
+
305
+ // Setup ChaCha20 state
306
+ uint32_t state[16];
307
+ std::memcpy(state, "expand 32-byte k", 16);
308
+ std::memcpy(state + 4, key.data(), 32);
309
+ state[12] = 0;
310
+ state[13] = (uint32_t)nonce;
311
+ state[14] = (uint32_t)(nonce >> 32);
312
+ state[15] = 0;
313
+
314
+ // Generate Poly1305 key and verify MAC
315
+ uint32_t poly_state[16];
316
+ std::memcpy(poly_state, state, sizeof(state));
317
+ poly_state[12] = 0;
318
+ uint32_t poly_key[16];
319
+ ChaCha20::chacha20_block(poly_key, poly_state);
320
+
321
+ std::vector<uint8_t> mac_data;
322
+ mac_data.insert(mac_data.end(), ad.begin(), ad.end());
323
+ mac_data.insert(mac_data.end(), ciphertext.begin(), ciphertext.begin() + plaintext_size);
324
+
325
+ uint8_t computed_mac[16];
326
+ Poly1305::poly1305_mac(computed_mac, mac_data.data(), mac_data.size(), (uint8_t*)poly_key);
327
+
328
+ // Verify MAC
329
+ if (std::memcmp(computed_mac, ciphertext.data() + plaintext_size, 16) != 0) {
330
+ return {}; // MAC verification failed
331
+ }
332
+
333
+ // Decrypt
334
+ std::vector<uint8_t> plaintext(plaintext_size);
335
+ state[12] = 1; // Start from counter 1 (0 was used for Poly1305 key)
336
+
337
+ for (size_t i = 0; i < plaintext_size; i += 64) {
338
+ uint32_t keystream[16];
339
+ ChaCha20::chacha20_block(keystream, state);
340
+ state[12]++;
341
+
342
+ size_t chunk_size = (std::min)(size_t(64), plaintext_size - i);
343
+ for (size_t j = 0; j < chunk_size; ++j) {
344
+ plaintext[i + j] = ciphertext[i + j] ^ ((uint8_t*)keystream)[j];
345
+ }
346
+ }
347
+
348
+ return plaintext;
349
+ }
350
+
351
+ NoiseHash NoiseCrypto::hash(const std::vector<uint8_t>& data) {
352
+ NoiseHash result;
353
+ SHA256::hash(result.data(), data.data(), data.size());
354
+ return result;
355
+ }
356
+
357
+ void NoiseCrypto::hkdf(const std::vector<uint8_t>& salt, const std::vector<uint8_t>& ikm,
358
+ const std::vector<uint8_t>& info, uint8_t* okm, size_t okm_len) {
359
+ // Simplified HKDF implementation
360
+ std::vector<uint8_t> prk_data = salt;
361
+ prk_data.insert(prk_data.end(), ikm.begin(), ikm.end());
362
+ NoiseHash prk = hash(prk_data);
363
+
364
+ std::vector<uint8_t> okm_data = info;
365
+ okm_data.insert(okm_data.end(), prk.begin(), prk.end());
366
+ NoiseHash result = hash(okm_data);
367
+
368
+ std::memcpy(okm, result.data(), (std::min)(okm_len, size_t(NOISE_HASH_SIZE)));
369
+ }
370
+
371
+ void NoiseCrypto::secure_memzero(void* ptr, size_t size) {
372
+ volatile uint8_t* p = static_cast<volatile uint8_t*>(ptr);
373
+ for (size_t i = 0; i < size; ++i) {
374
+ p[i] = 0;
375
+ }
376
+ }
377
+
378
+ void NoiseCrypto::random_bytes(uint8_t* buffer, size_t size) {
379
+ #ifdef _WIN32
380
+ BCRYPT_ALG_HANDLE hAlg;
381
+ if (BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM, nullptr, 0) == 0) {
382
+ BCryptGenRandom(hAlg, buffer, (ULONG)size, 0);
383
+ BCryptCloseAlgorithmProvider(hAlg, 0);
384
+ } else {
385
+ // Fallback to less secure method
386
+ std::random_device rd;
387
+ std::mt19937 gen(rd());
388
+ std::uniform_int_distribution<> dis(0, 255);
389
+ for (size_t i = 0; i < size; ++i) {
390
+ buffer[i] = static_cast<uint8_t>(dis(gen));
391
+ }
392
+ }
393
+ #else
394
+ int fd = open("/dev/urandom", O_RDONLY);
395
+ if (fd >= 0) {
396
+ read(fd, buffer, size);
397
+ close(fd);
398
+ } else {
399
+ // Fallback to less secure method
400
+ std::random_device rd;
401
+ std::mt19937 gen(rd());
402
+ std::uniform_int_distribution<> dis(0, 255);
403
+ for (size_t i = 0; i < size; ++i) {
404
+ buffer[i] = static_cast<uint8_t>(dis(gen));
405
+ }
406
+ }
407
+ #endif
408
+ }
409
+
410
+ //=============================================================================
411
+ // NoiseCipherState Implementation
412
+ //=============================================================================
413
+
414
+ NoiseCipherState::NoiseCipherState() : nonce_(0), has_key_(false) {
415
+ key_.fill(0);
416
+ }
417
+
418
+ NoiseCipherState::~NoiseCipherState() {
419
+ NoiseCrypto::secure_memzero(key_.data(), key_.size());
420
+ }
421
+
422
+ void NoiseCipherState::initialize_key(const NoiseKey& key) {
423
+ key_ = key;
424
+ nonce_ = 0;
425
+ has_key_ = true;
426
+ }
427
+
428
+ std::vector<uint8_t> NoiseCipherState::encrypt_with_ad(const std::vector<uint8_t>& plaintext,
429
+ const std::vector<uint8_t>& ad) {
430
+ if (!has_key_) {
431
+ return plaintext; // No encryption if no key
432
+ }
433
+
434
+ auto result = NoiseCrypto::encrypt(key_, nonce_, plaintext, ad);
435
+ nonce_++;
436
+ return result;
437
+ }
438
+
439
+ std::vector<uint8_t> NoiseCipherState::decrypt_with_ad(const std::vector<uint8_t>& ciphertext,
440
+ const std::vector<uint8_t>& ad) {
441
+ if (!has_key_) {
442
+ return ciphertext; // No decryption if no key
443
+ }
444
+
445
+ auto result = NoiseCrypto::decrypt(key_, nonce_, ciphertext, ad);
446
+ if (!result.empty()) {
447
+ nonce_++;
448
+ }
449
+ return result;
450
+ }
451
+
452
+ //=============================================================================
453
+ // NoiseSymmetricState Implementation
454
+ //=============================================================================
455
+
456
+ NoiseSymmetricState::NoiseSymmetricState() {
457
+ ck_.fill(0);
458
+ h_.fill(0);
459
+ }
460
+
461
+ NoiseSymmetricState::~NoiseSymmetricState() {
462
+ NoiseCrypto::secure_memzero(ck_.data(), ck_.size());
463
+ NoiseCrypto::secure_memzero(h_.data(), h_.size());
464
+ }
465
+
466
+ void NoiseSymmetricState::initialize(const std::string& protocol_name) {
467
+ if (protocol_name.length() <= NOISE_HASH_SIZE) {
468
+ std::memcpy(h_.data(), protocol_name.c_str(), protocol_name.length());
469
+ std::memset(h_.data() + protocol_name.length(), 0, NOISE_HASH_SIZE - protocol_name.length());
470
+ } else {
471
+ h_ = NoiseCrypto::hash(std::vector<uint8_t>(protocol_name.begin(), protocol_name.end()));
472
+ }
473
+ ck_ = h_;
474
+ }
475
+
476
+ void NoiseSymmetricState::mix_key(const std::vector<uint8_t>& input_key_material) {
477
+ std::vector<uint8_t> temp_k(NOISE_KEY_SIZE);
478
+ std::vector<uint8_t> salt(ck_.begin(), ck_.end());
479
+
480
+ NoiseCrypto::hkdf(salt, input_key_material, {}, temp_k.data(), NOISE_KEY_SIZE);
481
+ NoiseCrypto::hkdf(salt, input_key_material, {1}, ck_.data(), NOISE_KEY_SIZE);
482
+
483
+ NoiseKey key;
484
+ std::memcpy(key.data(), temp_k.data(), NOISE_KEY_SIZE);
485
+ cipher_state_.initialize_key(key);
486
+
487
+ NoiseCrypto::secure_memzero(temp_k.data(), temp_k.size());
488
+ }
489
+
490
+ void NoiseSymmetricState::mix_hash(const std::vector<uint8_t>& data) {
491
+ std::vector<uint8_t> hash_input(h_.begin(), h_.end());
492
+ hash_input.insert(hash_input.end(), data.begin(), data.end());
493
+ h_ = NoiseCrypto::hash(hash_input);
494
+ }
495
+
496
+ void NoiseSymmetricState::mix_key_and_hash(const std::vector<uint8_t>& input_key_material) {
497
+ std::vector<uint8_t> temp_h(NOISE_HASH_SIZE);
498
+ std::vector<uint8_t> temp_k(NOISE_KEY_SIZE);
499
+ std::vector<uint8_t> salt(ck_.begin(), ck_.end());
500
+
501
+ NoiseCrypto::hkdf(salt, input_key_material, {}, temp_h.data(), NOISE_HASH_SIZE);
502
+ NoiseCrypto::hkdf(salt, input_key_material, {1}, temp_k.data(), NOISE_KEY_SIZE);
503
+ NoiseCrypto::hkdf(salt, input_key_material, {2}, ck_.data(), NOISE_KEY_SIZE);
504
+
505
+ std::memcpy(h_.data(), temp_h.data(), NOISE_HASH_SIZE);
506
+
507
+ NoiseKey key;
508
+ std::memcpy(key.data(), temp_k.data(), NOISE_KEY_SIZE);
509
+ cipher_state_.initialize_key(key);
510
+
511
+ NoiseCrypto::secure_memzero(temp_h.data(), temp_h.size());
512
+ NoiseCrypto::secure_memzero(temp_k.data(), temp_k.size());
513
+ }
514
+
515
+ std::vector<uint8_t> NoiseSymmetricState::encrypt_and_hash(const std::vector<uint8_t>& plaintext) {
516
+ auto ciphertext = cipher_state_.encrypt_with_ad(plaintext, std::vector<uint8_t>(h_.begin(), h_.end()));
517
+ mix_hash(ciphertext);
518
+ return ciphertext;
519
+ }
520
+
521
+ std::vector<uint8_t> NoiseSymmetricState::decrypt_and_hash(const std::vector<uint8_t>& ciphertext) {
522
+ auto plaintext = cipher_state_.decrypt_with_ad(ciphertext, std::vector<uint8_t>(h_.begin(), h_.end()));
523
+ if (!plaintext.empty()) {
524
+ mix_hash(ciphertext);
525
+ }
526
+ return plaintext;
527
+ }
528
+
529
+ std::pair<NoiseCipherState, NoiseCipherState> NoiseSymmetricState::split() {
530
+ std::vector<uint8_t> temp_k1(NOISE_KEY_SIZE);
531
+ std::vector<uint8_t> temp_k2(NOISE_KEY_SIZE);
532
+ std::vector<uint8_t> salt(ck_.begin(), ck_.end());
533
+
534
+ NoiseCrypto::hkdf(salt, {}, {}, temp_k1.data(), NOISE_KEY_SIZE);
535
+ NoiseCrypto::hkdf(salt, {}, {1}, temp_k2.data(), NOISE_KEY_SIZE);
536
+
537
+ NoiseCipherState c1, c2;
538
+ NoiseKey key1, key2;
539
+ std::memcpy(key1.data(), temp_k1.data(), NOISE_KEY_SIZE);
540
+ std::memcpy(key2.data(), temp_k2.data(), NOISE_KEY_SIZE);
541
+
542
+ c1.initialize_key(key1);
543
+ c2.initialize_key(key2);
544
+
545
+ NoiseCrypto::secure_memzero(temp_k1.data(), temp_k1.size());
546
+ NoiseCrypto::secure_memzero(temp_k2.data(), temp_k2.size());
547
+
548
+ return std::make_pair(std::move(c1), std::move(c2));
549
+ }
550
+
551
+ //=============================================================================
552
+ // NoiseHandshake Implementation
553
+ //=============================================================================
554
+
555
+ NoiseHandshake::NoiseHandshake() : role_(NoiseRole::INITIATOR), state_(NoiseHandshakeState::UNINITIALIZED) {
556
+ s_.fill(0);
557
+ e_.fill(0);
558
+ rs_.fill(0);
559
+ re_.fill(0);
560
+ }
561
+
562
+ NoiseHandshake::~NoiseHandshake() {
563
+ NoiseCrypto::secure_memzero(s_.data(), s_.size());
564
+ NoiseCrypto::secure_memzero(e_.data(), e_.size());
565
+ }
566
+
567
+ bool NoiseHandshake::initialize(NoiseRole role, const NoiseKey& static_private_key) {
568
+ role_ = role;
569
+ s_ = static_private_key;
570
+
571
+ symmetric_state_.initialize(NOISE_PROTOCOL_NAME);
572
+
573
+ if (role == NoiseRole::INITIATOR) {
574
+ state_ = NoiseHandshakeState::WRITE_MESSAGE_1;
575
+ } else {
576
+ state_ = NoiseHandshakeState::READ_MESSAGE_1;
577
+ }
578
+
579
+ LOG_NOISE_INFO("Initialized Noise handshake as " << (role == NoiseRole::INITIATOR ? "initiator" : "responder"));
580
+ return true;
581
+ }
582
+
583
+ std::vector<uint8_t> NoiseHandshake::write_message(const std::vector<uint8_t>& payload) {
584
+ std::vector<uint8_t> message;
585
+
586
+ try {
587
+ switch (state_) {
588
+ case NoiseHandshakeState::WRITE_MESSAGE_1: {
589
+ // -> e
590
+ NoiseKey e_public = NoiseCrypto::generate_keypair(e_);
591
+ message.insert(message.end(), e_public.begin(), e_public.end());
592
+ symmetric_state_.mix_hash(std::vector<uint8_t>(e_public.begin(), e_public.end()));
593
+ break;
594
+ }
595
+
596
+ case NoiseHandshakeState::WRITE_MESSAGE_2: {
597
+ // <- e, ee, s, es
598
+ NoiseKey e_public = NoiseCrypto::generate_keypair(e_);
599
+ message.insert(message.end(), e_public.begin(), e_public.end());
600
+ symmetric_state_.mix_hash(std::vector<uint8_t>(e_public.begin(), e_public.end()));
601
+
602
+ // ee
603
+ NoiseKey ee = NoiseCrypto::dh(e_, re_);
604
+ symmetric_state_.mix_key(std::vector<uint8_t>(ee.begin(), ee.end()));
605
+
606
+ // s
607
+ NoiseKey s_public = NoiseCrypto::generate_keypair(s_); // Get public from private
608
+ auto encrypted_s = symmetric_state_.encrypt_and_hash(std::vector<uint8_t>(s_public.begin(), s_public.end()));
609
+ message.insert(message.end(), encrypted_s.begin(), encrypted_s.end());
610
+
611
+ // es
612
+ NoiseKey es = NoiseCrypto::dh(s_, re_);
613
+ symmetric_state_.mix_key(std::vector<uint8_t>(es.begin(), es.end()));
614
+ break;
615
+ }
616
+
617
+ case NoiseHandshakeState::WRITE_MESSAGE_3: {
618
+ // -> s, se
619
+ NoiseKey s_public = NoiseCrypto::generate_keypair(s_); // Get public from private
620
+ auto encrypted_s = symmetric_state_.encrypt_and_hash(std::vector<uint8_t>(s_public.begin(), s_public.end()));
621
+ message.insert(message.end(), encrypted_s.begin(), encrypted_s.end());
622
+
623
+ // se
624
+ NoiseKey se = NoiseCrypto::dh(s_, re_);
625
+ symmetric_state_.mix_key(std::vector<uint8_t>(se.begin(), se.end()));
626
+ break;
627
+ }
628
+
629
+ default:
630
+ LOG_NOISE_ERROR("Invalid state for write_message: " << static_cast<int>(state_));
631
+ fail_handshake();
632
+ return {};
633
+ }
634
+
635
+ // Encrypt payload
636
+ if (!payload.empty()) {
637
+ auto encrypted_payload = symmetric_state_.encrypt_and_hash(payload);
638
+ message.insert(message.end(), encrypted_payload.begin(), encrypted_payload.end());
639
+ }
640
+
641
+ advance_state();
642
+ LOG_NOISE_DEBUG("Wrote handshake message, new state: " << static_cast<int>(state_));
643
+
644
+ } catch (const std::exception& e) {
645
+ LOG_NOISE_ERROR("Exception in write_message: " << e.what());
646
+ fail_handshake();
647
+ return {};
648
+ }
649
+
650
+ return message;
651
+ }
652
+
653
+ std::vector<uint8_t> NoiseHandshake::read_message(const std::vector<uint8_t>& message) {
654
+ std::vector<uint8_t> payload;
655
+ size_t offset = 0;
656
+
657
+ try {
658
+ switch (state_) {
659
+ case NoiseHandshakeState::READ_MESSAGE_1: {
660
+ // -> e
661
+ if (message.size() < NOISE_KEY_SIZE) {
662
+ LOG_NOISE_ERROR("Message too short for e");
663
+ fail_handshake();
664
+ return {};
665
+ }
666
+
667
+ std::memcpy(re_.data(), message.data() + offset, NOISE_KEY_SIZE);
668
+ offset += NOISE_KEY_SIZE;
669
+ symmetric_state_.mix_hash(std::vector<uint8_t>(re_.begin(), re_.end()));
670
+ break;
671
+ }
672
+
673
+ case NoiseHandshakeState::READ_MESSAGE_2: {
674
+ // <- e, ee, s, es
675
+ if (message.size() < NOISE_KEY_SIZE) {
676
+ LOG_NOISE_ERROR("Message too short for e");
677
+ fail_handshake();
678
+ return {};
679
+ }
680
+
681
+ std::memcpy(re_.data(), message.data() + offset, NOISE_KEY_SIZE);
682
+ offset += NOISE_KEY_SIZE;
683
+ symmetric_state_.mix_hash(std::vector<uint8_t>(re_.begin(), re_.end()));
684
+
685
+ // ee
686
+ NoiseKey ee = NoiseCrypto::dh(e_, re_);
687
+ symmetric_state_.mix_key(std::vector<uint8_t>(ee.begin(), ee.end()));
688
+
689
+ // s
690
+ size_t s_encrypted_size = NOISE_KEY_SIZE + NOISE_TAG_SIZE;
691
+ if (message.size() < offset + s_encrypted_size) {
692
+ LOG_NOISE_ERROR("Message too short for encrypted s");
693
+ fail_handshake();
694
+ return {};
695
+ }
696
+
697
+ std::vector<uint8_t> encrypted_s(message.begin() + offset, message.begin() + offset + s_encrypted_size);
698
+ offset += s_encrypted_size;
699
+
700
+ auto decrypted_s = symmetric_state_.decrypt_and_hash(encrypted_s);
701
+ if (decrypted_s.size() != NOISE_KEY_SIZE) {
702
+ LOG_NOISE_ERROR("Failed to decrypt s");
703
+ fail_handshake();
704
+ return {};
705
+ }
706
+ std::memcpy(rs_.data(), decrypted_s.data(), NOISE_KEY_SIZE);
707
+
708
+ // es
709
+ NoiseKey es = NoiseCrypto::dh(e_, rs_);
710
+ symmetric_state_.mix_key(std::vector<uint8_t>(es.begin(), es.end()));
711
+ break;
712
+ }
713
+
714
+ case NoiseHandshakeState::READ_MESSAGE_3: {
715
+ // -> s, se
716
+ size_t s_encrypted_size = NOISE_KEY_SIZE + NOISE_TAG_SIZE;
717
+ if (message.size() < s_encrypted_size) {
718
+ LOG_NOISE_ERROR("Message too short for encrypted s");
719
+ fail_handshake();
720
+ return {};
721
+ }
722
+
723
+ std::vector<uint8_t> encrypted_s(message.begin() + offset, message.begin() + offset + s_encrypted_size);
724
+ offset += s_encrypted_size;
725
+
726
+ auto decrypted_s = symmetric_state_.decrypt_and_hash(encrypted_s);
727
+ if (decrypted_s.size() != NOISE_KEY_SIZE) {
728
+ LOG_NOISE_ERROR("Failed to decrypt s");
729
+ fail_handshake();
730
+ return {};
731
+ }
732
+ std::memcpy(rs_.data(), decrypted_s.data(), NOISE_KEY_SIZE);
733
+
734
+ // se
735
+ NoiseKey se = NoiseCrypto::dh(e_, rs_);
736
+ symmetric_state_.mix_key(std::vector<uint8_t>(se.begin(), se.end()));
737
+ break;
738
+ }
739
+
740
+ default:
741
+ LOG_NOISE_ERROR("Invalid state for read_message: " << static_cast<int>(state_));
742
+ fail_handshake();
743
+ return {};
744
+ }
745
+
746
+ // Decrypt payload
747
+ if (offset < message.size()) {
748
+ std::vector<uint8_t> encrypted_payload(message.begin() + offset, message.end());
749
+ payload = symmetric_state_.decrypt_and_hash(encrypted_payload);
750
+ if (payload.empty() && !encrypted_payload.empty()) {
751
+ LOG_NOISE_ERROR("Failed to decrypt payload");
752
+ fail_handshake();
753
+ return {};
754
+ }
755
+ }
756
+
757
+ advance_state();
758
+ LOG_NOISE_DEBUG("Read handshake message, new state: " << static_cast<int>(state_));
759
+
760
+ } catch (const std::exception& e) {
761
+ LOG_NOISE_ERROR("Exception in read_message: " << e.what());
762
+ fail_handshake();
763
+ return {};
764
+ }
765
+
766
+ return payload;
767
+ }
768
+
769
+ std::pair<NoiseCipherState, NoiseCipherState> NoiseHandshake::get_cipher_states() {
770
+ if (state_ != NoiseHandshakeState::COMPLETED) {
771
+ return std::make_pair(NoiseCipherState(), NoiseCipherState());
772
+ }
773
+
774
+ return symmetric_state_.split();
775
+ }
776
+
777
+ void NoiseHandshake::advance_state() {
778
+ switch (state_) {
779
+ case NoiseHandshakeState::WRITE_MESSAGE_1:
780
+ state_ = NoiseHandshakeState::READ_MESSAGE_2;
781
+ break;
782
+ case NoiseHandshakeState::READ_MESSAGE_1:
783
+ state_ = NoiseHandshakeState::WRITE_MESSAGE_2;
784
+ break;
785
+ case NoiseHandshakeState::WRITE_MESSAGE_2:
786
+ state_ = NoiseHandshakeState::READ_MESSAGE_3;
787
+ break;
788
+ case NoiseHandshakeState::READ_MESSAGE_2:
789
+ state_ = NoiseHandshakeState::WRITE_MESSAGE_3;
790
+ break;
791
+ case NoiseHandshakeState::WRITE_MESSAGE_3:
792
+ case NoiseHandshakeState::READ_MESSAGE_3:
793
+ state_ = NoiseHandshakeState::COMPLETED;
794
+ LOG_NOISE_INFO("Noise handshake completed successfully");
795
+ break;
796
+ default:
797
+ break;
798
+ }
799
+ }
800
+
801
+ void NoiseHandshake::fail_handshake() {
802
+ state_ = NoiseHandshakeState::FAILED;
803
+ LOG_NOISE_ERROR("Noise handshake failed");
804
+ }
805
+
806
+ //=============================================================================
807
+ // NoiseSession Implementation
808
+ //=============================================================================
809
+
810
+ NoiseSession::NoiseSession() : handshake_completed_(false) {
811
+ handshake_state_ = std::make_unique<NoiseHandshake>();
812
+ }
813
+
814
+ NoiseSession::~NoiseSession() = default;
815
+
816
+ bool NoiseSession::initialize_as_initiator(const NoiseKey& static_private_key) {
817
+ return handshake_state_->initialize(NoiseRole::INITIATOR, static_private_key);
818
+ }
819
+
820
+ bool NoiseSession::initialize_as_responder(const NoiseKey& static_private_key) {
821
+ return handshake_state_->initialize(NoiseRole::RESPONDER, static_private_key);
822
+ }
823
+
824
+ bool NoiseSession::is_handshake_completed() const {
825
+ return handshake_completed_;
826
+ }
827
+
828
+ bool NoiseSession::has_handshake_failed() const {
829
+ return handshake_state_->has_failed();
830
+ }
831
+
832
+ std::vector<uint8_t> NoiseSession::create_handshake_message(const std::vector<uint8_t>& payload) {
833
+ if (handshake_completed_) {
834
+ LOG_NOISE_WARN("Handshake already completed");
835
+ return {};
836
+ }
837
+
838
+ auto message = handshake_state_->write_message(payload);
839
+
840
+ if (handshake_state_->is_completed()) {
841
+ auto cipher_states = handshake_state_->get_cipher_states();
842
+
843
+ // According to Noise protocol spec: initiator gets (send=first, receive=second)
844
+ // responder gets (send=second, receive=first)
845
+ if (handshake_state_->get_role() == NoiseRole::INITIATOR) {
846
+ send_cipher_ = std::make_unique<NoiseCipherState>(std::move(cipher_states.first));
847
+ receive_cipher_ = std::make_unique<NoiseCipherState>(std::move(cipher_states.second));
848
+ } else {
849
+ send_cipher_ = std::make_unique<NoiseCipherState>(std::move(cipher_states.second));
850
+ receive_cipher_ = std::make_unique<NoiseCipherState>(std::move(cipher_states.first));
851
+ }
852
+
853
+ handshake_completed_ = true;
854
+ LOG_NOISE_INFO("Handshake completed, transport encryption enabled");
855
+ }
856
+
857
+ return message;
858
+ }
859
+
860
+ std::vector<uint8_t> NoiseSession::process_handshake_message(const std::vector<uint8_t>& message) {
861
+ if (handshake_completed_) {
862
+ LOG_NOISE_WARN("Handshake already completed");
863
+ return {};
864
+ }
865
+
866
+ auto payload = handshake_state_->read_message(message);
867
+
868
+ if (handshake_state_->is_completed()) {
869
+ auto cipher_states = handshake_state_->get_cipher_states();
870
+
871
+ // According to Noise protocol spec: initiator gets (send=first, receive=second)
872
+ // responder gets (send=second, receive=first)
873
+ if (handshake_state_->get_role() == NoiseRole::INITIATOR) {
874
+ send_cipher_ = std::make_unique<NoiseCipherState>(std::move(cipher_states.first));
875
+ receive_cipher_ = std::make_unique<NoiseCipherState>(std::move(cipher_states.second));
876
+ } else {
877
+ send_cipher_ = std::make_unique<NoiseCipherState>(std::move(cipher_states.second));
878
+ receive_cipher_ = std::make_unique<NoiseCipherState>(std::move(cipher_states.first));
879
+ }
880
+
881
+ handshake_completed_ = true;
882
+ LOG_NOISE_INFO("Handshake completed, transport encryption enabled");
883
+ }
884
+
885
+ return payload;
886
+ }
887
+
888
+ std::vector<uint8_t> NoiseSession::encrypt_transport_message(const std::vector<uint8_t>& plaintext) {
889
+ if (!handshake_completed_ || !send_cipher_) {
890
+ LOG_NOISE_ERROR("Cannot encrypt: handshake not completed");
891
+ return {};
892
+ }
893
+
894
+ return send_cipher_->encrypt_with_ad(plaintext);
895
+ }
896
+
897
+ std::vector<uint8_t> NoiseSession::decrypt_transport_message(const std::vector<uint8_t>& ciphertext) {
898
+ if (!handshake_completed_ || !receive_cipher_) {
899
+ LOG_NOISE_ERROR("Cannot decrypt: handshake not completed");
900
+ return {};
901
+ }
902
+
903
+ return receive_cipher_->decrypt_with_ad(ciphertext);
904
+ }
905
+
906
+ NoiseRole NoiseSession::get_role() const {
907
+ return handshake_state_->get_role();
908
+ }
909
+
910
+ NoiseHandshakeState NoiseSession::get_handshake_state() const {
911
+ return handshake_state_->get_state();
912
+ }
913
+
914
+ const NoiseKey& NoiseSession::get_remote_static_public_key() const {
915
+ return handshake_state_->get_remote_static_public_key();
916
+ }
917
+
918
+ //=============================================================================
919
+ // Utility Functions Implementation
920
+ //=============================================================================
921
+
922
+ namespace noise_utils {
923
+
924
+ NoiseKey generate_static_keypair() {
925
+ NoiseKey private_key;
926
+ NoiseCrypto::generate_keypair(private_key);
927
+ return private_key;
928
+ }
929
+
930
+ std::string key_to_hex(const NoiseKey& key) {
931
+ std::ostringstream hex_stream;
932
+ for (uint8_t byte : key) {
933
+ hex_stream << std::setfill('0') << std::setw(2) << std::hex << static_cast<int>(byte);
934
+ }
935
+ return hex_stream.str();
936
+ }
937
+
938
+ NoiseKey hex_to_key(const std::string& hex) {
939
+ NoiseKey key;
940
+ key.fill(0);
941
+
942
+ if (hex.length() != NOISE_KEY_SIZE * 2) {
943
+ return key;
944
+ }
945
+
946
+ for (size_t i = 0; i < NOISE_KEY_SIZE; ++i) {
947
+ std::string byte_str = hex.substr(i * 2, 2);
948
+ try {
949
+ key[i] = static_cast<uint8_t>(std::stoul(byte_str, nullptr, 16));
950
+ } catch (const std::exception&) {
951
+ key.fill(0);
952
+ return key;
953
+ }
954
+ }
955
+
956
+ return key;
957
+ }
958
+
959
+ std::string get_protocol_name() {
960
+ return NOISE_PROTOCOL_NAME;
961
+ }
962
+
963
+ bool validate_message_size(size_t size) {
964
+ return size <= NOISE_MAX_MESSAGE_SIZE;
965
+ }
966
+
967
+ std::string noise_error_to_string(NoiseError error) {
968
+ switch (error) {
969
+ case NoiseError::SUCCESS: return "Success";
970
+ case NoiseError::INVALID_STATE: return "Invalid state";
971
+ case NoiseError::HANDSHAKE_FAILED: return "Handshake failed";
972
+ case NoiseError::DECRYPTION_FAILED: return "Decryption failed";
973
+ case NoiseError::INVALID_MESSAGE_SIZE: return "Invalid message size";
974
+ case NoiseError::CRYPTO_ERROR: return "Cryptographic error";
975
+ default: return "Unknown error";
976
+ }
977
+ }
978
+
979
+ } // namespace noise_utils
980
+
981
+ } // namespace librats