Hash
Create cryptographic message digests
The Hash class is a utility for creating fixed-size message digests from arbitrary data. It is fully compatible with the Node.js crypto.createHash API and implements the stream.Transform interface.
Table of Contents
- Theory
- Class: Hash
- Stream API
- Module Methods
- Supported Algorithms
- Real-World Examples
- Security Considerations
Theory
A cryptographic hash function H(x) takes an input of arbitrary length and produces a fixed-length output (the "digest"). Key properties include:
- Deterministic: The same input always produces the exact same output.
- Efficient: It is computationally fast to calculate the hash for any given message.
- Avalanche Effect: A small change to the input (e.g., flipping 1 bit) should change the output so significantly that it appears uncorrelated.
- Pre-image Resistance: Given a hash
h, it should be computationally infeasible to find any messagemsuch thatH(m) = h. - Collision Resistance: It should be computationally infeasible to find two different messages
m1andm2such thatH(m1) = H(m2).
Algorithms like MD5, SHA-1, and SHA-2 (SHA-256, SHA-512) use the Merkle-Damgård construction. The input is padded and split into fixed-size blocks. A compression function iteratively processes these blocks.
SHA-3 (Keccak) uses a "Sponge" construction. It "absorbs" data into a large internal state, permutes it, and then "squeezes" out the hash. This allows for arbitrary output lengths (XOFs), utilized in SHAKE128/SHAKE256.
Performance Optimization
RNQC optimizes passing strings to native code. If you have string data, pass it directly to update() rather than converting it to a Buffer first. This avoids an unnecessary round-trip copy across the React Native bridge.
Class: Hash
The Hash class creates digest streams. Instances are created using createHash().
hash.update(data[, inputEncoding])
Updates the hash content with the given data. This method can be called multiple times with new data as it is streamed.
Parameters:
Prop
Type
Returns: Hash (this, for chaining)
Example:
const hash = createHash('sha512');
hash.update('utf8 string');
hash.update('48656c6c6f', 'hex'); // "Hello"hash.digest([encoding])
Calculates the digest of all of the data passed to be hashed (using the hash.update() method).
Parameters:
Prop
Type
Returns: Buffer | string
The Hash object can not be used again after hash.digest() method has been called. Attempting to call update or digest again will throw a native error (ERR_CRYPTO_HASH_FINALIZED).
Example:
import { } from 'crypto';
const = ('sha256');
.('hello');
const digest = .('hex');hash.copy([options])
Creates a new Hash object that contains a deep copy of the internal state of the current Hash object.
Parameters:
Prop
Type
Returns: Hash (New instance)
Example:
const hash = createHash('sha256');
hash.update('block1');
const snapshot = hash.copy();
hash.update('block2-A');
snapshot.update('block2-B');Stream API
Since Hash implements stream.Transform, you can use standard Node.js stream methods.
hash.write(chunk[, encoding][, callback])
Writes data to the stream.
hash.pipe(destination)
Pipes the output digest to a destination stream.
Example:
import fs from 'fs';
const hash = createHash('sha256');
const input = fs.createReadStream('file.txt');
input.pipe(hash).pipe(process.stdout);Module Methods
createHash(algorithm[, options])
Creates and returns a Hash object that can be used to generate hash digests using the given algorithm.
Parameters:
Prop
Type
Returns: Hash
getHashes()
Returns an array of the names of the supported hash algorithms.
Returns: string[]
Supported Algorithms
Support depends on the version of OpenSSL bundled with the OS (iOS/Android), but typically includes:
| Algorithm | Digest Size | Security | Notes |
|---|---|---|---|
| MD5 | 128 bits | ❌ Broken | Use only for non-crypto checksums. |
| SHA-1 | 160 bits | ❌ Broken | Do not use for new signatures. |
| SHA-256 | 256 bits | ✅ Secure | Industry standard. |
| SHA-512 | 512 bits | ✅ Secure | Faster on 64-bit CPUs. |
| SHA-3 | Variable | ✅ Secure | NIST standard (Keccak). |
| BLAKE2b | 512 bits | ✅ Secure | High speed. |
Real-World Examples
File Checksum (Streaming)
Computing the hash of a large file without loading it entirely into memory.
import { createHash } from 'react-native-quick-crypto';
import RNFS from 'react-native-fs';
async function computeFileHash(filePath: string): Promise<string> {
const hash = createHash('sha256');
const stats = await RNFS.stat(filePath);
const fileSize = stats.size;
const chunkSize = 1024 * 1024; // 1MB
let offset = 0;
while (offset < fileSize) {
const chunk = await RNFS.read(filePath, chunkSize, offset, 'base64');
hash.update(chunk, 'base64');
offset += chunkSize;
}
return hash.digest('hex');
}Git Object ID (SHA-1)
Git calculates Object IDs (OIDs) by taking the SHA-1 hash of: type + space + length + null byte + content.
import { createHash } from 'react-native-quick-crypto';
function calculateGitBlobId(content: string): string {
const hash = createHash('sha1');
const size = Buffer.byteLength(content, 'utf8');
const header = `blob ${size}\0`;
hash.update(header);
hash.update(content);
return hash.digest('hex');
}Security Considerations
Algorithm Selection
Always prefer SHA-256 or SHA-512 for new applications. Avoid MD5 and SHA-1 unless required for compatibility with legacy systems.
Password Hashing
Do not use createHash (SHA-256 etc.) for passwords. They are too fast and vulnerable to brute-force attacks. Use scrypt or pbkdf2 instead.