Low level bindings for libsodium cryptographic library
—
Symmetric authenticated encryption using the crypto_secretbox construction (XSalsa20 + Poly1305) for protecting data with shared keys.
Encrypts a message using a secret key and nonce, producing authenticated ciphertext.
/**
* Encrypt message using secret key (authenticated encryption)
* @param c - Output buffer for ciphertext (must be m.length + MACBYTES)
* @param m - Message buffer to encrypt
* @param n - Nonce buffer (must be NONCEBYTES long)
* @param k - Secret key buffer (must be KEYBYTES long)
* @throws Error if buffer sizes are incorrect or encryption fails
*/
function crypto_secretbox_easy(c: Buffer, m: Buffer, n: Buffer, k: Buffer): void;Decrypts and verifies authenticated ciphertext using a secret key and nonce.
/**
* Decrypt and verify ciphertext using secret key
* @param m - Output buffer for plaintext (must be c.length - MACBYTES)
* @param c - Ciphertext buffer to decrypt
* @param n - Nonce buffer (must be NONCEBYTES long)
* @param k - Secret key buffer (must be KEYBYTES long)
* @returns true if decryption successful, false if verification fails
* @throws Error if buffer sizes are incorrect
*/
function crypto_secretbox_open_easy(m: Buffer, c: Buffer, n: Buffer, k: Buffer): boolean;Usage Example:
const sodium = require('sodium-native');
// Generate key and nonce
const key = Buffer.alloc(sodium.crypto_secretbox_KEYBYTES);
const nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES);
sodium.randombytes_buf(key);
sodium.randombytes_buf(nonce);
// Encrypt a message
const message = Buffer.from('Hello, World!');
const ciphertext = Buffer.alloc(message.length + sodium.crypto_secretbox_MACBYTES);
sodium.crypto_secretbox_easy(ciphertext, message, nonce, key);
// Decrypt the message
const plaintext = Buffer.alloc(ciphertext.length - sodium.crypto_secretbox_MACBYTES);
if (sodium.crypto_secretbox_open_easy(plaintext, ciphertext, nonce, key)) {
console.log('Decrypted:', plaintext.toString());
} else {
console.log('Decryption failed - invalid ciphertext or key');
}Encrypts a message with the authentication tag stored separately from the ciphertext.
/**
* Encrypt message with detached authentication tag
* @param c - Output buffer for ciphertext (must be same length as message)
* @param mac - Output buffer for authentication tag (must be MACBYTES long)
* @param m - Message buffer to encrypt
* @param n - Nonce buffer (must be NONCEBYTES long)
* @param k - Secret key buffer (must be KEYBYTES long)
* @throws Error if buffer sizes are incorrect or encryption fails
*/
function crypto_secretbox_detached(c: Buffer, mac: Buffer, m: Buffer, n: Buffer, k: Buffer): void;Decrypts a message using a separate authentication tag.
/**
* Decrypt message with detached authentication tag
* @param m - Output buffer for plaintext (must be same length as ciphertext)
* @param c - Ciphertext buffer to decrypt
* @param mac - Authentication tag buffer (must be MACBYTES long)
* @param n - Nonce buffer (must be NONCEBYTES long)
* @param k - Secret key buffer (must be KEYBYTES long)
* @returns true if decryption successful, false if verification fails
* @throws Error if buffer sizes are incorrect
*/
function crypto_secretbox_open_detached(m: Buffer, c: Buffer, mac: Buffer, n: Buffer, k: Buffer): boolean;Usage Example:
const sodium = require('sodium-native');
// Generate key and nonce
const key = Buffer.alloc(sodium.crypto_secretbox_KEYBYTES);
const nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES);
sodium.randombytes_buf(key);
sodium.randombytes_buf(nonce);
// Encrypt with detached MAC
const message = Buffer.from('Secret message');
const ciphertext = Buffer.alloc(message.length);
const mac = Buffer.alloc(sodium.crypto_secretbox_MACBYTES);
sodium.crypto_secretbox_detached(ciphertext, mac, message, nonce, key);
// Decrypt with detached MAC
const plaintext = Buffer.alloc(ciphertext.length);
if (sodium.crypto_secretbox_open_detached(plaintext, ciphertext, mac, nonce, key)) {
console.log('Decrypted:', plaintext.toString());
} else {
console.log('Authentication failed');
}// Secret key size in bytes
const crypto_secretbox_KEYBYTES: number;
// Nonce size in bytes
const crypto_secretbox_NONCEBYTES: number;
// Authentication tag size in bytes
const crypto_secretbox_MACBYTES: number;sodium_malloc() for secure key storage.const sodium = require('sodium-native');
const fs = require('fs');
function encryptFile(inputFile, outputFile, key) {
const plaintext = fs.readFileSync(inputFile);
const nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES);
sodium.randombytes_buf(nonce);
const ciphertext = Buffer.alloc(plaintext.length + sodium.crypto_secretbox_MACBYTES);
sodium.crypto_secretbox_easy(ciphertext, plaintext, nonce, key);
// Prepend nonce to ciphertext for storage
const encrypted = Buffer.concat([nonce, ciphertext]);
fs.writeFileSync(outputFile, encrypted);
}
function decryptFile(inputFile, outputFile, key) {
const encrypted = fs.readFileSync(inputFile);
const nonce = encrypted.subarray(0, sodium.crypto_secretbox_NONCEBYTES);
const ciphertext = encrypted.subarray(sodium.crypto_secretbox_NONCEBYTES);
const plaintext = Buffer.alloc(ciphertext.length - sodium.crypto_secretbox_MACBYTES);
if (sodium.crypto_secretbox_open_easy(plaintext, ciphertext, nonce, key)) {
fs.writeFileSync(outputFile, plaintext);
return true;
}
return false;
}const sodium = require('sodium-native');
class SecretBoxWithCounter {
constructor(key) {
this.key = key;
this.counter = 0n;
}
encrypt(message) {
const nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES);
nonce.writeBigUInt64LE(this.counter++, 0);
const ciphertext = Buffer.alloc(message.length + sodium.crypto_secretbox_MACBYTES);
sodium.crypto_secretbox_easy(ciphertext, message, nonce, this.key);
return { ciphertext, nonce };
}
decrypt(ciphertext, nonce) {
const plaintext = Buffer.alloc(ciphertext.length - sodium.crypto_secretbox_MACBYTES);
if (sodium.crypto_secretbox_open_easy(plaintext, ciphertext, nonce, this.key)) {
return plaintext;
}
return null;
}
}Install with Tessl CLI
npx tessl i tessl/npm-sodium-native