Files
entropy/README.md
T
Radek de17686a9b Update README and notes for DRBG, health checks, and HTTP service
Rewrite README to reflect the actual pipeline (frame -> health check
-> SHA-256 -> HMAC-DRBG -> emit), document all entropy.py flags, the
HTTP service endpoints and env vars, container build/run, Kubernetes
notes, and the remote-consumption rngd flow. Fix the notes.md typos
and align its commands with the new --out flag.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-09-02 11:52:24 +01:00

4.8 KiB

Entropy-RNG: Camera-Based Random Number Generator

This project uses a live video feed from a network camera (e.g. an Axis M1013) to generate cryptographically secure random numbers. The camera is pointed at a high-contrast, ever-changing scene (e.g. ceiling and lamps) so the pixel data carries genuine entropy.


How It Works

  1. Capture frame — fetch a single MJPEG frame from the camera via OpenCV.
  2. Health check — the raw JPEG bytes are run through FIPS 140-2 continuous tests (monobit, runs, long-run). A frozen or degraded frame is rejected before use.
  3. Extract entropy — the frame is SHA-256 hashed to a 32-byte digest.
  4. DRBG — the digest seeds a NIST SP 800-90A HMAC-DRBG (SHA-256), which generates the output bytes. The camera genuinely contributes entropy; the output is not just relabeled OS randomness.
  5. Emit — hex to stdout, or raw bytes to a file/FIFO (--out).

Requirements

  • Python 3.10+
  • opencv-python, fastapi, uvicorn, pytest
pip install -r requirements.txt

On Debian/Ubuntu you also need OpenCV runtime libs: apt-get install libgl1 libglib2.0-0.


Local Usage

Single number

python3 entropy.py --bit 256

Loop, writing raw bytes to a FIFO for rngd

mkfifo /tmp/entropy.fifo
python3 entropy.py --loop --bit 512 --out /tmp/entropy.fifo &
sudo rngd -f -W 90% -x rdrand -x jitter -x pkcs11 -x rtlsdr \
  -O namedpipe:path:/tmp/entropy.fifo -O namedpipe:timeout:2

Flags

Flag Default Description
--url http://192.168.0.200/mjpg/video.mjpg Camera MJPEG stream URL
--bit 256 Bit length of each random number (multiple of 8)
--single N 1 Generate N numbers and exit
--loop off Run forever
--interval 1.0 Seconds between iterations in --loop
--out PATH stdout Append raw bytes to a file/FIFO instead of printing hex
--no-health off Disable FIPS 140-2 health checks

--loop and --single are mutually exclusive.


HTTP Service (for remote systems)

api.py runs the camera producer in a background thread and serves the latest entropy blob over HTTP, so other systems can pull entropy to seed their own pools.

Run locally

uvicorn api:app --host 0.0.0.0 --port 8000

Endpoints

Method Path Auth Returns
GET / none service info
GET /healthz none {status: ok} (liveness probe)
GET /entropy X-API-Key if configured {hex, bits, ts}

Configuration (env vars)

Var Default Description
ENTROPY_CAMERA_URL http://192.168.0.200/mjpg/video.mjpg Camera MJPEG URL
ENTROPY_BITS 256 Bits per blob
ENTROPY_INTERVAL 1.0 Seconds between frames
ENTROPY_NO_HEALTH 0 1 disables health checks
ENTROPY_API_KEY empty Shared secret for /entropy; empty = no auth

Container Deployment

Build and run

docker build -t entropy-rng .
docker run -d -p 8000:8000 \
  -e ENTROPY_CAMERA_URL=http://192.168.0.200/mjpg/video.mjpg \
  -e ENTROPY_API_KEY=changeme \
  entropy-rng

The container has a healthcheck against /healthz. The camera must be reachable from the container's network.

Kubernetes notes

  • Replicas: 1. Multiple pods hitting the same camera produce correlated output. Pin to a single replica.
  • Camera reachability is the real constraint. Schedule the pod on a node that can reach the camera (use nodeSelector or a labeled node), or expose the camera via a Service.
  • Store ENTROPY_API_KEY in a Secret and mount as an env var.
  • Use an Ingress or Service for TLS termination in front of uvicorn.

Consuming Remotely (seed another system's pool)

A remote Linux box can pull a blob and feed its kernel RNG via rngd:

curl -s -H "X-API-Key: changeme" https://entropy-svc.internal/entropy \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['hex'])" \
  | xxd -r -p > /tmp/entropy.fifo
sudo rngd -f -W 90% -x rdrand -x jitter -x pkcs11 -x rtlsdr \
  -O namedpipe:path:/tmp/entropy.fifo -O namedpipe:timeout:2

Tests

pytest -q

Covers the HMAC-DRBG (determinism, reseed, length, reseed limit), health checks (random passes, frozen/all-ones/short/long-run rejected), a bit-balance smoke test, and the API endpoints including auth gating. Tests stub the camera, so they run without hardware.


Notes

  • Point the camera at a dynamic scene. A static frame will fail health checks and be rejected.
  • The DRBG is reseeded from each frame, so output changes even if the camera noise is modest.
  • Auth is a single shared secret for now. When you need per-client keys, rotate to HMAC-signed blobs or mTLS — the API layer is where that plugs in.