Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

wj-diode-quantum

Collects quantum random numbers from the Australian National University, streams them across a data diode, and serves them one at a time on the protected side. Each value is 1024 bits.

A data diode only carries data one way, so a machine behind one cannot ask ANU for random numbers itself. This program splits the job in two: one side collects and pushes, the other stockpiles what arrives and hands it out on request.

Quick start

Two machines, one command each.

Machine 1 — internet side

uv tool install wj-diode-quantum
wj-diode-quantum setup send
wj-diode-quantum collect -c config.json

Machine 2 — protected side

uv tool install wj-diode-quantum
wj-diode-quantum setup recv
wj-diode-quantum serve -c config.json

Check it works

curl localhost:8099/api/status    # numbers are arriving
curl localhost:8099/api/random    # take one
{
  "value": "74b033a4332c7112cf0c3ff5...67f6b30ee",
  "timestamp": "2026-08-02T04:14:58Z",
  "source": "quantumnumbers",
  "bits": 1024
}

value is your 1024-bit random number, 256 lowercase hex characters. timestamp is when it was collected. You will never be given that number again.

Or without the JSON around it — each of these carries the same metadata in X-Quantum-* headers:

curl localhost:8099/api/random/hex               # 256 hex characters
curl localhost:8099/api/random/base64            # the same value, base64
curl -o key.bin localhost:8099/api/random/binary # exactly 128 raw bytes

Open http://localhost:8099/ in a browser for the same thing with live pool figures, or curl localhost:8099/api/help for it as plain text. There is an OpenAPI description at /api/spec.

Full documentation: docs.waterjuice.org/wj-diode-quantum

Features

  • The numbers are never written in the clear. The collecting side writes nothing at all. The serving side can keep its pool across restarts, but only encrypted, under a passphrase held in the environment and never stored beside the file.
  • Both ANU APIs — the current keyed service and the older unkeyed one, each on its own schedule sized to its rate limit. Enable either or both.
  • Any diode tool — the transfer is a configured external command reading and writing a stream. Built against diodetool, but nothing about it is hard-coded.
  • Never serves the same number twice — including across a restart, when the pool is persisted. A value is recorded as served on disk before it reaches the client, so a crash mid-request can only lose it, never hand it out again.
  • Four output formats — JSON, hex, base64 and raw bytes, with the metadata in response headers.
  • Bounded, self-trimming pool — newest served first, oldest discarded at capacity.
  • One process per machine — the receiving side runs the diode tool for you.
  • Damage is contained — a diode cannot retransmit, so a corrupted value is dropped and the stream resynchronises rather than losing everything behind it.
  • Zero dependencies — a single static binary, Go standard library only.

Requirements

  • A tool that can move a file across your diode, on both sides.
  • An ANU API key from quantumnumbers.anu.edu.au, free with an account. Optional if you only use the legacy endpoint.

Building

make build        # wheels for all platforms, plus documentation
make check        # tests, format check, and vet
make dev          # run from source via a .venv launcher

How it fits together

  internet side                     diode                  protected side
  ─────────────                     ─────                  ──────────────
  ANU ──> collect ──> [ stream-send ] ══════> [ stream-recv ] ──> serve ──> GET /api/random
                            stdin                  stdout          │
                                                                   v
                                                          pool (encrypted on
                                                           disk, or memory)

Nothing comes back, so the collector never learns whether anything arrived. On the sending side nothing is stored at all: a transfer the diode will not take is retried and then discarded. On the serving side the pool may be kept across restarts, encrypted; without that it is lost on restart and refills from the far side's next cycle.

Security

There is no authentication on the API. Anyone who can reach the port can drain the pool. The default binds to 127.0.0.1 — keep it on loopback or a trusted network, or put a reverse proxy in front of it. Supply is finite, so a rate limit matters as much as authentication.

Diode passwords are written to a file with mode 0600 and passed with --password-file rather than on a command line, where ps would expose them.

The pool file is AES-256-GCM under a key stretched from $WJ_POOL_KEY with PBKDF2-HMAC-SHA256, and is written mode 0600. That protects it where it travels without the key — backups, volume snapshots, a disk pulled out of a machine — not against something that can already read both the file and the process environment. Lose the key and the pool is gone: there is no escrow, and a diode carries nothing back to ask for the numbers again.

Because a diode carries nothing back, the collector cannot be told the server is running low. Watch /api/status, the root page, or wj-diode-quantum stats on the protected side.

Licence

Released under the Unlicense — public domain.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

wj_diode_quantum-1.0.0b4-py3-none-win_arm64.whl (2.7 MB view details)

Uploaded Python 3Windows ARM64

wj_diode_quantum-1.0.0b4-py3-none-win_amd64.whl (3.0 MB view details)

Uploaded Python 3Windows x86-64

wj_diode_quantum-1.0.0b4-py3-none-manylinux_2_17_x86_64.whl (2.9 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

wj_diode_quantum-1.0.0b4-py3-none-manylinux_2_17_aarch64.whl (2.6 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

wj_diode_quantum-1.0.0b4-py3-none-macosx_11_0_arm64.whl (2.7 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

wj_diode_quantum-1.0.0b4-py3-none-macosx_10_9_x86_64.whl (3.0 MB view details)

Uploaded Python 3macOS 10.9+ x86-64

File details

Details for the file wj_diode_quantum-1.0.0b4-py3-none-win_arm64.whl.

File metadata

File hashes

Hashes for wj_diode_quantum-1.0.0b4-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 663c5b3f031bc708828ee2c5b4189ff827f51894b613309dc175c43d8e1e41f0
MD5 4addf276e5ad6db078ebf69596c3fa17
BLAKE2b-256 d3aa8919624a14d603d52ce97212bb099cd3f693421f04a827c405b6108e7819

See more details on using hashes here.

File details

Details for the file wj_diode_quantum-1.0.0b4-py3-none-win_amd64.whl.

File metadata

File hashes

Hashes for wj_diode_quantum-1.0.0b4-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 facb72a48ca872845079cc40b5ef375b8ac5f35e1c329fc6a9cf213cc01162b9
MD5 c69d551fbd8a68e782b12310e7b5e23c
BLAKE2b-256 c996a70088d787fd961321b0dab4e33d3791d7516a31bf257ee0bc47683e7d81

See more details on using hashes here.

File details

Details for the file wj_diode_quantum-1.0.0b4-py3-none-manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for wj_diode_quantum-1.0.0b4-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 13c3ac70fbef371f8a36071e09af4094683e6b8ea59a193aa501e64b743a5518
MD5 012137f55cb6fdc39419349815364b12
BLAKE2b-256 9118ab32bad29f60fa5029a62c598f635e707e72d7a1f45382665923a4b41991

See more details on using hashes here.

File details

Details for the file wj_diode_quantum-1.0.0b4-py3-none-manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for wj_diode_quantum-1.0.0b4-py3-none-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 c25b96a9ab9cf5c95957c6acf79b7e860aefb3dd42895b4b63ca4b610e402228
MD5 870acfbfd42da93f1c7a47cde5b37779
BLAKE2b-256 652ffeb539b005bba1e4d99a7c90e9710547f1d8f02f18ee6cfe96087c114ac9

See more details on using hashes here.

File details

Details for the file wj_diode_quantum-1.0.0b4-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for wj_diode_quantum-1.0.0b4-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c5671dcb48767464f7bc4fcd60fb0ec494e9833d516ce5e4e767b72406818d90
MD5 088a54fca5e788f07e6a9a97c036128c
BLAKE2b-256 03927a66eab5a5e3d12ec37f8165b4bf5bb6c5d19c6570e926e17c4693797253

See more details on using hashes here.

File details

Details for the file wj_diode_quantum-1.0.0b4-py3-none-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for wj_diode_quantum-1.0.0b4-py3-none-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 920c281a764f26874334695c9023dd717c86d0131216c22ccf369874e8c58cb9
MD5 10c2332ce40d33719699dd55e7f88956
BLAKE2b-256 dd72e7bd06dda9048b1ec868f2980477d222ebffdd152c527199d7385b081d7a

See more details on using hashes here.

Release history Release notifications | RSS feed

1.0.0

6 files

This release

1.0.0b4 This release

6 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page