Cryptographic Hash Functions
Hash functions produce fixed-size digests from arbitrary input data. MetaMUI implements both traditional and modern hash functions for various security requirements.
Available Algorithms
SHA-256
Secure Hash Algorithm 256-bit
- Output: 256 bits (32 bytes)
- Block Size: 512 bits
- Security: 128-bit collision resistance
- Standard: NIST FIPS 180-4
- Detailed Documentation
SHA-512
Secure Hash Algorithm 512-bit
- Output: 512 bits (64 bytes)
- Block Size: 1024 bits
- Security: 256-bit collision resistance
- Standard: NIST FIPS 180-4
- Detailed Documentation
Blake2b
Fast Cryptographic Hash
- Output: 1-64 bytes (configurable)
- Default: 512 bits (64 bytes)
- Security: Min(output_bits/2, 256) bits
- Features: Keyed hashing, personalization
- Detailed Documentation
Blake2s
Optimized for 32-bit Platforms
- Output: 1-32 bytes (configurable)
- Default: 256 bits (32 bytes)
- Security: Min(output_bits/2, 128) bits
- Features: Keyed hashing, personalization
- Detailed Documentation
Blake3
Parallel-Friendly Hash
- Output: Unlimited (XOF)
- Default: 256 bits (32 bytes)
- Security: 128-bit minimum
- Features: Parallel processing, keyed mode, XOF
- Detailed Documentation
SHAKE-256
Extendable Output Function
- Output: Unlimited
- Security: Min(output_bits/2, 256) bits
- Based on: SHA-3/Keccak
- Features: Variable output length
- Detailed Documentation
Algorithm Selection Guide
For New Applications
Recommended: Blake3
- Fastest performance
- Parallel processing
- Modern design
- Flexible output
For Compatibility
Use: SHA-256
- Universal support
- Required by many standards
- Hardware acceleration
- Well-analyzed
For Special Requirements
- Long outputs: SHA-512, Blake2b
- Embedded systems: Blake2s
- Variable output: SHAKE-256, Blake3
- Keyed hashing: Blake2b/s, Blake3
Usage Examples
Basic Hashing
from metamui_crypto import SHA256, Blake3
# SHA-256
data = b"Hello, World!"
hash_sha = SHA256.hash(data)
print(f"SHA-256: {hash_sha.hex()}")
# Blake3
hash_blake = Blake3.hash(data)
print(f"Blake3: {hash_blake.hex()}")
Streaming/Incremental Hashing
from metamui_crypto import SHA256
# Create hasher
hasher = SHA256.new()
# Update with chunks
with open('large_file.bin', 'rb') as f:
while chunk := f.read(8192):
hasher.update(chunk)
# Get final hash
file_hash = hasher.finalize()
Keyed Hashing (MAC)
from metamui_crypto import Blake2b
import os
# Generate random key
key = os.urandom(32)
# Keyed hash (MAC)
mac = Blake2b.new(key=key)
mac.update(b"Authenticated message")
auth_tag = mac.finalize()
# Verify MAC
mac_verify = Blake2b.new(key=key)
mac_verify.update(b"Authenticated message")
if mac_verify.finalize() == auth_tag:
print("Message authentic")
Variable Output Length
from metamui_crypto import Blake3, SHAKE256
# Blake3 with custom output length
data = b"Input data"
hash_128bit = Blake3.hash(data, length=16) # 128 bits
hash_256bit = Blake3.hash(data, length=32) # 256 bits
hash_512bit = Blake3.hash(data, length=64) # 512 bits
# SHAKE-256 XOF
xof = SHAKE256.new()
xof.update(data)
output_128bit = xof.read(16) # Read 128 bits
output_256bit = xof.read(32) # Read another 256 bits
Parallel Hashing (Blake3)
from metamui_crypto import Blake3
import concurrent.futures
# Hash multiple files in parallel
def hash_file(filename):
hasher = Blake3.new()
with open(filename, 'rb') as f:
hasher.update(f.read())
return filename, hasher.finalize()
files = ['file1.bin', 'file2.bin', 'file3.bin']
with concurrent.futures.ThreadPoolExecutor() as executor:
results = list(executor.map(hash_file, files))
Hash-based Key Derivation
from metamui_crypto import SHA256, Blake2b
# Simple KDF using hash
password = b"user_password"
salt = os.urandom(16)
# SHA-256 based
key_sha = SHA256.hash(salt + password)
# Blake2b with personalization
key_blake = Blake2b.hash(
password,
salt=salt,
person=b"MyApp v1.0",
length=32
)
Security Properties
Collision Resistance
| Algorithm | Collision Resistance | Preimage Resistance | |———–|———————|——————-| | SHA-256 | 128 bits | 256 bits | | SHA-512 | 256 bits | 512 bits | | Blake2b-512 | 256 bits | 512 bits | | Blake2s-256 | 128 bits | 256 bits | | Blake3 | 128 bits minimum | 256 bits | | SHAKE-256 | min(d/2, 256) bits | d bits |
Quantum Resistance
- Classical: Full security levels
- Post-Quantum: Security reduced by ~50%
- Grover’s algorithm impact: √n operations
Performance Benchmarks
| Algorithm | Speed (MB/s) | Hardware Accelerated |
|---|---|---|
| Blake3 | 3,000 | No (but parallel) |
| Blake2b | 1,000 | No |
| Blake2s | 800 | No |
| SHA-256 | 500* | Yes |
| SHA-512 | 800* | Yes |
| SHAKE-256 | 600 | No |
*With hardware acceleration
Common Use Cases
1. File Integrity
from metamui_crypto import Blake3
import json
def create_manifest(directory):
manifest = {}
for file in directory.iterdir():
if file.is_file():
hash = Blake3.hash_file(file)
manifest[file.name] = hash.hex()
with open('manifest.json', 'w') as f:
json.dump(manifest, f)
2. Password Hashing
# Note: Use Argon2 for passwords, not raw hashes!
from metamui_crypto import Argon2
# Good: Purpose-built password hashing
password = b"user_password"
salt = os.urandom(16)
hash = Argon2.hash(password, salt)
# Bad: Don't use raw hashes for passwords
# hash = SHA256.hash(password) # Vulnerable to attacks!
3. Digital Signatures
from metamui_crypto import Ed25519, SHA256
# Hash then sign pattern
document = b"Large document content..."
doc_hash = SHA256.hash(document)
# Sign the hash
keypair = Ed25519.generate_keypair()
signature = Ed25519.sign(doc_hash, keypair.private_key)
4. Proof of Work
from metamui_crypto import SHA256
import struct
def proof_of_work(data, difficulty):
nonce = 0
target = '0' * difficulty
while True:
candidate = data + struct.pack('<Q', nonce)
hash = SHA256.hash(candidate)
if hash.hex().startswith(target):
return nonce, hash
nonce += 1
Best Practices
1. Don’t Use for Passwords
# Bad: Raw hash for passwords
# password_hash = SHA256.hash(password)
# Good: Use key derivation function
from metamui_crypto import Argon2
password_hash = Argon2.hash(
password,
salt=salt,
time_cost=3,
memory_cost=65536
)
2. Include Domain Separation
# Prevent cross-protocol attacks
def hash_for_purpose(data, purpose):
hasher = Blake3.new()
hasher.update(purpose.encode())
hasher.update(b'\x00') # Separator
hasher.update(data)
return hasher.finalize()
# Different hashes for different purposes
signing_hash = hash_for_purpose(data, "signing")
storage_hash = hash_for_purpose(data, "storage")
3. Verify Hash Implementations
# Test with known vectors
test_vectors = {
"": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"abc": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
}
for input, expected in test_vectors.items():
result = SHA256.hash(input.encode()).hex()
assert result == expected
Migration Guide
From MD5/SHA-1
# Old: Broken algorithms
# import hashlib
# hash = hashlib.md5(data).hexdigest()
# hash = hashlib.sha1(data).hexdigest()
# New: Secure algorithms
from metamui_crypto import SHA256, Blake3
hash = SHA256.hash(data).hex()
# or
hash = Blake3.hash(data).hex()
Upgrading Hash Lengths
# Transitioning from SHA-256 to SHA-512
def dual_hash(data):
# During transition, compute both
hash_256 = SHA256.hash(data)
hash_512 = SHA512.hash(data)
# Store both, verify old, use new
return {
'sha256': hash_256.hex(),
'sha512': hash_512.hex()
}