CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-libsodium-wrappers-sumo

The Sodium cryptographic library compiled to pure JavaScript (wrappers, sumo variant)

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

box.mddocs/

Public-Key Encryption (Box)

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.

Supported Variants

  • Curve25519XSalsa20Poly1305: Original NaCl-compatible implementation
  • Curve25519XChaCha20Poly1305: Extended nonce variant for better security
  • Generic Box: Defaults to Curve25519XSalsa20Poly1305

Key Pair Generation

Generic Key Pair

/**
 * Generate a random Curve25519 key pair
 * @returns Object with publicKey and privateKey properties
 */
function crypto_box_keypair(): {
  publicKey: Uint8Array;  // 32 bytes
  privateKey: Uint8Array; // 32 bytes
};

/**
 * Generate deterministic key pair from seed
 * @param seed - 32-byte seed for key generation
 * @returns Object with publicKey and privateKey properties
 */
function crypto_box_seed_keypair(seed: Uint8Array): {
  publicKey: Uint8Array;
  privateKey: Uint8Array;
};

XChaCha20 Variant Key Pairs

/**
 * Generate key pair for XChaCha20 variant
 * @returns Object with publicKey and secretKey properties
 */
function crypto_box_curve25519xchacha20poly1305_keypair(): {
  publicKey: Uint8Array;  // 32 bytes
  secretKey: Uint8Array;  // 32 bytes
};

/**
 * Generate deterministic XChaCha20 key pair from seed
 * @param seed - 32-byte seed
 * @returns Object with publicKey and privateKey properties
 */
function crypto_box_curve25519xchacha20poly1305_seed_keypair(seed: Uint8Array): {
  publicKey: Uint8Array;
  privateKey: Uint8Array;
};

Authenticated Encryption

Generic Box (XSalsa20Poly1305)

/**
 * Encrypt message for a recipient using public key cryptography
 * @param message - Plaintext to encrypt
 * @param nonce - 24-byte nonce (must be unique per key pair)
 * @param publicKey - Recipient's 32-byte public key
 * @param privateKey - Sender's 32-byte private key
 * @returns Uint8Array - Encrypted message with authentication tag
 */
function crypto_box_easy(
  message: Uint8Array,
  nonce: Uint8Array,
  publicKey: Uint8Array,
  privateKey: Uint8Array
): Uint8Array;

/**
 * Decrypt message using public key cryptography
 * @param ciphertext - Encrypted message with authentication tag
 * @param nonce - 24-byte nonce used for encryption
 * @param publicKey - Sender's 32-byte public key
 * @param privateKey - Recipient's 32-byte private key
 * @returns Uint8Array - Decrypted plaintext
 * @throws Error if decryption fails
 */
function crypto_box_open_easy(
  ciphertext: Uint8Array,
  nonce: Uint8Array,
  publicKey: Uint8Array,
  privateKey: Uint8Array
): Uint8Array;

XChaCha20 Variant

/**
 * Encrypt using XChaCha20-Poly1305 (recommended)
 * @param message - Plaintext to encrypt
 * @param nonce - 24-byte nonce (can be random)
 * @param publicKey - Recipient's public key
 * @param privateKey - Sender's private key
 * @returns Uint8Array - Encrypted message
 */
function crypto_box_curve25519xchacha20poly1305_easy(
  message: Uint8Array,
  nonce: Uint8Array,
  publicKey: Uint8Array,
  privateKey: Uint8Array
): Uint8Array;

/**
 * Decrypt using XChaCha20-Poly1305
 * @param ciphertext - Encrypted message
 * @param nonce - 24-byte nonce
 * @param publicKey - Sender's public key
 * @param privateKey - Recipient's private key
 * @returns Uint8Array - Decrypted plaintext
 */
function crypto_box_curve25519xchacha20poly1305_open_easy(
  ciphertext: Uint8Array,
  nonce: Uint8Array,
  publicKey: Uint8Array,
  privateKey: Uint8Array
): Uint8Array;

Detached Authentication

Generic Box Detached

/**
 * Encrypt with separate authentication tag
 * @param message - Plaintext to encrypt
 * @param nonce - 24-byte nonce
 * @param publicKey - Recipient's public key
 * @param privateKey - Sender's private key
 * @returns Object with ciphertext and mac properties
 */
function crypto_box_detached(
  message: Uint8Array,
  nonce: Uint8Array,
  publicKey: Uint8Array,
  privateKey: Uint8Array
): { ciphertext: Uint8Array; mac: Uint8Array };

/**
 * Decrypt with separate authentication tag
 * @param ciphertext - Encrypted data (without tag)
 * @param mac - Authentication tag
 * @param nonce - 24-byte nonce
 * @param publicKey - Sender's public key
 * @param privateKey - Recipient's private key
 * @returns Uint8Array - Decrypted plaintext
 */
function crypto_box_open_detached(
  ciphertext: Uint8Array,
  mac: Uint8Array,
  nonce: Uint8Array,
  publicKey: Uint8Array,
  privateKey: Uint8Array
): Uint8Array;

XChaCha20 Detached

function crypto_box_curve25519xchacha20poly1305_detached(
  message: Uint8Array,
  nonce: Uint8Array,
  publicKey: Uint8Array,
  privateKey: Uint8Array
): { ciphertext: Uint8Array; mac: Uint8Array };

function crypto_box_curve25519xchacha20poly1305_open_detached(
  ciphertext: Uint8Array,
  mac: Uint8Array,
  nonce: Uint8Array,
  publicKey: Uint8Array,
  privateKey: Uint8Array
): Uint8Array;

Precomputed Shared Keys

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

Generic Box Precomputation

/**
 * Precompute shared secret for multiple encryptions
 * @param publicKey - Other party's public key
 * @param privateKey - Your private key
 * @returns Uint8Array - 32-byte shared secret
 */
function crypto_box_beforenm(
  publicKey: Uint8Array,
  privateKey: Uint8Array
): Uint8Array;

/**
 * Encrypt using precomputed shared secret
 * @param message - Plaintext to encrypt
 * @param nonce - 24-byte nonce
 * @param sharedKey - Precomputed shared secret
 * @returns Uint8Array - Encrypted message
 */
function crypto_box_easy_afternm(
  message: Uint8Array,
  nonce: Uint8Array,
  sharedKey: Uint8Array
): Uint8Array;

/**
 * Decrypt using precomputed shared secret
 * @param ciphertext - Encrypted message
 * @param nonce - 24-byte nonce
 * @param sharedKey - Precomputed shared secret
 * @returns Uint8Array - Decrypted plaintext
 */
function crypto_box_open_easy_afternm(
  ciphertext: Uint8Array,
  nonce: Uint8Array,
  sharedKey: Uint8Array
): Uint8Array;

XChaCha20 Precomputation

function crypto_box_curve25519xchacha20poly1305_beforenm(
  publicKey: Uint8Array,
  privateKey: Uint8Array
): Uint8Array;

function crypto_box_curve25519xchacha20poly1305_easy_afternm(
  message: Uint8Array,
  nonce: Uint8Array,
  sharedKey: Uint8Array
): Uint8Array;

function crypto_box_curve25519xchacha20poly1305_open_easy_afternm(
  ciphertext: Uint8Array,
  nonce: Uint8Array,
  sharedKey: Uint8Array
): Uint8Array;

function crypto_box_curve25519xchacha20poly1305_detached_afternm(
  message: Uint8Array,
  nonce: Uint8Array,
  sharedKey: Uint8Array
): { ciphertext: Uint8Array; mac: Uint8Array };

function crypto_box_curve25519xchacha20poly1305_open_detached_afternm(
  ciphertext: Uint8Array,
  mac: Uint8Array,
  nonce: Uint8Array,
  sharedKey: Uint8Array
): Uint8Array;

Sealed Boxes (Anonymous Encryption)

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

Generic Sealed Boxes

/**
 * Encrypt message anonymously for recipient
 * @param message - Plaintext to encrypt
 * @param publicKey - Recipient's public key
 * @returns Uint8Array - Anonymous encrypted message
 */
function crypto_box_seal(
  message: Uint8Array,
  publicKey: Uint8Array
): Uint8Array;

/**
 * Decrypt anonymously encrypted message
 * @param ciphertext - Anonymous encrypted message
 * @param publicKey - Recipient's public key
 * @param secretKey - Recipient's private key
 * @returns Uint8Array - Decrypted plaintext
 */
function crypto_box_seal_open(
  ciphertext: Uint8Array,
  publicKey: Uint8Array,
  secretKey: Uint8Array
): Uint8Array;

XChaCha20 Sealed Boxes

function crypto_box_curve25519xchacha20poly1305_seal(
  message: Uint8Array,
  publicKey: Uint8Array
): Uint8Array;

function crypto_box_curve25519xchacha20poly1305_seal_open(
  ciphertext: Uint8Array,
  publicKey: Uint8Array,
  secretKey: Uint8Array
): Uint8Array;

Constants

Generic Box Constants

const crypto_box_PUBLICKEYBYTES: number;    // 32
const crypto_box_SECRETKEYBYTES: number;    // 32
const crypto_box_NONCEBYTES: number;        // 24
const crypto_box_MACBYTES: number;          // 16
const crypto_box_BEFORENMBYTES: number;     // 32
const crypto_box_SEALBYTES: number;         // 48
const crypto_box_SEEDBYTES: number;         // 32
const crypto_box_MESSAGEBYTES_MAX: number;  // Large value

XChaCha20 Variant Constants

const crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES: number;  // 32
const crypto_box_curve25519xchacha20poly1305_SECRETKEYBYTES: number;  // 32
const crypto_box_curve25519xchacha20poly1305_NONCEBYTES: number;      // 24
const crypto_box_curve25519xchacha20poly1305_MACBYTES: number;        // 16
const crypto_box_curve25519xchacha20poly1305_BEFORENMBYTES: number;   // 32
const crypto_box_curve25519xchacha20poly1305_SEALBYTES: number;       // 48
const crypto_box_curve25519xchacha20poly1305_SEEDBYTES: number;       // 32

Usage Examples

Basic Public Key Encryption

import _sodium from 'libsodium-wrappers-sumo';
await _sodium.ready;
const sodium = _sodium;

// Generate key pairs for Alice and Bob
const alice = sodium.crypto_box_keypair();
const bob = sodium.crypto_box_keypair();

// Alice encrypts message for Bob
const message = sodium.from_string('Secret message from Alice');
const nonce = sodium.randombytes_buf(sodium.crypto_box_NONCEBYTES);

const ciphertext = sodium.crypto_box_easy(
  message, nonce, bob.publicKey, alice.privateKey
);

// Bob decrypts message from Alice
const plaintext = sodium.crypto_box_open_easy(
  ciphertext, nonce, alice.publicKey, bob.privateKey
);

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

Using XChaCha20 Variant (Recommended)

// XChaCha20 allows safe random nonce generation
const alice = sodium.crypto_box_curve25519xchacha20poly1305_keypair();
const bob = sodium.crypto_box_curve25519xchacha20poly1305_keypair();

const message = sodium.from_string('Secure message');
const nonce = sodium.randombytes_buf(24); // Safe to generate randomly

const ciphertext = sodium.crypto_box_curve25519xchacha20poly1305_easy(
  message, nonce, bob.publicKey, alice.secretKey
);

const plaintext = sodium.crypto_box_curve25519xchacha20poly1305_open_easy(
  ciphertext, nonce, alice.publicKey, bob.secretKey
);

Precomputed Keys for Performance

// For multiple messages between same parties
const sharedAB = sodium.crypto_box_beforenm(bob.publicKey, alice.privateKey);
const sharedBA = sodium.crypto_box_beforenm(alice.publicKey, bob.privateKey);

// Alice encrypts multiple messages efficiently
for (let i = 0; i < 100; i++) {
  const message = sodium.from_string(`Message ${i}`);
  const nonce = sodium.randombytes_buf(sodium.crypto_box_NONCEBYTES);
  
  const ciphertext = sodium.crypto_box_easy_afternm(message, nonce, sharedAB);
  const plaintext = sodium.crypto_box_open_easy_afternm(ciphertext, nonce, sharedBA);
}

Sealed Boxes (Anonymous Encryption)

// Anonymous encryption - only recipient's public key needed
const recipient = sodium.crypto_box_keypair();
const anonymousMessage = sodium.from_string('Anonymous tip');

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

// Only recipient can decrypt (no sender identity revealed)
const decrypted = sodium.crypto_box_seal_open(
  sealedBox, recipient.publicKey, recipient.privateKey
);

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

Deterministic Key Generation

// Generate keys from seed for reproducible key pairs
const seed = sodium.randombytes_buf(sodium.crypto_box_SEEDBYTES);
const keyPair1 = sodium.crypto_box_seed_keypair(seed);
const keyPair2 = sodium.crypto_box_seed_keypair(seed);

// Keys are identical
console.log(sodium.memcmp(keyPair1.publicKey, keyPair2.publicKey)); // true
console.log(sodium.memcmp(keyPair1.privateKey, keyPair2.privateKey)); // true

Detached Authentication

const alice = sodium.crypto_box_keypair();
const bob = sodium.crypto_box_keypair();
const message = sodium.from_string('Message with separate MAC');
const nonce = sodium.randombytes_buf(sodium.crypto_box_NONCEBYTES);

// Encrypt with separate MAC
const { ciphertext, mac } = sodium.crypto_box_detached(
  message, nonce, bob.publicKey, alice.privateKey
);

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

// Decrypt with separate MAC
const plaintext = sodium.crypto_box_open_detached(
  ciphertext, mac, nonce, alice.publicKey, bob.privateKey
);

Security Considerations

  • Nonce Uniqueness: Never reuse nonces with the same key pair
  • Key Management: Keep private keys secure, public keys can be shared
  • XChaCha20 Preference: Use XChaCha20 variant for new applications (safer nonce handling)
  • Authenticated Encryption: All box functions provide both confidentiality and authenticity
  • Forward Secrecy: Generate new ephemeral keys for forward secrecy
  • Side Channels: All operations are designed to be constant-time

Algorithm Selection Guide

  • XChaCha20 variant: Recommended for new applications, safer nonce handling
  • Generic box: NaCl compatibility, careful nonce management required
  • Sealed boxes: Anonymous encryption, perfect for drop-boxes or whistleblowing
  • Precomputed keys: Performance optimization for repeated communication between same parties

All variants provide equivalent security when used correctly.

docs

aead.md

auth.md

box.md

hash.md

index.md

key-derivation.md

secretbox.md

sign.md

streaming.md

utilities.md

tile.json