Message Authentication

šŸ” SipHash Short-input PRF

Security Level 64-bit PRF
Performance ⭐⭐⭐⭐⭐ Excellent
Key Size 128 bits (16 bytes)
Output Size 64 bits (8 bytes)
Block Size 64 bits (8 bytes)
Primary Use Hash Tables & DoS Protection

šŸ“– Overview

SipHash is a family of cryptographic pseudorandom functions (PRFs) designed by Jean-Philippe Aumasson and Daniel J. Bernstein. It's optimized for short inputs and provides strong security guarantees while maintaining exceptional performance. SipHash is primarily used to protect hash tables against hash-flooding denial-of-service attacks.

✨ Key Features

⚔

High Performance

Extremely fast on short inputs (< 1KB)

šŸ›”ļø

DoS Protection

Designed to prevent hash-flooding attacks

šŸ”’

Cryptographically Secure

Provides strong PRF security guarantees

šŸ“

Simple Design

Easy to implement correctly and efficiently

ā±ļø

Constant Time

Resistant to timing attacks when properly implemented

šŸŒ

Widely Adopted

Used in Rust, Python, Ruby, and many other systems

šŸŽÆ Common Use Cases

šŸ›”ļø Security Applications

  • Hash table protection against DoS attacks
  • Short message authentication (< 1KB)
  • Network protocol header authentication
  • Secure cache key generation

šŸ’¾ Data Structures

  • Database indexing with DoS protection
  • Consistent hashing for load balancing
  • Bloom filters with security guarantees
  • Secure hash maps and dictionaries

šŸ”§ Algorithm Details

šŸ“Š SipHash Variants

SipHash-2-4
Standard
2 compression, 4 finalization rounds
SipHash-1-3
Fast
1 compression, 3 finalization rounds
SipHash-4-8
Conservative
4 compression, 8 finalization rounds

šŸ” Security Properties

šŸ”

PRF Security

Indistinguishable from random function

šŸ’„

Collision Resistance

2^32 expected collisions for 8-byte output

šŸ”‘

Key Recovery

Computationally infeasible without side-channels

šŸ›”ļø

DoS Resistance

Prevents algorithmic complexity attacks

🧮 Algorithm Structure

SipHash processes input in 8-byte blocks using ARX operations:

SipHash(k, m) = SipRound^d(vā‚€, v₁, vā‚‚, vā‚ƒ)

The internal state is initialized with the key and updated through compression and finalization rounds.

šŸ’» Implementation

SipHash is designed for ease of implementation while maintaining security. The following examples demonstrate various use cases.

Basic Usage

Basic SipHash Authentication Python
```python from metamui_crypto import SipHash import os # Generate a random 16-byte key key = os.urandom(16) # Create SipHash instance (default: SipHash-2-4) siphash = SipHash(key) # Hash short messages message1 = b"Hello, world!" message2 = b"Short message authentication" hash1 = siphash.hash(message1) hash2 = siphash.hash(message2) print(f"Message 1: {message1}") print(f"Hash 1: {hash1.hex()}") print(f"Message 2: {message2}") print(f"Hash 2: {hash2.hex()}") # Verify deterministic behavior hash1_verify = siphash.hash(message1) assert hash1 == hash1_verify, "Hash should be deterministic" print("Deterministic verification passed!") ```

Hash Table Protection

Secure Hash Table Implementation Python
```python from metamui_crypto import SipHash import os class SecureHashTable: """ Hash table protected against hash-flooding attacks using SipHash. """ def __init__(self, initial_capacity: int = 16): # Generate random key for this hash table instance self._siphash_key = os.urandom(16) self._siphash = SipHash(self._siphash_key) self._capacity = initial_capacity self._size = 0 self._buckets = [[] for _ in range(self._capacity)] self._load_factor_threshold = 0.75 def _hash(self, key: bytes) -> int: """ Compute secure hash of key using SipHash. """ hash_value = self._siphash.hash(key) # Convert 8-byte hash to integer and mod by capacity hash_int = int.from_bytes(hash_value, byteorder='little') return hash_int % self._capacity def put(self, key: bytes, value: any): """ Insert key-value pair into hash table. """ if self._size >= self._capacity * self._load_factor_threshold: self._resize() hash_index = self._hash(key) bucket = self._buckets[hash_index] # Check if key already exists for i, (existing_key, _) in enumerate(bucket): if existing_key == key: bucket[i] = (key, value) # Update existing return # Add new key-value pair bucket.append((key, value)) self._size += 1 ```

Network Protocol Authentication

Authenticated UDP Protocol Python
```python from metamui_crypto import SipHash import struct class AuthenticatedUDPProtocol: """ UDP protocol with SipHash authentication for packet headers. """ def __init__(self, shared_key: bytes): self._siphash = SipHash(shared_key) self._sequence_number = 0 def create_packet(self, payload: bytes, packet_type: int = 1) -> bytes: """ Create authenticated packet with SipHash protection. Packet format: - 4 bytes: packet type - 8 bytes: sequence number - 4 bytes: payload length - 8 bytes: SipHash authentication tag - N bytes: payload """ self._sequence_number += 1 # Create header header = struct.pack( '<IQI', # little-endian: uint32, uint64, uint32 packet_type, self._sequence_number, len(payload) ) # Compute authentication tag over header + payload auth_data = header + payload auth_tag = self._siphash.hash(auth_data) # Assemble final packet packet = header + auth_tag + payload return packet def parse_packet(self, packet: bytes) -> tuple[int, int, bytes]: """ Parse and verify authenticated packet. """ if len(packet) < 24: # Minimum packet size raise ValueError("Packet too short") # Parse header packet_type, sequence_number, payload_length = struct.unpack('<IQI', packet[:16]) # Extract authentication tag and payload auth_tag = packet[16:24] payload = packet[24:] # Verify authentication tag header = packet[:16] auth_data = header + payload expected_tag = self._siphash.hash(auth_data) if auth_tag != expected_tag: raise ValueError("Authentication verification failed") return packet_type, sequence_number, payload ```

šŸ”’ Security Considerations

āš ļø Important Security Notes

  • Always use random keys from a CSPRNG
  • Never reuse keys across different contexts
  • Implement constant-time comparison for authentication tags
  • Rotate keys periodically in long-running applications
  • SipHash is NOT suitable for password hashing

Secure Key Management

Key Rotation Example Python
```python from metamui_crypto import SipHash import os import time import threading class SecureSipHashManager: """ Secure management of SipHash keys with rotation. """ def __init__(self, key_rotation_interval: int = 3600): # 1 hour self._current_key = os.urandom(16) self._previous_key = None self._key_rotation_interval = key_rotation_interval self._last_rotation = time.time() self._lock = threading.Lock() # Create SipHash instances self._current_siphash = SipHash(self._current_key) self._previous_siphash = None def _rotate_key(self): """ Perform key rotation. """ # Save current key as previous self._previous_key = self._current_key self._previous_siphash = self._current_siphash # Generate new current key self._current_key = os.urandom(16) self._current_siphash = SipHash(self._current_key) self._last_rotation = time.time() def hash(self, data: bytes) -> bytes: """ Compute hash with current key. """ with self._lock: return self._current_siphash.hash(data) def verify_hash(self, data: bytes, expected_hash: bytes) -> bool: """ Verify hash against current or previous key. """ with self._lock: # Try current key first current_hash = self._current_siphash.hash(data) if current_hash == expected_hash: return True # Try previous key if available if self._previous_siphash is not None: previous_hash = self._previous_siphash.hash(data) if previous_hash == expected_hash: return True return False ```

⚔ Performance Analysis

Speed Benchmarks

Input Size SipHash-2-4 SipHash-1-3 Throughput
8 bytes 3.2 cycles/byte 2.1 cycles/byte 7.5 GB/s
64 bytes 1.8 cycles/byte 1.2 cycles/byte 13.3 GB/s
256 bytes 1.5 cycles/byte 1.0 cycles/byte 16.0 GB/s
1024 bytes 1.4 cycles/byte 0.9 cycles/byte 17.1 GB/s

Performance Optimization

Benchmark Different Variants Python
```python from metamui_crypto import SipHash import time import os def benchmark_siphash_variants(): """ Benchmark different SipHash variants. """ key = os.urandom(16) # Test different variants variants = [ ("SipHash-1-3", SipHash(key, c=1, d=3)), ("SipHash-2-4", SipHash(key, c=2, d=4)), ("SipHash-4-8", SipHash(key, c=4, d=8)), ] # Test different input sizes input_sizes = [8, 32, 64, 256, 1024] print("SipHash Performance Benchmark") print("=" * 50) for variant_name, siphash in variants: print(f"\n{variant_name}:") print("-" * 30) for size in input_sizes: test_data = b'A' * size # Benchmark iterations = 10000 start_time = time.perf_counter() for _ in range(iterations): result = siphash.hash(test_data) end_time = time.perf_counter() total_time = end_time - start_time throughput = (size * iterations) / total_time / (1024 * 1024) # MB/s print(f" {size:4d} bytes: {throughput:8.1f} MB/s") ```

šŸŽÆ Use Cases and Examples

Secure Cache Implementation

Thread-safe cache with SipHash-protected keys to prevent cache poisoning attacks.

Consistent Hashing

Load balancing with consistent hashing protected against malicious key distribution.

DoS Attack Protection

Demonstration of how SipHash prevents hash-flooding attacks in hash tables.

āš–ļø Comparison with Other Hash Functions

SipHash vs HMAC

Aspect SipHash HMAC-SHA256
Speed (short inputs) ~7.5 GB/s ~1.2 GB/s
Output Size 8 bytes 32 bytes
Key Size 16 bytes Any length
Primary Use Hash tables, short MACs General MAC
DoS Protection Excellent Good

SipHash vs Non-Cryptographic Hashes

Aspect SipHash CityHash MurmurHash
Cryptographic Security Yes No No
DoS Resistance Yes No No
Speed Fast Faster Faster
Key Required Yes No Optional

šŸ“š References