FlatHash Security-Focused API Documentation
Algorithm: FlatHash
Type: Non-Cryptographic Hash Function
Output Size: 32/64/128 bits (configurable)
Speed: Ultra-fast (designed for hash tables)
Design: Multiplication-shift with minimal collisions
Use Case: Hash tables, checksums, data structures
Table of Contents
- Security Contract
- Attack Resistance Matrix
- Secure Usage Examples
- Common Mistakes
- Performance vs Security
- Platform-Specific Notes
- Compliance Information
⚠️ CRITICAL WARNING
FlatHash is NOT a cryptographic hash function! It provides:
- ❌ NO cryptographic security
- ❌ NO collision resistance
- ❌ NO preimage resistance
- ❌ NO avalanche properties
- ✅ ONLY distribution uniformity for hash tables
NEVER use FlatHash for:
- Password hashing
- Digital signatures
- Message authentication
- Key derivation
- Any security-critical application
Security Contract
hash32(data: Uint8Array, seed?: number): number
Preconditions:
datacan be any lengthseed(optional) for different hash families- NOT for security purposes
Postconditions:
- Returns 32-bit hash value
- Uniform distribution for random data
- Deterministic output
- Fast computation
Side Effects:
- No security guarantees
- Predictable collisions possible
hash64(data: Uint8Array, seed?: bigint): bigint
Preconditions:
datacan be any lengthseed(optional) 64-bit seed
Postconditions:
- Returns 64-bit hash value
- Better distribution than 32-bit
- Still not cryptographically secure
Side Effects:
- No timing attack resistance
- No security properties
hash128(data: Uint8Array, seed?: Uint8Array): Uint8Array
Preconditions:
datacan be any lengthseed(optional) 16-byte seed
Postconditions:
- Returns 16-byte hash
- Lowest collision probability
- Still not cryptographic
Side Effects:
- Larger output size
- No security guarantees
Attack Resistance Matrix
❌ NO Security Against Any Attacks
| Attack Type | Protection | Reason |
|---|---|---|
| Collision Finding | ❌ None | Trivial to find collisions |
| Preimage Attack | ❌ None | Reversible with effort |
| Second Preimage | ❌ None | Easy to construct |
| Length Extension | ❌ None | Not applicable |
| Differential Analysis | ❌ None | Predictable differences |
| Birthday Attack | ❌ None | Much worse than birthday bound |
✅ Performance Characteristics
| Property | Performance | Notes |
|---|---|---|
| Speed | Ultra-fast | ~3-5 cycles per byte |
| Memory | Minimal | No lookup tables |
| Parallelism | Limited | Sequential design |
| Simplicity | Very simple | ~10 lines of code |
| Distribution | Good | For random inputs |
Secure Usage Examples
✅ CORRECT: Hash Table Implementation
import { FlatHash } from '@metamui/flathash';
class FastHashTable<K, V> {
private buckets: Map<number, Array<[K, V]>>;
private size: number;
private seed: number;
constructor(initialSize: number = 1024) {
this.buckets = new Map();
this.size = initialSize;
this.seed = Math.floor(Math.random() * 0xFFFFFFFF);
}
private hashKey(key: K): number {
// Convert key to bytes
const keyBytes = this.keyToBytes(key);
// Use FlatHash for bucket selection
const hash = FlatHash.hash32(keyBytes, this.seed);
return Math.abs(hash) % this.size;
}
set(key: K, value: V): void {
const bucket = this.hashKey(key);
if (!this.buckets.has(bucket)) {
this.buckets.set(bucket, []);
}
const items = this.buckets.get(bucket)!;
// Check for existing key
for (let i = 0; i < items.length; i++) {
if (this.keysEqual(items[i][0], key)) {
items[i][1] = value;
return;
}
}
// Add new entry
items.push([key, value]);
}
get(key: K): V | undefined {
const bucket = this.hashKey(key);
const items = this.buckets.get(bucket);
if (!items) return undefined;
for (const [k, v] of items) {
if (this.keysEqual(k, key)) {
return v;
}
}
return undefined;
}
private keyToBytes(key: K): Uint8Array {
if (typeof key === 'string') {
return new TextEncoder().encode(key);
} else if (typeof key === 'number') {
const bytes = new Uint8Array(8);
new DataView(bytes.buffer).setFloat64(0, key);
return bytes;
} else if (key instanceof Uint8Array) {
return key;
} else {
// Fallback to JSON serialization
return new TextEncoder().encode(JSON.stringify(key));
}
}
private keysEqual(a: K, b: K): boolean {
return a === b || JSON.stringify(a) === JSON.stringify(b);
}
}
✅ CORRECT: Fast Checksum for Data Integrity
class DataIntegrityCheck {
// Use FlatHash for fast, non-secure checksums
static computeChecksum(data: Uint8Array): number {
return FlatHash.hash32(data);
}
static verifyChecksum(data: Uint8Array, checksum: number): boolean {
return FlatHash.hash32(data) === checksum;
}
// For network packets with error detection (not security)
static addChecksum(packet: Uint8Array): Uint8Array {
const checksum = FlatHash.hash32(packet);
const result = new Uint8Array(packet.length + 4);
result.set(packet, 0);
new DataView(result.buffer).setUint32(
packet.length,
checksum,
false // big-endian
);
return result;
}
static validatePacket(packet: Uint8Array): {
valid: boolean;
data?: Uint8Array;
} {
if (packet.length < 4) {
return { valid: false };
}
const data = packet.slice(0, -4);
const receivedChecksum = new DataView(
packet.buffer,
packet.byteOffset + packet.length - 4
).getUint32(0, false);
const computedChecksum = FlatHash.hash32(data);
return {
valid: computedChecksum === receivedChecksum,
data: computedChecksum === receivedChecksum ? data : undefined
};
}
}
✅ CORRECT: Cache Key Generation
class CacheKeyGenerator {
private static seed = Date.now();
static generateKey(
method: string,
url: string,
params?: Record<string, any>
): string {
// Combine cache key components
const components = [
method,
url,
params ? JSON.stringify(params, Object.keys(params).sort()) : ''
];
const data = new TextEncoder().encode(components.join(':'));
// Use 64-bit hash for better distribution
const hash = FlatHash.hash64(data, BigInt(this.seed));
// Convert to hex string
return hash.toString(16);
}
// For distributed caching with multiple buckets
static selectCacheBucket(
key: string,
bucketCount: number
): number {
const keyBytes = new TextEncoder().encode(key);
const hash = FlatHash.hash32(keyBytes);
return Math.abs(hash) % bucketCount;
}
}
✅ CORRECT: Bloom Filter Implementation
class BloomFilter {
private bits: Uint8Array;
private size: number;
private hashCount: number;
constructor(expectedItems: number, falsePositiveRate: number = 0.01) {
// Calculate optimal size and hash count
this.size = Math.ceil(
-expectedItems * Math.log(falsePositiveRate) / (Math.log(2) ** 2)
);
this.hashCount = Math.ceil(
this.size / expectedItems * Math.log(2)
);
this.bits = new Uint8Array(Math.ceil(this.size / 8));
}
add(item: string): void {
const itemBytes = new TextEncoder().encode(item);
// Use multiple hash functions via different seeds
for (let i = 0; i < this.hashCount; i++) {
const hash = FlatHash.hash32(itemBytes, i);
const bitIndex = Math.abs(hash) % this.size;
const byteIndex = Math.floor(bitIndex / 8);
const bitOffset = bitIndex % 8;
this.bits[byteIndex] |= (1 << bitOffset);
}
}
contains(item: string): boolean {
const itemBytes = new TextEncoder().encode(item);
for (let i = 0; i < this.hashCount; i++) {
const hash = FlatHash.hash32(itemBytes, i);
const bitIndex = Math.abs(hash) % this.size;
const byteIndex = Math.floor(bitIndex / 8);
const bitOffset = bitIndex % 8;
if ((this.bits[byteIndex] & (1 << bitOffset)) === 0) {
return false;
}
}
return true; // Might be false positive!
}
}
Common Mistakes
❌ CRITICAL: Using for Security
// NEVER DO THIS - Catastrophic security failure!
function insecurePasswordStorage(password: string): number {
// FlatHash is NOT cryptographic!
return FlatHash.hash32(new TextEncoder().encode(password));
}
// CORRECT - Use proper password hashing
import { Argon2 } from '@metamui/argon2';
async function securePasswordStorage(password: string): Promise<Uint8Array> {
const salt = randomBytes(16);
return Argon2.hash(password, salt);
}
❌ Using for Message Authentication
// WRONG - No security properties!
function brokenMAC(key: Uint8Array, message: Uint8Array): number {
const combined = new Uint8Array(key.length + message.length);
combined.set(key, 0);
combined.set(message, key.length);
// This provides NO authentication!
return FlatHash.hash32(combined);
}
// CORRECT - Use proper MAC
import { HMAC } from '@metamui/hmac';
function properMAC(key: Uint8Array, message: Uint8Array): Uint8Array {
return HMAC.compute(key, message);
}
❌ Using for Unique IDs
// BAD - High collision probability
function generateId(data: string): string {
const hash = FlatHash.hash32(new TextEncoder().encode(data));
return hash.toString(16); // Only 32 bits!
}
// BETTER - Use proper random IDs
function generateSecureId(): string {
return randomBytes(16).toString('hex'); // 128 bits
}
❌ Assuming Collision Resistance
// WRONG - Collisions are easy to find
class BrokenDeduplication {
private seen = new Set<number>();
isDuplicate(data: Uint8Array): boolean {
const hash = FlatHash.hash32(data);
if (this.seen.has(hash)) {
// WRONG - Different data can have same hash!
return true;
}
this.seen.add(hash);
return false;
}
}
// CORRECT - Store actual data or use cryptographic hash
class ProperDeduplication {
private seen = new Set<string>();
isDuplicate(data: Uint8Array): boolean {
// Use cryptographic hash
const hash = SHA256.hash(data);
const hashHex = Buffer.from(hash).toString('hex');
if (this.seen.has(hashHex)) {
return true;
}
this.seen.add(hashHex);
return false;
}
}
Performance vs Security
Performance Characteristics
// Benchmark results (approximate)
// Platform: Intel i7-10700K @ 3.8GHz
//
// FlatHash-32: ~10 GB/s
// FlatHash-64: ~8 GB/s
// FlatHash-128: ~6 GB/s
//
// Compared to:
// SHA-256: ~300 MB/s (30x slower)
// BLAKE3: ~3 GB/s (3x slower)
// xxHash: ~15 GB/s (similar speed)
When to Use FlatHash
| Use Case | Suitable? | Alternative |
|---|---|---|
| Hash tables | ✅ Yes | - |
| Checksums (non-secure) | ✅ Yes | CRC32 |
| Cache keys | ✅ Yes | - |
| Bloom filters | ✅ Yes | - |
| Load balancing | ✅ Yes | - |
| Password hashing | ❌ NO! | Argon2 |
| File integrity | ❌ NO! | SHA-256 |
| Digital signatures | ❌ NO! | Ed25519 |
| Key derivation | ❌ NO! | HKDF |
Platform-Specific Notes
All Platforms
- Simple implementation (~50 lines)
- No platform-specific optimizations needed
- Works well on 32-bit and 64-bit systems
- No SIMD required
JavaScript/TypeScript
- Use
numberfor 32-bit variant - Use
BigIntfor 64-bit variant - Good performance in V8
Embedded Systems
- Minimal code size
- No lookup tables
- Low memory usage
- Suitable for microcontrollers
Compliance Information
Design Principles
- Speed First: Optimized for performance
- Simplicity: Minimal implementation
- Distribution: Good uniformity for random data
- Non-Cryptographic: No security claims
Appropriate Uses
✅ Use for:
- Hash table implementations
- Non-secure checksums
- Load distribution
- Cache key generation
- Data structure internals
❌ Never use for:
- Any security purpose
- Password storage
- Authentication
- Cryptographic protocols
- Data integrity (security)
Comparison with Alternatives
| Algorithm | Type | Speed | Security | Use Case |
|---|---|---|---|---|
| FlatHash | Non-crypto | Fastest | None | Hash tables |
| xxHash | Non-crypto | Very fast | None | Checksums |
| CityHash | Non-crypto | Very fast | None | Hash tables |
| SHA-256 | Crypto | Slow | High | Security |
| BLAKE3 | Crypto | Fast | High | Security |
Security Notice: FlatHash is explicitly NOT a cryptographic hash function. It provides NO security properties. Use ONLY for performance-critical, non-security applications like hash tables. For ANY security need, use SHA-256, BLAKE3, or other cryptographic functions. Report misuse to security@metamui.id
Last Updated: 2025-07-14
Version: 3.0.0
License: BSL-1.1
Security Analysis
Threat Model: FlatHash Threat Model
The comprehensive threat analysis covers:
- Algorithm-specific attack vectors
- Implementation vulnerabilities
- Side-channel considerations
- Quantum resistance analysis (where applicable)
- Deployment recommendations
For complete security analysis and risk assessment, see the dedicated threat model documentation.