or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

aead.mdauth.mdbox.mdhash.mdindex.mdkey-derivation.mdsecretbox.mdsign.mdstreaming.mdutilities.md
tile.json

box.mddocs/

0

# Public-Key Encryption (Box)

1

2

Public-key encryption functions enable secure communication between parties using public key cryptography. The "box" functions use Curve25519 for key exchange combined with authenticated encryption algorithms.

3

4

## Supported Variants

5

6

- **Curve25519XSalsa20Poly1305**: Original NaCl-compatible implementation

7

- **Curve25519XChaCha20Poly1305**: Extended nonce variant for better security

8

- **Generic Box**: Defaults to Curve25519XSalsa20Poly1305

9

10

## Key Pair Generation

11

12

### Generic Key Pair

13

14

```javascript { .api }

15

/**

16

* Generate a random Curve25519 key pair

17

* @returns Object with publicKey and privateKey properties

18

*/

19

function crypto_box_keypair(): {

20

publicKey: Uint8Array; // 32 bytes

21

privateKey: Uint8Array; // 32 bytes

22

};

23

24

/**

25

* Generate deterministic key pair from seed

26

* @param seed - 32-byte seed for key generation

27

* @returns Object with publicKey and privateKey properties

28

*/

29

function crypto_box_seed_keypair(seed: Uint8Array): {

30

publicKey: Uint8Array;

31

privateKey: Uint8Array;

32

};

33

```

34

35

### XChaCha20 Variant Key Pairs

36

37

```javascript { .api }

38

/**

39

* Generate key pair for XChaCha20 variant

40

* @returns Object with publicKey and secretKey properties

41

*/

42

function crypto_box_curve25519xchacha20poly1305_keypair(): {

43

publicKey: Uint8Array; // 32 bytes

44

secretKey: Uint8Array; // 32 bytes

45

};

46

47

/**

48

* Generate deterministic XChaCha20 key pair from seed

49

* @param seed - 32-byte seed

50

* @returns Object with publicKey and privateKey properties

51

*/

52

function crypto_box_curve25519xchacha20poly1305_seed_keypair(seed: Uint8Array): {

53

publicKey: Uint8Array;

54

privateKey: Uint8Array;

55

};

56

```

57

58

## Authenticated Encryption

59

60

### Generic Box (XSalsa20Poly1305)

61

62

```javascript { .api }

63

/**

64

* Encrypt message for a recipient using public key cryptography

65

* @param message - Plaintext to encrypt

66

* @param nonce - 24-byte nonce (must be unique per key pair)

67

* @param publicKey - Recipient's 32-byte public key

68

* @param privateKey - Sender's 32-byte private key

69

* @returns Uint8Array - Encrypted message with authentication tag

70

*/

71

function crypto_box_easy(

72

message: Uint8Array,

73

nonce: Uint8Array,

74

publicKey: Uint8Array,

75

privateKey: Uint8Array

76

): Uint8Array;

77

78

/**

79

* Decrypt message using public key cryptography

80

* @param ciphertext - Encrypted message with authentication tag

81

* @param nonce - 24-byte nonce used for encryption

82

* @param publicKey - Sender's 32-byte public key

83

* @param privateKey - Recipient's 32-byte private key

84

* @returns Uint8Array - Decrypted plaintext

85

* @throws Error if decryption fails

86

*/

87

function crypto_box_open_easy(

88

ciphertext: Uint8Array,

89

nonce: Uint8Array,

90

publicKey: Uint8Array,

91

privateKey: Uint8Array

92

): Uint8Array;

93

```

94

95

### XChaCha20 Variant

96

97

```javascript { .api }

98

/**

99

* Encrypt using XChaCha20-Poly1305 (recommended)

100

* @param message - Plaintext to encrypt

101

* @param nonce - 24-byte nonce (can be random)

102

* @param publicKey - Recipient's public key

103

* @param privateKey - Sender's private key

104

* @returns Uint8Array - Encrypted message

105

*/

106

function crypto_box_curve25519xchacha20poly1305_easy(

107

message: Uint8Array,

108

nonce: Uint8Array,

109

publicKey: Uint8Array,

110

privateKey: Uint8Array

111

): Uint8Array;

112

113

/**

114

* Decrypt using XChaCha20-Poly1305

115

* @param ciphertext - Encrypted message

116

* @param nonce - 24-byte nonce

117

* @param publicKey - Sender's public key

118

* @param privateKey - Recipient's private key

119

* @returns Uint8Array - Decrypted plaintext

120

*/

121

function crypto_box_curve25519xchacha20poly1305_open_easy(

122

ciphertext: Uint8Array,

123

nonce: Uint8Array,

124

publicKey: Uint8Array,

125

privateKey: Uint8Array

126

): Uint8Array;

127

```

128

129

## Detached Authentication

130

131

### Generic Box Detached

132

133

```javascript { .api }

134

/**

135

* Encrypt with separate authentication tag

136

* @param message - Plaintext to encrypt

137

* @param nonce - 24-byte nonce

138

* @param publicKey - Recipient's public key

139

* @param privateKey - Sender's private key

140

* @returns Object with ciphertext and mac properties

141

*/

142

function crypto_box_detached(

143

message: Uint8Array,

144

nonce: Uint8Array,

145

publicKey: Uint8Array,

146

privateKey: Uint8Array

147

): { ciphertext: Uint8Array; mac: Uint8Array };

148

149

/**

150

* Decrypt with separate authentication tag

151

* @param ciphertext - Encrypted data (without tag)

152

* @param mac - Authentication tag

153

* @param nonce - 24-byte nonce

154

* @param publicKey - Sender's public key

155

* @param privateKey - Recipient's private key

156

* @returns Uint8Array - Decrypted plaintext

157

*/

158

function crypto_box_open_detached(

159

ciphertext: Uint8Array,

160

mac: Uint8Array,

161

nonce: Uint8Array,

162

publicKey: Uint8Array,

163

privateKey: Uint8Array

164

): Uint8Array;

165

```

166

167

### XChaCha20 Detached

168

169

```javascript { .api }

170

function crypto_box_curve25519xchacha20poly1305_detached(

171

message: Uint8Array,

172

nonce: Uint8Array,

173

publicKey: Uint8Array,

174

privateKey: Uint8Array

175

): { ciphertext: Uint8Array; mac: Uint8Array };

176

177

function crypto_box_curve25519xchacha20poly1305_open_detached(

178

ciphertext: Uint8Array,

179

mac: Uint8Array,

180

nonce: Uint8Array,

181

publicKey: Uint8Array,

182

privateKey: Uint8Array

183

): Uint8Array;

184

```

185

186

## Precomputed Shared Keys

187

188

For multiple messages between the same key pair, you can precompute the shared key for better performance.

189

190

### Generic Box Precomputation

191

192

```javascript { .api }

193

/**

194

* Precompute shared secret for multiple encryptions

195

* @param publicKey - Other party's public key

196

* @param privateKey - Your private key

197

* @returns Uint8Array - 32-byte shared secret

198

*/

199

function crypto_box_beforenm(

200

publicKey: Uint8Array,

201

privateKey: Uint8Array

202

): Uint8Array;

203

204

/**

205

* Encrypt using precomputed shared secret

206

* @param message - Plaintext to encrypt

207

* @param nonce - 24-byte nonce

208

* @param sharedKey - Precomputed shared secret

209

* @returns Uint8Array - Encrypted message

210

*/

211

function crypto_box_easy_afternm(

212

message: Uint8Array,

213

nonce: Uint8Array,

214

sharedKey: Uint8Array

215

): Uint8Array;

216

217

/**

218

* Decrypt using precomputed shared secret

219

* @param ciphertext - Encrypted message

220

* @param nonce - 24-byte nonce

221

* @param sharedKey - Precomputed shared secret

222

* @returns Uint8Array - Decrypted plaintext

223

*/

224

function crypto_box_open_easy_afternm(

225

ciphertext: Uint8Array,

226

nonce: Uint8Array,

227

sharedKey: Uint8Array

228

): Uint8Array;

229

```

230

231

### XChaCha20 Precomputation

232

233

```javascript { .api }

234

function crypto_box_curve25519xchacha20poly1305_beforenm(

235

publicKey: Uint8Array,

236

privateKey: Uint8Array

237

): Uint8Array;

238

239

function crypto_box_curve25519xchacha20poly1305_easy_afternm(

240

message: Uint8Array,

241

nonce: Uint8Array,

242

sharedKey: Uint8Array

243

): Uint8Array;

244

245

function crypto_box_curve25519xchacha20poly1305_open_easy_afternm(

246

ciphertext: Uint8Array,

247

nonce: Uint8Array,

248

sharedKey: Uint8Array

249

): Uint8Array;

250

251

function crypto_box_curve25519xchacha20poly1305_detached_afternm(

252

message: Uint8Array,

253

nonce: Uint8Array,

254

sharedKey: Uint8Array

255

): { ciphertext: Uint8Array; mac: Uint8Array };

256

257

function crypto_box_curve25519xchacha20poly1305_open_detached_afternm(

258

ciphertext: Uint8Array,

259

mac: Uint8Array,

260

nonce: Uint8Array,

261

sharedKey: Uint8Array

262

): Uint8Array;

263

```

264

265

## Sealed Boxes (Anonymous Encryption)

266

267

Sealed boxes provide anonymous encryption where only the recipient's public key is needed.

268

269

### Generic Sealed Boxes

270

271

```javascript { .api }

272

/**

273

* Encrypt message anonymously for recipient

274

* @param message - Plaintext to encrypt

275

* @param publicKey - Recipient's public key

276

* @returns Uint8Array - Anonymous encrypted message

277

*/

278

function crypto_box_seal(

279

message: Uint8Array,

280

publicKey: Uint8Array

281

): Uint8Array;

282

283

/**

284

* Decrypt anonymously encrypted message

285

* @param ciphertext - Anonymous encrypted message

286

* @param publicKey - Recipient's public key

287

* @param secretKey - Recipient's private key

288

* @returns Uint8Array - Decrypted plaintext

289

*/

290

function crypto_box_seal_open(

291

ciphertext: Uint8Array,

292

publicKey: Uint8Array,

293

secretKey: Uint8Array

294

): Uint8Array;

295

```

296

297

### XChaCha20 Sealed Boxes

298

299

```javascript { .api }

300

function crypto_box_curve25519xchacha20poly1305_seal(

301

message: Uint8Array,

302

publicKey: Uint8Array

303

): Uint8Array;

304

305

function crypto_box_curve25519xchacha20poly1305_seal_open(

306

ciphertext: Uint8Array,

307

publicKey: Uint8Array,

308

secretKey: Uint8Array

309

): Uint8Array;

310

```

311

312

## Constants

313

314

### Generic Box Constants

315

316

```javascript { .api }

317

const crypto_box_PUBLICKEYBYTES: number; // 32

318

const crypto_box_SECRETKEYBYTES: number; // 32

319

const crypto_box_NONCEBYTES: number; // 24

320

const crypto_box_MACBYTES: number; // 16

321

const crypto_box_BEFORENMBYTES: number; // 32

322

const crypto_box_SEALBYTES: number; // 48

323

const crypto_box_SEEDBYTES: number; // 32

324

const crypto_box_MESSAGEBYTES_MAX: number; // Large value

325

```

326

327

### XChaCha20 Variant Constants

328

329

```javascript { .api }

330

const crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES: number; // 32

331

const crypto_box_curve25519xchacha20poly1305_SECRETKEYBYTES: number; // 32

332

const crypto_box_curve25519xchacha20poly1305_NONCEBYTES: number; // 24

333

const crypto_box_curve25519xchacha20poly1305_MACBYTES: number; // 16

334

const crypto_box_curve25519xchacha20poly1305_BEFORENMBYTES: number; // 32

335

const crypto_box_curve25519xchacha20poly1305_SEALBYTES: number; // 48

336

const crypto_box_curve25519xchacha20poly1305_SEEDBYTES: number; // 32

337

```

338

339

## Usage Examples

340

341

### Basic Public Key Encryption

342

343

```javascript

344

import _sodium from 'libsodium-wrappers-sumo';

345

await _sodium.ready;

346

const sodium = _sodium;

347

348

// Generate key pairs for Alice and Bob

349

const alice = sodium.crypto_box_keypair();

350

const bob = sodium.crypto_box_keypair();

351

352

// Alice encrypts message for Bob

353

const message = sodium.from_string('Secret message from Alice');

354

const nonce = sodium.randombytes_buf(sodium.crypto_box_NONCEBYTES);

355

356

const ciphertext = sodium.crypto_box_easy(

357

message, nonce, bob.publicKey, alice.privateKey

358

);

359

360

// Bob decrypts message from Alice

361

const plaintext = sodium.crypto_box_open_easy(

362

ciphertext, nonce, alice.publicKey, bob.privateKey

363

);

364

365

console.log(sodium.to_string(plaintext)); // "Secret message from Alice"

366

```

367

368

### Using XChaCha20 Variant (Recommended)

369

370

```javascript

371

// XChaCha20 allows safe random nonce generation

372

const alice = sodium.crypto_box_curve25519xchacha20poly1305_keypair();

373

const bob = sodium.crypto_box_curve25519xchacha20poly1305_keypair();

374

375

const message = sodium.from_string('Secure message');

376

const nonce = sodium.randombytes_buf(24); // Safe to generate randomly

377

378

const ciphertext = sodium.crypto_box_curve25519xchacha20poly1305_easy(

379

message, nonce, bob.publicKey, alice.secretKey

380

);

381

382

const plaintext = sodium.crypto_box_curve25519xchacha20poly1305_open_easy(

383

ciphertext, nonce, alice.publicKey, bob.secretKey

384

);

385

```

386

387

### Precomputed Keys for Performance

388

389

```javascript

390

// For multiple messages between same parties

391

const sharedAB = sodium.crypto_box_beforenm(bob.publicKey, alice.privateKey);

392

const sharedBA = sodium.crypto_box_beforenm(alice.publicKey, bob.privateKey);

393

394

// Alice encrypts multiple messages efficiently

395

for (let i = 0; i < 100; i++) {

396

const message = sodium.from_string(`Message ${i}`);

397

const nonce = sodium.randombytes_buf(sodium.crypto_box_NONCEBYTES);

398

399

const ciphertext = sodium.crypto_box_easy_afternm(message, nonce, sharedAB);

400

const plaintext = sodium.crypto_box_open_easy_afternm(ciphertext, nonce, sharedBA);

401

}

402

```

403

404

### Sealed Boxes (Anonymous Encryption)

405

406

```javascript

407

// Anonymous encryption - only recipient's public key needed

408

const recipient = sodium.crypto_box_keypair();

409

const anonymousMessage = sodium.from_string('Anonymous tip');

410

411

// Encrypt anonymously

412

const sealedBox = sodium.crypto_box_seal(anonymousMessage, recipient.publicKey);

413

414

// Only recipient can decrypt (no sender identity revealed)

415

const decrypted = sodium.crypto_box_seal_open(

416

sealedBox, recipient.publicKey, recipient.privateKey

417

);

418

419

console.log(sodium.to_string(decrypted)); // "Anonymous tip"

420

```

421

422

### Deterministic Key Generation

423

424

```javascript

425

// Generate keys from seed for reproducible key pairs

426

const seed = sodium.randombytes_buf(sodium.crypto_box_SEEDBYTES);

427

const keyPair1 = sodium.crypto_box_seed_keypair(seed);

428

const keyPair2 = sodium.crypto_box_seed_keypair(seed);

429

430

// Keys are identical

431

console.log(sodium.memcmp(keyPair1.publicKey, keyPair2.publicKey)); // true

432

console.log(sodium.memcmp(keyPair1.privateKey, keyPair2.privateKey)); // true

433

```

434

435

### Detached Authentication

436

437

```javascript

438

const alice = sodium.crypto_box_keypair();

439

const bob = sodium.crypto_box_keypair();

440

const message = sodium.from_string('Message with separate MAC');

441

const nonce = sodium.randombytes_buf(sodium.crypto_box_NONCEBYTES);

442

443

// Encrypt with separate MAC

444

const { ciphertext, mac } = sodium.crypto_box_detached(

445

message, nonce, bob.publicKey, alice.privateKey

446

);

447

448

console.log('Ciphertext:', sodium.to_hex(ciphertext));

449

console.log('MAC:', sodium.to_hex(mac));

450

451

// Decrypt with separate MAC

452

const plaintext = sodium.crypto_box_open_detached(

453

ciphertext, mac, nonce, alice.publicKey, bob.privateKey

454

);

455

```

456

457

## Security Considerations

458

459

- **Nonce Uniqueness**: Never reuse nonces with the same key pair

460

- **Key Management**: Keep private keys secure, public keys can be shared

461

- **XChaCha20 Preference**: Use XChaCha20 variant for new applications (safer nonce handling)

462

- **Authenticated Encryption**: All box functions provide both confidentiality and authenticity

463

- **Forward Secrecy**: Generate new ephemeral keys for forward secrecy

464

- **Side Channels**: All operations are designed to be constant-time

465

466

## Algorithm Selection Guide

467

468

- **XChaCha20 variant**: Recommended for new applications, safer nonce handling

469

- **Generic box**: NaCl compatibility, careful nonce management required

470

- **Sealed boxes**: Anonymous encryption, perfect for drop-boxes or whistleblowing

471

- **Precomputed keys**: Performance optimization for repeated communication between same parties

472

473

All variants provide equivalent security when used correctly.