0
# Stream Ciphers
1
2
High-performance stream ciphers including ChaCha20, XChaCha20, and Salsa20 for fast symmetric encryption with XOR operations.
3
4
## Capabilities
5
6
### ChaCha20 Stream Cipher
7
8
High-speed stream cipher suitable for bulk encryption.
9
10
```javascript { .api }
11
/**
12
* Generate ChaCha20 keystream
13
* @param c - Output buffer for keystream
14
* @param n - Nonce buffer (must be NONCEBYTES long)
15
* @param k - Key buffer (must be KEYBYTES long)
16
* @throws Error if buffer sizes are incorrect or generation fails
17
*/
18
function crypto_stream_chacha20(c: Buffer, n: Buffer, k: Buffer): void;
19
20
/**
21
* Encrypt/decrypt data with ChaCha20 (XOR operation)
22
* @param c - Output buffer for ciphertext/plaintext (same length as message)
23
* @param m - Message buffer to encrypt/decrypt
24
* @param n - Nonce buffer (must be NONCEBYTES long)
25
* @param k - Key buffer (must be KEYBYTES long)
26
* @throws Error if buffer sizes are incorrect or operation fails
27
*/
28
function crypto_stream_chacha20_xor(c: Buffer, m: Buffer, n: Buffer, k: Buffer): void;
29
30
/**
31
* Encrypt/decrypt with ChaCha20 and initial counter
32
* @param c - Output buffer for ciphertext/plaintext (same length as message)
33
* @param m - Message buffer to encrypt/decrypt
34
* @param n - Nonce buffer (must be NONCEBYTES long)
35
* @param ic - Initial counter value
36
* @param k - Key buffer (must be KEYBYTES long)
37
* @throws Error if buffer sizes are incorrect or operation fails
38
*/
39
function crypto_stream_chacha20_xor_ic(c: Buffer, m: Buffer, n: Buffer, ic: number, k: Buffer): void;
40
```
41
42
**Usage Example:**
43
44
```javascript
45
const sodium = require('sodium-native');
46
47
// ChaCha20 encryption/decryption
48
const key = Buffer.alloc(sodium.crypto_stream_chacha20_KEYBYTES);
49
const nonce = Buffer.alloc(sodium.crypto_stream_chacha20_NONCEBYTES);
50
sodium.randombytes_buf(key);
51
sodium.randombytes_buf(nonce);
52
53
const message = Buffer.from('Hello, ChaCha20!');
54
const ciphertext = Buffer.alloc(message.length);
55
const plaintext = Buffer.alloc(message.length);
56
57
// Encrypt
58
sodium.crypto_stream_chacha20_xor(ciphertext, message, nonce, key);
59
60
// Decrypt (same operation)
61
sodium.crypto_stream_chacha20_xor(plaintext, ciphertext, nonce, key);
62
console.log(plaintext.toString()); // "Hello, ChaCha20!"
63
```
64
65
### ChaCha20-IETF Stream Cipher
66
67
IETF-standardized variant of ChaCha20 with different nonce size.
68
69
```javascript { .api }
70
/**
71
* Generate ChaCha20-IETF keystream
72
* @param c - Output buffer for keystream
73
* @param n - Nonce buffer (must be NONCEBYTES long)
74
* @param k - Key buffer (must be KEYBYTES long)
75
* @throws Error if buffer sizes are incorrect or generation fails
76
*/
77
function crypto_stream_chacha20_ietf(c: Buffer, n: Buffer, k: Buffer): void;
78
79
/**
80
* Encrypt/decrypt data with ChaCha20-IETF
81
* @param c - Output buffer for ciphertext/plaintext (same length as message)
82
* @param m - Message buffer to encrypt/decrypt
83
* @param n - Nonce buffer (must be NONCEBYTES long)
84
* @param k - Key buffer (must be KEYBYTES long)
85
* @throws Error if buffer sizes are incorrect or operation fails
86
*/
87
function crypto_stream_chacha20_ietf_xor(c: Buffer, m: Buffer, n: Buffer, k: Buffer): void;
88
89
/**
90
* Encrypt/decrypt with ChaCha20-IETF and initial counter
91
* @param c - Output buffer for ciphertext/plaintext (same length as message)
92
* @param m - Message buffer to encrypt/decrypt
93
* @param n - Nonce buffer (must be NONCEBYTES long)
94
* @param ic - Initial counter value
95
* @param k - Key buffer (must be KEYBYTES long)
96
* @throws Error if buffer sizes are incorrect or operation fails
97
*/
98
function crypto_stream_chacha20_ietf_xor_ic(c: Buffer, m: Buffer, n: Buffer, ic: number, k: Buffer): void;
99
```
100
101
### XChaCha20 Stream Cipher
102
103
Extended nonce variant of ChaCha20 for better nonce management.
104
105
```javascript { .api }
106
/**
107
* Generate XChaCha20 keystream
108
* @param c - Output buffer for keystream
109
* @param n - Nonce buffer (must be NONCEBYTES long)
110
* @param k - Key buffer (must be KEYBYTES long)
111
* @throws Error if buffer sizes are incorrect or generation fails
112
*/
113
function crypto_stream_xchacha20(c: Buffer, n: Buffer, k: Buffer): void;
114
115
/**
116
* Encrypt/decrypt data with XChaCha20
117
* @param c - Output buffer for ciphertext/plaintext (same length as message)
118
* @param m - Message buffer to encrypt/decrypt
119
* @param n - Nonce buffer (must be NONCEBYTES long)
120
* @param k - Key buffer (must be KEYBYTES long)
121
* @throws Error if buffer sizes are incorrect or operation fails
122
*/
123
function crypto_stream_xchacha20_xor(c: Buffer, m: Buffer, n: Buffer, k: Buffer): void;
124
125
/**
126
* Encrypt/decrypt with XChaCha20 and initial counter
127
* @param c - Output buffer for ciphertext/plaintext (same length as message)
128
* @param m - Message buffer to encrypt/decrypt
129
* @param n - Nonce buffer (must be NONCEBYTES long)
130
* @param ic - Initial counter value
131
* @param k - Key buffer (must be KEYBYTES long)
132
* @throws Error if buffer sizes are incorrect or operation fails
133
*/
134
function crypto_stream_xchacha20_xor_ic(c: Buffer, m: Buffer, n: Buffer, ic: number, k: Buffer): void;
135
```
136
137
### Salsa20 Stream Cipher
138
139
High-performance stream cipher, predecessor to ChaCha20.
140
141
```javascript { .api }
142
/**
143
* Generate Salsa20 keystream
144
* @param c - Output buffer for keystream
145
* @param n - Nonce buffer (must be NONCEBYTES long)
146
* @param k - Key buffer (must be KEYBYTES long)
147
* @throws Error if buffer sizes are incorrect or generation fails
148
*/
149
function crypto_stream_salsa20(c: Buffer, n: Buffer, k: Buffer): void;
150
151
/**
152
* Encrypt/decrypt data with Salsa20
153
* @param c - Output buffer for ciphertext/plaintext (same length as message)
154
* @param m - Message buffer to encrypt/decrypt
155
* @param n - Nonce buffer (must be NONCEBYTES long)
156
* @param k - Key buffer (must be KEYBYTES long)
157
* @throws Error if buffer sizes are incorrect or operation fails
158
*/
159
function crypto_stream_salsa20_xor(c: Buffer, m: Buffer, n: Buffer, k: Buffer): void;
160
161
/**
162
* Encrypt/decrypt with Salsa20 and initial counter
163
* @param c - Output buffer for ciphertext/plaintext (same length as message)
164
* @param m - Message buffer to encrypt/decrypt
165
* @param n - Nonce buffer (must be NONCEBYTES long)
166
* @param ic - Initial counter value
167
* @param k - Key buffer (must be KEYBYTES long)
168
* @throws Error if buffer sizes are incorrect or operation fails
169
*/
170
function crypto_stream_salsa20_xor_ic(c: Buffer, m: Buffer, n: Buffer, ic: number, k: Buffer): void;
171
```
172
173
### Stateful Stream Cipher Wrappers
174
175
Sodium-native specific wrappers for streaming encryption with state management.
176
177
```javascript { .api }
178
/**
179
* Initialize ChaCha20 streaming encryption state
180
* @param state - State buffer (must be STATEBYTES long)
181
* @param n - Nonce buffer (must be NONCEBYTES long)
182
* @param k - Key buffer (must be KEYBYTES long)
183
*/
184
function crypto_stream_chacha20_xor_wrap_init(state: Buffer, n: Buffer, k: Buffer): void;
185
186
/**
187
* Update ChaCha20 streaming encryption with more data
188
* @param state - State buffer from init
189
* @param c - Output buffer for ciphertext/plaintext (same length as message)
190
* @param m - Message buffer to encrypt/decrypt
191
*/
192
function crypto_stream_chacha20_xor_wrap_update(state: Buffer, c: Buffer, m: Buffer): void;
193
194
/**
195
* Finalize ChaCha20 streaming encryption
196
* @param state - State buffer from init/update
197
*/
198
function crypto_stream_chacha20_xor_wrap_final(state: Buffer): void;
199
```
200
201
**Usage Example:**
202
203
```javascript
204
const sodium = require('sodium-native');
205
206
// Streaming encryption for large data
207
const key = Buffer.alloc(sodium.crypto_stream_chacha20_KEYBYTES);
208
const nonce = Buffer.alloc(sodium.crypto_stream_chacha20_NONCEBYTES);
209
sodium.randombytes_buf(key);
210
sodium.randombytes_buf(nonce);
211
212
const state = Buffer.alloc(sodium.crypto_stream_chacha20_xor_STATEBYTES);
213
sodium.crypto_stream_chacha20_xor_wrap_init(state, nonce, key);
214
215
// Process data in chunks
216
const chunk1 = Buffer.from('First chunk of data');
217
const chunk2 = Buffer.from('Second chunk of data');
218
const encrypted1 = Buffer.alloc(chunk1.length);
219
const encrypted2 = Buffer.alloc(chunk2.length);
220
221
sodium.crypto_stream_chacha20_xor_wrap_update(state, encrypted1, chunk1);
222
sodium.crypto_stream_chacha20_xor_wrap_update(state, encrypted2, chunk2);
223
224
sodium.crypto_stream_chacha20_xor_wrap_final(state);
225
```
226
227
## Constants
228
229
```javascript { .api }
230
// Generic stream cipher constants
231
const crypto_stream_KEYBYTES: number;
232
const crypto_stream_NONCEBYTES: number;
233
234
// ChaCha20 constants
235
const crypto_stream_chacha20_KEYBYTES: number;
236
const crypto_stream_chacha20_NONCEBYTES: number;
237
const crypto_stream_chacha20_MESSAGEBYTES_MAX: number;
238
const crypto_stream_chacha20_xor_STATEBYTES: number;
239
240
// ChaCha20-IETF constants
241
const crypto_stream_chacha20_ietf_KEYBYTES: number;
242
const crypto_stream_chacha20_ietf_NONCEBYTES: number;
243
const crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX: number;
244
const crypto_stream_chacha20_ietf_xor_STATEBYTES: number;
245
246
// XChaCha20 constants
247
const crypto_stream_xchacha20_KEYBYTES: number;
248
const crypto_stream_xchacha20_NONCEBYTES: number;
249
const crypto_stream_xchacha20_MESSAGEBYTES_MAX: number;
250
const crypto_stream_xchacha20_xor_STATEBYTES: number;
251
252
// Salsa20 constants
253
const crypto_stream_salsa20_KEYBYTES: number;
254
const crypto_stream_salsa20_NONCEBYTES: number;
255
const crypto_stream_salsa20_MESSAGEBYTES_MAX: number;
256
const crypto_stream_salsa20_xor_STATEBYTES: number;
257
258
// Sodium-native specific
259
const sn_crypto_stream_xor_STATEBYTES: number;
260
```
261
262
## Security Considerations
263
264
- **Nonce Reuse**: Never reuse nonces with the same key. Each encryption must use a unique nonce.
265
- **Key Management**: Use secure key generation and storage practices.
266
- **Message Size**: Be aware of maximum message size limits for each cipher variant.
267
- **Authentication**: Stream ciphers provide no authentication - consider using AEAD modes or separate MAC.
268
269
## Common Patterns
270
271
### File Encryption with Stream Cipher
272
273
```javascript
274
const sodium = require('sodium-native');
275
const fs = require('fs');
276
277
class StreamFileEncryption {
278
constructor(cipher = 'xchacha20') {
279
this.cipher = cipher;
280
this.keyBytes = sodium[`crypto_stream_${cipher}_KEYBYTES`];
281
this.nonceBytes = sodium[`crypto_stream_${cipher}_NONCEBYTES`];
282
}
283
284
encryptFile(inputFile, outputFile, key) {
285
const nonce = Buffer.alloc(this.nonceBytes);
286
sodium.randombytes_buf(nonce);
287
288
const input = fs.readFileSync(inputFile);
289
const output = Buffer.alloc(input.length);
290
291
sodium[`crypto_stream_${this.cipher}_xor`](output, input, nonce, key);
292
293
// Prepend nonce to encrypted data
294
const encrypted = Buffer.concat([nonce, output]);
295
fs.writeFileSync(outputFile, encrypted);
296
}
297
298
decryptFile(inputFile, outputFile, key) {
299
const encrypted = fs.readFileSync(inputFile);
300
const nonce = encrypted.subarray(0, this.nonceBytes);
301
const ciphertext = encrypted.subarray(this.nonceBytes);
302
303
const output = Buffer.alloc(ciphertext.length);
304
sodium[`crypto_stream_${this.cipher}_xor`](output, ciphertext, nonce, key);
305
306
fs.writeFileSync(outputFile, output);
307
}
308
}
309
```
310
311
### Streaming Data Encryption
312
313
```javascript
314
const sodium = require('sodium-native');
315
316
class StreamCipher {
317
constructor(key, nonce, cipher = 'chacha20') {
318
this.cipher = cipher;
319
this.state = Buffer.alloc(sodium[`crypto_stream_${cipher}_xor_STATEBYTES`]);
320
sodium[`crypto_stream_${cipher}_xor_wrap_init`](this.state, nonce, key);
321
}
322
323
process(data) {
324
const output = Buffer.alloc(data.length);
325
sodium[`crypto_stream_${this.cipher}_xor_wrap_update`](this.state, output, data);
326
return output;
327
}
328
329
finalize() {
330
sodium[`crypto_stream_${this.cipher}_xor_wrap_final`](this.state);
331
}
332
}
333
334
// Usage
335
const key = Buffer.alloc(sodium.crypto_stream_chacha20_KEYBYTES);
336
const nonce = Buffer.alloc(sodium.crypto_stream_chacha20_NONCEBYTES);
337
sodium.randombytes_buf(key);
338
sodium.randombytes_buf(nonce);
339
340
const cipher = new StreamCipher(key, nonce);
341
342
// Process data in chunks
343
const encrypted1 = cipher.process(Buffer.from('First chunk'));
344
const encrypted2 = cipher.process(Buffer.from('Second chunk'));
345
346
cipher.finalize();
347
```
348
349
### Counter Mode with Custom Position
350
351
```javascript
352
const sodium = require('sodium-native');
353
354
function encryptAtPosition(data, key, nonce, position) {
355
// Calculate initial counter based on position
356
const blockSize = 64; // ChaCha20 block size
357
const initialCounter = Math.floor(position / blockSize);
358
359
const output = Buffer.alloc(data.length);
360
sodium.crypto_stream_chacha20_xor_ic(output, data, nonce, initialCounter, key);
361
362
return output;
363
}
364
365
// Useful for random access in encrypted files
366
const key = Buffer.alloc(sodium.crypto_stream_chacha20_KEYBYTES);
367
const nonce = Buffer.alloc(sodium.crypto_stream_chacha20_NONCEBYTES);
368
sodium.randombytes_buf(key);
369
sodium.randombytes_buf(nonce);
370
371
// Encrypt data at specific file position
372
const position = 1024; // Start encryption at byte 1024
373
const data = Buffer.from('Data to encrypt at position');
374
const encrypted = encryptAtPosition(data, key, nonce, position);
375
```