0
# Streaming Operations
1
2
Streaming functions provide encryption and stream generation for large data sets, real-time communication, and custom protocols. These functions process data in chunks rather than requiring the entire message in memory.
3
4
## Secret Stream (XChaCha20-Poly1305)
5
6
Secret stream provides streaming authenticated encryption with rekeying support, perfect for encrypting large files or real-time data streams.
7
8
### Key Generation
9
10
```javascript { .api }
11
/**
12
* Generate a random key for secret stream operations
13
* @returns Uint8Array - 32-byte stream key
14
*/
15
function crypto_secretstream_xchacha20poly1305_keygen(): Uint8Array;
16
```
17
18
### Stream Initialization
19
20
#### Push (Encryption) Stream
21
22
```javascript { .api }
23
/**
24
* Initialize stream for encryption (push)
25
* @param key - 32-byte stream key
26
* @returns Object with state and header
27
*/
28
function crypto_secretstream_xchacha20poly1305_init_push(key: Uint8Array): {
29
state: Uint8Array; // State object for streaming
30
header: Uint8Array; // 24-byte header to send with stream
31
};
32
```
33
34
#### Pull (Decryption) Stream
35
36
```javascript { .api }
37
/**
38
* Initialize stream for decryption (pull)
39
* @param header - 24-byte header from encryption stream
40
* @param key - 32-byte stream key
41
* @returns Uint8Array - State object for streaming
42
*/
43
function crypto_secretstream_xchacha20poly1305_init_pull(
44
header: Uint8Array,
45
key: Uint8Array
46
): Uint8Array;
47
```
48
49
### Stream Operations
50
51
#### Push (Encrypt) Data
52
53
```javascript { .api }
54
/**
55
* Encrypt data chunk in stream
56
* @param state_address - State from init_push
57
* @param message_chunk - Data chunk to encrypt
58
* @param ad - Additional authenticated data (optional)
59
* @param tag - Stream tag (MESSAGE, PUSH, REKEY, or FINAL)
60
* @returns Uint8Array - Encrypted chunk with authentication
61
*/
62
function crypto_secretstream_xchacha20poly1305_push(
63
state_address: any,
64
message_chunk: Uint8Array,
65
ad: Uint8Array | null,
66
tag: number
67
): Uint8Array;
68
```
69
70
#### Pull (Decrypt) Data
71
72
```javascript { .api }
73
/**
74
* Decrypt data chunk from stream
75
* @param state_address - State from init_pull
76
* @param cipher - Encrypted chunk
77
* @param ad - Additional authenticated data (optional)
78
* @returns Object with message_chunk and tag
79
*/
80
function crypto_secretstream_xchacha20poly1305_pull(
81
state_address: any,
82
cipher: Uint8Array,
83
ad: Uint8Array | null
84
): {
85
message_chunk: Uint8Array;
86
tag: number;
87
};
88
```
89
90
#### Rekeying
91
92
```javascript { .api }
93
/**
94
* Rekey the stream for forward secrecy
95
* @param state_address - Stream state to rekey
96
*/
97
function crypto_secretstream_xchacha20poly1305_rekey(state_address: any): void;
98
```
99
100
### Stream Tags
101
102
```javascript { .api }
103
const crypto_secretstream_xchacha20poly1305_TAG_MESSAGE: number; // 0 - Normal message
104
const crypto_secretstream_xchacha20poly1305_TAG_PUSH: number; // 1 - End of chunk
105
const crypto_secretstream_xchacha20poly1305_TAG_REKEY: number; // 2 - Rekey after this
106
const crypto_secretstream_xchacha20poly1305_TAG_FINAL: number; // 3 - End of stream
107
```
108
109
### Secret Stream Constants
110
111
```javascript { .api }
112
const crypto_secretstream_xchacha20poly1305_KEYBYTES: number; // 32
113
const crypto_secretstream_xchacha20poly1305_HEADERBYTES: number; // 24
114
const crypto_secretstream_xchacha20poly1305_ABYTES: number; // 17
115
const crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX: number; // Large value
116
```
117
118
## Stream Ciphers
119
120
Stream cipher functions generate pseudorandom streams for XOR-based encryption or random number generation.
121
122
### ChaCha20
123
124
#### Key Generation
125
126
```javascript { .api }
127
/**
128
* Generate key for ChaCha20 stream cipher
129
* @returns Uint8Array - 32-byte stream key
130
*/
131
function crypto_stream_chacha20_keygen(): Uint8Array;
132
```
133
134
#### Stream Generation
135
136
```javascript { .api }
137
/**
138
* Generate ChaCha20 keystream
139
* @param outLength - Length of stream to generate
140
* @param key - 32-byte stream key
141
* @param nonce - 8-byte nonce
142
* @returns Uint8Array - Generated keystream
143
*/
144
function crypto_stream_chacha20(
145
outLength: number,
146
key: Uint8Array,
147
nonce: Uint8Array
148
): Uint8Array;
149
```
150
151
#### XOR Operations
152
153
```javascript { .api }
154
/**
155
* Encrypt/decrypt data using ChaCha20 stream XOR
156
* @param input_message - Data to encrypt/decrypt
157
* @param nonce - 8-byte nonce
158
* @param key - 32-byte stream key
159
* @returns Uint8Array - XOR result
160
*/
161
function crypto_stream_chacha20_xor(
162
input_message: Uint8Array,
163
nonce: Uint8Array,
164
key: Uint8Array
165
): Uint8Array;
166
167
/**
168
* ChaCha20 XOR with initial counter
169
* @param input_message - Data to encrypt/decrypt
170
* @param nonce - 8-byte nonce
171
* @param nonce_increment - Initial counter value
172
* @param key - 32-byte stream key
173
* @returns Uint8Array - XOR result
174
*/
175
function crypto_stream_chacha20_xor_ic(
176
input_message: Uint8Array,
177
nonce: Uint8Array,
178
nonce_increment: number,
179
key: Uint8Array
180
): Uint8Array;
181
```
182
183
### ChaCha20 IETF
184
185
#### XOR Operations
186
187
```javascript { .api }
188
/**
189
* ChaCha20 IETF variant XOR (12-byte nonce)
190
* @param input_message - Data to encrypt/decrypt
191
* @param nonce - 12-byte nonce
192
* @param key - 32-byte stream key
193
* @returns Uint8Array - XOR result
194
*/
195
function crypto_stream_chacha20_ietf_xor(
196
input_message: Uint8Array,
197
nonce: Uint8Array,
198
key: Uint8Array
199
): Uint8Array;
200
201
/**
202
* ChaCha20 IETF XOR with initial counter
203
* @param input_message - Data to encrypt/decrypt
204
* @param nonce - 12-byte nonce
205
* @param nonce_increment - Initial counter value
206
* @param key - 32-byte stream key
207
* @returns Uint8Array - XOR result
208
*/
209
function crypto_stream_chacha20_ietf_xor_ic(
210
input_message: Uint8Array,
211
nonce: Uint8Array,
212
nonce_increment: number,
213
key: Uint8Array
214
): Uint8Array;
215
```
216
217
### XChaCha20
218
219
Extended nonce variant of ChaCha20 for better security.
220
221
#### Key Generation
222
223
```javascript { .api }
224
/**
225
* Generate key for XChaCha20 stream cipher
226
* @returns Uint8Array - 32-byte stream key
227
*/
228
function crypto_stream_xchacha20_keygen(): Uint8Array;
229
```
230
231
#### XOR Operations
232
233
```javascript { .api }
234
/**
235
* XChaCha20 XOR encryption/decryption
236
* @param input_message - Data to encrypt/decrypt
237
* @param nonce - 24-byte nonce
238
* @param key - 32-byte stream key
239
* @returns Uint8Array - XOR result
240
*/
241
function crypto_stream_xchacha20_xor(
242
input_message: Uint8Array,
243
nonce: Uint8Array,
244
key: Uint8Array
245
): Uint8Array;
246
247
/**
248
* XChaCha20 XOR with initial counter
249
* @param input_message - Data to encrypt/decrypt
250
* @param nonce - 24-byte nonce
251
* @param nonce_increment - Initial counter value
252
* @param key - 32-byte stream key
253
* @returns Uint8Array - XOR result
254
*/
255
function crypto_stream_xchacha20_xor_ic(
256
input_message: Uint8Array,
257
nonce: Uint8Array,
258
nonce_increment: number,
259
key: Uint8Array
260
): Uint8Array;
261
```
262
263
### Generic Stream
264
265
Default stream cipher functions.
266
267
```javascript { .api }
268
/**
269
* Generate key for generic stream cipher
270
* @returns Uint8Array - Stream key
271
*/
272
function crypto_stream_keygen(): Uint8Array;
273
```
274
275
### Stream Cipher Constants
276
277
```javascript { .api }
278
// ChaCha20
279
const crypto_stream_chacha20_KEYBYTES: number; // 32
280
const crypto_stream_chacha20_NONCEBYTES: number; // 8
281
const crypto_stream_chacha20_MESSAGEBYTES_MAX: number; // Large value
282
283
// ChaCha20 IETF
284
const crypto_stream_chacha20_ietf_KEYBYTES: number; // 32
285
const crypto_stream_chacha20_ietf_NONCEBYTES: number; // 12
286
const crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX: number; // Large value
287
288
// XChaCha20
289
const crypto_stream_xchacha20_KEYBYTES: number; // 32
290
const crypto_stream_xchacha20_NONCEBYTES: number; // 24
291
const crypto_stream_xchacha20_MESSAGEBYTES_MAX: number; // Large value
292
293
// Generic stream
294
const crypto_stream_KEYBYTES: number; // 32
295
const crypto_stream_NONCEBYTES: number; // 24
296
const crypto_stream_MESSAGEBYTES_MAX: number; // Large value
297
```
298
299
## Usage Examples
300
301
### Basic Secret Stream
302
303
```javascript
304
import _sodium from 'libsodium-wrappers-sumo';
305
await _sodium.ready;
306
const sodium = _sodium;
307
308
// Generate stream key
309
const key = sodium.crypto_secretstream_xchacha20poly1305_keygen();
310
311
// Initialize encryption stream
312
const { state: pushState, header } = sodium.crypto_secretstream_xchacha20poly1305_init_push(key);
313
314
// Initialize decryption stream
315
const pullState = sodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key);
316
317
// Encrypt data chunks
318
const chunk1 = sodium.from_string('First chunk of data');
319
const chunk2 = sodium.from_string('Second chunk of data');
320
const chunk3 = sodium.from_string('Final chunk of data');
321
322
const encrypted1 = sodium.crypto_secretstream_xchacha20poly1305_push(
323
pushState, chunk1, null, sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE
324
);
325
326
const encrypted2 = sodium.crypto_secretstream_xchacha20poly1305_push(
327
pushState, chunk2, null, sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE
328
);
329
330
const encrypted3 = sodium.crypto_secretstream_xchacha20poly1305_push(
331
pushState, chunk3, null, sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL
332
);
333
334
// Decrypt data chunks
335
const { message_chunk: decrypted1, tag: tag1 } = sodium.crypto_secretstream_xchacha20poly1305_pull(
336
pullState, encrypted1, null
337
);
338
339
const { message_chunk: decrypted2, tag: tag2 } = sodium.crypto_secretstream_xchacha20poly1305_pull(
340
pullState, encrypted2, null
341
);
342
343
const { message_chunk: decrypted3, tag: tag3 } = sodium.crypto_secretstream_xchacha20poly1305_pull(
344
pullState, encrypted3, null
345
);
346
347
console.log('Decrypted chunk 1:', sodium.to_string(decrypted1));
348
console.log('Decrypted chunk 2:', sodium.to_string(decrypted2));
349
console.log('Decrypted chunk 3:', sodium.to_string(decrypted3));
350
console.log('Final tag:', tag3 === sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL); // true
351
```
352
353
### File Streaming Encryption
354
355
```javascript
356
class StreamingFileEncryption {
357
constructor() {
358
this.key = sodium.crypto_secretstream_xchacha20poly1305_keygen();
359
}
360
361
// Encrypt file in chunks
362
encryptFile(fileData, chunkSize = 4096) {
363
const { state, header } = sodium.crypto_secretstream_xchacha20poly1305_init_push(this.key);
364
const encryptedChunks = [];
365
366
// Store header first
367
encryptedChunks.push({
368
type: 'header',
369
data: header
370
});
371
372
// Process file in chunks
373
for (let i = 0; i < fileData.length; i += chunkSize) {
374
const chunk = fileData.subarray(i, i + chunkSize);
375
const isLast = i + chunkSize >= fileData.length;
376
377
const tag = isLast
378
? sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL
379
: sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE;
380
381
const encrypted = sodium.crypto_secretstream_xchacha20poly1305_push(
382
state, chunk, null, tag
383
);
384
385
encryptedChunks.push({
386
type: 'chunk',
387
data: encrypted,
388
tag: tag
389
});
390
}
391
392
return encryptedChunks;
393
}
394
395
// Decrypt file from chunks
396
decryptFile(encryptedChunks) {
397
if (encryptedChunks[0].type !== 'header') {
398
throw new Error('First chunk must be header');
399
}
400
401
const header = encryptedChunks[0].data;
402
const state = sodium.crypto_secretstream_xchacha20poly1305_init_pull(header, this.key);
403
404
const decryptedChunks = [];
405
406
for (let i = 1; i < encryptedChunks.length; i++) {
407
const { message_chunk, tag } = sodium.crypto_secretstream_xchacha20poly1305_pull(
408
state, encryptedChunks[i].data, null
409
);
410
411
decryptedChunks.push(message_chunk);
412
413
// Check if this is the final chunk
414
if (tag === sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL) {
415
break;
416
}
417
}
418
419
// Concatenate all chunks
420
const totalLength = decryptedChunks.reduce((sum, chunk) => sum + chunk.length, 0);
421
const result = new Uint8Array(totalLength);
422
let offset = 0;
423
424
for (const chunk of decryptedChunks) {
425
result.set(chunk, offset);
426
offset += chunk.length;
427
}
428
429
return result;
430
}
431
}
432
433
// Usage
434
const fileEnc = new StreamingFileEncryption();
435
const largeFile = new Uint8Array(100000); // 100KB file
436
sodium.randombytes_buf_into(largeFile);
437
438
console.time('Encrypt large file');
439
const encryptedChunks = fileEnc.encryptFile(largeFile, 8192); // 8KB chunks
440
console.timeEnd('Encrypt large file');
441
442
console.log('Encrypted chunks:', encryptedChunks.length);
443
444
console.time('Decrypt large file');
445
const decryptedFile = fileEnc.decryptFile(encryptedChunks);
446
console.timeEnd('Decrypt large file');
447
448
console.log('Files match:', sodium.memcmp(largeFile, decryptedFile)); // true
449
```
450
451
### Real-Time Streaming with Rekeying
452
453
```javascript
454
class SecureDataStream {
455
constructor(isEncryptor = true) {
456
this.key = sodium.crypto_secretstream_xchacha20poly1305_keygen();
457
this.isEncryptor = isEncryptor;
458
this.messageCount = 0;
459
this.rekeyInterval = 100; // Rekey every 100 messages
460
461
if (isEncryptor) {
462
const { state, header } = sodium.crypto_secretstream_xchacha20poly1305_init_push(this.key);
463
this.state = state;
464
this.header = header;
465
} else {
466
this.state = null; // Will be set when header received
467
}
468
}
469
470
// Initialize decryptor with header
471
initDecryptor(header) {
472
if (this.isEncryptor) {
473
throw new Error('Cannot init decryptor on encryptor');
474
}
475
this.state = sodium.crypto_secretstream_xchacha20poly1305_init_pull(header, this.key);
476
}
477
478
// Process outgoing message
479
encrypt(message, metadata = null) {
480
if (!this.isEncryptor || !this.state) {
481
throw new Error('Invalid encryptor state');
482
}
483
484
this.messageCount++;
485
let tag = sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE;
486
487
// Rekey periodically for forward secrecy
488
if (this.messageCount % this.rekeyInterval === 0) {
489
tag = sodium.crypto_secretstream_xchacha20poly1305_TAG_REKEY;
490
}
491
492
const encrypted = sodium.crypto_secretstream_xchacha20poly1305_push(
493
this.state, message, metadata, tag
494
);
495
496
// Perform rekeying after REKEY tag
497
if (tag === sodium.crypto_secretstream_xchacha20poly1305_TAG_REKEY) {
498
sodium.crypto_secretstream_xchacha20poly1305_rekey(this.state);
499
console.log('Stream rekeyed at message', this.messageCount);
500
}
501
502
return encrypted;
503
}
504
505
// Process incoming message
506
decrypt(encrypted, expectedMetadata = null) {
507
if (this.isEncryptor || !this.state) {
508
throw new Error('Invalid decryptor state');
509
}
510
511
const { message_chunk, tag } = sodium.crypto_secretstream_xchacha20poly1305_pull(
512
this.state, encrypted, expectedMetadata
513
);
514
515
// Handle rekeying
516
if (tag === sodium.crypto_secretstream_xchacha20poly1305_TAG_REKEY) {
517
sodium.crypto_secretstream_xchacha20poly1305_rekey(this.state);
518
console.log('Stream rekeyed by peer');
519
}
520
521
return { message: message_chunk, tag };
522
}
523
524
// Finalize stream
525
finalize(finalMessage = null) {
526
if (!this.isEncryptor) {
527
throw new Error('Only encryptor can finalize');
528
}
529
530
const message = finalMessage || new Uint8Array(0);
531
return sodium.crypto_secretstream_xchacha20poly1305_push(
532
this.state, message, null, sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL
533
);
534
}
535
536
getHeader() {
537
return this.header;
538
}
539
}
540
541
// Simulate real-time communication with rekeying
542
const sender = new SecureDataStream(true);
543
const receiver = new SecureDataStream(false);
544
545
// Initialize receiver with sender's header
546
receiver.initDecryptor(sender.getHeader());
547
548
// Send many messages to trigger rekeying
549
for (let i = 1; i <= 150; i++) {
550
const message = sodium.from_string(`Message ${i}`);
551
const metadata = sodium.from_string(`meta${i}`);
552
553
// Encrypt
554
const encrypted = sender.encrypt(message, metadata);
555
556
// Decrypt
557
const { message: decrypted, tag } = receiver.decrypt(encrypted, metadata);
558
559
if (i % 50 === 0) { // Log every 50th message
560
console.log(`Message ${i}:`, sodium.to_string(decrypted));
561
}
562
}
563
564
// Finalize stream
565
const finalEncrypted = sender.finalize(sodium.from_string('Stream ended'));
566
const { message: finalDecrypted, tag: finalTag } = receiver.decrypt(finalEncrypted);
567
568
console.log('Final message:', sodium.to_string(finalDecrypted));
569
console.log('Stream finalized:', finalTag === sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL);
570
```
571
572
### Stream Cipher Usage
573
574
```javascript
575
// Basic stream cipher usage
576
const streamKey = sodium.crypto_stream_xchacha20_keygen();
577
const nonce = sodium.randombytes_buf(sodium.crypto_stream_xchacha20_NONCEBYTES);
578
579
const plaintext = sodium.from_string('Stream cipher encryption');
580
581
// Encrypt using XOR
582
const ciphertext = sodium.crypto_stream_xchacha20_xor(plaintext, nonce, streamKey);
583
console.log('Encrypted:', sodium.to_hex(ciphertext));
584
585
// Decrypt using XOR (same operation)
586
const decrypted = sodium.crypto_stream_xchacha20_xor(ciphertext, nonce, streamKey);
587
console.log('Decrypted:', sodium.to_string(decrypted)); // "Stream cipher encryption"
588
589
// Generate raw keystream
590
const keystream = sodium.crypto_stream_chacha20(100, streamKey.subarray(0, 32), nonce.subarray(0, 8));
591
console.log('Keystream sample:', sodium.to_hex(keystream.subarray(0, 16)));
592
```
593
594
### Custom Protocol with Stream Chunks
595
596
```javascript
597
class ChunkedProtocol {
598
constructor(chunkSize = 1024) {
599
this.chunkSize = chunkSize;
600
this.key = sodium.crypto_secretstream_xchacha20poly1305_keygen();
601
}
602
603
// Encode message into protocol chunks
604
encodeMessage(message, messageType = 'data') {
605
const { state, header } = sodium.crypto_secretstream_xchacha20poly1305_init_push(this.key);
606
607
const chunks = [];
608
609
// Add protocol header
610
chunks.push({
611
type: 'protocol_header',
612
data: header
613
});
614
615
// Add message metadata
616
const metadata = {
617
messageType,
618
totalLength: message.length,
619
timestamp: Date.now()
620
};
621
622
const metadataBytes = sodium.from_string(JSON.stringify(metadata));
623
const encryptedMetadata = sodium.crypto_secretstream_xchacha20poly1305_push(
624
state, metadataBytes, null, sodium.crypto_secretstream_xchacha20poly1305_TAG_PUSH
625
);
626
627
chunks.push({
628
type: 'metadata',
629
data: encryptedMetadata
630
});
631
632
// Add message chunks
633
for (let i = 0; i < message.length; i += this.chunkSize) {
634
const chunk = message.subarray(i, i + this.chunkSize);
635
const isLast = i + this.chunkSize >= message.length;
636
637
const tag = isLast
638
? sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL
639
: sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE;
640
641
const encrypted = sodium.crypto_secretstream_xchacha20poly1305_push(
642
state, chunk, null, tag
643
);
644
645
chunks.push({
646
type: 'data',
647
data: encrypted
648
});
649
}
650
651
return chunks;
652
}
653
654
// Decode protocol chunks back to message
655
decodeMessage(chunks) {
656
if (chunks[0].type !== 'protocol_header') {
657
throw new Error('Invalid protocol: missing header');
658
}
659
660
const header = chunks[0].data;
661
const state = sodium.crypto_secretstream_xchacha20poly1305_init_pull(header, this.key);
662
663
// Decrypt metadata
664
if (chunks[1].type !== 'metadata') {
665
throw new Error('Invalid protocol: missing metadata');
666
}
667
668
const { message_chunk: metadataBytes } = sodium.crypto_secretstream_xchacha20poly1305_pull(
669
state, chunks[1].data, null
670
);
671
672
const metadata = JSON.parse(sodium.to_string(metadataBytes));
673
console.log('Message metadata:', metadata);
674
675
// Decrypt data chunks
676
const dataChunks = [];
677
for (let i = 2; i < chunks.length; i++) {
678
if (chunks[i].type === 'data') {
679
const { message_chunk, tag } = sodium.crypto_secretstream_xchacha20poly1305_pull(
680
state, chunks[i].data, null
681
);
682
683
dataChunks.push(message_chunk);
684
685
if (tag === sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL) {
686
break;
687
}
688
}
689
}
690
691
// Reconstruct complete message
692
const totalLength = dataChunks.reduce((sum, chunk) => sum + chunk.length, 0);
693
const result = new Uint8Array(totalLength);
694
let offset = 0;
695
696
for (const chunk of dataChunks) {
697
result.set(chunk, offset);
698
offset += chunk.length;
699
}
700
701
return {
702
message: result,
703
metadata
704
};
705
}
706
}
707
708
// Usage
709
const protocol = new ChunkedProtocol(512); // 512-byte chunks
710
const message = sodium.from_string('This is a long message that will be split into multiple chunks for transmission over the network. Each chunk is encrypted separately for security.');
711
712
// Encode
713
const encodedChunks = protocol.encodeMessage(message, 'text_message');
714
console.log('Encoded into', encodedChunks.length, 'chunks');
715
716
// Decode
717
const { message: decodedMessage, metadata } = protocol.decodeMessage(encodedChunks);
718
console.log('Decoded message:', sodium.to_string(decodedMessage));
719
console.log('Messages match:', sodium.memcmp(message, decodedMessage)); // true
720
```
721
722
## Security Considerations
723
724
- **Stream Reuse**: Never reuse stream states or nonces
725
- **Rekeying**: Use periodic rekeying for forward secrecy in long streams
726
- **Tag Handling**: Properly handle stream tags to maintain protocol integrity
727
- **Memory Management**: Clear stream states after use
728
- **Authentication**: Secret streams provide authentication, stream ciphers do not
729
- **Nonce Management**: Use proper nonce generation for stream ciphers
730
731
## Algorithm Selection Guide
732
733
- **Secret Stream**: Use for authenticated streaming encryption with rekeying
734
- **XChaCha20**: Best stream cipher choice for new applications
735
- **ChaCha20 IETF**: Standards compliance, careful nonce management
736
- **ChaCha20**: Original variant, 8-byte nonces
737
- **Stream Rekeying**: Essential for long-running streams and forward secrecy
738
739
Streaming operations are perfect for large files, real-time communication, and memory-constrained environments.