The Sodium cryptographic library compiled to pure JavaScript (wrappers, sumo variant)
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
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.
/**
* 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;
};/**
* 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;
};/**
* 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;/**
* 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;/**
* 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;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;For multiple messages between the same key pair, you can precompute the shared key for better performance.
/**
* 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;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 provide anonymous encryption where only the recipient's public key is needed.
/**
* 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;function crypto_box_curve25519xchacha20poly1305_seal(
message: Uint8Array,
publicKey: Uint8Array
): Uint8Array;
function crypto_box_curve25519xchacha20poly1305_seal_open(
ciphertext: Uint8Array,
publicKey: Uint8Array,
secretKey: Uint8Array
): Uint8Array;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 valueconst 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; // 32import _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"// 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
);// 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);
}// 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"// 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)); // trueconst 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
);All variants provide equivalent security when used correctly.