A Python port of the Invisible Internet Project (I2P)
at main 48 lines 1.4 kB view raw
1"""Fortuna-based cryptographically secure PRNG. 2 3Wraps Python's secrets/os.urandom with a Fortuna-style interface 4matching Java's FortunaRandomSource API. 5 6Ported from net.i2p.util.FortunaRandomSource. 7""" 8 9from __future__ import annotations 10 11import hashlib 12import os 13import struct 14 15 16class FortunaRandomSource: 17 """Fortuna-inspired CSPRNG. 18 19 Uses os.urandom as the entropy source with optional seed mixing. 20 """ 21 22 def __init__(self, seed: bytes | None = None) -> None: 23 self._state = os.urandom(32) 24 if seed is not None: 25 self._state = hashlib.sha256(self._state + seed).digest() 26 27 def _generate(self, n: int) -> bytes: 28 """Generate n bytes of random data.""" 29 result = bytearray() 30 while len(result) < n: 31 self._state = hashlib.sha256( 32 self._state + os.urandom(32) 33 ).digest() 34 result.extend(self._state) 35 return bytes(result[:n]) 36 37 def next_bytes(self, count: int) -> bytes: 38 """Generate count random bytes.""" 39 return self._generate(count) 40 41 def next_int(self, bound: int) -> int: 42 """Generate a random int in [0, bound).""" 43 raw = struct.unpack(">I", self._generate(4))[0] 44 return raw % bound 45 46 def next_boolean(self) -> bool: 47 """Generate a random boolean.""" 48 return self._generate(1)[0] & 1 == 1