Introduction to String Hashing in JavaScript
String hashing is a crucial concept in computer science and web development. It is used extensively in data structures, algorithms, and security. Hashing converts a given string into a fixed-size alphanumeric string, often a hash code. In this blog post, we’ll introduce string hashing in JavaScript and explore various useful APIs with code snippets.
Useful APIs for String Hashing
1. Built-in Hash Functions
JavaScript does not come with built-in string hashing functions, but we can use the crypto library in Node.js.
const crypto = require('crypto'); function hashString(str) { return crypto.createHash('sha256').update(str).digest('hex'); } console.log(hashString('hello')); // Hash of the string 'hello'
2. Simple Hash Function
Here’s a simple custom hash function for learning purposes:
function simpleHash(str) { let hash = 0; for (let i = 0; i < str.length; i++) { const char = str.charCodeAt(i); hash = (hash << 5) - hash + char; hash |= 0; // Convert to 32bit integer } return hash; } console.log(simpleHash('hello world')); // Simple hash of the string 'hello world'
3. Using MurmurHash
MurmurHash is a popular non-cryptographic hash function:
function murmurhash3_32_gc(key, seed) { let remainder, bytes, h1, h1b, c1, c2, k1, i; remainder = key.length & 3; // key.length % 4 bytes = key.length - remainder; h1 = seed; c1 = 0xcc9e2d51; c2 = 0x1b873593; i = 0; while (i < bytes) { k1 = (key.charCodeAt(i) & 0xff) | ((key.charCodeAt(++i) & 0xff) << 8) | ((key.charCodeAt(++i) & 0xff) << 16) | ((key.charCodeAt(++i) & 0xff) << 24); ++i; k1 = ((k1 & 0xffff) * c1 + ((((k1 >> 16) * c1) & 0xffff) << 16)) & 0xffffffff; k1 = (k1 << 15) | (k1 >> 17); k1 = ((k1 & 0xffff) * c2 + ((((k1 >> 16) * c2) & 0xffff) << 16)) & 0xffffffff; h1 ^= k1; h1 = (h1 << 13) | (h1 >> 19); h1b = ((h1 & 0xffff) * 5 + ((((h1 >> 16) * 5) & 0xffff) << 16)) & 0xffffffff; h1 = (h1b + 0x6b64e854 + (((h1b >> 16) + (h1b & 0xffff)) & 0xffff)) & 0xffffffff; } k1 = 0; switch (remainder) { case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16; case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8; case 1: k1 ^= (key.charCodeAt(i) & 0xff); k1 = ((k1 & 0xffff) * c1 + ((((k1 >> 16) * c1) & 0xffff) << 16)) & 0xffffffff; k1 = (k1 << 15) | (k1 >> 17); k1 = ((k1 & 0xffff) * c2 + ((((k1 >> 16) * c2) & 0xffff) << 16)) & 0xffffffff; h1 ^= k1; } h1 ^= key.length; h1 ^= h1 >> 16; h1 = ((h1 & 0xffff) * 0x85ebca6b + ((((h1 >> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff; h1 ^= h1 >> 13; h1 = ((h1 & 0xffff) * 0xc2b2ae35 + ((((h1 >> 16) * 0xc2b2ae35) & 0xffff) << 16)) & 0xffffffff; h1 ^= h1 >> 16; return h1 >>> 0; } console.log(murmurhash3_32_gc('hello world', 1)); // MurmurHash of the string 'hello world'
App Example Using Introduced APIs
Let's create a simple Node.js application to store and verify user passwords using hashing:
const crypto = require('crypto'); // Function to hash a string (password) function hashString(str) { return crypto.createHash('sha256').update(str).digest('hex'); } // Register user with hashed password let users = []; function registerUser(username, password) { const hashedPassword = hashString(password); users.push({ username, password: hashedPassword }); console.log(`User ${username} registered successfully!`); } // Verify user password function verifyUser(username, password) { const user = users.find(user => user.username === username); if (user && user.password === hashString(password)) { console.log('Password is correct!'); } else { console.log('Password is incorrect!'); } } // Demonstrate the usage registerUser('john_doe', '12345'); verifyUser('john_doe', '12345'); verifyUser('john_doe', 'wrongpassword');
In the example above, we used the crypto
library to hash user passwords and verify them during login attempts.
Hash: bec26dca2ca64f141838ceb3db254cc424373c5ac3c9d60636cf1d63dcbd30c4