SHA-512 Security-Focused API Documentation

Version: 1.0
Last Updated: 2025-07-05
**Security Classification:
PUBLIC
Author: Phantom (phantom@metamui.id)

Overview

SHA-512 is a cryptographic hash function that produces a 512-bit (64-byte) hash value. Part of the SHA-2 family, it offers higher security margins than SHA-256 and is often preferred for applications requiring long-term security or higher collision resistance. SHA-512 is particularly efficient on 64-bit platforms.

Security Level: 256-bit collision resistance
Output Size: 64 bytes (512 bits)
Block Size: 128 bytes (1024 bits)

Security Warnings ⚠️

  1. Not for Passwords: NEVER use SHA-512 directly for passwords - use Argon2
  2. Not a MAC: SHA-512 alone doesn’t authenticate - use HMAC-SHA512
  3. Length Extension: Vulnerable like SHA-256 - use SHA-512/256 to prevent
  4. Truncation Weakens: Don’t truncate output without careful analysis
  5. Quantum Security: Grover’s algorithm reduces to 256-bit security

API Functions

hash(data: bytes) -> bytes[64]

Security Contract:

Attack Resistance: | Attack Type | Protected | Notes | |————-|———–|——-| | Collision | ✅ | 2^256 operations required | | Preimage | ✅ | 2^512 operations required | | Second Preimage | ✅ | 2^512 operations required | | Length Extension | ❌ | Vulnerable - use HMAC or SHA-512/256 | | Timing Attack | ✅ | Constant time for same length |

Security Requirements:

Secure Usage Example:

import hashlib
import hmac
from typing import List, Tuple
import json

class SecureHashingService:
    """Secure SHA-512 usage patterns"""
    
    @staticmethod
    def hash_file_content(filepath: str, chunk_size: int = 8192) -> str:
        """Hash large file efficiently"""
        
        sha512 = hashlib.sha512()
        
        with open(filepath, 'rb') as f:
            while chunk := f.read(chunk_size):
                sha512.update(chunk)
        
        return sha512.hexdigest()
    
    @staticmethod
    def create_merkle_root(leaves: List[bytes]) -> bytes:
        """Build Merkle tree with SHA-512"""
        
        if not leaves:
            return hashlib.sha512(b"empty-tree").digest()
        
        # Hash all leaves
        current_level = [hashlib.sha512(leaf).digest() for leaf in leaves]
        
        while len(current_level) > 1:
            next_level = []
            
            for i in range(0, len(current_level), 2):
                if i + 1 < len(current_level):
                    # Hash pair with separator
                    combined = b"\x00" + current_level[i] + b"\x01" + current_level[i + 1]
                else:
                    # Odd node - promote
                    combined = b"\x02" + current_level[i]
                
                next_level.append(hashlib.sha512(combined).digest())
            
            current_level = next_level
        
        return current_level[0]
    
    @staticmethod
    def hash_structured_data(data: dict) -> bytes:
        """Hash structured data canonically"""
        
        # Canonical JSON encoding
        canonical = json.dumps(data, sort_keys=True, separators=(',', ':'))
        
        # Include type identifier
        typed_data = b"JSON:" + canonical.encode('utf-8')
        
        return hashlib.sha512(typed_data).digest()
    
    @staticmethod
    def create_commitment(value: bytes, nonce: bytes) -> Tuple[bytes, bytes]:
        """Create hash-based commitment"""
        
        # Commitment = H(nonce || value)
        commitment = hashlib.sha512(nonce + value).digest()
        
        return commitment, nonce
    
    @staticmethod
    def verify_commitment(value: bytes, nonce: bytes, commitment: bytes) -> bool:
        """Verify hash commitment"""
        
        expected = hashlib.sha512(nonce + value).digest()
        return hmac.compare_digest(expected, commitment)

# SECURE: Content addressing with verification
class ContentAddressableStorage:
    def __init__(self):
        self.storage = {}
        
    def store(self, content: bytes, metadata: dict = None) -> str:
        """Store content with SHA-512 address"""
        
        # Hash content
        content_hash = hashlib.sha512(content).digest()
        
        # Include metadata in verification
        if metadata:
            meta_bytes = json.dumps(metadata, sort_keys=True).encode()
            meta_hash = hashlib.sha512(meta_bytes).digest()
            
            # Combined verification hash
            combined = hashlib.sha512(
                b"CONTENT:" + content_hash + 
                b"META:" + meta_hash
            ).digest()
            
            address = combined.hex()
        else:
            address = content_hash.hex()
        
        # Store with integrity data
        self.storage[address] = {
            'content': content,
            'content_hash': content_hash,
            'metadata': metadata,
            'stored_at': time.time()
        }
        
        return address
    
    def retrieve(self, address: str) -> Tuple[bytes, dict]:
        """Retrieve and verify content"""
        
        if address not in self.storage:
            raise KeyError("Content not found")
        
        stored = self.storage[address]
        
        # Verify content integrity
        actual_hash = hashlib.sha512(stored['content']).digest()
        if not hmac.compare_digest(actual_hash, stored['content_hash']):
            raise IntegrityError("Content corrupted")
        
        return stored['content'], stored['metadata']

# SECURE: Using SHA-512/256 to prevent length extension
def sha512_256(data: bytes) -> bytes:
    """SHA-512/256 - truncated SHA-512 for length extension resistance"""
    
    # Full SHA-512 hash
    full_hash = hashlib.sha512(data).digest()
    
    # Return first 256 bits (32 bytes)
    # This prevents length extension attacks
    return full_hash[:32]

def create_secure_mac(key: bytes, message: bytes) -> bytes:
    """Create MAC using HMAC-SHA512"""
    
    # HMAC prevents length extension attacks
    return hmac.new(key, message, hashlib.sha512).digest()

Common Mistakes:

# INSECURE: Password hashing
password_hash = hashlib.sha512(password.encode()).hexdigest()  # NO!

# INSECURE: Simple MAC construction
def bad_mac(key: bytes, message: bytes) -> bytes:
    return hashlib.sha512(key + message).digest()  # Length extension!

# INSECURE: Using as encryption
def bad_encrypt(data: bytes, key: bytes) -> bytes:
    return hashlib.sha512(key + data).digest()  # Not encryption!

# INSECURE: Truncating without analysis
short_hash = hashlib.sha512(data).digest()[:8]  # Only 64 bits!

create() -> SHA512Context

Security Contract:

Security Notes:

Secure Usage Example:

use sha2::{Sha512, Digest};
use std::io::{self, Read};

/// Secure streaming hash implementation
pub struct StreamingHasher {
    hasher: Sha512,
    bytes_processed: u64,
}

impl StreamingHasher {
    pub fn new() -> Self {
        Self {
            hasher: Sha512::new(),
            bytes_processed: 0,
        }
    }
    
    pub fn update(&mut self, data: &[u8]) -> Result<(), Error> {
        // Check for overflow (2^128 bit limit)
        let new_total = self.bytes_processed
            .saturating_add(data.len() as u64);
        
        if new_total > (1u128 << 125) as u64 {
            return Err(Error::InputTooLarge);
        }
        
        self.hasher.update(data);
        self.bytes_processed = new_total;
        
        Ok(())
    }
    
    pub fn finalize(self) -> [u8; 64] {
        self.hasher.finalize().into()
    }
    
    pub fn finalize_reset(&mut self) -> [u8; 64] {
        let result = self.hasher.clone().finalize();
        self.hasher.reset();
        self.bytes_processed = 0;
        result.into()
    }
}

/// Hash with progress callback
pub fn hash_with_progress<R: Read, F: Fn(u64)>(
    mut input: R,
    mut progress_callback: F,
) -> io::Result<[u8; 64]> {
    let mut hasher = Sha512::new();
    let mut buffer = [0u8; 16384];  // 16KB buffer
    let mut total_bytes = 0u64;
    
    loop {
        let count = input.read(&mut buffer)?;
        if count == 0 {
            break;
        }
        
        hasher.update(&buffer[..count]);
        total_bytes += count as u64;
        
        // Report progress
        progress_callback(total_bytes);
    }
    
    Ok(hasher.finalize().into())
}

/// Parallel hashing for multiple inputs
pub fn hash_parallel(inputs: &[&[u8]]) -> Vec<[u8; 64]> {
    use rayon::prelude::*;
    
    inputs.par_iter()
        .map(|input| {
            let mut hasher = Sha512::new();
            hasher.update(input);
            hasher.finalize().into()
        })
        .collect()
}

update(data: bytes) -> void

Security Contract:

Security Requirements:

Secure Usage Example:

import { createHash } from 'crypto';

class SecureDocumentHasher {
    private hasher = createHash('sha512');
    private sections: string[] = [];
    
    addSection(name: string, content: Buffer): void {
        // Include section boundaries to prevent collision
        this.hasher.update(`[SECTION:${name}:${content.length}]`);
        this.hasher.update(content);
        this.hasher.update('[/SECTION]');
        
        this.sections.push(name);
    }
    
    addMetadata(metadata: Record<string, any>): void {
        // Canonical encoding for metadata
        const canonical = JSON.stringify(metadata, Object.keys(metadata).sort());
        
        this.hasher.update('[METADATA]');
        this.hasher.update(canonical);
        this.hasher.update('[/METADATA]');
    }
    
    finalize(): { hash: string; manifest: any } {
        const hash = this.hasher.digest('hex');
        
        return {
            hash,
            manifest: {
                algorithm: 'SHA-512',
                sections: this.sections,
                timestamp: new Date().toISOString()
            }
        };
    }
}

// Secure multi-source hashing
class MultiSourceHasher {
    private hasher = createHash('sha512');
    private sourceCount = 0;
    
    addSource(sourceId: string, data: Buffer): void {
        // Unambiguous encoding
        const header = Buffer.alloc(4 + 32 + 8);
        header.writeUInt32BE(this.sourceCount, 0);
        header.write(sourceId.padEnd(32, '\0'), 4);
        header.writeBigUInt64BE(BigInt(data.length), 36);
        
        this.hasher.update(header);
        this.hasher.update(data);
        
        this.sourceCount++;
    }
    
    getHash(): Buffer {
        // Include source count in final hash
        const countBuffer = Buffer.alloc(4);
        countBuffer.writeUInt32BE(this.sourceCount, 0);
        this.hasher.update(countBuffer);
        
        return this.hasher.digest();
    }
}

finalize() -> bytes[64]

Security Contract:

Security Notes:

Security Best Practices

Digital Signatures with SHA-512

class Ed25519WithSHA512:
    """Ed25519 signatures with explicit SHA-512 usage"""
    
    @staticmethod
    def sign_large_message(private_key: bytes, message: bytes) -> bytes:
        """Sign message with pre-hashing for large messages"""
        
        # For messages > 1MB, pre-hash with SHA-512
        if len(message) > 1024 * 1024:
            # Create pre-hash
            message_hash = hashlib.sha512(message).digest()
            
            # Sign the hash with domain separation
            to_sign = b"SHA512-PREHASH:" + message_hash
            
            signature = ed25519_sign(private_key, to_sign)
            
            return signature
        else:
            # Sign directly for small messages
            return ed25519_sign(private_key, message)
    
    @staticmethod
    def verify_large_message(
        public_key: bytes, 
        message: bytes, 
        signature: bytes
    ) -> bool:
        """Verify signature with pre-hashing"""
        
        if len(message) > 1024 * 1024:
            message_hash = hashlib.sha512(message).digest()
            to_verify = b"SHA512-PREHASH:" + message_hash
            
            return ed25519_verify(public_key, to_verify, signature)
        else:
            return ed25519_verify(public_key, message, signature)

HMAC-SHA512 Patterns

use hmac::{Hmac, Mac};
use sha2::Sha512;

type HmacSha512 = Hmac<Sha512>;

/// Secure API authentication with HMAC-SHA512
pub struct ApiAuthenticator {
    signing_key: Vec<u8>,
}

impl ApiAuthenticator {
    pub fn new(master_key: &[u8]) -> Self {
        // Derive signing key
        let mut mac = HmacSha512::new_from_slice(master_key)
            .expect("HMAC can take key of any size");
        mac.update(b"API-Signing-Key-v1");
        let signing_key = mac.finalize().into_bytes().to_vec();
        
        Self { signing_key }
    }
    
    pub fn create_request_signature(
        &self,
        method: &str,
        path: &str,
        body: &[u8],
        timestamp: u64,
    ) -> String {
        // Create canonical request
        let canonical = format!(
            "{}\n{}\n{}\n{}",
            method,
            path,
            hex::encode(Sha512::digest(body)),
            timestamp
        );
        
        // Sign with HMAC-SHA512
        let mut mac = HmacSha512::new_from_slice(&self.signing_key)
            .expect("HMAC can take key of any size");
        mac.update(canonical.as_bytes());
        
        base64::encode(mac.finalize().into_bytes())
    }
    
    pub fn verify_request_signature(
        &self,
        method: &str,
        path: &str,
        body: &[u8],
        timestamp: u64,
        signature: &str,
    ) -> Result<(), Error> {
        // Check timestamp freshness (5 minute window)
        let current_time = SystemTime::now()
            .duration_since(UNIX_EPOCH)?
            .as_secs();
        
        if (current_time as i64 - timestamp as i64).abs() > 300 {
            return Err(Error::RequestExpired);
        }
        
        // Recreate signature
        let expected = self.create_request_signature(
            method, path, body, timestamp
        );
        
        // Constant-time comparison
        if !constant_time_eq(expected.as_bytes(), signature.as_bytes()) {
            return Err(Error::InvalidSignature);
        }
        
        Ok(())
    }
}

Key Derivation with SHA-512

def derive_keys_sha512(master_secret: bytes, context: str) -> dict:
    """Derive multiple keys using SHA-512 based KDF"""
    
    # Use HKDF with SHA-512 for higher security
    from cryptography.hazmat.primitives import hashes
    from cryptography.hazmat.primitives.kdf.hkdf import HKDF
    
    hkdf = HKDF(
        algorithm=hashes.SHA512(),
        length=128,  # 4 × 32-byte keys
        salt=b"KeyDerivation-SHA512-v1",
        info=context.encode()
    )
    
    key_material = hkdf.derive(master_secret)
    
    return {
        'encryption_key': key_material[0:32],
        'signing_key': key_material[32:64],
        'storage_key': key_material[64:96],
        'backup_key': key_material[96:128]
    }

class SHA512XOF:
    """Extended output using SHA-512 (like SHAKE)"""
    
    def __init__(self, seed: bytes):
        self.seed = seed
        
    def extract(self, length: int, context: bytes = b"") -> bytes:
        """Extract arbitrary length output"""
        
        output = b""
        counter = 0
        
        while len(output) < length:
            # Hash seed || context || counter
            h = hashlib.sha512()
            h.update(self.seed)
            h.update(context)
            h.update(counter.to_bytes(8, 'big'))
            
            output += h.digest()
            counter += 1
        
        return output[:length]

Common Integration Patterns

Blockchain Proof-of-Work

def mine_block_sha512(block_data: dict, difficulty: int) -> dict:
    """Mine block using SHA-512 (educational example)"""
    
    block_bytes = json.dumps(block_data, sort_keys=True).encode()
    target = 2 ** (512 - difficulty)
    nonce = 0
    
    while True:
        candidate = block_bytes + nonce.to_bytes(8, 'big')
        
        # Double SHA-512 (like Bitcoin but with SHA-512)
        hash1 = hashlib.sha512(candidate).digest()
        hash2 = hashlib.sha512(hash1).digest()
        
        if int.from_bytes(hash2, 'big') < target:
            return {
                **block_data,
                'nonce': nonce,
                'hash': hash2.hex()
            }
        
        nonce += 1

Password-Based Key Derivation

/// PBKDF2-HMAC-SHA512 for cases where Argon2 isn't available
pub fn pbkdf2_sha512(
    password: &[u8],
    salt: &[u8],
    iterations: u32,
    key_length: usize,
) -> Vec<u8> {
    use pbkdf2::pbkdf2_hmac;
    
    let mut key = vec![0u8; key_length];
    pbkdf2_hmac::<Sha512>(
        password,
        salt,
        iterations,
        &mut key
    );
    
    key
}

/// Secure password verification with SHA-512
pub struct PasswordVerifier {
    iterations: u32,
}

impl PasswordVerifier {
    pub fn new(iterations: u32) -> Self {
        // NIST recommends minimum 10,000 iterations
        assert!(iterations >= 10_000);
        Self { iterations }
    }
    
    pub fn hash_password(&self, password: &str) -> String {
        let salt = generate_random_bytes(32);
        
        let key = pbkdf2_sha512(
            password.as_bytes(),
            &salt,
            self.iterations,
            64  // Full SHA-512 output
        );
        
        // Encode as storable string
        format!(
            "$pbkdf2-sha512${}${}${}",
            self.iterations,
            base64::encode(&salt),
            base64::encode(&key)
        )
    }
}

Performance Considerations

Operation SHA-256 SHA-512 Notes
Small message (<64B) ~500 ns ~600 ns SHA-256 slightly faster
1 KB message ~2 μs ~1.5 μs SHA-512 faster on 64-bit
1 MB message ~2 ms ~1.5 ms SHA-512 more efficient
64-bit platform Baseline 1.3x faster SHA-512 optimized for 64-bit
32-bit platform Baseline 0.7x speed SHA-256 better on 32-bit

When to Use SHA-512

When to Use SHA-256

Security Auditing

Verification Checklist

Code Review Patterns

# ✅ GOOD: HMAC for authentication
auth_tag = hmac.new(key, message, hashlib.sha512).digest()

# ❌ BAD: Direct concatenation
auth_tag = hashlib.sha512(key + message).digest()

# ✅ GOOD: KDF for key derivation
derived_key = hkdf(master_key, salt, info, hashlib.sha512)

# ❌ BAD: Direct hashing for keys
derived_key = hashlib.sha512(master_key + purpose).digest()

# ✅ GOOD: Proper password hashing
password_hash = argon2.hash(password)

# ❌ BAD: SHA-512 for passwords
password_hash = hashlib.sha512(password + salt).digest()

Security Analysis

Threat Model: SHA-512 Threat Model

The comprehensive threat analysis covers:

For complete security analysis and risk assessment, see the dedicated threat model documentation.

References

  1. FIPS 180-4 - SHA-512 Specification
  2. SHA-512/256 Specification
  3. HMAC RFC 2104

Support

Security Issues: security@metamui.id
Documentation Updates: phantom@metamui.id
Vulnerability Disclosure: See SECURITY.md


Document Version: 1.0
Review Cycle: Quarterly
Next Review: 2025-04-05
Classification: PUBLIC