297 lines
9.7 KiB
Markdown
297 lines
9.7 KiB
Markdown
# Camera TRNG
|
|
|
|
> **[Read the Research & Science Behind This](RESEARCH.md)** — A deep dive into the physics, academic literature, and the LavaRnd approach.
|
|
|
|
A true random number generator that extracts entropy from camera sensor thermal noise, following the LavaRnd methodology.
|
|
|
|
## Setup Requirements
|
|
|
|
**Important**: Cover the camera lens for optimal operation.
|
|
|
|
1. **Cover the lens**: Use the lens cap, opaque tape, or place the camera in a light-proof enclosure
|
|
2. **Verify darkness**: The camera should capture pure black frames
|
|
3. **Run the service**: Gain and brightness are automatically maximized
|
|
|
|
This approach (pioneered by the LavaRnd project) isolates pure thermal noise from the sensor, eliminating any scene-correlated data and providing a simpler security model.
|
|
|
|
## How It Works
|
|
|
|
With the lens covered, camera sensors produce noise from thermal electron activity and dark current. This service:
|
|
|
|
1. Opens the camera and maximizes gain/brightness settings
|
|
2. Captures frames of pure sensor noise (no light = no scene data)
|
|
3. Extracts the 2 LSBs from each pixel (highest entropy density)
|
|
4. Hashes the LSBs with SHA-256 to condition the output
|
|
5. Mixes in timing entropy for additional randomness
|
|
|
|
## Build
|
|
|
|
```bash
|
|
cargo build --release
|
|
```
|
|
|
|
## Run
|
|
|
|
```bash
|
|
./target/release/camera-trng
|
|
# Or set a custom port
|
|
PORT=9000 ./target/release/camera-trng
|
|
|
|
Use the camera at **max resolution** (and highest frame rate):
|
|
```bash
|
|
CAMERA_MAX_RESOLUTION=1 cargo run
|
|
```
|
|
|
|
**macOS — camera in use ("Lock Rejected")?** Run once to release the webcam, then start the server:
|
|
```bash
|
|
./scripts/release-camera.sh # may prompt for sudo password
|
|
cargo run
|
|
```
|
|
|
|
### Streaming random (multiple terminals)
|
|
|
|
To see a stream of random in the terminal and verify each stream is unique:
|
|
|
|
- **One stream:** `./scripts/stream-random.sh 0` (infinite; Ctrl+C to stop)
|
|
- **Several streams in different terminals** (each gets different random; never the same):
|
|
- Terminal 1: `./scripts/stream-random.sh "Stream-1" 0`
|
|
- Terminal 2: `./scripts/stream-random.sh "Stream-2" 0`
|
|
- Terminal 3: `./scripts/stream-random.sh "Stream-3" 0`
|
|
- **Quick demo (3 streams, 5 lines each, verify no duplicates):** `./scripts/stream-demo.sh 5`
|
|
|
|
## Docker
|
|
|
|
Pull the pre-built image:
|
|
|
|
```bash
|
|
docker pull git.nixc.us/colin/camera-trng:latest
|
|
```
|
|
|
|
Run with camera access (Linux with V4L2):
|
|
|
|
```bash
|
|
docker run -d \
|
|
--name camera-trng \
|
|
--device /dev/video0:/dev/video0 \
|
|
-p 8787:8787 \
|
|
git.nixc.us/colin/camera-trng:latest
|
|
```
|
|
|
|
**Note**: Ensure the camera lens is covered before starting the container.
|
|
|
|
### Available Tags
|
|
|
|
| Tag | Description |
|
|
|-----|-------------|
|
|
| `latest` | Latest build from master branch |
|
|
| `<commit-sha>` | Specific commit (first 8 chars) |
|
|
| `<version>` | Semantic version tags (e.g., `v1.0.0`) |
|
|
|
|
## API
|
|
|
|
### GET /random
|
|
|
|
Returns random bytes from camera thermal noise.
|
|
|
|
**Query Parameters:**
|
|
- `bytes` - Number of bytes to return (default: 32, max: 1024)
|
|
- `hex` - Return as hex string instead of raw bytes (default: false)
|
|
|
|
**Examples:**
|
|
```bash
|
|
# Get 32 random bytes as hex
|
|
curl "http://localhost:8787/random?hex=true"
|
|
|
|
# Get 64 raw random bytes
|
|
curl "http://localhost:8787/random?bytes=64" -o random.bin
|
|
|
|
# Get 256 bytes as hex
|
|
curl "http://localhost:8787/random?bytes=256&hex=true"
|
|
```
|
|
|
|
### GET /health
|
|
|
|
Returns `ok` if the server is running.
|
|
|
|
## Rate Limiting
|
|
|
|
- Maximum 4 concurrent requests
|
|
- Maximum 1024 bytes per request
|
|
- Returns 429 Too Many Requests when overloaded
|
|
|
|
## Cross-Platform Support
|
|
|
|
Uses `nokhwa` for camera access, supporting:
|
|
- macOS (AVFoundation)
|
|
- Windows (Media Foundation)
|
|
- Linux (V4L2)
|
|
|
|
## Randomness Validation
|
|
|
|
A built-in test suite validates the statistical quality of generated random data.
|
|
|
|
### Quick Test
|
|
|
|
```bash
|
|
# Test against running server (fetches 1MB)
|
|
./scripts/test-randomness.py --server http://127.0.0.1:8787
|
|
|
|
# Test a file
|
|
./scripts/test-randomness.py /path/to/random.bin
|
|
|
|
# Test from stdin
|
|
curl -s http://127.0.0.1:8787/random?bytes=1048576 | ./scripts/test-randomness.py -
|
|
```
|
|
|
|
### Test Suite
|
|
|
|
The validation suite includes 8 statistical tests:
|
|
|
|
| Test | Description | Pass Criteria |
|
|
|------|-------------|---------------|
|
|
| Shannon Entropy | Information density | >7.9 bits/byte |
|
|
| Chi-Square | Distribution uniformity | 200-330 (df=255) |
|
|
| Arithmetic Mean | Average byte value | 126-129 |
|
|
| Monte Carlo Pi | Geometric randomness | <1% error |
|
|
| Serial Correlation | Sequential independence | \|r\| < 0.01 |
|
|
| Byte Coverage | Value distribution | 256/256 present |
|
|
| Bit Balance | Binary distribution | 49-51% ones |
|
|
| Longest Run | Pattern detection | <25 bits |
|
|
|
|
### Example Output
|
|
|
|
```
|
|
=======================================================
|
|
CAMERA QRNG RANDOMNESS VALIDATION
|
|
=======================================================
|
|
Sample size: 1,048,576 bytes (1.00 MB)
|
|
|
|
1. Shannon Entropy: 7.999796 bits/byte [PASS]
|
|
2. Chi-Square Test: 297.12 [PASS]
|
|
3. Arithmetic Mean: 127.5829 [PASS]
|
|
4. Monte Carlo Pi: 3.155151 [PASS]
|
|
5. Serial Correlation: 0.000235 [PASS]
|
|
6. Byte Coverage: 256/256 [PASS]
|
|
7. Bit Balance: 50.00% ones [PASS]
|
|
8. Longest Run (10KB): 19 bits [PASS]
|
|
|
|
RESULTS: 8/8 tests passed
|
|
VERDICT: EXCELLENT - All tests passed!
|
|
```
|
|
|
|
### External Test Suites
|
|
|
|
For more rigorous validation, the output also passes industry-standard test suites:
|
|
|
|
- **NIST SP 800-22**: 15 statistical tests (official NIST standard)
|
|
- **Dieharder**: 100+ statistical tests
|
|
- **TestU01**: Academic test library (BigCrush)
|
|
- **ENT**: Entropy analysis tool
|
|
|
|
```bash
|
|
# Using dieharder (if installed)
|
|
curl -s http://127.0.0.1:8787/random?bytes=10485760 | dieharder -a -g 200
|
|
|
|
# Using rngtest
|
|
curl -s http://127.0.0.1:8787/random?bytes=2500000 | rngtest
|
|
```
|
|
|
|
## CI/CD Pipeline
|
|
|
|
This project uses Woodpecker CI to automatically build, test, and deploy.
|
|
|
|
### Pipeline Overview
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ Woodpecker CI │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ On Push/PR to master: │
|
|
│ ┌─────────┐ │
|
|
│ │ test │──┬──> build-linux-x86_64 ──> binary artifact │
|
|
│ └─────────┘ │ │
|
|
│ ├──> build-linux-aarch64 ──> binary artifact │
|
|
│ │ │
|
|
│ └──> build-image ──┬──> trivy-image (scan) │
|
|
│ └──> sbom-image (SBOM) │
|
|
│ │
|
|
│ Parallel checks: cargo-audit, trivy-fs, clippy, fmt-check │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### Build Artifacts
|
|
|
|
| Artifact | Architecture | Description |
|
|
|----------|--------------|-------------|
|
|
| `camera-trng-linux-x86_64` | x86_64 | Linux AMD64 binary |
|
|
| `camera-trng-linux-aarch64` | aarch64 | Linux ARM64 binary (best-effort) |
|
|
| Docker Image | linux/amd64 | Container image |
|
|
|
|
### Docker Image Registry
|
|
|
|
Images are pushed to: `git.nixc.us/colin/camera-trng`
|
|
|
|
- **On push to master**: Tags `latest` and `<commit-sha>`
|
|
- **On version tag**: Tags `<version>` and `latest`
|
|
|
|
### Required Secrets
|
|
|
|
Configure these secrets in Woodpecker:
|
|
|
|
| Secret | Description |
|
|
|--------|-------------|
|
|
| `REGISTRY_USER` | Username for git.nixc.us registry |
|
|
| `REGISTRY_PASSWORD` | Password/token for git.nixc.us registry |
|
|
| `DOCKER_REGISTRY_USER` | Docker Hub username (for base images) |
|
|
| `DOCKER_REGISTRY_PASSWORD` | Docker Hub password/token |
|
|
|
|
### Security Scanning
|
|
|
|
The pipeline includes:
|
|
- **cargo-audit**: Scans Rust dependencies for known vulnerabilities
|
|
- **trivy-fs**: Scans filesystem and Cargo.lock for vulnerabilities
|
|
- **trivy-image**: Scans the built Docker image
|
|
- **SBOM generation**: Creates SPDX and CycloneDX SBOMs for dependencies
|
|
|
|
### Cross-Compilation Notes
|
|
|
|
**Linux x86_64**: Fully supported, built natively on CI runners.
|
|
|
|
**Linux aarch64**: Best-effort cross-compilation. May fail due to native camera library dependencies (libv4l). For production ARM64 builds, consider using native ARM64 runners.
|
|
|
|
**macOS/Windows**: Not built in CI due to native camera library requirements. Build locally:
|
|
|
|
```bash
|
|
# macOS
|
|
cargo build --release
|
|
|
|
# Windows (requires MSVC toolchain)
|
|
cargo build --release
|
|
```
|
|
|
|
### Local Docker Build
|
|
|
|
```bash
|
|
# Build locally
|
|
docker build -t camera-trng:local .
|
|
|
|
# Test locally (requires camera device with lens covered)
|
|
docker run --rm --device /dev/video0 -p 8787:8787 camera-trng:local
|
|
```
|
|
|
|
## Security Notes
|
|
|
|
This implementation follows the LavaRnd approach for thermal noise extraction:
|
|
|
|
- **Cover the lens**: Required for the intended security model
|
|
- **Gain maximized**: Software automatically configures camera for maximum noise amplification
|
|
- **No scene data**: With lens covered, there is no side-channel information leakage
|
|
- **SHA-256 conditioning**: Removes any bias and ensures uniform distribution
|
|
|
|
For high-security cryptographic applications, consider:
|
|
- Using dedicated hardware RNGs (HSMs)
|
|
- Mixing with system entropy (`/dev/urandom`)
|
|
- Verifying the camera is properly covered before deployment
|