Source code for apifrom.utils.sri

from typing import Dict, List, Optional, Union
import hashlib
import base64
from enum import Enum


class SRIHashAlgorithm(str, Enum):
    SHA256 = "sha256"
    SHA384 = "sha384"
    SHA512 = "sha512"


[docs] def generate_integrity_hash(content: Union[str, bytes], algorithm: SRIHashAlgorithm = SRIHashAlgorithm.SHA384) -> str: """ Generates a Subresource Integrity hash for the given content. Args: content: The content to generate the hash for algorithm: The hashing algorithm to use Returns: The integrity hash string """ if isinstance(content, str): content = content.encode('utf-8') hash_func = getattr(hashlib, algorithm.value) digest = hash_func(content).digest() b64_digest = base64.b64encode(digest).decode('utf-8') return f"{algorithm.value}-{b64_digest}"
[docs] def validate_integrity(content: Union[str, bytes], integrity: str) -> bool: """ Validates that the given content matches the provided integrity hash. Args: content: The content to validate integrity: The integrity hash to validate against Returns: True if the content is valid, False otherwise """ if not integrity: return False parts = integrity.split('-', 1) if len(parts) != 2: return False algorithm, expected_hash = parts if algorithm not in [alg.value for alg in SRIHashAlgorithm]: return False calculated_integrity = generate_integrity_hash(content, SRIHashAlgorithm(algorithm)) return calculated_integrity == integrity
[docs] class SRIMiddleware: def __init__( self, algorithms: Optional[List[SRIHashAlgorithm]] = None, script_sources: Optional[Dict[str, str]] = None, style_sources: Optional[Dict[str, str]] = None, exempt_paths: Optional[List[str]] = None ): """ Middleware for adding and verifying Subresource Integrity hashes. Args: algorithms: List of hash algorithms to use script_sources: Mapping of script URLs to their content style_sources: Mapping of style URLs to their content exempt_paths: List of paths that should be exempt from integrity checks """ self.algorithms = algorithms or [SRIHashAlgorithm.SHA384] self.script_sources = script_sources or {} self.style_sources = style_sources or {} self.exempt_paths = exempt_paths or [] self._integrity_cache: Dict[str, str] = {}