I have been experimenting with a new hardware RNG based on Wi-Fi background noise. Wi-Fi (also known as WLAN, Wireless LAN, or IEEE 802.11) devices measure the background noise in their environment. Electromagnetic noise is a physical phenomena, and hence it (its shape and its variations) should be random, in theory. Using standard Wi-Fi hardware and software, today, the noise level information is accessible to the user. No special hardware is needed. You only need an association with a standard access point (infrastructure mode, or "managed mode" in Linux jargon). The ad hoc mode will be studied later.
In Linux, the character special device /dev/random already provides high quality random numbers. Why bother with an alternative solution? Because, the /dev/random device's entropy sources are the keyboard, mouse pointer, and hard drive (see the theory of operation and C code by Theodore Ts'o). These entropy sources may not be available on handheld or even smaller devices which are, however, likely to be equipped with a wireless interface e.g. Wi-Fi.
HARDWARE & SOFTWARE THAT I USED
Laptop computer Linux Wireless extensions and wireless tools (this should be available by default) Intel PRO/Wireless 2200BG Intel PRO/Wireless 2200BG Driver
pars@lazylizard:~$ iwconfig
lo no wireless extensions.
eth1 no wireless extensions.
eth0 IEEE 802.11g ESSID:"lepassager"
Mode:Managed Frequency:2.462 GHz Access Point: 00:0F:66:D9:DE:14
Bit Rate=5.5 Mb/s Tx-Power=20 dBm
Retry limit:7 RTS thr:off Fragment thr:off
Power Management:off
Link Quality=55/100 Signal level=-68 dBm Noise level=-83 dBm
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:96 Invalid misc:1 Missed beacon:1
sit0 no wireless extensions.
pars@lazylizard:~$
Some Wi-Fi cards will report "zero" noise level. This is wrong. It is
never zero. If you are lucky and you do not have one of those cards, you
should see a very small noise level (this is my case as shown above). If so, repeat the
iwrandom command and observe how the noise level changes. It is hard
to predict "when" it will change. The variations look random
(see the initial test results below). The iwconfig command reads
/proc/net/wireless to get this information. Here is a snapshot:
pars@lazylizard:~$ cat /proc/net/wireless
Inter-| sta-| Quality | Discarded packets | Missed
face | tus | link level noise | nwid crypt frag retry misc | beacon
eth0: 0000 64. 194. 172. 0 0 0 78 0 0
pars@lazylizard:~$
Here we see the signal and noise levels (and many other information
that are off topic here). These are reported in unsigned dBm (decibel
milliwatt), i.e. dBm+256. Consequently, in the above example 172
corresponds to -84 dBm, or 10-8.4 milliwatt of background noise.
To generate random bits, I wrote a C code and called it
iwrandom.c (available below for download). Here
is how it works (illustrated on the left):
gcc iwrandom.c -o iwrandom
This will generate the iwrandom file in your current directory. This is the
executable file.
Type
./iwrandom
This will generate the following message:
pars@lazylizard:~/Desktop/iwrandom$ ./iwrandom
Usage: iwrandom -n NUMBER -s SPEED -o FILE
(where, NUMBER>0, SPEED>0 and top speed is the 8th.)
Recommended speed is the 2nd speed.
Example command:
iwrandom -n 1024 -s 2 -o result
pars@lazylizard:~/Desktop/iwrandom$
Here NUMBER is the number of random bytes that you want to generate. FILE
is the name of the output file where the random bytes will be written.
SPEED is the speed factor for random number generation. It has no unit. It is rather like: 1st speed, 2nd speed, 3rd speed etc. It multiplies the random number generation speed by a factor or your choice. As described above, whenever a noise level change is detected, a number of random bits are taken from the CounTer variable, and CounTer is reset to zero. The speed option determines the number of random bits taken from CounTer (starting from the least significant bit). For example if you select the first speed (-s 1) only the least significant bit of CounTer will be taken for random number generation. The remaining 7 bits will be thrown away. If you select the second speed (-s 2) the two least significant bits of CounTer will be taken, etc. Clearly, the greater the speed value, the faster the random numbers will be generated. Because, a smaller number of bits will be thrown away.
However, care should be taken. AT HIGH SPEEDS, RANDOMNESS CAN BE LOST. This is probably because the noise level, sometimes, changes frequently. Therefore, the leftmost bits of CounTer may sometimes be "non-randomly zero". Be careful with the SPEED option. High speeds are for experimenting.
pars@lazylizard:~/Desktop/iwrandom/RESULTIWRANDOM$ ent result Entropy = 7.976640 bits per byte. Optimum compression would reduce the size of this 8192 byte file by 0 percent. Chi square distribution for 8192 samples is 263.81, and randomly would exceed this value 50.00 percent of the times. Arithmetic mean value of data bytes is 126.4719 (127.5 = random). Monte Carlo value for Pi is 3.117948718 (error 0.75 percent). Serial correlation coefficient is -0.012639 (totally uncorrelated = 0.0). pars@lazylizard:~/Desktop/iwrandom/RESULTIWRANDOM$In the above example, ENT is applied to the 8192-byte (8K) file "result" produced with iwrandom. ENT performs six different tests. It measures the entropy per byte (ideally 8 bits), compressibility (ideally 0%), performs a Chi square test (ideally 50.00%), calculates the arithmetic mean value (ideally 127.5), the Monte Carlo value for Pi (ideally equals Pi) and the serial correlation coefficient (ideally 0).
Here are 10 results obtained with iwrandom (at 2nd speed) and 10 results obtained with /dev/random:
| FILE | Size | Entropy | Comp | ChiSqr | Mean | Pierr | Scc |
| iwrandom-s2-r1 | 8192 | 7.976640 | 0% | 50.00% | 126.4719 | 0.75% | -0.012639 |
| iwrandom-s2-r2 | 8192 | 7.977084 | 0% | 50.00% | 127.0900 | 1.13% | -0.014197 |
| iwrandom-s2-r3 | 8192 | 7.977875 | 0% | 50.00% | 127.9049 | 0.55 % | 0.005516 |
| iwrandom-s2-r4 | 8192 | 7.975658 | 0% | 25.00% | 127.4629 | 1.21% | -0.003286 |
| iwrandom-s2-r5 | 8192 | 7.974438 | 0% | 10.00% | 127.4209 | 2.43% | -0.016758 |
| iwrandom-s2-r6 | 8192 | 7.977012 | 0% | 50.00% | 127.7972 | 1.86% | 0.001800 |
| iwrandom-s2-r7 | 8192 | 7.981149 | 0% | 95.00% | 126.6578 | 1.30% | 0.003421 |
| iwrandom-s2-r8 | 8192 | 7.978407 | 0% | 50.00% | 127.4510 | 2.33% | -0.001519 |
| iwrandom-s2-r9 | 8192 | 7.974169 | 0% | 10.00% | 127.8157 | 0.18 % | -0.021584 |
| iwrandom-s2-r10 | 8192 | 7.977851 | 0% | 50.00 % | 127.6062 | 2.51% | -0.002849 |
| FILE | Size | Entropy | Comp | ChiSqr | Mean | Pierr | Scc |
| devrandom-r1 | 8192 | 7.973796 | 0% | 5.00% | 127.3165 | 0.74% | 0.005814 |
| devrandom-r2 | 8192 | 7.981868 | 0% | 99.00% | 127.4762 | 0.55% | 0.010902 |
| devrandom-r3 | 8192 | 7.979595 | 0% | 75.00% | 127.4924 | 1.78% | -0.009067 |
| devrandom-r4 | 8192 | 7.976297 | 0% | 50.00% | 127.2339 | 0.46% | -0.014335 |
| devrandom-r5 | 8192 | 7.980761 | 0% | 95.00% | 126.2734 | 0.83% | 0.022369 |
| devrandom-r6 | 8192 | 7.976833 | 0% | 50.00% | 127.4653 | 1.39% | 0.008806 |
| devrandom-r7 | 8192 | 7.978933 | 0% | 75.00% | 127.4277 | 1.39% | 0.023459 |
| devrandom-r8 | 8192 | 7.976584 | 0% | 50.00% | 127.3192 | 0.55% | 0.007596 |
| devrandom-r9 | 8192 | 7.976848 | 0% | 50.00% | 128.2788 | 1.97% | 0.017584 |
| devrandom-r10 | 8192 | 7.976315 | 0% | 25.00% | 127.8433 | 0.75% | 0.008954 |
It can be noted that iwrandom and /dev/random produce similar results. For more interpretation of the results check here. The most difficult test to pass the Chi square test. Quoting John Walker, "If the percentage is greater than 99% or less than 1%, the sequence is almost certainly not random. If the percentage is between 99% and 95% or between 1% and 5%, the sequence is suspect. Percentages between 90% and 95% and 5% and 10% indicate the sequence is almost suspect."
iwrandom successfully passed the chi square test. Below is an ENT test
result produced with larger, 80122 byte, random data generated with iwrandom.
The result is promising.
pars@lazylizard:~/Desktop/iwrandom$ ent iwrandom-s2-rBIG
Entropy = 7.997535 bits per byte.
Optimum compression would reduce the size
of this 80122 byte file by 0 percent.
Chi square distribution for 80122 samples is 272.23, and randomly
would exceed this value 25.00 percent of the times.
Arithmetic mean value of data bytes is 127.8388 (127.5 = random).
Monte Carlo value for Pi is 3.152549989 (error 0.35 percent).
Serial correlation coefficient is -0.000224 (totally uncorrelated = 0.0).
pars@lazylizard:~/Desktop/iwrandom$
These files are available on demand.
For further comparison, you can also check the ENT results obtained by the random.org team. Their randomness source is the atmospheric noise from a radio. Note that this technique is similar to that of iwrandom. However, with iwrandom no special hardware is needed. It uses commodity Wi-Fi equipment.
When you execute the iwrandom command, you should see something
like:
pars@lazylizard:~/Desktop/iwrandom$ ./iwrandom -n 10 -s 2 -o result
Creating output file 'result'... OK.
Checking "/proc/net/wireless"... OK.
Checking noise level variations... OK.
Generating random numbers (2nd speed):
<00001011> 1 of 10 bytes OK.
<00111010> 2 of 10 bytes OK.
<10111100> 3 of 10 bytes OK.
<11101011> 4 of 10 bytes OK.
<11011110> 5 of 10 bytes OK.
<00010111> 6 of 10 bytes OK.
<11101010> 7 of 10 bytes OK.
<11001111> 8 of 10 bytes OK.
<00000111> 9 of 10 bytes OK.
<01100010> 10 of 10 bytes OK.
Generated 0.7 bytes per second on the average.
pars@lazylizard:~/Desktop/iwrandom$
The program first checks the presence of /proc/net/wireless, where the noise
values will be read. If this fails, you probably do not have wireless tools. Next, noise
levels variations are checked. The program will block until a change is detected. As
described above, iwrandom is based on noise level variations. If, for some
reason, the noise level does not change, the program will block. You can exit with
Ctrl-C, in this case. The noise level may be constant (or, zero), if for example your
Wi-Fi device, or driver does not report low noise levels. If you think that this
is your case, please tell me which Wi-Fi hardware and driver you are using. Or,
there may be a bug in my parsing code, and it fails to read /proc/net/wireless
on your system correctly, for some reason that I could not foresee! Please tell
me in this case.