strix/README.md
2026-10-26 16:06:05 +02:00

4.5 KiB
Raw Blame History

STRIX

Satellite True Random Information eXtractor

Arduino MKR Vidor 4000 Built with Devbox License: Apache 2.0 AI-DECLARATION: copilot

A portable wireless True Random Number Generator built on an Arduino MKR Vidor 4000.

Design

Entropy comes from FPGA ring oscillators whose sampled timing jitter is XOR-combined into output bits, with no pseudo-random post-processing. A SAMD21 serves the results over USB, over HTTP on its own WiFi access point (stationary mode, on a charger), or over Bluetooth LE (mobile mode, on battery).

  • 4 independent generators × 90 ring oscillators. Each generator XORs its rings every 120 MHz clock (spatial) and then several consecutive bits (temporal, default 5): about 24 Mbps per generator.
  • Separate stream per generator, plus a combined stream of all healthy generators
  • On-device health tests per generator: NIST SP 800-90B repetition count and adaptive proportion, plus a dead-ring monitor
  • Live statistics per trial: bias, z-score, random walk and lag-1 autocorrelation, with rolling and cumulative windows
  • Configurable random-walk / majority-vote bias amplifier on a bias path and an autocorrelation path, with sub-trial voting
  • Von Neumann extractor that can be toggled on the stream, statistics and amplifier paths
  • Per-second trials in Global Consciousness Project format (200-bit XOR-masked sums per generator, plus full-rate sums), with Stouffer Z and network variance
  • Raw ring captures and frequency measurement for characterization
flowchart LR
    subgraph FPGA["FPGA: Cyclone 10 LP, 120 MHz from a PLL on the SAMD21's 48 MHz clock"]
        direction LR
        subgraph GEN["4 generators"]
            direction TB
            RO["90 ring oscillators<br/>3 taps XORed per ring"] --> SMP["2-flip-flop sampling"]
            SMP --> SX["spatial XOR<br/>of all rings"]
            SX --> TX["temporal XOR<br/>of 1-8 bits"]
        end
        SMP --> HM["health monitors<br/>repetition count, adaptive<br/>proportion, dead rings"]
        SX --> HM
        TX --> SEL["healthy generators<br/>g0-g3 and combined XOR"]
        HM -->|healthy| SEL
        SEL --> ST["entropy stream<br/>4 KB FIFO"]
        SEL --> STATS["statistics<br/>per-trial counts"]
        SEL --> AMP["bias amplifier<br/>2 paths, 3 stages"]
        SEL --> GCP["GCP trials<br/>per second"]
        GEN -.-> CAP["raw capture,<br/>frequency counter"]
        ST & STATS & AMP & GCP & CAP & HM --> REG["SPI registers"]
        PT["WiFi module<br/>pin pass-through"]
    end
    REG <-->|SPI 8 MHz| MCU["SAMD21 firmware"]
    MCU <--> PT
    PT <--> NINA["NINA-W102<br/>WiFi and BLE"]
    MCU --> USB["USB serial"]
    NINA --> HTTP["HTTP on its own<br/>access point"]
    NINA --> BLE["BLE GATT service"]

The USB, HTTP and BLE API is documented in arduino/strix/API.md.

Command-line client

tools/strix.py talks to the device over USB; run it with devbox run strix <command> or uv run tools/strix.py <command>. It finds the board by its USB ID (override with --port or STRIX_PORT).

Command Does
id, health, amp, get Prints the device's reply
stats [--reset] Prints the statistics, or restarts them
set KEY VALUE Changes a setting (keys in the API documentation)
entropy N [--out FILE] N entropy bytes as hex, or binary into a file
watch stats|amp Prints every new trial until Ctrl-C
gcp [--log FILE] [--full] [--seconds N] Follows the per-second GCP-format trials
send LINE Sends any command line and prints the reply

gcp prints one line per second: UTC time, second number, the four 200-bit sums, Stouffer Z, Z², and the cumulative Z² − 1 with its p = 0.05 envelope (* when outside). --full tracks the full-rate trials instead. It reconnects after USB dropouts and fills missed seconds from the device's 60-second history. --log appends GCP-style CSV rows, 13,<unix time>,<UTC date-time>,<g0>,<g1>,<g2>,<g3> (empty for unhealthy generators), after a 12,gmtime,Date/Time,g0,g1,g2,g3 header.

TODO

  • WiFi credentials stored on the device instead of compile-time defaults
  • Battery pack
  • 3D case

Development Notes