Port of TweetNaCl cryptographic library to JavaScript providing comprehensive cryptographic primitives
—
Core utility functions including SHA-512 hashing, secure random byte generation, constant-time comparison, and PRNG configuration. These functions support the cryptographic operations and provide essential security primitives.
SHA-512 cryptographic hash function for message digests and key derivation.
/**
* Computes SHA-512 hash of a message
* @param {Uint8Array} message - The message to hash
* @returns {Uint8Array} SHA-512 hash (64 bytes)
*/
nacl.hash(message): Uint8ArrayUsage Examples:
const nacl = require('tweetnacl');
// Hash a simple message
const message = new TextEncoder().encode("Hello, world!");
const hash = nacl.hash(message);
console.log(hash.length); // 64
// Hash for key derivation
function deriveKey(password, salt) {
const combined = new Uint8Array(password.length + salt.length);
combined.set(password);
combined.set(salt, password.length);
return nacl.hash(combined).slice(0, 32); // Take first 32 bytes as key
}
const password = new TextEncoder().encode("my-password");
const salt = nacl.randomBytes(16);
const derivedKey = deriveKey(password, salt);Multiple Round Hashing:
const nacl = require('tweetnacl');
// Hash multiple times for key stretching
function hashMultiple(data, rounds) {
let result = nacl.hash(data);
for (let i = 1; i < rounds; i++) {
result = nacl.hash(result);
}
return result;
}
const data = new TextEncoder().encode("sensitive data");
const stretched = hashMultiple(data, 10000);Cryptographically secure random byte generation using platform-appropriate sources.
/**
* Generates cryptographically secure random bytes
* @param {number} length - Number of random bytes to generate
* @returns {Uint8Array} Array of random bytes
* @throws {Error} If no secure PRNG is available
*/
nacl.randomBytes(length): Uint8ArrayUsage Examples:
const nacl = require('tweetnacl');
// Generate random keys
const secretKey = nacl.randomBytes(32);
const nonce = nacl.randomBytes(24);
// Generate random data for testing
const randomData = nacl.randomBytes(100);
// Generate random identifiers
const sessionId = nacl.randomBytes(16);
const userId = Array.from(nacl.randomBytes(8))
.map(b => b.toString(16).padStart(2, '0'))
.join('');Secure comparison function that prevents timing attacks.
/**
* Compares two arrays in constant time to prevent timing attacks
* @param {Uint8Array} x - First array to compare
* @param {Uint8Array} y - Second array to compare
* @returns {boolean} True if arrays are equal and non-zero length, false otherwise
*/
nacl.verify(x, y): booleanUsage Examples:
const nacl = require('tweetnacl');
// Compare authentication tokens safely
function verifyToken(receivedToken, expectedToken) {
return nacl.verify(receivedToken, expectedToken);
}
const token1 = new TextEncoder().encode("secret-token-123");
const token2 = new TextEncoder().encode("secret-token-123");
const token3 = new TextEncoder().encode("secret-token-456");
console.log(nacl.verify(token1, token2)); // true
console.log(nacl.verify(token1, token3)); // false
// Verify hashes securely
const data = new TextEncoder().encode("important data");
const hash1 = nacl.hash(data);
const hash2 = nacl.hash(data);
console.log(nacl.verify(hash1, hash2)); // trueImportant Timing Attack Prevention:
const nacl = require('tweetnacl');
// WRONG: Vulnerable to timing attacks
function unsafeVerify(received, expected) {
if (received.length !== expected.length) return false;
for (let i = 0; i < received.length; i++) {
if (received[i] !== expected[i]) return false; // Early return leaks timing
}
return true;
}
// CORRECT: Constant-time comparison
function safeVerify(received, expected) {
return nacl.verify(received, expected);
}Configure custom pseudo-random number generator for environments without standard crypto APIs.
/**
* Sets a custom pseudo-random number generator function
* @param {function} fn - Function that fills array with random bytes: (x: Uint8Array, n: number) => void
* @returns {void}
*/
nacl.setPRNG(fn): voidUsage Example:
const nacl = require('tweetnacl');
// Custom PRNG implementation (example only - don't use in production)
function customPRNG(x, n) {
// This is just an example - use a cryptographically secure source
const crypto = require('crypto');
const bytes = crypto.randomBytes(n);
for (let i = 0; i < n; i++) {
x[i] = bytes[i];
}
}
// Set custom PRNG
nacl.setPRNG(customPRNG);
// Now randomBytes will use the custom function
const randomData = nacl.randomBytes(32);Platform Detection Example:
// TweetNaCl.js automatically detects and configures PRNG based on environment:
// Browser: Uses window.crypto.getRandomValues or window.msCrypto.getRandomValues
// Node.js: Uses crypto.randomBytes
// Custom: Can be overridden with nacl.setPRNG
// Check if PRNG is available
try {
nacl.randomBytes(1);
console.log("Secure PRNG is available");
} catch (error) {
console.log("No secure PRNG available - need to configure one");
// Set custom PRNG here
}nacl.hash.hashLength: number // 64 - Length of SHA-512 hash in bytessetPRNG if you understand cryptographic security requirements. Poor random sources break security.nacl.verify for comparing sensitive data like tokens, hashes, or MACs.nacl.verify returns false for zero-length arrays to prevent edge case vulnerabilities.These utilities are used throughout TweetNaCl.js:
randomBytes: Used by key generation functions (nacl.box.keyPair, nacl.sign.keyPair)hash: Used internally by signing operations and can be used for custom key derivationverify: Essential for secure token/MAC verification in custom authentication schemessetPRNG: Allows customization for specialized environments or testing scenariosInstall with Tessl CLI
npx tessl i tessl/npm-tweetnacl