Both ent
tests distinguish the files from random data with high confidence (99.84% for the bit test, >99.99% for the byte test). That follows from the "randomly would exceed this value.." reports.
It would only be an issue in actual use if the random data was directly used. Which would be bad practice in cryptography, where the rule is that the output of an unconditioned TRNG is, under operating conditions, fed exclusively to
- a monitoring scheme which ensures that the unconditioned TRNG outputs some entropy;
- and a PRNG processing the output of the unconditioned TRNG.
Note: if the PRNG is not cryptographically secure (which is often the case for hardware ones), its output is further processed with a CSPRNG.
With this structure the monitoring scheme's purpose should not be to try to determine that/if the TRNG is near-perfect. It should be to rule out that the TRNG is badly broken (like, insure that the entropy rate if at least 0.5).
The ent
test is ill-suited to the purpose: it is not operating in real time, is not designed to ignore minor defects, and most importantly it fails to detect some huge, not-unlikely defects: if there was a triple-trigger for every Geiger event, making three identical or incremental values recorded for each Geiger event, that would not be detected by ent
(except for very small input), when that's a disaster.
Still, from an engineering perspective, it is interesting to understand what makes the ent
tests fail. Some ideas (before the question was updated with raw data and code):
- The Geiger event determines when a free-running 16-bit timer clocked at about $2^{16}/10^{-3}$Hz (about 70 MHz) is sampled. It could be that there is some analog feedback from the counter, or from something derived from the same clock as the counter, to the sampling logic. For example, if when the Geiger event occurs near the active edge of the clock, the current state of the low-order bit of the counter influences (by e.g. capacitive coupling) the decision of the gate that determines if the event is going to be registered as having happened before or after the edge, then that low-order bit is going to be biased. It may be that ent's byte test will detect this bias more accurately than it's bit test (because the biased bit is always at the same position in a byte).
- If the sampling is in software (e.g. an interrupt triggered by the Geiger event reads the 16-bit timer), then the latency in the processing of that interrupt can play a role. For example, if the 16-bit timer generates an interrupt of identical priority when it overflows, that makes it impossible that some 16-bit values (those right after the overflow) get sampled, creating a bias. I believe ent's byte test would detect that kind of issue more selectively than it's bit test.
Summary (before the question was updated with raw data and code):
- The
ent
tests failed, and that's likely related to some minor imperfection. We can only make guesses at which.
- It is no indication that this unconditioned TRNG is unsuitable to seed a (CS)PRNG, which is the Right Thing to do with an unconditioned TRNG.
- The
ent
test is not adequate for an unconditioned TRNG source; not even in an exploratory phase, much less for the continuous surveillance of the unconditioned TRNG, as necessary in serious cryptographic uses.
Update: Mystery solved!
Summary frequency analysis of the raw data demonstrates beyond doubt that byte values 0x11 and 0x13 have been filtered out. That's what allows ent
to raise alert. Certainly, XON/XOFF software flow control strikes again!
0x00 281 0x01 300 0x02 343 0x03 313 0x04 322 0x05 321 0x06 295 0x07 342 0x08 317 0x09 319 0x0A 337 0x0B 320 0x0C 328 0x0D 308 0x0E 324 0x0F 344
0x10 316 0x11 0 0x12 320 0x13 0 0x14 314 0x15 376 0x16 336 0x17 325 0x18 295 0x19 342 0x1A 325 0x1B 338 0x1C 326 0x1D 293 0x1E 324 0x1F 296
0x20 328 0x21 300 0x22 322 0x23 313 0x24 340 0x25 334 0x26 342 0x27 315 0x28 336 0x29 295 0x2A 313 0x2B 305 0x2C 322 0x2D 341 0x2E 303 0x2F 331
0x30 308 0x31 339 0x32 371 0x33 325 0x34 323 0x35 319 0x36 324 0x37 309 0x38 337 0x39 296 0x3A 323 0x3B 338 0x3C 335 0x3D 302 0x3E 335 0x3F 348
0x40 331 0x41 318 0x42 334 0x43 285 0x44 323 0x45 348 0x46 323 0x47 333 0x48 325 0x49 370 0x4A 345 0x4B 318 0x4C 338 0x4D 302 0x4E 330 0x4F 326
0x50 332 0x51 308 0x52 307 0x53 362 0x54 300 0x55 292 0x56 335 0x57 333 0x58 352 0x59 355 0x5A 317 0x5B 326 0x5C 329 0x5D 334 0x5E 316 0x5F 331
0x60 318 0x61 324 0x62 293 0x63 318 0x64 302 0x65 324 0x66 317 0x67 313 0x68 297 0x69 310 0x6A 330 0x6B 334 0x6C 300 0x6D 340 0x6E 310 0x6F 317
0x70 324 0x71 335 0x72 309 0x73 335 0x74 333 0x75 336 0x76 314 0x77 313 0x78 354 0x79 333 0x7A 294 0x7B 333 0x7C 324 0x7D 340 0x7E 343 0x7F 336
0x80 309 0x81 294 0x82 352 0x83 324 0x84 306 0x85 295 0x86 314 0x87 342 0x88 324 0x89 311 0x8A 331 0x8B 292 0x8C 305 0x8D 318 0x8E 324 0x8F 321
0x90 307 0x91 325 0x92 335 0x93 329 0x94 324 0x95 335 0x96 318 0x97 336 0x98 335 0x99 302 0x9A 310 0x9B 342 0x9C 315 0x9D 326 0x9E 290 0x9F 323
0xA0 308 0xA1 319 0xA2 347 0xA3 323 0xA4 305 0xA5 312 0xA6 336 0xA7 293 0xA8 323 0xA9 310 0xAA 352 0xAB 323 0xAC 305 0xAD 312 0xAE 340 0xAF 306
0xB0 305 0xB1 311 0xB2 334 0xB3 333 0xB4 303 0xB5 324 0xB6 343 0xB7 308 0xB8 305 0xB9 309 0xBA 331 0xBB 322 0xBC 332 0xBD 329 0xBE 311 0xBF 327
0xC0 350 0xC1 349 0xC2 352 0xC3 313 0xC4 319 0xC5 350 0xC6 282 0xC7 316 0xC8 305 0xC9 348 0xCA 316 0xCB 325 0xCC 335 0xCD 337 0xCE 295 0xCF 309
0xD0 305 0xD1 344 0xD2 325 0xD3 311 0xD4 296 0xD5 301 0xD6 349 0xD7 285 0xD8 328 0xD9 308 0xDA 323 0xDB 338 0xDC 276 0xDD 299 0xDE 323 0xDF 314
0xE0 286 0xE1 360 0xE2 315 0xE3 308 0xE4 329 0xE5 321 0xE6 302 0xE7 315 0xE8 346 0xE9 326 0xEA 315 0xEB 352 0xEC 346 0xED 319 0xEE 333 0xEF 289
0xF0 320 0xF1 309 0xF2 317 0xF3 325 0xF4 312 0xF5 366 0xF6 331 0xF7 316 0xF8 283 0xF9 344 0xFA 336 0xFB 302 0xFC 331 0xFD 310 0xFE 347 0xFF 335
Note 1: As a minor aside, the 16-bit counter is sampled by software in an interrupt, rather than in hardware by an input capture mechanism. It follows that any variation in interrupt latency influences what's sampled. In many CPUs, interrupt latency varies slightly according to foreground activity (like, a multi-cycle instruction or access to a peripheral requiring wait states increases latency). The ATMega328P has instructions lasting 1 to 4 cycles, thus this could have some minor influence, especially on the low-order bits. While I have seen the uncertainty in sampling by interrupt about halved by putting a CPU in wait/sleep mode rather than in a loop with a 2-cyles branch, that's a non-scalable kludge, and using the ATMega328P's Input Capture Unit would be best (depending on what pin the signal to sample is connected, that could be software-only change).
Note 2: putting a radioactive source nearby will have several effects:
- The entropy rate (in bit/s) will increase.
- The samples will get closer, and that will increase a currently minor issue: by design, the difference between a 16-bit sample and the next (modulo 65536) is biased.
- Odds of upset in the nearby logic/CPU will increase, which could have dramatic negative side effects.
Note 3: Proper monitoring of the unconditioned source is best done with knowledge of which is high and low byte of 16-bit samples. This currently is possible only by timing considerations (especially with the disappearing bytes). We can solve that and make the output plain ASCII by sending a 16-bit sample as 4 characters, the first in PQRSTUVWHIJKLMNO
and the others in pqrstuvwhijklmno
, with the low-order 4 bits of each character equal to 4 bits of the 16-bit sample (I suggest, in big-endian order, which is the most common in crypto).
Note 4: In some cryptographic contexts, adding a proper CSPRNG somewhere will be essential. If this unconditionned generator was used as /dev/random directly
, it would be easy to distinguish the output from good randomness, at least if it can be timed when the output becomes available! Proper monitoring is important too, and essential if an adversary can approach the device (sabotage is a thing; and forcing Geiger events to occur is not rocket science).