0
# Secret Key Encryption
1
2
Symmetric authenticated encryption using the crypto_secretbox construction (XSalsa20 + Poly1305) for protecting data with shared keys.
3
4
## Capabilities
5
6
### Easy Mode Encryption
7
8
Encrypts a message using a secret key and nonce, producing authenticated ciphertext.
9
10
```javascript { .api }
11
/**
12
* Encrypt message using secret key (authenticated encryption)
13
* @param c - Output buffer for ciphertext (must be m.length + MACBYTES)
14
* @param m - Message buffer to encrypt
15
* @param n - Nonce buffer (must be NONCEBYTES long)
16
* @param k - Secret key buffer (must be KEYBYTES long)
17
* @throws Error if buffer sizes are incorrect or encryption fails
18
*/
19
function crypto_secretbox_easy(c: Buffer, m: Buffer, n: Buffer, k: Buffer): void;
20
```
21
22
### Easy Mode Decryption
23
24
Decrypts and verifies authenticated ciphertext using a secret key and nonce.
25
26
```javascript { .api }
27
/**
28
* Decrypt and verify ciphertext using secret key
29
* @param m - Output buffer for plaintext (must be c.length - MACBYTES)
30
* @param c - Ciphertext buffer to decrypt
31
* @param n - Nonce buffer (must be NONCEBYTES long)
32
* @param k - Secret key buffer (must be KEYBYTES long)
33
* @returns true if decryption successful, false if verification fails
34
* @throws Error if buffer sizes are incorrect
35
*/
36
function crypto_secretbox_open_easy(m: Buffer, c: Buffer, n: Buffer, k: Buffer): boolean;
37
```
38
39
**Usage Example:**
40
41
```javascript
42
const sodium = require('sodium-native');
43
44
// Generate key and nonce
45
const key = Buffer.alloc(sodium.crypto_secretbox_KEYBYTES);
46
const nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES);
47
sodium.randombytes_buf(key);
48
sodium.randombytes_buf(nonce);
49
50
// Encrypt a message
51
const message = Buffer.from('Hello, World!');
52
const ciphertext = Buffer.alloc(message.length + sodium.crypto_secretbox_MACBYTES);
53
sodium.crypto_secretbox_easy(ciphertext, message, nonce, key);
54
55
// Decrypt the message
56
const plaintext = Buffer.alloc(ciphertext.length - sodium.crypto_secretbox_MACBYTES);
57
if (sodium.crypto_secretbox_open_easy(plaintext, ciphertext, nonce, key)) {
58
console.log('Decrypted:', plaintext.toString());
59
} else {
60
console.log('Decryption failed - invalid ciphertext or key');
61
}
62
```
63
64
### Detached Mode Encryption
65
66
Encrypts a message with the authentication tag stored separately from the ciphertext.
67
68
```javascript { .api }
69
/**
70
* Encrypt message with detached authentication tag
71
* @param c - Output buffer for ciphertext (must be same length as message)
72
* @param mac - Output buffer for authentication tag (must be MACBYTES long)
73
* @param m - Message buffer to encrypt
74
* @param n - Nonce buffer (must be NONCEBYTES long)
75
* @param k - Secret key buffer (must be KEYBYTES long)
76
* @throws Error if buffer sizes are incorrect or encryption fails
77
*/
78
function crypto_secretbox_detached(c: Buffer, mac: Buffer, m: Buffer, n: Buffer, k: Buffer): void;
79
```
80
81
### Detached Mode Decryption
82
83
Decrypts a message using a separate authentication tag.
84
85
```javascript { .api }
86
/**
87
* Decrypt message with detached authentication tag
88
* @param m - Output buffer for plaintext (must be same length as ciphertext)
89
* @param c - Ciphertext buffer to decrypt
90
* @param mac - Authentication tag buffer (must be MACBYTES long)
91
* @param n - Nonce buffer (must be NONCEBYTES long)
92
* @param k - Secret key buffer (must be KEYBYTES long)
93
* @returns true if decryption successful, false if verification fails
94
* @throws Error if buffer sizes are incorrect
95
*/
96
function crypto_secretbox_open_detached(m: Buffer, c: Buffer, mac: Buffer, n: Buffer, k: Buffer): boolean;
97
```
98
99
**Usage Example:**
100
101
```javascript
102
const sodium = require('sodium-native');
103
104
// Generate key and nonce
105
const key = Buffer.alloc(sodium.crypto_secretbox_KEYBYTES);
106
const nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES);
107
sodium.randombytes_buf(key);
108
sodium.randombytes_buf(nonce);
109
110
// Encrypt with detached MAC
111
const message = Buffer.from('Secret message');
112
const ciphertext = Buffer.alloc(message.length);
113
const mac = Buffer.alloc(sodium.crypto_secretbox_MACBYTES);
114
115
sodium.crypto_secretbox_detached(ciphertext, mac, message, nonce, key);
116
117
// Decrypt with detached MAC
118
const plaintext = Buffer.alloc(ciphertext.length);
119
if (sodium.crypto_secretbox_open_detached(plaintext, ciphertext, mac, nonce, key)) {
120
console.log('Decrypted:', plaintext.toString());
121
} else {
122
console.log('Authentication failed');
123
}
124
```
125
126
## Constants
127
128
```javascript { .api }
129
// Secret key size in bytes
130
const crypto_secretbox_KEYBYTES: number;
131
132
// Nonce size in bytes
133
const crypto_secretbox_NONCEBYTES: number;
134
135
// Authentication tag size in bytes
136
const crypto_secretbox_MACBYTES: number;
137
```
138
139
## Security Considerations
140
141
- **Nonce Reuse**: Never reuse a nonce with the same key. Each encryption operation must use a unique nonce.
142
- **Key Management**: Keep secret keys secure and use `sodium_malloc()` for secure key storage.
143
- **Authentication**: The Poly1305 authenticator ensures ciphertext integrity and authenticity.
144
- **Timing Safety**: All operations are designed to be timing-attack resistant.
145
146
## Common Patterns
147
148
### File Encryption
149
150
```javascript
151
const sodium = require('sodium-native');
152
const fs = require('fs');
153
154
function encryptFile(inputFile, outputFile, key) {
155
const plaintext = fs.readFileSync(inputFile);
156
const nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES);
157
sodium.randombytes_buf(nonce);
158
159
const ciphertext = Buffer.alloc(plaintext.length + sodium.crypto_secretbox_MACBYTES);
160
sodium.crypto_secretbox_easy(ciphertext, plaintext, nonce, key);
161
162
// Prepend nonce to ciphertext for storage
163
const encrypted = Buffer.concat([nonce, ciphertext]);
164
fs.writeFileSync(outputFile, encrypted);
165
}
166
167
function decryptFile(inputFile, outputFile, key) {
168
const encrypted = fs.readFileSync(inputFile);
169
const nonce = encrypted.subarray(0, sodium.crypto_secretbox_NONCEBYTES);
170
const ciphertext = encrypted.subarray(sodium.crypto_secretbox_NONCEBYTES);
171
172
const plaintext = Buffer.alloc(ciphertext.length - sodium.crypto_secretbox_MACBYTES);
173
if (sodium.crypto_secretbox_open_easy(plaintext, ciphertext, nonce, key)) {
174
fs.writeFileSync(outputFile, plaintext);
175
return true;
176
}
177
return false;
178
}
179
```
180
181
### Message Encryption with Counter
182
183
```javascript
184
const sodium = require('sodium-native');
185
186
class SecretBoxWithCounter {
187
constructor(key) {
188
this.key = key;
189
this.counter = 0n;
190
}
191
192
encrypt(message) {
193
const nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES);
194
nonce.writeBigUInt64LE(this.counter++, 0);
195
196
const ciphertext = Buffer.alloc(message.length + sodium.crypto_secretbox_MACBYTES);
197
sodium.crypto_secretbox_easy(ciphertext, message, nonce, this.key);
198
199
return { ciphertext, nonce };
200
}
201
202
decrypt(ciphertext, nonce) {
203
const plaintext = Buffer.alloc(ciphertext.length - sodium.crypto_secretbox_MACBYTES);
204
if (sodium.crypto_secretbox_open_easy(plaintext, ciphertext, nonce, this.key)) {
205
return plaintext;
206
}
207
return null;
208
}
209
}
210
```