sdrrand 📡 v0.1.0

True-random entropy, relayed from real RTL-SDR hardware.

Contributors run sdr-rand against a USB RTL-SDR dongle, harvest the LSBs of the ADC quantization noise, and POST the bytes here under their nuts.services identity. Anyone can drain. No PRNG. No seed. Just thermal noise from a tuner chip somewhere.

64
Pool bytes
65536
Capacity
1
Contributors
53100360
Bytes received
1000
Bytes drained
0
Pushes rejected

How we verify pushes

Every POST runs three lightweight ingress checks before its bytes enter the pool. Failures are recorded against the contributor and never served to drainers.

TestWhat it catchesThreshold
Repetition CountDead ADC, stuck driver, all-same-byte attacks≤ 40 identical bytes in a row
Byte frequency capMostly-one-value pushes (e.g. 90% zeros)No byte > 25% of batch
Shannon entropy floorStructured / low-entropy input≥ 6.0 bits/byte (true random scores ~7.6)

Modeled on NIST SP 800-90B health tests. Accepted bytes are absorbed into a SHA-3 (Shake256) duplex sponge — a rolling 64-byte state seeded at boot from the OS RNG. Drainers squeeze bytes from the same state; each squeeze re-mixes its output back, so no two squeezes are correlated. As long as at least one absorbed source has entropy the attacker doesn't know, a malicious contributor cannot determine what drainers see.

Drain entropy

curl https://sdrrand.nuts.services/api/entropy?bytes=32
curl https://sdrrand.nuts.services/api/entropy?bytes=64&format=hex
curl https://sdrrand.nuts.services/api/entropy?bytes=256&format=raw > bytes.bin

Push entropy (contributors)

POST raw bytes with a nuts-auth bearer token. Get one at auth.nuts.services (either an ahp_ API token or a session JWT).

# From the sdr-rand CLI:
sdr-rand push \
  --remote https://sdrrand.nuts.services \
  --token "$NUTS_TOKEN" \
  --frequency 433000000

# Or raw:
curl -X POST https://sdrrand.nuts.services/api/entropy \
  -H "Authorization: Bearer $NUTS_TOKEN" \
  --data-binary @entropy.bin

Endpoints

MethodPathDescription
GET/api/entropy?bytes=N&format=json|hex|rawDrain up to 4096 bytes (consumed on read).
GET/api/entropy/streamServer-Sent Events stream, one event per second.
POST/api/entropyPush raw bytes from a contributor. Auth required.
GET/api/statusPool stats + uptime.
GET/api/contributorsLeaderboard, by bytes contributed.
GET/healthzLiveness.