Stanford JavaScript Crypto Library providing comprehensive cryptographic operations including AES encryption, hash functions, key derivation, and elliptic curve cryptography.
—
SJCL provides various cipher modes for secure encryption including authenticated modes (CCM, GCM, OCB2) and traditional modes (CBC, CTR). Authenticated modes are recommended for most applications as they provide both encryption and authentication.
Authenticated encryption mode combining CTR encryption with CBC-MAC authentication, providing both confidentiality and integrity.
/**
* CCM mode name constant
*/
sjcl.mode.ccm.name = "ccm";
/**
* CCM authenticated encryption
* @param {Cipher} prf - Block cipher instance (typically AES)
* @param {BitArray} plaintext - Data to encrypt
* @param {BitArray} iv - Initialization vector (7-15 bytes)
* @param {BitArray} [adata] - Additional authenticated data (not encrypted)
* @param {number} [tlen] - Authentication tag length in bits (default 64)
* @returns {BitArray} Concatenated ciphertext and authentication tag
* @throws {sjcl.exception.invalid} If IV length is invalid
*/
sjcl.mode.ccm.encrypt(prf, plaintext, iv, adata, tlen);
/**
* CCM authenticated decryption
* @param {Cipher} prf - Block cipher instance (same as used for encryption)
* @param {BitArray} ciphertext - Encrypted data with authentication tag
* @param {BitArray} iv - Initialization vector (must match encryption)
* @param {BitArray} [adata] - Additional authenticated data (must match encryption)
* @param {number} [tlen] - Authentication tag length in bits (default 64)
* @returns {BitArray} Decrypted plaintext
* @throws {sjcl.exception.corrupt} If authentication tag doesn't match
*/
sjcl.mode.ccm.decrypt(prf, ciphertext, iv, adata, tlen);Progress Monitoring:
/**
* Add progress callback for long operations
* @param {Function} cb - Callback function receiving progress value
*/
sjcl.mode.ccm.listenProgress(cb);
/**
* Remove progress callback
* @param {Function} cb - Callback function to remove
*/
sjcl.mode.ccm.unListenProgress(cb);Usage Examples:
const sjcl = require('sjcl');
// Basic CCM encryption
const key = sjcl.random.randomWords(8); // 256-bit key
const aes = new sjcl.cipher.aes(key);
const plaintext = sjcl.codec.utf8String.toBits("Hello, World!");
const iv = sjcl.random.randomWords(3); // 12-byte IV
const adata = sjcl.codec.utf8String.toBits("authenticated data");
const encrypted = sjcl.mode.ccm.encrypt(aes, plaintext, iv, adata, 128);
const decrypted = sjcl.mode.ccm.decrypt(aes, encrypted, iv, adata, 128);
console.log(sjcl.codec.utf8String.fromBits(decrypted)); // "Hello, World!"
// Progress monitoring for large operations
sjcl.mode.ccm.listenProgress(function(progress) {
console.log("CCM progress:", Math.round(progress * 100) + "%");
});Authenticated encryption mode providing both encryption and authentication with excellent performance characteristics.
/**
* GCM mode name constant
*/
sjcl.mode.gcm.name = "gcm";
/**
* GCM authenticated encryption
* @param {Cipher} prf - Block cipher instance (typically AES)
* @param {BitArray} plaintext - Data to encrypt
* @param {BitArray} iv - Initialization vector (recommended 12 bytes)
* @param {BitArray} [adata] - Additional authenticated data
* @param {number} [tlen] - Authentication tag length in bits (default 128)
* @returns {BitArray} Concatenated ciphertext and authentication tag
*/
sjcl.mode.gcm.encrypt(prf, plaintext, iv, adata, tlen);
/**
* GCM authenticated decryption
* @param {Cipher} prf - Block cipher instance (same as used for encryption)
* @param {BitArray} ciphertext - Encrypted data with authentication tag
* @param {BitArray} iv - Initialization vector (must match encryption)
* @param {BitArray} [adata] - Additional authenticated data (must match encryption)
* @param {number} [tlen] - Authentication tag length in bits (default 128)
* @returns {BitArray} Decrypted plaintext
* @throws {sjcl.exception.corrupt} If authentication tag doesn't match
*/
sjcl.mode.gcm.decrypt(prf, ciphertext, iv, adata, tlen);Usage Examples:
const sjcl = require('sjcl');
// GCM encryption with 12-byte IV (recommended)
const key = sjcl.random.randomWords(8);
const aes = new sjcl.cipher.aes(key);
const plaintext = sjcl.codec.utf8String.toBits("Sensitive data");
const iv = sjcl.random.randomWords(3); // 12 bytes
const adata = sjcl.codec.utf8String.toBits("public metadata");
const encrypted = sjcl.mode.gcm.encrypt(aes, plaintext, iv, adata);
const decrypted = sjcl.mode.gcm.decrypt(aes, encrypted, iv, adata);
console.log(sjcl.codec.utf8String.fromBits(decrypted)); // "Sensitive data"
// GCM with custom tag length
const encryptedShortTag = sjcl.mode.gcm.encrypt(aes, plaintext, iv, adata, 96);
const decryptedShortTag = sjcl.mode.gcm.decrypt(aes, encryptedShortTag, iv, adata, 96);Authenticated encryption mode providing both encryption and authentication in a single pass.
/**
* OCB2 mode name constant
*/
sjcl.mode.ocb2.name = "ocb2";
/**
* OCB2 authenticated encryption
* @param {Cipher} prp - Block cipher instance (typically AES)
* @param {BitArray} plaintext - Data to encrypt
* @param {BitArray} iv - 128-bit initialization vector
* @param {BitArray} [adata] - Additional authenticated data
* @param {number} [tlen] - Authentication tag length in bits (default 64)
* @param {boolean} [premac] - Whether adata is already processed
* @returns {BitArray} Concatenated ciphertext and authentication tag
* @throws {sjcl.exception.invalid} If IV is not 128 bits
*/
sjcl.mode.ocb2.encrypt(prp, plaintext, iv, adata, tlen, premac);
/**
* OCB2 authenticated decryption
* @param {Cipher} prp - Block cipher instance (same as used for encryption)
* @param {BitArray} ciphertext - Encrypted data with authentication tag
* @param {BitArray} iv - 128-bit initialization vector (must match encryption)
* @param {BitArray} [adata] - Additional authenticated data (must match encryption)
* @param {number} [tlen] - Authentication tag length in bits (default 64)
* @param {boolean} [premac] - Whether adata is already processed
* @returns {BitArray} Decrypted plaintext
* @throws {sjcl.exception.corrupt} If authentication tag doesn't match
*/
sjcl.mode.ocb2.decrypt(prp, ciphertext, iv, adata, tlen, premac);
/**
* Compute PMAC authentication for additional data
* @param {Cipher} prp - Block cipher instance
* @param {BitArray} adata - Additional data to authenticate
* @returns {BitArray} PMAC authentication tag
*/
sjcl.mode.ocb2.pmac(prp, adata);Usage Examples:
const sjcl = require('sjcl');
// OCB2 encryption (requires 128-bit IV)
const key = sjcl.random.randomWords(8);
const aes = new sjcl.cipher.aes(key);
const plaintext = sjcl.codec.utf8String.toBits("OCB2 test data");
const iv = sjcl.random.randomWords(4); // Must be exactly 128 bits
const adata = sjcl.codec.utf8String.toBits("additional data");
const encrypted = sjcl.mode.ocb2.encrypt(aes, plaintext, iv, adata);
const decrypted = sjcl.mode.ocb2.decrypt(aes, encrypted, iv, adata);
console.log(sjcl.codec.utf8String.fromBits(decrypted)); // "OCB2 test data"
// Using PMAC for separate authentication
const pmacTag = sjcl.mode.ocb2.pmac(aes, adata);Traditional encryption mode that requires separate authentication. Security Warning: CBC mode without authentication is vulnerable to padding oracle attacks.
/**
* CBC mode name constant
*/
sjcl.mode.cbc.name = "cbc";
/**
* CBC encryption - REQUIRES sjcl.beware acknowledgment
* @param {Cipher} prp - Block cipher instance
* @param {BitArray} plaintext - Data to encrypt (must be multiple of block size)
* @param {BitArray} iv - Initialization vector (128 bits)
* @param {BitArray} [adata] - Ignored parameter for compatibility
* @returns {BitArray} Encrypted ciphertext
*/
sjcl.mode.cbc.encrypt(prp, plaintext, iv, adata);
/**
* CBC decryption - REQUIRES sjcl.beware acknowledgment
* @param {Cipher} prp - Block cipher instance
* @param {BitArray} ciphertext - Data to decrypt
* @param {BitArray} iv - Initialization vector (must match encryption)
* @param {BitArray} [adata] - Ignored parameter for compatibility
* @returns {BitArray} Decrypted plaintext
*/
sjcl.mode.cbc.decrypt(prp, ciphertext, iv, adata);Usage Examples:
const sjcl = require('sjcl');
// CBC mode requires acknowledging security risks
sjcl.beware["CBC mode is dangerous because it doesn't protect message integrity."]();
const key = sjcl.random.randomWords(8);
const aes = new sjcl.cipher.aes(key);
const plaintext = sjcl.codec.utf8String.toBits("This must be padded to block boundary");
// Pad to multiple of 128 bits (4 words)
const paddedPlaintext = sjcl.bitArray.clamp(plaintext, Math.ceil(sjcl.bitArray.bitLength(plaintext) / 128) * 128);
const iv = sjcl.random.randomWords(4);
const encrypted = sjcl.mode.cbc.encrypt(aes, paddedPlaintext, iv);
const decrypted = sjcl.mode.cbc.decrypt(aes, encrypted, iv);
// Must also implement authentication separately (HMAC recommended)
const hmacKey = sjcl.random.randomWords(8);
const hmac = new sjcl.misc.hmac(hmacKey);
const authTag = hmac.encrypt(encrypted);Stream cipher mode that converts block ciphers into stream ciphers. Security Warning: Requires separate authentication.
/**
* CTR mode name constant
*/
sjcl.mode.ctr.name = "ctr";
/**
* CTR encryption - REQUIRES sjcl.beware acknowledgment
* @param {Cipher} prf - Block cipher instance
* @param {BitArray} plaintext - Data to encrypt
* @param {BitArray} iv - Initialization vector/counter
* @param {BitArray} [adata] - Ignored parameter for compatibility
* @returns {BitArray} Encrypted ciphertext
*/
sjcl.mode.ctr.encrypt(prf, plaintext, iv, adata);
/**
* CTR decryption - REQUIRES sjcl.beware acknowledgment
* @param {Cipher} prf - Block cipher instance
* @param {BitArray} ciphertext - Data to decrypt
* @param {BitArray} iv - Initialization vector/counter (must match encryption)
* @param {BitArray} [adata] - Ignored parameter for compatibility
* @returns {BitArray} Decrypted plaintext
*/
sjcl.mode.ctr.decrypt(prf, ciphertext, iv, adata);Usage Examples:
const sjcl = require('sjcl');
// CTR mode requires acknowledging security risks
sjcl.beware["CTR mode is dangerous because it doesn't protect message integrity."]();
const key = sjcl.random.randomWords(8);
const aes = new sjcl.cipher.aes(key);
const plaintext = sjcl.codec.utf8String.toBits("CTR mode can encrypt any length");
const iv = sjcl.random.randomWords(4); // Counter/IV
const encrypted = sjcl.mode.ctr.encrypt(aes, plaintext, iv);
const decrypted = sjcl.mode.ctr.decrypt(aes, encrypted, iv);
console.log(sjcl.codec.utf8String.fromBits(decrypted));
// Must implement authentication separately
const authKey = sjcl.random.randomWords(8);
const hmac = new sjcl.misc.hmac(authKey);
const authTag = hmac.encrypt(sjcl.bitArray.concat(iv, encrypted));CCM mode with ArrayBuffer support for working with binary data directly.
/**
* CCM encryption for ArrayBuffers
* @param {Cipher} prf - Block cipher instance
* @param {ArrayBuffer} plaintext - Data to encrypt
* @param {ArrayBuffer} iv - Initialization vector
* @param {ArrayBuffer} [adata] - Additional authenticated data
* @param {number} [tlen] - Authentication tag length in bits
* @returns {ArrayBuffer} Encrypted data with authentication tag
*/
sjcl.mode.ccmArrayBuffer.encrypt(prf, plaintext, iv, adata, tlen);
/**
* CCM decryption for ArrayBuffers
* @param {Cipher} prf - Block cipher instance
* @param {ArrayBuffer} ciphertext - Encrypted data with tag
* @param {ArrayBuffer} iv - Initialization vector
* @param {ArrayBuffer} [adata] - Additional authenticated data
* @param {number} [tlen] - Authentication tag length in bits
* @returns {ArrayBuffer} Decrypted plaintext
*/
sjcl.mode.ccmArrayBuffer.decrypt(prf, ciphertext, iv, adata, tlen);OCB2 mode with progressive/streaming capabilities for large data processing.
/**
* Create progressive OCB2 encryptor
* @param {Cipher} prf - Block cipher instance
* @param {BitArray} iv - 128-bit initialization vector
* @param {BitArray} [adata] - Additional authenticated data
* @returns {Object} Progressive encryptor object
*/
sjcl.mode.ocb2progressive.createEncryptor(prf, iv, adata);
/**
* Create progressive OCB2 decryptor
* @param {Cipher} prf - Block cipher instance
* @param {BitArray} iv - 128-bit initialization vector
* @param {BitArray} [adata] - Additional authenticated data
* @returns {Object} Progressive decryptor object
*/
sjcl.mode.ocb2progressive.createDecryptor(prf, iv, adata);| Mode | Authentication | Performance | IV Requirements | Security Level |
|---|---|---|---|---|
| GCM | Yes | Excellent | 12 bytes (rec.) | High |
| CCM | Yes | Good | 7-15 bytes | High |
| OCB2 | Yes | Excellent | 16 bytes | High |
| CBC | No | Good | 16 bytes | Low (vulnerable) |
| CTR | No | Excellent | 16 bytes | Low (vulnerable) |
Install with Tessl CLI
npx tessl i tessl/npm-sjcl