A True Random Number Generator (TRNG) using raw camera sensor data to extract physical entropy.
src/photorand/- Main package source code.low_level/- Modular primitives (ingest, sample, hash, csprng).high_level/- Clean OO abstractions (PhotoRandSeed,PhotoRandEngine).cli/- Command-line interface logic.
docs/- Technical and scientific documentation detailing the entropy extraction and entropy expansion mechanisms.tests/- Comprehensive test suite organized by architectural layer.examples/- Code samples, useful scripts
This project is available on PyPI:
pip install photorandThis project uses pyproject.toml for managing dependencies.
-
Create and activate a virtual environment (recommended):
python -m venv .venv source .venv/bin/activate # On Windows, use `.venv\Scripts\activate`
-
Install the project in editable mode:
pip install -e . # or this one for also installing the dev tools pip install -e ".[dev]"
Note: you can use photorand from the cli using python -m photorand instead of just photorand
The high-level classes provide a stateful and convenient interface for both TRNG and CSPRNG operations.
Encapsulates the process of extracting entropy from a RAW image. It is perfect for generating one-off secure seeds, keys, or dice rolls directly from physical noise.
from photorand import PhotoRandSeed
# 1. Extract entropy from a RAW image
seed = PhotoRandSeed("path/to/image.raw")
# 2. Access as bytes, hex, or large integer
print(seed.to_hex_string())
print(seed.to_int())
# 3. Roll a D100 using physical entropy (Rejection Sampling)
luck = seed.to_int_range(1, 100)
# 4. Get a float in range
prob = seed.to_float_range(0.5, 1.5)An infinite stream generator powered by ChaCha20, seeded by a PhotoRandSeed. It handles salting (Time + PID) automatically to ensure that even consecutive runs with the same image produce unique streams.
from photorand import PhotoRandEngine
# 1. Initialize from image or existing Seed object
engine = PhotoRandEngine("path/to/image.raw")
# 2. Pull arbitrary amounts of secure data
key = engine.next_bytes(32)
pin = engine.next_string(length=6, charset='numeric')
dice = engine.next_int_range(1, 20)
float_luck = engine.next_float_range(10.5, 20.5)
coin_flip = engine.next_bool()
probability = engine.next_float()
# 3. Batch generation
multiple_passwords = engine.generate_batch(engine.next_string, count=5, length=16)The package includes a powerful CLI to use these classes directly from your terminal.
# Extract 64-byte photorand seed (hex)
photorand extract hex --from path/to/raw_image.ARW
# Roll a D20
photorand extract int-range --from path/to/raw_image.ARW --min 1 --max 20
# Extract a float in range (e.g. -1.0 to 1.0)
photorand extract float-range --from path/to/raw_image.ARW --min -1.0 --max 1.0
# Generate 5 random 16-char alphanumeric passwords
photorand generate string --from path/to/raw_image.ARW -n 5 -l 16 --charset alpha
# Extract a floating point number between 0 and 1
photorand extract float --from path/to/raw_image.ARW
# Generate 10 boolean values
photorand generate bool --from path/to/raw_image.ARW -n 10
# Generate 5 floats in a specific range
photorand generate float-range --from path/to/raw_image.ARW --min 0.5 --max 1.5 -n 5For more details, run: photorand --help
For maximum control or research, you can use the modular primitives directly.
from photorand.low_level import ingest_raw_image
from photorand.low_level import sample_entropy_grid
from photorand.low_level import hash_entropy_pool
# 1. Ingest raw sensor data
raw_data = ingest_raw_image("path/to/image.raw")
# 2. Extract raw LSB bits
entropy_pool = sample_entropy_grid(raw_data)
# 3. Condition entropy into uniform bytes
seed_bytes = hash_entropy_pool(entropy_pool)Alternatively, use the functional pipeline. It accepts custom functions for each part of the algorithm (ingest_fn, sample_fn and hash_fn) although we already provide the values as default parameters:
from photorand.low_level import generate_true_random_number
seed = generate_true_random_number("path/to/image.raw") # returns bytespython -m pytest -v --log-cli-level=INFO
# or just this one to skip logs
pytestruff check --fix src tests examples- Blog Post: Physical Entropy with PhotoRand
- PyPI Package: photorand on PyPI
