The NIST Frequency Monobit test in Ruby
In some symmetric key systems pseudorandom number generators (PNRG) are used to create a keystream for encrypting plaintext. An important part of cryptography is key generation, and a strong key is as close to random as possible (PNRG sequences aren’t truly random, as they are generated from a seed, but that’s for another day).
We won’t get into the actual key generation in this post, but we are going to look at how to evaluate the randomness of the key. The National Institute of Standards and Technology (NIST) created a suite of 15 tests to check for randomness in binary sequences generated by PNRGs.
We’re going to implement the first test, The Frequency (Monobit) Test, in Ruby!
The Frequency (Monobit) Test
Given a sequence of bits, the test checks the proportions of zeroes and ones in the sequence, with the purpose of determining if the number of ones and zeros in the input is close to what we would expect for a random sequence. It’s important to note that the NIST also recommends a minimum length of 100 for the input, but I’ve chosen a small input for simplicity’s sake.
The test has a few (relatively) straightforward steps:
-
First given a sequence of bits, we have to change the 0’s to -1, and sum the result
To simplify the implementation, we’ll use an array to hold the sequence.
Then convert it:
Sum the result from step 1, and take the absolute value
- Calculate the test statistic Sobs, here’s the formula:
Where S is the sum from step 1, and n the number of elements in the original input: Sobs = S/√n
-
With the value for Sobs, we compute the P-value. For this we’ll need the complementary error function (erfc), which luckily for us is included in Ruby!
P-value = erfc(Sobs/2)
Interpreting the results
As a threshold for the randomness test, the NIST specifies a minimum value of 1%. So
if the result from step 3 is greater or equal to 0.01, we can conclude the sequence is random.
So for the example above, we could conclude that our test sequence with a value of 0.59, passes the test!
———
A more complete implementation in Ruby could look something like this:
Further reading
If you’re interested in the tests at a deeper level, check out the original publication by the NIST. It’s a really interesting read:
NIST: A. Rukhin; J. Soto; J. Nechvatal et al. (2010): A Statistical Test Suite for Random and Pseudorandom Number Generators for Cryptographic Applications
[“ruby”, “cryptography”]