
Security News
Happy Birthday, Shai-Hulud
It has been one year since Shai-Hulud made its first appearance on npm.
Browser / Nodejs Compatible Object Hashing
WebCrypto API for both environmentsparse and stringify with custom functionsnpm install hashery
import { Hashery } from 'hashery';
const hashery = new Hashery();
// Hash an object (defaults to SHA-256)
const hash = await hashery.toHash({ name: 'John', age: 30 });
console.log(hash); // SHA-256 hash string
// Hash a string
const stringHash = await hashery.toHash('hello world');
// Hash any value (numbers, arrays, etc.)
const numberHash = await hashery.toHash(42);
const arrayHash = await hashery.toHash([1, 2, 3, 4, 5]);
For performance-critical applications or when you need to avoid async/await, use the synchronous hashing methods. These work with non-cryptographic hash algorithms (djb2, fnv1, murmer, crc32) and are significantly faster than WebCrypto methods.
import { Hashery } from 'hashery';
const hashery = new Hashery();
// Synchronous hash (defaults to djb2)
const hash = hashery.toHashSync({ name: 'John', age: 30 });
console.log(hash); // djb2 hash string (8 hex characters)
// Sync with specific algorithm
const fnv1Hash = hashery.toHashSync({ data: 'example' }, { algorithm: 'fnv1' });
const murmerHash = hashery.toHashSync({ data: 'example' }, { algorithm: 'murmer' });
const crcHash = hashery.toHashSync({ data: 'example' }, { algorithm: 'crc32' });
// Note: WebCrypto algorithms (SHA-256, SHA-384, SHA-512) are NOT supported in sync mode
// This will throw an error:
// hashery.toHashSync({ data: 'example' }, { algorithm: 'SHA-256' }); // ❌ Error!
import { Hashery } from 'hashery';
const hashery = new Hashery();
// Use SHA-384
const hash384 = await hashery.toHash({ data: 'example' }, { algorithm: 'SHA-384' });
// Use SHA-512
const hash512 = await hashery.toHash({ data: 'example' }, { algorithm: 'SHA-512' });
// Use non-crypto hash algorithms
const fastHash = await hashery.toHash({ data: 'example' }, { algorithm: 'djb2' });
You can set a default algorithm for all hash operations via constructor or property:
import { Hashery } from 'hashery';
// Set default algorithm via constructor
const hashery = new Hashery({ defaultAlgorithm: 'SHA-512' });
// Now all hashes use SHA-512 by default
const hash1 = await hashery.toHash({ data: 'example' }); // Uses SHA-512
console.log(hash1.length); // 128 (SHA-512 produces 128 hex characters)
// You can still override it per call
const hash2 = await hashery.toHash({ data: 'example' }, { algorithm: 'SHA-256' });
console.log(hash2.length); // 64 (SHA-256 produces 64 hex characters)
// Change default algorithm at runtime
hashery.defaultAlgorithm = 'djb2';
const hash3 = await hashery.toHash({ data: 'example' }); // Uses djb2
You can limit the length of the hash output using the maxLength option:
import { Hashery } from 'hashery';
const hashery = new Hashery();
// Get a shorter hash (16 characters instead of 64)
const shortHash = await hashery.toHash(
{ data: 'example' },
{ algorithm: 'SHA-256', maxLength: 16 }
);
console.log(shortHash); // "3f79bb7b435b0518" (16 chars)
// Full hash for comparison
const fullHash = await hashery.toHash({ data: 'example' });
console.log(fullHash); // "3f79bb7b435b05181e4ccf0d4e8..." (64 chars)
import { Hashery } from 'hashery';
const hashery = new Hashery();
// Convert hash to a number within a range
const slot = await hashery.toNumber({ userId: 123 }, { min: 0, max: 100 });
console.log(slot); // Deterministic number between 0-100
// Use for consistent slot assignment
const userSlot = await hashery.toNumber({ userId: 'user@example.com' }, { min: 0, max: 9 });
// Same user will always get the same slot number
Generate deterministic numbers synchronously for high-performance scenarios. Perfect for A/B testing, sharding, and load balancing without async overhead.
import { Hashery } from 'hashery';
const hashery = new Hashery();
// Synchronous number generation (defaults to djb2)
const slot = hashery.toNumberSync({ userId: 123 }, { min: 0, max: 100 });
console.log(slot); // Deterministic number between 0-100
// A/B testing without async/await
const variant = hashery.toNumberSync({ userId: 'user123' }, { min: 0, max: 1 });
console.log(variant === 0 ? 'Group A' : 'Group B');
// Load balancing across servers
const serverIndex = hashery.toNumberSync(
{ requestId: 'req_abc123' },
{ min: 0, max: 9, algorithm: 'fnv1' } // 10 servers
);
// Sharding assignment
const shardId = hashery.toNumberSync(
{ customerId: 'cust_xyz' },
{ min: 0, max: 15, algorithm: 'murmer' } // 16 shards
);
// Set default sync algorithm for all sync operations
const hashery2 = new Hashery({ defaultAlgorithmSync: 'fnv1' });
const num = hashery2.toNumberSync({ data: 'test' }); // Uses fnv1 by default
Hashery works seamlessly in the browser using the Web Crypto API. You can include it via CDN or bundle it with your application.
<!DOCTYPE html>
<html>
<head>
<title>Hashery Browser Example</title>
</head>
<body>
<script type="module">
import { Hashery } from 'https://cdn.jsdelivr.net/npm/hashery@latest/dist/browser/index.js';
const hashery = new Hashery();
// Hash data in the browser
const hash = await hashery.toHash({ page: 'home', userId: 123 });
console.log('Hash:', hash);
// Generate slot numbers for A/B testing
const variant = await hashery.toNumber({ userId: 'user123' }, { min: 0, max: 1 });
console.log('A/B Test Variant:', variant === 0 ? 'A' : 'B');
</script>
</body>
</html>
Hashery extends Hookified to provide event-based functionality through hooks. Hooks allow you to intercept and modify behavior during the hashing process.
before:toHashFired before hashing occurs. This hook receives a context object containing:
data - The data to be hashed (can be modified)algorithm - The hash algorithm to use (can be modified)maxLength - Optional maximum length for the hash outputafter:toHashFired after hashing completes. This hook receives a result object containing:
hash - The generated hash (can be modified)data - The data that was hashedalgorithm - The algorithm that was usedbefore:toHashSyncFired before synchronous hashing occurs. This hook receives a context object containing:
data - The data to be hashed (can be modified)algorithm - The hash algorithm to use (can be modified)maxLength - Optional maximum length for the hash outputNote: This hook fires asynchronously (non-blocking) to maintain the synchronous nature of toHashSync(). Hook execution happens in the background and won't delay the method's return.
after:toHashSyncFired after synchronous hashing completes. This hook receives a result object containing:
hash - The generated hash (can be modified)data - The data that was hashedalgorithm - The algorithm that was usedNote: This hook fires asynchronously (non-blocking) to maintain the synchronous nature of toHashSync(). Hook execution happens in the background.
import { Hashery } from 'hashery';
const hashery = new Hashery();
// Listen to before:toHash hook
hashery.onHook('before:toHash', async (context) => {
console.log('About to hash:', context.data);
console.log('Using algorithm:', context.algorithm);
});
// Listen to after:toHash hook
hashery.onHook('after:toHash', async (result) => {
console.log('Hash generated:', result.hash);
console.log('Original data:', result.data);
});
await hashery.toHash({ name: 'John', age: 30 });
You can modify the data before it's hashed:
const hashery = new Hashery();
// Add a timestamp to all hashed data
hashery.onHook('before:toHash', async (context) => {
context.data = {
original: context.data,
timestamp: new Date().toISOString()
};
});
const hash = await hashery.toHash({ userId: 123 });
// Data will be hashed with timestamp included
You can force a specific algorithm regardless of what's requested:
const hashery = new Hashery();
// Force all hashes to use SHA-512
hashery.onHook('before:toHash', async (context) => {
context.algorithm = 'SHA-512';
});
// Even though we request SHA-256, it will use SHA-512
const hash = await hashery.toHash({ data: 'example' }, { algorithm: 'SHA-256' });
console.log(hash.length); // 128 (SHA-512 hash length)
You can transform the hash after it's generated:
const hashery = new Hashery();
// Convert all hashes to uppercase
hashery.onHook('after:toHash', async (result) => {
result.hash = result.hash.toUpperCase();
});
const hash = await hashery.toHash({ data: 'example' });
console.log(hash); // Hash will be in uppercase
Use hooks to implement a caching layer:
const hashery = new Hashery();
const cache = new Map<string, string>();
// Store hashes in cache after generation
hashery.onHook('after:toHash', async (result) => {
const cacheKey = `${result.algorithm}:${JSON.stringify(result.data)}`;
cache.set(cacheKey, result.hash);
});
// Later you can check the cache before hashing
// (Note: You would need to implement cache lookup logic in your application)
Hooks are perfect for logging and debugging:
const hashery = new Hashery();
hashery.onHook('before:toHash', async (context) => {
console.log(`[DEBUG] Hashing data with ${context.algorithm}:`, context.data);
});
hashery.onHook('after:toHash', async (result) => {
console.log(`[DEBUG] Hash generated: ${result.hash.substring(0, 8)}...`);
});
await hashery.toHash({ userId: 'user123' });
You can register multiple hooks, and they will execute in the order they were registered:
const hashery = new Hashery();
hashery.onHook('before:toHash', async (context) => {
console.log('First hook');
context.data = { step: 1, original: context.data };
});
hashery.onHook('before:toHash', async (context) => {
console.log('Second hook');
context.data = { step: 2, previous: context.data };
});
await hashery.toHash({ name: 'test' });
// Output: "First hook" then "Second hook"
// Data will be wrapped twice
Synchronous methods (toHashSync, toNumberSync) support hooks, but they fire asynchronously in the background to maintain the synchronous nature of the methods.
const hashery = new Hashery();
// Listen to synchronous hash hooks
hashery.onHook('before:toHashSync', async (context) => {
console.log('About to hash synchronously:', context.data);
console.log('Using algorithm:', context.algorithm);
});
hashery.onHook('after:toHashSync', async (result) => {
console.log('Sync hash generated:', result.hash);
});
// Call synchronous method - hooks fire in background
const hash = hashery.toHashSync({ name: 'John', age: 30 });
console.log('Method returned:', hash);
// Method returns immediately, hooks execute asynchronously
Important Notes:
toHash, toNumber)Synchronous methods are designed for maximum performance. Making hooks blocking would defeat this purpose. The async hook execution allows:
If you need hooks that modify data or behavior, use the async methods (toHash, toNumber).
You can remove hooks when they're no longer needed:
const hashery = new Hashery();
const myHook = async (context: any) => {
console.log('Hook called');
};
// Add the hook
hashery.onHook('before:toHash', myHook);
// Remove the hook
hashery.offHook('before:toHash', myHook);
// Same works for sync hooks
hashery.onHook('before:toHashSync', myHook);
hashery.offHook('before:toHashSync', myHook);
Control how errors in hooks are handled using the throwOnEmitError option:
// Throw errors that occur in hooks
const hashery1 = new Hashery({ throwOnEmitError: true });
hashery1.onHook('before:toHash', async (context) => {
throw new Error('Hook error');
});
// This will throw the error
await hashery1.toHash({ data: 'example' }); // Throws Error: Hook error
// Silently handle errors in hooks
const hashery2 = new Hashery({ throwOnEmitError: false });
hashery2.onHook('before:toHash', async (context) => {
throw new Error('Hook error');
});
// This will not throw, hashing continues
const hash = await hashery2.toHash({ data: 'example' }); // Returns hash successfully
Hashery is built on top of the Web Crypto API, which provides cryptographic operations in both browser and Node.js environments. This ensures consistent, secure hashing across all platforms.
The Web Crypto API is supported in all modern browsers:
Node.js 15+ includes the Web Crypto API via the crypto.webcrypto global. Hashery automatically detects and uses the appropriate crypto implementation for your environment.
These algorithms use the Web Crypto API and are only available asynchronously:
These are cryptographically secure and suitable for security-sensitive applications.
These algorithms support both synchronous and asynchronous operation:
Async methods (toHash, toNumber):
SHA-256Sync methods (toHashSync, toNumberSync):
djb2import { Hashery } from 'hashery';
const hashery = new Hashery();
// Web Crypto algorithms
const sha256 = await hashery.toHash({ data: 'example' }); // Default SHA-256
const sha384 = await hashery.toHash({ data: 'example' }, { algorithm: 'SHA-384' });
const sha512 = await hashery.toHash({ data: 'example' }, { algorithm: 'SHA-512' });
// Non-crypto algorithms (faster, but not cryptographically secure)
const djb2Hash = await hashery.toHash({ data: 'example' }, { algorithm: 'djb2' });
const fnv1Hash = await hashery.toHash({ data: 'example' }, { algorithm: 'fnv1' });
DJB2 is a non-cryptographic hash function created by Daniel J. Bernstein. It's known for its simplicity and speed, making it ideal for hash tables, checksums, and other non-security applications.
Good for:
Not suitable for:
| Feature | DJB2 | SHA-256 |
|---|---|---|
| Speed | Very Fast | Slower |
| Security | Not Secure | Cryptographically Secure |
| Hash Length | 32-bit | 256-bit |
| Collision Resistance | Good | Excellent |
| Use Case | General Purpose | Security |
import { Hashery } from 'hashery';
const hashery = new Hashery();
// Hash with DJB2 (fast, non-cryptographic)
const djb2Hash = await hashery.toHash({ userId: 123, action: 'login' }, { algorithm: 'djb2' });
// Use for cache keys
const cacheKey = await hashery.toHash({
endpoint: '/api/users',
params: { page: 1, limit: 10 }
}, { algorithm: 'djb2' });
// Generate slot numbers with DJB2
const slot = await hashery.toNumber({ userId: 'user123' }, { min: 0, max: 99, algorithm: 'djb2' });
DJB2 uses a simple formula:
hash = 5381
for each character c:
hash = ((hash << 5) + hash) + c
This translates to: hash * 33 + c, where 5381 is the magic initial value chosen by Daniel J. Bernstein for its distribution properties.
FNV1 (Fowler-Noll-Vo) is a non-cryptographic hash function designed for fast hash table and checksum use. Created by Glenn Fowler, Landon Curt Noll, and Kiem-Phong Vo, it's known for its excellent distribution properties and simplicity.
Good for:
Not suitable for:
| Feature | FNV1 | DJB2 | SHA-256 |
|---|---|---|---|
| Speed | Very Fast | Very Fast | Slower |
| Distribution | Excellent | Good | Excellent |
| Security | Not Secure | Not Secure | Cryptographically Secure |
| Collision Resistance | Good | Good | Excellent |
| Use Case | Hash Tables | General Purpose | Security |
import { Hashery } from 'hashery';
const hashery = new Hashery();
// Hash with FNV1 (fast, excellent distribution)
const fnv1Hash = await hashery.toHash({ productId: 'ABC123', variant: 'red' }, { algorithm: 'fnv1' });
// Use for hash table keys
const tableKey = await hashery.toHash({
userId: 'user@example.com',
resource: 'profile'
}, { algorithm: 'fnv1' });
// Generate distributed slot numbers with FNV1
const slot = await hashery.toNumber({ sessionId: 'sess_xyz789' }, { min: 0, max: 999, algorithm: 'fnv1' });
// Use for data deduplication
const fingerprint = await hashery.toHash({
content: 'document content here',
metadata: { author: 'John', date: '2024-01-01' }
}, { algorithm: 'fnv1' });
FNV1 uses the following formula:
hash = FNV_offset_basis
for each byte b:
hash = hash * FNV_prime
hash = hash XOR b
Where:
The algorithm multiplies by a prime and XORs with each input byte, creating excellent avalanche properties where small input changes result in very different hash values.
CRC (Cyclic Redundancy Check) is a non-cryptographic hash function designed primarily for detecting accidental changes to data. CRC32 is a 32-bit variant widely used in network protocols, file formats, and data integrity verification.
Good for:
Not suitable for:
| Feature | CRC32 | DJB2 | FNV1 | SHA-256 |
|---|---|---|---|---|
| Primary Use | Error Detection | Hash Tables | Hash Tables | Security |
| Speed | Very Fast | Very Fast | Very Fast | Slower |
| Security | Not Secure | Not Secure | Not Secure | Cryptographically Secure |
| Hash Length | 32-bit | 32-bit | 32-bit/64-bit | 256-bit |
| Error Detection | Excellent | Poor | Poor | Excellent |
| Use Case | Data Integrity | General Purpose | Hash Tables | Security |
import { Hashery } from 'hashery';
const hashery = new Hashery();
// Hash with CRC32 for data integrity
const crcHash = await hashery.toHash({ fileData: 'content here' }, { algorithm: 'crc32' });
// Verify file integrity
const fileChecksum = await hashery.toHash({
filename: 'document.pdf',
size: 1024000,
modified: '2024-01-01'
}, { algorithm: 'crc32' });
// Network packet validation
const packetChecksum = await hashery.toHash({
header: { type: 'data', seq: 123 },
payload: 'packet payload data'
}, { algorithm: 'crc32' });
// Quick data validation
const dataIntegrity = await hashery.toHash({
recordId: 'rec_123',
data: { field1: 'value1', field2: 'value2' }
}, { algorithm: 'crc32' });
CRC32 uses polynomial division in a finite field (GF(2)):
CRC32 polynomial: 0x04C11DB7 (IEEE 802.3 standard)
for each byte b:
crc = (crc >> 8) XOR table[(crc XOR b) & 0xFF]
Key characteristics:
⚠️ Security Warning: CRC is NOT cryptographically secure. It's designed to detect accidental errors, not intentional tampering. For security applications, use SHA-256 or other cryptographic hash functions.
✅ Best Practice: Use CRC32 for checksums and error detection in non-adversarial environments. Use cryptographic hashes (SHA-256, SHA-512) when security matters.
parseGets or sets the parse function used to deserialize stored values.
Type: ParseFn
Default: JSON.parse
const hashery = new Hashery();
hashery.parse = customParseFunction;
stringifyGets or sets the stringify function used to serialize values for storage.
Type: StringifyFn
Default: JSON.stringify
const hashery = new Hashery();
hashery.stringify = customStringifyFunction;
providersGets or sets the HashProviders instance used to manage hash providers.
Type: HashProviders
const hashery = new Hashery();
console.log(hashery.providers);
namesGets the names of all registered hash algorithm providers.
Type: Array<string>
Returns: An array of provider names (e.g., ['SHA-256', 'SHA-384', 'SHA-512', 'djb2', 'fnv1', 'murmer', 'crc32'])
const hashery = new Hashery();
console.log(hashery.names); // ['SHA-256', 'SHA-384', 'SHA-512', 'djb2', 'fnv1', 'murmer', 'crc32']
defaultAlgorithmGets or sets the default hash algorithm to use when none is specified for async methods.
Type: string
Default: 'SHA-256'
const hashery = new Hashery();
// Get default algorithm
console.log(hashery.defaultAlgorithm); // 'SHA-256'
// Set default algorithm
hashery.defaultAlgorithm = 'SHA-512';
// Now all async hashes use SHA-512 by default
const hash = await hashery.toHash({ data: 'example' });
console.log(hash.length); // 128 (SHA-512 produces 128 hex characters)
defaultAlgorithmSyncGets or sets the default hash algorithm to use when none is specified for synchronous methods.
Type: string
Default: 'djb2'
const hashery = new Hashery();
// Get default sync algorithm
console.log(hashery.defaultAlgorithmSync); // 'djb2'
// Set default sync algorithm
hashery.defaultAlgorithmSync = 'fnv1';
// Now all sync hashes use fnv1 by default
const hash = hashery.toHashSync({ data: 'example' });
// You can also set it in the constructor
const hashery2 = new Hashery({ defaultAlgorithmSync: 'murmer' });
const hash2 = hashery2.toHashSync({ data: 'test' }); // Uses murmer
toHash(data, options?)Generates a cryptographic hash of the provided data using the specified algorithm (async). The data is first stringified using the configured stringify function, then hashed.
Parameters:
data (unknown) - The data to hash (will be stringified before hashing)options (object, optional) - Configuration options
algorithm (string, optional) - The hash algorithm to use (defaults to 'SHA-256')maxLength (number, optional) - Maximum length for the hash output (truncates from the start)Returns: Promise<string> - A Promise that resolves to the hexadecimal string representation of the hash
Example:
const hashery = new Hashery();
// Using default SHA-256
const hash = await hashery.toHash({ name: 'John', age: 30 });
// Using a different algorithm
const hash512 = await hashery.toHash({ name: 'John' }, { algorithm: 'SHA-512' });
const fastHash = await hashery.toHash({ name: 'John' }, { algorithm: 'djb2' });
// Truncating hash output
const shortHash = await hashery.toHash(
{ name: 'John' },
{ algorithm: 'SHA-256', maxLength: 16 }
);
toHashSync(data, options?)Generates a hash of the provided data synchronously using a non-cryptographic hash algorithm. The data is first stringified using the configured stringify function, then hashed.
Important: This method only works with synchronous hash providers (djb2, fnv1, murmer, crc32). WebCrypto algorithms (SHA-256, SHA-384, SHA-512) are not supported and will throw an error.
Parameters:
data (unknown) - The data to hash (will be stringified before hashing)options (object, optional) - Configuration options
algorithm (string, optional) - The hash algorithm to use (defaults to 'djb2')maxLength (number, optional) - Maximum length for the hash output (truncates from the start)Returns: string - The hexadecimal string representation of the hash
Throws: Error if the specified algorithm does not support synchronous hashing
Example:
const hashery = new Hashery();
// Using default djb2
const hash = hashery.toHashSync({ name: 'John', age: 30 });
// Using a different algorithm
const hashFnv1 = hashery.toHashSync({ name: 'John' }, { algorithm: 'fnv1' });
const hashMurmer = hashery.toHashSync({ name: 'John' }, { algorithm: 'murmer' });
const hashCrc = hashery.toHashSync({ name: 'John' }, { algorithm: 'crc32' });
// Truncating hash output
const shortHash = hashery.toHashSync(
{ name: 'John' },
{ algorithm: 'djb2', maxLength: 4 }
);
// This will throw an error (WebCrypto not supported in sync mode)
// const invalid = hashery.toHashSync({ name: 'John' }, { algorithm: 'SHA-256' }); // ❌
toNumber(data, options?)Generates a deterministic number within a specified range based on the hash of the provided data (async). This method uses the toHash function to create a consistent hash, then maps it to a number between min and max (inclusive).
Parameters:
data (unknown) - The data to hash (will be stringified before hashing)options (object, optional) - Configuration options
min (number, optional) - The minimum value of the range (inclusive, defaults to 0)max (number, optional) - The maximum value of the range (inclusive, defaults to 100)algorithm (string, optional) - The hash algorithm to use (defaults to 'SHA-256')hashLength (number, optional) - Number of characters from hash to use for conversion (defaults to 16)Returns: Promise<number> - A Promise that resolves to a number between min and max (inclusive)
Throws: Error if min is greater than max
Example:
const hashery = new Hashery();
// Generate a number between 0 and 100 (default range)
const num = await hashery.toNumber({ user: 'john' });
// Generate a number with custom range
const num2 = await hashery.toNumber({ user: 'john' }, { min: 0, max: 100 });
// Using a different algorithm
const num512 = await hashery.toNumber({ user: 'john' }, { min: 0, max: 255, algorithm: 'SHA-512' });
toNumberSync(data, options?)Generates a deterministic number within a specified range based on the hash of the provided data synchronously. This method uses the toHashSync function to create a consistent hash, then maps it to a number between min and max (inclusive).
Important: This method only works with synchronous hash providers (djb2, fnv1, murmer, crc32).
Parameters:
data (unknown) - The data to hash (will be stringified before hashing)options (object, optional) - Configuration options
min (number, optional) - The minimum value of the range (inclusive, defaults to 0)max (number, optional) - The maximum value of the range (inclusive, defaults to 100)algorithm (string, optional) - The hash algorithm to use (defaults to 'djb2')hashLength (number, optional) - Number of characters from hash to use for conversion (defaults to 16)Returns: number - A number between min and max (inclusive)
Throws:
Example:
const hashery = new Hashery();
// Generate a number between 0 and 100 (default range)
const num = hashery.toNumberSync({ user: 'john' });
// Generate a number with custom range
const slot = hashery.toNumberSync({ user: 'john' }, { min: 0, max: 9 });
// Using a different algorithm
const numFnv1 = hashery.toNumberSync({ user: 'john' }, { min: 0, max: 255, algorithm: 'fnv1' });
// A/B testing
const variant = hashery.toNumberSync({ userId: 'user123' }, { min: 0, max: 1 });
console.log(variant === 0 ? 'Group A' : 'Group B');
// Load balancing
const serverId = hashery.toNumberSync(
{ requestId: 'req_abc' },
{ min: 0, max: 9, algorithm: 'murmer' } // 10 servers
);
// This will throw an error (WebCrypto not supported in sync mode)
// const invalid = hashery.toNumberSync({ user: 'john' }, { algorithm: 'SHA-256' }); // ❌
loadProviders(providers?, options?)Loads hash providers into the Hashery instance. This allows you to add custom hash providers or replace the default ones.
Parameters:
providers (Array, optional) - Array of hash providers to addoptions (HasheryLoadProviderOptions, optional) - Options object
includeBase (boolean) - Whether to include base providers (default: true)Returns: void
Example:
const hashery = new Hashery();
// Add a custom provider
const customProvider = {
name: 'custom',
toHash: async (data: BufferSource) => 'custom-hash'
};
hashery.loadProviders([customProvider]);
// Load without base providers
hashery.loadProviders([customProvider], { includeBase: false });
Overall view of the current algorithm's and their performance using simple hashing with random data. Many of these are not secure and should be used only for object hashing. Read about each one in the documentation and pick what works best for your use case.
| name | summary | ops/sec | time/op | margin | samples |
|---|---|---|---|---|---|
| DJB2 | 🥇 | 522K | 2µs | ±0.86% | 506K |
| MURMER | -0.24% | 521K | 2µs | ±0.96% | 504K |
| FNV1 | -3.9% | 501K | 2µs | ±0.27% | 487K |
| CRC32 | -12% | 457K | 2µs | ±0.22% | 446K |
| SHA-256 | -81% | 98K | 10µs | ±0.20% | 96K |
| SHA-384 | -83% | 90K | 12µs | ±2.88% | 85K |
| SHA-512 | -83% | 86K | 12µs | ±0.58% | 84K |
Please use our Code of Conduct and Contributing guidelines for development and testing. We appreciate your contributions!
MIT & © Jared Wray
FAQs
Browser Compatible Object Hashing
The npm package hashery receives a total of 8,423,962 weekly downloads. As such, hashery popularity was classified as popular.
We found that hashery demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
It has been one year since Shai-Hulud made its first appearance on npm.

Research
/Security News
Operators behind PolinRider used a compromised GitHub account to plant malware in four development versions of a Packagist package with 700,000+ downloads.

Security News
GitHub Actions now supports cache-mode, a least-privilege control on the Actions cache aimed at the cache poisoning technique behind recent compromises.