Stanford JavaScript Crypto Library providing comprehensive cryptographic operations including AES encryption, hash functions, key derivation, and elliptic curve cryptography.
—
SJCL provides comprehensive encoding and decoding capabilities for converting between bit arrays and various string formats including UTF-8, Base64, hexadecimal, Base32, and binary formats.
Convert between UTF-8 strings and SJCL's internal bit array format.
/**
* Convert UTF-8 string to bit array
* @param {string} str - UTF-8 string to convert
* @returns {BitArray} String data as bit array
*/
sjcl.codec.utf8String.toBits(str);
/**
* Convert bit array to UTF-8 string
* @param {BitArray} arr - Bit array to convert
* @returns {string} UTF-8 encoded string
*/
sjcl.codec.utf8String.fromBits(arr);Usage Examples:
const sjcl = require('sjcl');
// String to bit array conversion
const text = "Hello, 世界! 🌍";
const bits = sjcl.codec.utf8String.toBits(text);
console.log("Bits:", bits); // Array of 32-bit integers
// Bit array back to string
const decoded = sjcl.codec.utf8String.fromBits(bits);
console.log("Decoded:", decoded); // "Hello, 世界! 🌍"
// Use with encryption
const key = sjcl.random.randomWords(8);
const plaintext = sjcl.codec.utf8String.toBits("Secret message");
const encrypted = sjcl.encrypt("password", sjcl.codec.utf8String.fromBits(plaintext));Convert between hexadecimal strings and bit arrays for readable binary data representation.
/**
* Convert hexadecimal string to bit array
* @param {string} str - Hexadecimal string (case insensitive, spaces/0x ignored)
* @returns {BitArray} Binary data as bit array
*/
sjcl.codec.hex.toBits(str);
/**
* Convert bit array to hexadecimal string
* @param {BitArray} arr - Bit array to convert
* @returns {string} Lowercase hexadecimal string
*/
sjcl.codec.hex.fromBits(arr);Usage Examples:
const sjcl = require('sjcl');
// Hex string to bit array
const hexString = "deadbeef";
const hexBits = sjcl.codec.hex.toBits(hexString);
console.log("Hex bits:", hexBits);
// Bit array to hex string
const hexDecoded = sjcl.codec.hex.fromBits(hexBits);
console.log("Hex decoded:", hexDecoded); // "deadbeef"
// Hash to hex example
const hash = sjcl.hash.sha256.hash("Hello, World!");
const hexHash = sjcl.codec.hex.fromBits(hash);
console.log("SHA-256 hex:", hexHash);
// Flexible hex input (spaces, 0x prefix, mixed case)
const flexHex = sjcl.codec.hex.toBits("0xDEAD BEEF cafe");
console.log("Flexible hex:", sjcl.codec.hex.fromBits(flexHex));Standard Base64 encoding for binary data transmission and storage.
/**
* Convert bit array to Base64 string
* @param {BitArray} arr - Bit array to encode
* @param {boolean} [_noEquals] - Omit padding equals signs
* @param {boolean} [_url] - Use URL-safe Base64 alphabet
* @returns {string} Base64 encoded string
*/
sjcl.codec.base64.fromBits(arr, _noEquals, _url);
/**
* Convert Base64 string to bit array
* @param {string} str - Base64 string to decode
* @param {boolean} [_url] - Use URL-safe Base64 alphabet
* @returns {BitArray} Decoded binary data as bit array
* @throws {sjcl.exception.invalid} If Base64 string is invalid
*/
sjcl.codec.base64.toBits(str, _url);Usage Examples:
const sjcl = require('sjcl');
// Basic Base64 encoding
const data = sjcl.codec.utf8String.toBits("Hello, World!");
const base64 = sjcl.codec.base64.fromBits(data);
console.log("Base64:", base64); // "SGVsbG8sIFdvcmxkIQ=="
// Base64 decoding
const decoded = sjcl.codec.base64.toBits(base64);
const text = sjcl.codec.utf8String.fromBits(decoded);
console.log("Decoded:", text); // "Hello, World!"
// Base64 without padding
const noPadding = sjcl.codec.base64.fromBits(data, true);
console.log("No padding:", noPadding); // "SGVsbG8sIFdvcmxkIQ"
// URL-safe Base64
const urlSafe = sjcl.codec.base64.fromBits(data, false, true);
console.log("URL-safe:", urlSafe); // Uses - and _ instead of + and /URL and filename safe Base64 encoding variant.
/**
* Convert bit array to Base64URL string
* @param {BitArray} arr - Bit array to encode
* @returns {string} Base64URL encoded string (no padding)
*/
sjcl.codec.base64url.fromBits(arr);
/**
* Convert Base64URL string to bit array
* @param {string} str - Base64URL string to decode
* @returns {BitArray} Decoded binary data as bit array
*/
sjcl.codec.base64url.toBits(str);Usage Examples:
const sjcl = require('sjcl');
// Base64URL encoding (commonly used in JWT tokens)
const payload = sjcl.codec.utf8String.toBits('{"sub":"1234567890","name":"John Doe"}');
const base64url = sjcl.codec.base64url.fromBits(payload);
console.log("Base64URL:", base64url); // URL-safe, no padding
// JWT-style usage
function createJWTPayload(data) {
const payloadBits = sjcl.codec.utf8String.toBits(JSON.stringify(data));
return sjcl.codec.base64url.fromBits(payloadBits);
}
const tokenPayload = createJWTPayload({
sub: "user123",
exp: Math.floor(Date.now() / 1000) + 3600
});Base32 encoding for use cases requiring case-insensitive alphanumeric encoding.
/**
* Convert bit array to Base32 string
* @param {BitArray} arr - Bit array to encode
* @param {boolean} [_noEquals] - Omit padding equals signs
* @param {boolean} [_hex] - Use Base32hex alphabet instead of standard
* @returns {string} Base32 encoded string
*/
sjcl.codec.base32.fromBits(arr, _noEquals, _hex);
/**
* Convert Base32 string to bit array
* @param {string} str - Base32 string to decode (case insensitive)
* @param {boolean} [_hex] - Use Base32hex alphabet instead of standard
* @returns {BitArray} Decoded binary data as bit array
* @throws {sjcl.exception.invalid} If Base32 string is invalid
*/
sjcl.codec.base32.toBits(str, _hex);Base32Hex variant:
/**
* Convert bit array to Base32hex string
* @param {BitArray} arr - Bit array to encode
* @param {boolean} [_noEquals] - Omit padding equals signs
* @returns {string} Base32hex encoded string
*/
sjcl.codec.base32hex.fromBits(arr, _noEquals);
/**
* Convert Base32hex string to bit array
* @param {string} str - Base32hex string to decode
* @returns {BitArray} Decoded binary data as bit array
*/
sjcl.codec.base32hex.toBits(str);Usage Examples:
const sjcl = require('sjcl');
// Standard Base32 encoding
const data = sjcl.codec.utf8String.toBits("Hello, World!");
const base32 = sjcl.codec.base32.fromBits(data);
console.log("Base32:", base32); // "JBSWY3DPEBLW64TMMQQQ===="
// Base32 decoding (case insensitive)
const base32Lower = base32.toLowerCase();
const decoded = sjcl.codec.base32.toBits(base32Lower);
console.log("Decoded:", sjcl.codec.utf8String.fromBits(decoded));
// Base32hex (uses 0-9 and A-V instead of A-Z and 2-7)
const base32hex = sjcl.codec.base32hex.fromBits(data);
console.log("Base32hex:", base32hex);
// Without padding
const noPadding = sjcl.codec.base32.fromBits(data, true);
console.log("No padding:", noPadding);Convert between bit arrays and regular JavaScript byte arrays.
/**
* Convert bit array to byte array
* @param {BitArray} arr - Bit array to convert
* @returns {number[]} Array of bytes (0-255)
*/
sjcl.codec.bytes.fromBits(arr);
/**
* Convert byte array to bit array
* @param {number[]} bytes - Array of bytes (0-255)
* @returns {BitArray} Bit array representation
*/
sjcl.codec.bytes.toBits(bytes);Usage Examples:
const sjcl = require('sjcl');
// Bit array to byte array
const bits = sjcl.codec.utf8String.toBits("Hello!");
const bytes = sjcl.codec.bytes.fromBits(bits);
console.log("Bytes:", bytes); // [72, 101, 108, 108, 111, 33]
// Byte array to bit array
const backToBits = sjcl.codec.bytes.toBits(bytes);
const text = sjcl.codec.utf8String.fromBits(backToBits);
console.log("Back to text:", text); // "Hello!"
// Working with binary data
const binaryData = [0xFF, 0xFE, 0xFD, 0xFC];
const binaryBits = sjcl.codec.bytes.toBits(binaryData);
const hexView = sjcl.codec.hex.fromBits(binaryBits);
console.log("Hex view:", hexView); // "fffefdfc"Convert between bit arrays and ArrayBuffer objects for modern binary data handling.
/**
* Convert bit array to ArrayBuffer
* @param {BitArray} arr - Bit array to convert
* @param {boolean} [padding] - Add padding if needed
* @param {number} [padding_count] - Number of padding bytes
* @returns {ArrayBuffer} ArrayBuffer containing binary data
*/
sjcl.codec.arrayBuffer.fromBits(arr, padding, padding_count);
/**
* Convert ArrayBuffer to bit array
* @param {ArrayBuffer} buffer - ArrayBuffer to convert
* @returns {BitArray} Bit array representation
*/
sjcl.codec.arrayBuffer.toBits(buffer);
/**
* Generate hex dump of ArrayBuffer contents
* @param {ArrayBuffer} buffer - ArrayBuffer to dump
* @returns {string} Hex dump string for debugging
*/
sjcl.codec.arrayBuffer.hexDumpBuffer(buffer);Usage Examples:
const sjcl = require('sjcl');
// Bit array to ArrayBuffer
const bits = sjcl.codec.utf8String.toBits("Hello, ArrayBuffer!");
const buffer = sjcl.codec.arrayBuffer.fromBits(bits);
console.log("Buffer length:", buffer.byteLength);
// ArrayBuffer to bit array
const backToBits = sjcl.codec.arrayBuffer.toBits(buffer);
const text = sjcl.codec.utf8String.fromBits(backToBits);
console.log("Decoded:", text);
// Hex dump for debugging
const hexDump = sjcl.codec.arrayBuffer.hexDumpBuffer(buffer);
console.log("Hex dump:", hexDump);
// Working with TypedArrays
const uint8Array = new Uint8Array(buffer);
console.log("First bytes:", Array.from(uint8Array.slice(0, 5)));Z85 encoding (ZeroMQ Base85) for compact binary data representation.
/**
* Convert bit array to Z85 string
* @param {BitArray} arr - Bit array to encode (length must be multiple of 4 bytes)
* @returns {string} Z85 encoded string
* @throws {sjcl.exception.invalid} If data length is not multiple of 4 bytes
*/
sjcl.codec.z85.fromBits(arr);
/**
* Convert Z85 string to bit array
* @param {string} str - Z85 string to decode
* @returns {BitArray} Decoded binary data as bit array
* @throws {sjcl.exception.invalid} If Z85 string is invalid
*/
sjcl.codec.z85.toBits(str);Usage Examples:
const sjcl = require('sjcl');
// Z85 encoding (data must be multiple of 4 bytes)
const data = sjcl.random.randomWords(2); // 8 bytes = 64 bits
const z85 = sjcl.codec.z85.fromBits(data);
console.log("Z85:", z85);
// Z85 decoding
const decoded = sjcl.codec.z85.toBits(z85);
console.log("Equal:", sjcl.bitArray.equal(data, decoded));
// Padding data to 4-byte boundary
function padToZ85(bits) {\n const bitLength = sjcl.bitArray.bitLength(bits);\n const byteLength = Math.ceil(bitLength / 8);\n const paddedByteLength = Math.ceil(byteLength / 4) * 4;\n const paddedBitLength = paddedByteLength * 8;\n \n return sjcl.bitArray.clamp(sjcl.bitArray.concat(bits, [0]), paddedBitLength);\n}\n\nconst text = sjcl.codec.utf8String.toBits(\"Hello\"); // 5 bytes\nconst padded = padToZ85(text);\nconst z85Text = sjcl.codec.z85.fromBits(padded);\n```\n\n## Common Encoding Patterns\n\n### Multi-format Conversion\n\nConvert data between multiple formats:\n\n```javascript\nconst sjcl = require('sjcl');\n\nfunction convertFormats(data, fromFormat, toFormat) {\n let bits;\n \n // Convert from source format to bit array\n switch (fromFormat) {\n case 'utf8':\n bits = sjcl.codec.utf8String.toBits(data);\n break;\n case 'hex':\n bits = sjcl.codec.hex.toBits(data);\n break;\n case 'base64':\n bits = sjcl.codec.base64.toBits(data);\n break;\n case 'base32':\n bits = sjcl.codec.base32.toBits(data);\n break;\n default:\n throw new Error('Unknown source format');\n }\n \n // Convert from bit array to target format\n switch (toFormat) {\n case 'utf8':\n return sjcl.codec.utf8String.fromBits(bits);\n case 'hex':\n return sjcl.codec.hex.fromBits(bits);\n case 'base64':\n return sjcl.codec.base64.fromBits(bits);\n case 'base32':\n return sjcl.codec.base32.fromBits(bits);\n case 'bytes':\n return sjcl.codec.bytes.fromBits(bits);\n default:\n throw new Error('Unknown target format');\n }\n}\n\n// Usage\nconst hex = convertFormats(\"Hello, World!\", 'utf8', 'hex');\nconst base64 = convertFormats(hex, 'hex', 'base64');\nconst text = convertFormats(base64, 'base64', 'utf8');\nconsole.log(text); // \"Hello, World!\"\n```\n\n### Safe Encoding with Validation\n\nValidate and safely encode/decode data:\n\n```javascript\nconst sjcl = require('sjcl');\n\nclass SafeEncoder {\n static encodeText(text, format = 'base64') {\n if (typeof text !== 'string') {\n throw new sjcl.exception.invalid('Input must be a string');\n }\n \n const bits = sjcl.codec.utf8String.toBits(text);\n \n switch (format.toLowerCase()) {\n case 'hex':\n return sjcl.codec.hex.fromBits(bits);\n case 'base64':\n return sjcl.codec.base64.fromBits(bits);\n case 'base32':\n return sjcl.codec.base32.fromBits(bits);\n default:\n throw new sjcl.exception.invalid('Unsupported format');\n }\n }\n \n static decodeText(encoded, format = 'base64') {\n try {\n let bits;\n \n switch (format.toLowerCase()) {\n case 'hex':\n bits = sjcl.codec.hex.toBits(encoded);\n break;\n case 'base64':\n bits = sjcl.codec.base64.toBits(encoded);\n break;\n case 'base32':\n bits = sjcl.codec.base32.toBits(encoded);\n break;\n default:\n throw new sjcl.exception.invalid('Unsupported format');\n }\n \n return sjcl.codec.utf8String.fromBits(bits);\n } catch (e) {\n throw new sjcl.exception.corrupt('Invalid encoded data: ' + e.message);\n }\n }\n}\n\n// Usage\ntry {\n const encoded = SafeEncoder.encodeText(\"Hello, World!\", 'base64');\n const decoded = SafeEncoder.decodeText(encoded, 'base64');\n console.log('Success:', decoded);\n} catch (e) {\n console.error('Encoding error:', e.message);\n}\n```\n\n## Performance Considerations\n\n- **UTF-8**: Fastest for text data\n- **Hex**: Good for debugging and human-readable binary data\n- **Base64**: Standard for binary data transmission\n- **Base32**: Case-insensitive, good for user input\n- **Z85**: Most compact for binary data\n- **ArrayBuffer**: Best for modern JavaScript binary data handling\n\n## Security Considerations\n\n1. **Data Validation**: Always validate input before decoding\n2. **Error Handling**: Handle encoding/decoding errors gracefully\n3. **Memory**: Be aware of memory usage with large data\n4. **Timing**: Encoding/decoding operations are not constant-time\n5. **Character Sets**: Ensure proper UTF-8 handling for international textInstall with Tessl CLI
npx tessl i tessl/npm-sjcl