2
$\begingroup$

Out of interest I wanted to test the results of using a floating analogue pin on my Arduino to generate a sequence of random numbers using dieharder.

My working assumption was that it would be a poor source of random numbers and would fail many of the dieharder tests.

I used the following simple code on the Arduino and saved the serial output to a text file using python (about 10mb file size in total).


void setup() {
  Serial.begin(115200);
}

void loop() {
  randNumber = analogRead(0);
  Serial.println(randNumber);
  delay(10);
}

I added the expected file header and than ran dieharder (on Mint) using the following command: dieharder -a -m 10 -f Arduino_A0Float.txt

The results are as follows:

#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |           filename             |rands/second|
        mt19937|             Arduino_A0Float.txt|  9.74e+07  |
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
   diehard_birthdays|   0|       100|    1000|0.73031670|  PASSED
      diehard_operm5|   0|   1000000|    1000|0.65294393|  PASSED
  diehard_rank_32x32|   0|     40000|    1000|0.89005950|  PASSED
    diehard_rank_6x8|   0|    100000|    1000|0.88363318|  PASSED
   diehard_bitstream|   0|   2097152|    1000|0.42267863|  PASSED
        diehard_opso|   0|   2097152|    1000|0.59126884|  PASSED
        diehard_oqso|   0|   2097152|    1000|0.47305823|  PASSED
         diehard_dna|   0|   2097152|    1000|0.01372139|  PASSED
diehard_count_1s_str|   0|    256000|    1000|0.46612674|  PASSED
diehard_count_1s_byt|   0|    256000|    1000|0.64556106|  PASSED
 diehard_parking_lot|   0|     12000|    1000|0.00206969|   WEAK
    diehard_2dsphere|   2|      8000|    1000|0.57590249|  PASSED
    diehard_3dsphere|   3|      4000|    1000|0.29214417|  PASSED
     diehard_squeeze|   0|    100000|    1000|0.31946903|  PASSED
        diehard_sums|   0|       100|    1000|0.00000000|  FAILED
        diehard_runs|   0|    100000|    1000|0.36767252|  PASSED
        diehard_runs|   0|    100000|    1000|0.02008548|  PASSED
       diehard_craps|   0|    200000|    1000|0.12092819|  PASSED
       diehard_craps|   0|    200000|    1000|0.06600707|  PASSED
 marsaglia_tsang_gcd|   0|  10000000|    1000|0.77310206|  PASSED
 marsaglia_tsang_gcd|   0|  10000000|    1000|0.47402495|  PASSED
         sts_monobit|   1|    100000|    1000|0.84397643|  PASSED
            sts_runs|   2|    100000|    1000|0.28840743|  PASSED
          sts_serial|   1|    100000|    1000|0.62464446|  PASSED
          sts_serial|   2|    100000|    1000|0.28848284|  PASSED
          sts_serial|   3|    100000|    1000|0.69830642|  PASSED
          sts_serial|   3|    100000|    1000|0.78000793|  PASSED
          sts_serial|   4|    100000|    1000|0.97700164|  PASSED
          sts_serial|   4|    100000|    1000|0.46552535|  PASSED
          sts_serial|   5|    100000|    1000|0.45551106|  PASSED
          sts_serial|   5|    100000|    1000|0.47103481|  PASSED
          sts_serial|   6|    100000|    1000|0.36750460|  PASSED
          sts_serial|   6|    100000|    1000|0.20496000|  PASSED
          sts_serial|   7|    100000|    1000|0.91570738|  PASSED
          sts_serial|   7|    100000|    1000|0.15881843|  PASSED
          sts_serial|   8|    100000|    1000|0.06947957|  PASSED
          sts_serial|   8|    100000|    1000|0.15665433|  PASSED
          sts_serial|   9|    100000|    1000|0.40020387|  PASSED
          sts_serial|   9|    100000|    1000|0.72318346|  PASSED
          sts_serial|  10|    100000|    1000|0.01220847|  PASSED
          sts_serial|  10|    100000|    1000|0.08776241|  PASSED
          sts_serial|  11|    100000|    1000|0.54554757|  PASSED
          sts_serial|  11|    100000|    1000|0.22748736|  PASSED
          sts_serial|  12|    100000|    1000|0.49942875|  PASSED
          sts_serial|  12|    100000|    1000|0.72527116|  PASSED
          sts_serial|  13|    100000|    1000|0.30717941|  PASSED
          sts_serial|  13|    100000|    1000|0.32157401|  PASSED
          sts_serial|  14|    100000|    1000|0.15504601|  PASSED
          sts_serial|  14|    100000|    1000|0.85577118|  PASSED
          sts_serial|  15|    100000|    1000|0.13846467|  PASSED
          sts_serial|  15|    100000|    1000|0.46546627|  PASSED
          sts_serial|  16|    100000|    1000|0.57109789|  PASSED
          sts_serial|  16|    100000|    1000|0.91701563|  PASSED
         rgb_bitdist|   1|    100000|    1000|0.28807350|  PASSED
         rgb_bitdist|   2|    100000|    1000|0.78770507|  PASSED
         rgb_bitdist|   3|    100000|    1000|0.36736774|  PASSED
         rgb_bitdist|   4|    100000|    1000|0.71209177|  PASSED
         rgb_bitdist|   5|    100000|    1000|0.83857409|  PASSED
         rgb_bitdist|   6|    100000|    1000|0.64691681|  PASSED
         rgb_bitdist|   7|    100000|    1000|0.07003357|  PASSED
         rgb_bitdist|   8|    100000|    1000|0.54441864|  PASSED
         rgb_bitdist|   9|    100000|    1000|0.01044120|  PASSED
         rgb_bitdist|  10|    100000|    1000|0.67962073|  PASSED
         rgb_bitdist|  11|    100000|    1000|0.22160177|  PASSED
         rgb_bitdist|  12|    100000|    1000|0.85028915|  PASSED
rgb_minimum_distance|   2|     10000|   10000|0.28516744|  PASSED
rgb_minimum_distance|   3|     10000|   10000|0.96074747|  PASSED
rgb_minimum_distance|   4|     10000|   10000|0.73997869|  PASSED
rgb_minimum_distance|   5|     10000|   10000|0.00086553|   WEAK
    rgb_permutations|   2|    100000|    1000|0.93838879|  PASSED
    rgb_permutations|   3|    100000|    1000|0.25210870|  PASSED
    rgb_permutations|   4|    100000|    1000|0.46336270|  PASSED
    rgb_permutations|   5|    100000|    1000|0.67270150|  PASSED
      rgb_lagged_sum|   0|   1000000|    1000|0.61944536|  PASSED
      rgb_lagged_sum|   1|   1000000|    1000|0.61837410|  PASSED
      rgb_lagged_sum|   2|   1000000|    1000|0.64649179|  PASSED
      rgb_lagged_sum|   3|   1000000|    1000|0.46348870|  PASSED
      rgb_lagged_sum|   4|   1000000|    1000|0.51559903|  PASSED
      rgb_lagged_sum|   5|   1000000|    1000|0.04304912|  PASSED
      rgb_lagged_sum|   6|   1000000|    1000|0.86691690|  PASSED
      rgb_lagged_sum|   7|   1000000|    1000|0.54463199|  PASSED
      rgb_lagged_sum|   8|   1000000|    1000|0.86603081|  PASSED
      rgb_lagged_sum|   9|   1000000|    1000|0.70460057|  PASSED
      rgb_lagged_sum|  10|   1000000|    1000|0.94594142|  PASSED
      rgb_lagged_sum|  11|   1000000|    1000|0.67528686|  PASSED
      rgb_lagged_sum|  12|   1000000|    1000|0.49938567|  PASSED
      rgb_lagged_sum|  13|   1000000|    1000|0.66266073|  PASSED
      rgb_lagged_sum|  14|   1000000|    1000|0.78669828|  PASSED
      rgb_lagged_sum|  15|   1000000|    1000|0.36421853|  PASSED
      rgb_lagged_sum|  16|   1000000|    1000|0.00077916|   WEAK
      rgb_lagged_sum|  17|   1000000|    1000|0.74879746|  PASSED
      rgb_lagged_sum|  18|   1000000|    1000|0.28380304|  PASSED
      rgb_lagged_sum|  19|   1000000|    1000|0.70405307|  PASSED
      rgb_lagged_sum|  20|   1000000|    1000|0.87577003|  PASSED
      rgb_lagged_sum|  21|   1000000|    1000|0.50476110|  PASSED
      rgb_lagged_sum|  22|   1000000|    1000|0.94805829|  PASSED
      rgb_lagged_sum|  23|   1000000|    1000|0.89480085|  PASSED
      rgb_lagged_sum|  24|   1000000|    1000|0.75660420|  PASSED
      rgb_lagged_sum|  25|   1000000|    1000|0.23838709|  PASSED
      rgb_lagged_sum|  26|   1000000|    1000|0.43403099|  PASSED
      rgb_lagged_sum|  27|   1000000|    1000|0.51755046|  PASSED
      rgb_lagged_sum|  28|   1000000|    1000|0.44677913|  PASSED
      rgb_lagged_sum|  29|   1000000|    1000|0.85653707|  PASSED
      rgb_lagged_sum|  30|   1000000|    1000|0.86613678|  PASSED
      rgb_lagged_sum|  31|   1000000|    1000|0.50247500|  PASSED
      rgb_lagged_sum|  32|   1000000|    1000|0.55996539|  PASSED
     rgb_kstest_test|   0|     10000|   10000|0.02084002|  PASSED
     dab_bytedistrib|   0|  51200000|      10|0.89573738|  PASSED
             dab_dct| 256|     50000|      10|0.99617818|   WEAK
Preparing to run test 207.  ntuple = 0
        dab_filltree|  32|  15000000|      10|0.19025818|  PASSED
        dab_filltree|  32|  15000000|      10|0.99586747|   WEAK
Preparing to run test 208.  ntuple = 0
       dab_filltree2|   0|   5000000|      10|0.98940673|  PASSED
       dab_filltree2|   1|   5000000|      10|0.69246377|  PASSED
Preparing to run test 209.  ntuple = 0
        dab_monobit2|  12|  65000000|      10|0.44216213|  PASSED

There was just one FAILED for diehard_sums (which I think is a suspect test anyway) and several WEAK results.

I also generated a histogram of the numbers which clearly shows an uneven distribution (which I had expected): ATmega328p floating analogue pin A0 histogram

My questions are:

  1. have I run dieharder incorrectly,
  2. have I misinterpreted the results or
  3. is my expectation that the data would fail the tests incorrect?
$\endgroup$
3
  • $\begingroup$ First of all you don't define the ADC reading values measure. Is it mV? Also the noise in your environment can be interfered by for example Wifi signals or telephone signals which has a specific frequency range and amplitude depending on the working mode. $\endgroup$
    – tur11ng
    Jul 17, 2022 at 18:06
  • 1
    $\begingroup$ The ADC is 10-bit, so 0 to 5v is mapped between 0 and 1023, therefor 4.9mV per unit. It is floating with a centre around around 1.47v using the histogram shown above as an estimate. $\endgroup$
    – JamesH
    Jul 17, 2022 at 18:28
  • $\begingroup$ It would be useful if you posted a snippet of Arduino_A0Float.txt $\endgroup$
    – Paul Uszak
    Jul 17, 2022 at 21:36

1 Answer 1

1
$\begingroup$

No. No. Yesish.

You can't use a floating ADC pin as a source of reliable entropy. There are two main reasons:-

  1. The input impedance of an Arduino ADC pin is $ \approx 100 \text{M} \Omega $. That means even the slightest current passing through the air (like the latest song on the radio) will cause charge accumulation. Or static. What you have is a de facto but very poor radio receiver. The voltage will build and build and shift all over the place. It may drop too if you wave your hand close by the pin. It will also pick up some of the adjacent electrical activity on the Ardunio PCB. Or if you touch it. It's completely unreliable. Resetting the Arduino may create a false sense of security, but the charge accumulation cannot be avoided given the huge impedance. It will get you eventually, and I can't say when.

  2. Notice the bath tub distribution of the histogram. It's the probability mass function of a sine wave, with a bit of noise (Taylor Swift's latest, or a lawn mower) overlaid. What you have charted is the electrical mains frequency. With a little extra calculation, you will be able to determine that the fundamental is either 50 Hz or 60 Hz.

What you have proven though, and very worringly, is the inherent weakness of most randomness test suites. As further evidence of such weaknesses, ent and the FIPS-140 tests will happily pass a .7z compressed archive! You've kinda nearly passed with a very flawed architecture featuring some external noise and some quantization noise.

But don't forget my point 1 above. Have a read of a more detailed analysis of this technique at Ardrand: The Arduino as a Hardware Random-Number Generator.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.