ais31-headless is a CLI harness for the official BSI AIS 31 Java reference implementation, AIS 31 (V1) Referenzimplementierung - v1.0.
The project keeps the BSI implementation as an external artifact. It does not edit the original Evaluator.java in place. During installation it copies the BSI Java source/classes into .ais31/bsi, compiles them with the correct Latin-1 source encoding, and compiles one headless Java runner next to them.
The BSI implementation is a Swing GUI app. Its statistical logic lives in a package-private Tester class coupled to GUI fields in Evaluator. This harness gives Tester the fields it expects, runs it without a window, and captures the original log messages. The Python CLI handles installation, execution, parsing, and structured output.
python -m venv .venv
source .venv/bin/activate
python -m pip install -U pip
python -m pip install -e .[dev]You need a JDK, not only a JRE, because the harness compiles Java sources:
sudo apt-get install default-jdkInstall from the official BSI ZIP or an extracted BSI directory:
ais31 install --archive ~/Downloads/AIS_31_testsuit_zip.zipor:
ais31 install --source-dir ../AIS_31_testsuit_zipCheck the installed harness:
ais31 checkThe package also installs ais31v1 as an explicit alias for the same CLI.
Run procedure A, P1:T1-T5, over raw bytes interpreted as 8 random bits per byte:
ais31 run --input sample.bin --format raw --suite p1-t1-t5 --bit-width 8 --out results/p1.jsonRun P1:T0:
ais31 run --input sample.bin --format raw --suite p1-t0 --bit-width 8 --out results/t0.jsonRun P2-specific tests:
ais31 run --input sample.bin --format raw --suite p2 --bit-width 8 --out results/p2.jsonWhen --out is used, stdout stays compact and the full structured result is written to that file. Add --json to also print the full JSON to stdout.
The input must be random data in one of the supported encodings. For a quick smoke test, generate raw bytes from /dev/urandom.
mkdir -p samples results
head -c 393216 /dev/urandom > samples/p1-t0.raw
ais31 run --input samples/p1-t0.raw --format raw --suite p1-t0 --bit-width 8 --out results/p1-t0.jsonFor the larger suites with --bit-width 8:
head -c 652500 /dev/urandom > samples/p1-t1-t5.raw
ais31 run --input samples/p1-t1-t5.raw --format raw --suite p1-t1-t5 --bit-width 8 --out results/p1-t1-t5.json
head -c 900000 /dev/urandom > samples/p2.raw
ais31 run --input samples/p2.raw --format raw --suite p2 --bit-width 8 --out results/p2.jsonPassing the size check means the suite can run. It does not mean the sample will pass. The statistical result is in the CLI summary and in the JSON file.
The default output is short. The full BSI log remains in the JSON file.
p1-t0: passed; outcomes 1/1 passed; consumed 393216 of 393216 bytes; rest samples/p1-t0.raw_rest
json: results/p1-t0.json
Input formats:
raw: each file byte contains 8 random bits, most significant bit first.bit-bytes: each file byte is one random bit and must have value0x00or0x01.
Input sizes are checked before the Java runner starts. Minimum sizes follow the BSI AIS 31 V1 implementation formulas:
| Suite | Required random bits | Required bytes for raw |
Required bytes for bit-bytes |
|---|---|---|---|
p1-t0 |
bit_width * ceil(48 / bit_width) * 65536 |
ceil(bits / 8) |
bits |
p1-t1-t5 |
ceil(257 / (bit_width + 1)) * (ceil(20000 / bit_width) * bit_width + bit_width * 20000) |
ceil(bits / 8) |
bits |
p2 |
7200000 |
900000 |
7200000 |
For example, with --bit-width 8, p1-t0 requires 393,216 raw bytes, p1-t1-t5 requires 652,500 raw bytes, and p2 requires 900,000 raw bytes. These are minimum sizes, not pass guarantees. Statistically weak or unlucky data can still fail the tests. In bit-bytes mode the harness also verifies that the required portion of the file contains only 0x00 and 0x01 byte values.
If the input file is larger than the selected suite requires, the BSI V1 implementation tests only the first required bytes/bits. The full JSON result reports input.consumed_bits, input.consumed_bytes, and input.untested_remainder_bytes so callers can see exactly how much of the file was evaluated. The original BSI program writes the unused tail to a sibling _rest file and the harness reports that path in artifacts when present. In bit-bytes mode, the original BSI rest-file byte accounting appears inconsistent: the tests consume the first required_bits bytes, but the generated _rest file may not skip the same amount. This harness preserves and reports that reference behavior instead of silently correcting it.
For p2, the BSI implementation reads up to 7,200,000 random bits. Very degenerate inputs can still fail inside the BSI procedure with “too little test data” because the conditional tests need enough occurrences of several bit patterns; the preflight check can only prove that the file is physically large enough and correctly encoded.
Suites:
p1-t0: disjointness test, AIS criterionP1.i(i).p1-t1-t5: monobit, poker, runs, long-run, autocorrelation, AIS criterionP1.i(ii).p2: P2-specific testsT6a,T6b,T7a,T7b, andT8.
The JSON result contains:
summary: pass/fail, outcome counts, failed test names, consumed bytes, remainder bytes, rest files, and warning count- command/configuration metadata
- overall status
- parsed per-test outcomes where visible in the BSI log
- structured measurements parsed from the BSI log, such as monobit counts, poker statistics, run counts, autocorrelation values, and P2 statistics
- generated artifacts, including the BSI
_restfile path when present - consumed bytes and untested remainder bytes
- original BSI log lines
- stderr from the JVM, if any
This is a harness, not a rewrite. The Java runner calls the BSI Tester logic from the official source.
The original implementation writes a _rest file beside the input. The harness reports this path when expected. Be careful with bit-bytes mode and repetition workflows: the original code appears to have questionable rest-file byte accounting in that mode, so this harness preserves and reports the reference behavior rather than silently changing it.
- BSI AIS20/31 Java test suite page
- BSI random number generators overview
- AIS 20/31 functionality classes, version 2.0, 18 September 2011
- AIS 20/31 functionality classes, version 3.0, 10 September 2024
- Unofficial Saarinen archive of the BSI AIS 31 V1.0 test suite
- NIST IR 8446 final: Bridging the Gap Between Standards on Random Number Generation
- NIST IR 8446 initial public draft, now superseded by the final report
As of May 2026, BSI publishes AIS 20/31 functionality classes version 3.0 as the current mathematical-technical reference. The Java test suite wrapped here is still the older AIS 31 V1.0 reference implementation for the statistical tests A and B described around version 2.0; use this project as a harness for that reference implementation, not as evidence of a new BSI Java implementation for version 3.0.