SHA-256 Security-Focused API Documentation

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

Overview

SHA-256 is a cryptographic hash function that produces a 256-bit (32-byte) hash value. Part of the SHA-2 family designed by the NSA, it’s widely used for data integrity, digital signatures, and proof-of-work systems. This documentation provides security-focused guidance for using SHA-256 in the MetaMUI cryptographic library.

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

Security Warnings ⚠️

  1. Not for Passwords: NEVER use SHA-256 directly for password hashing - use Argon2
  2. Not a MAC: SHA-256 alone doesn’t provide authentication - use HMAC-SHA256
  3. Length Extension: Vulnerable to length extension attacks in certain constructions
  4. Not Encryption: Hash functions are one-way, they cannot encrypt data
  5. Quantum Vulnerable: Grover’s algorithm reduces security to 128 bits

API Functions

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

Security Contract:

Attack Resistance: | Attack Type | Protected | Notes | |————-|———–|——-| | Collision | ✅ | 2^128 operations required | | Preimage | ✅ | 2^256 operations required | | Second Preimage | ✅ | 2^256 operations required | | Length Extension | ❌ | Vulnerable in naive constructions | | Timing Attack | ✅ | Constant time for same length |

Security Requirements:

Secure Usage Example:

# SECURE: File integrity verification
def verify_file_integrity(filepath: str, expected_hash: str) -> bool:
    sha256 = SHA256()
    with open(filepath, 'rb') as f:
        # Process in chunks to handle large files
        while chunk := f.read(8192):
            sha256.update(chunk)
    
    computed_hash = sha256.finalize()
    # Constant-time comparison
    return hmac.compare_digest(
        computed_hash.hex(),
        expected_hash.lower()
    )

# SECURE: Content addressing
def content_address(data: bytes) -> str:
    """Generate content-based identifier"""
    return f"sha256:{sha256(data).hex()}"

Common Mistakes:

# INSECURE: Password hashing
def store_password(password: str):
    # NEVER DO THIS - easily cracked!
    password_hash = sha256(password.encode())
    database.save(password_hash)

# INSECURE: Simple MAC construction  
def create_mac(key: bytes, message: bytes) -> bytes:
    # Vulnerable to length extension!
    return sha256(key + message)

# INSECURE: Using as encryption
def "encrypt"(data: bytes, key: bytes) -> bytes:
    # This is NOT encryption!
    return sha256(key + data)

create() -> SHA256Context

Security Contract:

Security Notes:

Secure Usage Example:

// SECURE: Streaming large file
fn hash_large_file(path: &Path) -> Result<[u8; 32], Error> {
    let mut file = File::open(path)?;
    let mut hasher = Sha256::create();
    let mut buffer = [0u8; 16384];
    
    loop {
        let count = file.read(&mut buffer)?;
        if count == 0 {
            break;
        }
        hasher.update(&buffer[..count]);
    }
    
    Ok(hasher.finalize())
}

// SECURE: Multiple data sources
fn hash_request(headers: &[Header], body: &[u8]) -> [u8; 32] {
    let mut hasher = Sha256::create();
    
    // Hash headers
    for header in headers {
        hasher.update(header.name.as_bytes());
        hasher.update(b": ");
        hasher.update(header.value.as_bytes());
        hasher.update(b"\r\n");
    }
    hasher.update(b"\r\n");
    
    // Hash body
    hasher.update(body);
    
    hasher.finalize()
}

update(data: bytes) -> void

Security Contract:

Security Requirements:

Secure Usage Example:

// SECURE: Hashing structured data
class SecureDataHasher {
    private hasher: SHA256Context;
    
    constructor() {
        this.hasher = sha256.create();
    }
    
    addField(name: string, value: string): void {
        // Include field boundaries to prevent ambiguity
        const encoded = `${name.length}:${name}${value.length}:${value}`;
        this.hasher.update(Buffer.from(encoded, 'utf-8'));
    }
    
    finalize(): Buffer {
        return this.hasher.finalize();
    }
}

// Prevents collision between different structures
const h1 = new SecureDataHasher();
h1.addField("name", "value");
h1.addField("", "namevalue");

const h2 = new SecureDataHasher();  
h2.addField("", "namevalue");
h2.addField("name", "value");

// h1.finalize() !== h2.finalize()

finalize() -> bytes[32]

Security Contract:

Security Notes:

Security Best Practices

Data Integrity

class SecureFileManager:
    def __init__(self):
        self.hash_algorithm = "sha256"
    
    def store_file(self, data: bytes, metadata: dict) -> str:
        # Calculate hash for integrity
        file_hash = sha256(data)
        
        # Include metadata in integrity check
        meta_bytes = json.dumps(metadata, sort_keys=True).encode()
        combined_hash = sha256(file_hash + sha256(meta_bytes))
        
        # Store with hash
        file_id = combined_hash.hex()
        self.storage.put(file_id, {
            'data': data,
            'metadata': metadata,
            'hash': file_hash.hex(),
            'meta_hash': sha256(meta_bytes).hex()
        })
        
        return file_id
    
    def retrieve_file(self, file_id: str) -> tuple[bytes, dict]:
        stored = self.storage.get(file_id)
        
        # Verify data integrity
        if sha256(stored['data']).hex() != stored['hash']:
            raise IntegrityError("File data corrupted")
        
        # Verify metadata integrity  
        meta_bytes = json.dumps(stored['metadata'], sort_keys=True).encode()
        if sha256(meta_bytes).hex() != stored['meta_hash']:
            raise IntegrityError("File metadata corrupted")
        
        return stored['data'], stored['metadata']

Commitment Schemes

/// Secure commitment using SHA-256
pub struct Commitment {
    commitment: [u8; 32],
}

impl Commitment {
    pub fn create(value: &[u8], nonce: &[u8; 32]) -> Self {
        let mut hasher = Sha256::create();
        hasher.update(nonce);
        hasher.update(value);
        
        Self {
            commitment: hasher.finalize(),
        }
    }
    
    pub fn verify(&self, value: &[u8], nonce: &[u8; 32]) -> bool {
        let check = Self::create(value, nonce);
        constant_time_eq(&self.commitment, &check.commitment)
    }
}

// Usage
let secret = b"my bid is $1000";
let nonce = random_bytes::<32>();
let commitment = Commitment::create(secret, &nonce);

// Later: reveal
assert!(commitment.verify(secret, &nonce));

Merkle Trees

class MerkleTree:
    """Secure Merkle tree implementation"""
    
    def __init__(self, leaves: List[bytes]):
        self.leaves = [sha256(leaf) for leaf in leaves]
        self.tree = self._build_tree(self.leaves)
    
    def _build_tree(self, nodes: List[bytes]) -> List[List[bytes]]:
        tree = [nodes]
        
        while len(nodes) > 1:
            next_level = []
            
            for i in range(0, len(nodes), 2):
                if i + 1 < len(nodes):
                    # Hash pair with ordering
                    left, right = nodes[i], nodes[i + 1]
                    combined = sha256(b'\x00' + left + right)
                else:
                    # Odd node - promote as-is
                    combined = nodes[i]
                
                next_level.append(combined)
            
            tree.append(next_level)
            nodes = next_level
        
        return tree
    
    def get_root(self) -> bytes:
        return self.tree[-1][0] if self.tree else sha256(b'')
    
    def get_proof(self, index: int) -> List[Tuple[bytes, bool]]:
        """Generate inclusion proof for leaf at index"""
        proof = []
        
        for level in range(len(self.tree) - 1):
            level_nodes = self.tree[level]
            is_right_node = index % 2 == 1
            sibling_index = index - 1 if is_right_node else index + 1
            
            if sibling_index < len(level_nodes):
                proof.append((level_nodes[sibling_index], is_right_node))
            
            index //= 2
        
        return proof

Common Integration Patterns

Blockchain/Proof-of-Work

def mine_block(block_data: dict, difficulty: int) -> dict:
    """Mine block with proof-of-work using SHA-256"""
    target = 2 ** (256 - difficulty)
    nonce = 0
    
    block_bytes = json.dumps(block_data, sort_keys=True).encode()
    
    while True:
        candidate = block_bytes + nonce.to_bytes(8, 'little')
        hash_value = sha256(sha256(candidate))  # Double SHA-256
        
        if int.from_bytes(hash_value, 'big') < target:
            return {
                **block_data,
                'nonce': nonce,
                'hash': hash_value.hex()
            }
        
        nonce += 1

Git-style Content Addressing

pub fn create_git_hash(object_type: &str, content: &[u8]) -> String {
    let header = format!("{} {}\0", object_type, content.len());
    let mut hasher = Sha256::create();
    hasher.update(header.as_bytes());
    hasher.update(content);
    
    format!("sha256:{}", hex::encode(hasher.finalize()))
}

Performance Considerations

Input Size Time Throughput Notes
64 bytes ~500 ns 128 MB/s One block
1 KB ~2 μs 500 MB/s Optimal size
1 MB ~2 ms 500 MB/s Large file
1 GB ~2 s 500 MB/s Memory mapped

Hardware Acceleration:

Platform-Specific Security Notes

Python

Rust

TypeScript/JavaScript

Swift

Kotlin

Compliance and Standards

Security Auditing

Verification Checklist

Anti-Patterns to Detect

# AUDIT: Search for these dangerous patterns

# ❌ Password hashing
sha256(password)

# ❌ Keyed hash without HMAC
sha256(key + data)

# ❌ Assuming encryption
encrypted = sha256(plaintext + key)

# ❌ Weak randomness
nonce = sha256(str(time.time()))

Migration Guidelines

From MD5/SHA-1

# Step 1: Parallel hashing during transition
def migrate_hash(data: bytes) -> dict:
    return {
        'legacy_md5': md5(data).hex(),      # For compatibility
        'legacy_sha1': sha1(data).hex(),    # For compatibility  
        'sha256': sha256(data).hex(),       # New standard
        'algorithm': 'sha256'               # Current algorithm
    }

# Step 2: Verification supporting both
def verify_hash(data: bytes, hash_dict: dict) -> bool:
    algorithm = hash_dict.get('algorithm', 'legacy_md5')
    
    if algorithm == 'sha256':
        return sha256(data).hex() == hash_dict['sha256']
    elif algorithm == 'legacy_sha1':
        return sha1(data).hex() == hash_dict['legacy_sha1']
    else:
        return md5(data).hex() == hash_dict['legacy_md5']

Security Analysis

Threat Model: SHA-256 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-256 Specification
  2. RFC 6234 - SHA-256 Implementation
  3. Length Extension Attacks

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