"""Fortuna-based cryptographically secure PRNG. Wraps Python's secrets/os.urandom with a Fortuna-style interface matching Java's FortunaRandomSource API. Ported from net.i2p.util.FortunaRandomSource. """ from __future__ import annotations import hashlib import os import struct class FortunaRandomSource: """Fortuna-inspired CSPRNG. Uses os.urandom as the entropy source with optional seed mixing. """ def __init__(self, seed: bytes | None = None) -> None: self._state = os.urandom(32) if seed is not None: self._state = hashlib.sha256(self._state + seed).digest() def _generate(self, n: int) -> bytes: """Generate n bytes of random data.""" result = bytearray() while len(result) < n: self._state = hashlib.sha256( self._state + os.urandom(32) ).digest() result.extend(self._state) return bytes(result[:n]) def next_bytes(self, count: int) -> bytes: """Generate count random bytes.""" return self._generate(count) def next_int(self, bound: int) -> int: """Generate a random int in [0, bound).""" raw = struct.unpack(">I", self._generate(4))[0] return raw % bound def next_boolean(self) -> bool: """Generate a random boolean.""" return self._generate(1)[0] & 1 == 1