sjcl - Documentation

What is SJCL?

The Stanford JavaScript Crypto Library (SJCL) is a JavaScript library providing a comprehensive suite of cryptographic functions. It’s designed to be a robust and secure way to incorporate encryption, decryption, hashing, and other cryptographic primitives into web applications. SJCL prioritizes security best practices and aims to provide a relatively easy-to-use interface for developers, despite the inherent complexity of cryptography. It’s particularly useful for applications requiring secure handling of sensitive data client-side, such as password storage, secure communication, and data protection. However, it’s crucial to remember that client-side cryptography alone is not sufficient for robust security; appropriate server-side measures are always necessary.

Key Features and Benefits

Target Audience

SJCL is intended for web developers who need to incorporate cryptographic functionality into their JavaScript applications. This includes developers with a range of experience levels, from those with some familiarity with cryptography to those with more advanced expertise. However, even experienced developers should carefully review the documentation and security implications before using any cryptographic library. A basic understanding of cryptographic concepts is helpful, though not strictly required for basic usage.

Setting up the Development Environment

Setting up SJCL for development is straightforward. The core library is typically included via a <script> tag in your HTML:

<script src="sjcl.js"></script> 

You’ll need to obtain the sjcl.js file from the official SJCL repository (link to be provided in the main documentation). Make sure to download the latest version to benefit from the most recent security updates and bug fixes. After including the script, you can begin using the library’s functions in your JavaScript code. Refer to the API documentation for details on specific functions and usage examples. For more advanced usage and development, consider using a package manager like npm or yarn if the project is part of a larger Node.js environment, which would typically include build processes and testing frameworks. Further instructions on setting up for development within a Node.js environment will be detailed in a separate section of this manual (link to be provided if such section exists).

Core Functionality

Cipher Modes

SJCL supports several cipher modes of operation, each offering different properties and security characteristics. The choice of cipher mode depends on the specific application’s requirements. Key modes include:

The specific cipher mode is often selected implicitly by specifying the parameters in the encryption/decryption functions. Refer to the API documentation for detailed instructions on how to select a specific mode for each algorithm.

Key Generation and Management

Secure key generation and management are critical for cryptographic security. SJCL provides functions for generating cryptographically secure random keys of various lengths and algorithms. It’s crucial to use these functions and avoid generating keys manually or using weak random number generators.

Key management involves securely storing and handling keys to prevent unauthorized access or compromise. SJCL itself does not handle key persistence; secure key storage is the responsibility of the application developer. Appropriate measures, such as using strong password-based key derivation functions (PBKDF2), key stretching techniques, and secure storage mechanisms (e.g., browser-based key storage APIs if available and appropriate), must be employed. Never store keys directly in your application’s code or in easily accessible locations.

Data Encryption and Decryption

SJCL provides functions for encrypting and decrypting data using various symmetric algorithms and modes of operation. The typical process involves:

  1. Key Generation: Generate a cryptographically secure key using SJCL’s key generation functions.
  2. Initialization Vector (IV) Generation: Generate a random IV, unique for each encryption operation. This is crucial, especially for modes like CBC.
  3. Encryption: Use SJCL’s encryption functions, providing the key, IV, and the data to be encrypted.
  4. Decryption: Use SJCL’s decryption functions, providing the key, IV, and the ciphertext to be decrypted.

It is imperative to ensure that the same key and IV are used for both encryption and decryption. Incorrect usage will result in decryption failure.

Message Authentication Codes (MACs)

MACs provide data authenticity and integrity. SJCL supports generating MACs using algorithms like HMAC (Hash-based Message Authentication Code). HMACs combine a cryptographic hash function with a secret key to generate a tag that verifies both the authenticity and integrity of the message. A successful MAC verification confirms that the message has not been tampered with and originated from a legitimate source possessing the secret key. Incorrect usage or a compromised secret key will invalidate the MAC.

Random Number Generation

Cryptographically secure random number generation (CSPRNG) is essential for many cryptographic operations. SJCL incorporates a CSPRNG to generate random numbers used for key generation, IV generation, and other cryptographic processes. It’s vital to rely solely on SJCL’s built-in random number generation functions, as using less secure alternatives can significantly weaken the overall security of the system.

Hashing Algorithms

SJCL supports several cryptographic hash functions for computing message digests. These functions produce fixed-size outputs (hashes) that can be used for various purposes, such as password hashing, data integrity checks, and digital signatures. Supported algorithms typically include SHA-256 and potentially others, depending on the SJCL version. It’s important to choose an appropriate hash function based on security requirements and performance considerations. The choice of algorithm influences the length and collision resistance of the generated hash.

Advanced Usage

Public Key Cryptography

While SJCL’s primary focus is symmetric cryptography, it may offer some support for public-key cryptography through integrations or wrappers around other libraries (depending on the version). This typically involves using a combination of SJCL for symmetric encryption and a separate library for public key operations (key generation, encryption, decryption). The process often entails:

  1. Key Pair Generation: Generate a public-private key pair using a separate public-key cryptography library.
  2. Key Exchange: Exchange the public key securely with the intended recipient.
  3. Encryption/Decryption: The sender encrypts the message symmetrically using a randomly generated session key. They then encrypt this session key using the recipient’s public key. The recipient decrypts the session key using their private key and then uses it to decrypt the message. SJCL would be used for the symmetric encryption/decryption of the message itself.
  4. Digital Signatures (see below): Public-key cryptography is also fundamental to digital signatures, which are used to verify the authenticity and integrity of data.

Consult the specific SJCL documentation and any integrated libraries for detailed instructions on public key operations. The exact methods depend on the specific public-key algorithms and the integration available in the SJCL version you’re using.

Digital Signatures

Digital signatures use public-key cryptography to provide authentication and integrity verification. While SJCL might not directly implement digital signature algorithms, it can be used in conjunction with other libraries that do. A typical workflow could involve:

  1. Key Pair Generation: Generate a public-private key pair using a suitable library.
  2. Signature Generation: Hash the message using a suitable hash function (potentially from SJCL). Use a digital signature algorithm (e.g., RSA, ECDSA) with your private key to generate a digital signature from the hash.
  3. Signature Verification: The recipient uses the sender’s public key and the same hash function to verify the signature. A successful verification confirms both the authenticity (the message originated from the holder of the private key) and the integrity (the message has not been tampered with).

SJCL’s role is primarily in the hashing step, ensuring a secure and robust hash function is used for the signature process. The actual signature generation and verification would be handled by a separate library.

Key Derivation Functions (KDFs)

Key derivation functions are used to generate multiple keys from a single master secret. SJCL might provide support for KDFs, allowing for secure key stretching and the derivation of different keys for various purposes (e.g., encryption, authentication, MAC generation) from a single master password. This helps manage keys efficiently and reduces the risk of compromising multiple keys if one is exposed. Refer to the SJCL documentation for details on any available KDF functions and their usage.

Handling Different Data Formats

SJCL typically operates on byte arrays (arrays of bytes). Therefore, any data needing to be encrypted or decrypted using SJCL must be first converted into this format. This often involves encoding data from various formats (strings, numbers, objects, etc.) into a byte array before encryption and decoding the resulting byte array back into the original format after decryption. Encoding techniques such as UTF-8 (for strings) are typically used. The developer is responsible for correctly converting data to and from byte arrays.

Integration with Other Libraries

SJCL is designed to be integrated with other JavaScript libraries. This might involve combining its cryptographic functionalities with other libraries that provide specific functionalities or manage user interface aspects. This requires a careful consideration of security implications and ensuring consistent data handling across different libraries. The developer must be aware of potential compatibility issues and handle data conversions appropriately. Using a module bundler (like Webpack) in larger projects facilitates the management of dependencies and integrations, allowing for clear separation and controlled interaction of SJCL with other libraries.

Security Considerations

Best Practices for Key Management

Secure key management is paramount to the overall security of any system using SJCL. Failure to properly manage keys negates the security benefits provided by the library itself. Best practices include:

Protecting Against Common Attacks

SJCL is designed to mitigate many common cryptographic attacks, but proper usage is essential. Developers should be aware of and protect against:

Choosing Appropriate Algorithms and Parameters

The choice of cryptographic algorithm and parameters significantly impacts the security of your application.

Understanding Security Limitations

It’s crucial to understand that no cryptographic system is perfectly secure. Even using SJCL correctly does not provide absolute security. Limitations to consider include:

Regular Security Audits

Regularly audit your application’s security, including its use of SJCL. This involves reviewing your code, testing for vulnerabilities, and staying informed about new security threats and best practices. Consider employing penetration testing and security code reviews by experts to identify potential weaknesses in your implementation and usage of the library. Regular security audits help ensure that your application remains secure over time.

API Reference

This section provides a concise overview of the core classes and functions within the SJCL API. For detailed information, including parameter specifications, return values, and examples, refer to the comprehensive API documentation (link to be provided in the main documentation). Note that the specific functions and classes available may vary slightly depending on the SJCL version.

Cipher Class

The Cipher class is the primary interface for symmetric encryption and decryption. It encapsulates the selected cipher algorithm and mode of operation. Typical usage involves:

  1. Instantiation: Create a Cipher object, specifying the algorithm and mode (e.g., new sjcl.cipher.aes(key) for AES). The key parameter must be a valid key in the appropriate format for the chosen algorithm.
  2. Encryption: Use the encrypt method to encrypt a plaintext message. This usually requires an initialization vector (IV).
  3. Decryption: Use the decrypt method to decrypt a ciphertext message. The same key and IV used for encryption must be provided.

Example (Illustrative - adapt to specific SJCL version and algorithm):

var key = sjcl.random.randomWords(4, 0); // Generate a 128-bit key
var iv = sjcl.random.randomWords(4, 0);  // Generate a 128-bit IV
var cipher = new sjcl.cipher.aes(key);
var plaintext = "This is a secret message";
var ciphertext = cipher.encrypt(sjcl.codec.utf8String.toBits(plaintext), iv);
var decrypted = sjcl.codec.utf8String.fromBits(cipher.decrypt(ciphertext, iv));

HMAC Class

The HMAC class provides functionality for generating and verifying Message Authentication Codes (MACs). Typical usage involves:

  1. Instantiation: Create an HMAC object, specifying the hash function and key.
  2. HMAC Generation: Use the hmac method to generate an HMAC for a given message.
  3. HMAC Verification: Compare the generated HMAC with a received HMAC to verify message authenticity and integrity.

Example (Illustrative - adapt to specific SJCL version and algorithm):

var key = sjcl.random.randomWords(4, 0); // Generate a 128-bit key
var hmac = new sjcl.misc.hmac(key, sjcl.hash.sha256);
var message = "This is a message to be authenticated";
var hmacResult = hmac.encrypt(message);

Random Class

The Random class provides cryptographically secure random number generation. It’s crucial to always use this class for generating keys and IVs to avoid weakening the security of your system. Functions such as randomWords are used to generate arrays of random words (integers), which can be converted to bit arrays as needed by other functions.

Example:

var randomWords = sjcl.random.randomWords(8, 0); // Generates 256 bits of randomness

Util Functions

SJCL provides various utility functions for tasks such as bit array manipulation, encoding/decoding, and other helper functions. These functions are crucial for working with the library effectively. Examples include functions to convert between different data formats (strings, byte arrays, bit arrays). Consult the detailed API documentation for a complete list and usage details.

Key Derivation Functions (KDFs)

SJCL might incorporate key derivation functions (KDFs) such as PBKDF2. KDFs allow deriving multiple keys from a single master secret (often a password) by applying a key derivation process. This enhances security by increasing the computational cost of attacks and making the generation of multiple keys more secure. The specific KDFs available and their usage depend on the SJCL version. Refer to the API documentation for detailed information on available KDFs and their parameters. Usage typically involves providing a master secret, a salt value (to enhance security), and an iteration count (to increase computational cost).

Troubleshooting and FAQs

Common Errors and Solutions

This section addresses common errors encountered when using SJCL. Remember to always check the browser’s developer console for detailed error messages.

Frequently Asked Questions

Where to Find Additional Help

Examples and Use Cases

These examples illustrate how to use SJCL for common cryptographic tasks. Remember that these are simplified examples and might need adjustments based on your specific needs and the version of SJCL you are using. Always consult the complete API documentation for detailed parameter information and usage instructions.

Simple Encryption and Decryption

This example demonstrates basic AES encryption and decryption using a randomly generated key and IV. Remember to handle key management securely in a real-world application.

// Generate a 256-bit key
var key = sjcl.random.randomWords(8, 0);

// Generate a 128-bit IV
var iv = sjcl.random.randomWords(4, 0);

// Create a cipher object using AES
var cipher = new sjcl.cipher.aes(key);

// Message to be encrypted
var plaintext = "This is my secret message.";

// Encrypt the message
var ciphertext = cipher.encrypt(sjcl.codec.utf8String.toBits(plaintext), iv);

//Convert to a hex string for display/storage
var hexCiphertext = sjcl.codec.hex.fromBits(ciphertext);
console.log("Ciphertext (hex):", hexCiphertext);


// Decrypt the message
var decryptedBits = cipher.decrypt(sjcl.codec.hex.toBits(hexCiphertext), iv);
var decrypted = sjcl.codec.utf8String.fromBits(decryptedBits);
console.log("Decrypted message:", decrypted);

HMAC Authentication

This example demonstrates creating and verifying an HMAC using SHA256.

// Generate a 128-bit key
var key = sjcl.random.randomWords(4, 0);

// Create an HMAC object using SHA256
var hmac = new sjcl.misc.hmac(key, sjcl.hash.sha256);

// Message to be authenticated
var message = "This message needs authentication.";

// Generate the HMAC
var hmacResult = hmac.encrypt(sjcl.codec.utf8String.toBits(message));

// Convert HMAC to hex for display/storage
var hexHmac = sjcl.codec.hex.fromBits(hmacResult);
console.log("HMAC (hex):", hexHmac);


// Verification (replace with received HMAC in real application)
var receivedHmac = sjcl.codec.hex.toBits(hexHmac);
var verified = hmac.encrypt(sjcl.codec.utf8String.toBits(message)).equals(receivedHmac);
console.log("HMAC Verified:", verified);

Key Derivation Example

This example uses PBKDF2 to derive a key from a password. Never use this directly to store passwords - use a proper password management system that includes salting, strong hashing, and iteration counts many times higher than shown here. This is a minimal illustration for understanding the concept.

var password = "MySecretPassword";
var salt = sjcl.codec.hex.toBits("aRandomSaltValue"); // Replace with a securely generated salt
var iterations = 1000; // Use a much higher iteration count in production
var derivedKey = sjcl.misc.pbkdf2(password, salt, iterations, 256);
console.log("Derived key (bits):", derivedKey);
console.log("Derived key (hex):", sjcl.codec.hex.fromBits(derivedKey));

Integration with a Web Application

This illustrates a basic integration within a web application. Remember to adjust paths and error handling as needed.

<!DOCTYPE html>
<html>
<head>
<title>SJCL Example</title>
<script src="sjcl.js"></script> </head>
<body>
<button id="encryptButton">Encrypt</button>
<button id="decryptButton">Decrypt</button>
<p id="output"></p>

<script>
  document.getElementById("encryptButton").addEventListener("click", encrypt);
  document.getElementById("decryptButton").addEventListener("click", decrypt);

  // ... (encryption/decryption functions using SJCL from previous examples) ...

</script>
</body>
</html>

Remember to replace "sjcl.js" with the actual path to your SJCL library file. The encrypt and decrypt functions would contain the code from the “Simple Encryption and Decryption” example, suitably adapted for handling user input and displaying output in the web page. Consider adding appropriate error handling and user interface elements. This is a minimal example for illustration only. Robust error handling and user input validation are crucial in real-world web applications.