Buy

How the TKey Random Number Generator App works

Introduction

The TKey Secure Random Number Generator app allows a user and a client system to get high-quality random numbers from a source separate from the client. A unique feature of the app is that it can also sign the random data delivered, thus allowing the user to verify the integrity of the generator, the integrity of the data, and the origin of the data delivered. But a secure random number generator must also deliver high-quality random numbers. In this blog post, we will look at how the generator works and the measured quality. In a coming blog post will discuss the signing and verifying in more detail.

Secure Random Number Generators

The TKey Secure Random Number Generator app is influenced by the Hash_DRBG random number generator specified by NIST in SP 800-90A. The Hash_DRBG is what NIST refers to as a deterministic random bit generator (DBRG), basically an algorithm that, given a seed state, will generate a sequence of numbers while updating its internal state. Outside of NIST, these types of algorithms are called pseudorandom number generators (PRNGs) and, for security-related use cases, cryptographically secure pseudo random number generators (CSPRNG).

An important aspect of a CSPRNG is that there is an internal, secret state that is used to generate the output. But observing the generated output does not aid an attacker in being able to guess previous or future outputs. The state may also be reseeded to add new entropy (i.e., random noise collected from a physical source) to make it harder for an attacker to guess the internal state.

The Hash_DRBG is built around a cryptographically secure hash function, for example SHA-256. The internal state is hashed. Parts of the resulting digest are presented as output. The digest, combined with internal counters, is used to update the internal state.

The NIST Hash_DRBG standard is quite complex, with requirements on functions to instantiate or remove a generator, mechanisms to set and check security levels, etc. For the TKey application, these functions do not really make sense, and we chose not to implement all of the required functionality according to the standard. This is why we say that the generator is influenced by, not an implementation of, the NIST Hash_DRBG.

Internals

The app uses the BLAKE2s hash function. BLAKE2s is available in the TKey firmware for applications to use. BLAKE2s is also faster than SHA-256. The internal state is a complete, 512-bit BLAKE2s block. The digest generated by BLAKE2s is 256 bits and of these, 128 bits (16 bytes) are presented to the client as output.

The internal state as well as support counters, etc. are defined in a rng_ctx (ctx as in context) struct that can be found in rng.h. The structure is as follows:

// state context
typedef struct {
uint32_t state_ctr_lsb;
uint32_t state_ctr_msb;
uint32_t reseed_ctr;
uint32_t state[16];
uint32_t digest[8];
} rng_ctx;

Going through the context structure will help explain how the context is created, updated, and used during random data generation.

state_ctr_lsb and state_ctr_msb

The state_ctr_lsb and state_ctr_msb together form a 64-bit, non-saturating counter. This counter is randomly initialized when the TKey application is started using the TKey True Random Number Generator (TRNG) entropy source. The counter is monotonically increased each time a hash digest is generated. The counter values are mixed into two of the state words updated with the digest. This prevents the hash state from being static between two hash operations, even if the digest generated is the same.

reseed_ctr

The reseed_ctr keeps track of the number of hash operations performed and, thus, when it is time to reseed the state. By default, reseed happens every 1000 hash operations. That is, every 16 kiByte of generated data will be based on new entropy. The reseed frequency is defined at compile time to not allow an attacker to change the frequency through a command.

state[16]

The state array is the “message” being hashed to generate the digest. The state is divided into two parts: The lower eight 32-bit words are updated every time a digest has been calculated. The upper eight 32-bit words contain the entropy collected during the last reseed. When updating the state, the latest digest is moved into the lower eight words of the state. Additionally, the counter is updated, and its 64-bit value is added to word 14 and 15, meaning that the entropy part will always change between hash operations.
When the TKey app has been loaded, the lower eight words of the state are initialized with the CDI calculated using the UDS and any User Supplied Secret (USS) by the firmware when the device app was loaded onto the TKey.

digest[8]

The digest is the latest digest generated and is stored until all 16 bytes have been provided to the client, and a new digest will then be generated.

Testing

We tested the generator by extracting about 1 GByte of data and then using two well-known programs.

ENT is a tool that is fast and easy to use. It does not provide a comprehensive test of random data, but its set of tests will detect a really broken generator. Thus, it is a good initial test. The test results from ENT:

Entropy = 8.000000 bits per byte.

Optimum compression would reduce the size
of this 1135320598 byte file by 0 percent.

Chi square distribution for 1135320598 samples is 250.82, and randomly
would exceed this value 56.22 percent of the times.

Arithmetic mean value of data bytes is 127.5021 (127.5 = random).
Monte Carlo value for Pi is 3.141601316 (error 0.00 percent).
Serial correlation coefficient is -0.000001 (totally uncorrelated = 0.0).

The ENT results indicate no obvious patterns that can be compressed, no bias, and a distribution close to what is expected for a uniform random number source.

A much more comprehensive test suite is provided by the tool PractRand. Compared to tools such as Dieharder, PractRand is harder to misuse. But similarly to Dieharder, it needs a lot of data to run its battery of tests. The test results from PractRand:

rng=RNG_stdin, seed=unknown
length= 1 gigabyte (2^30 bytes), time= 8.5 seconds
Test Name                       Raw      Processed   Evaluation
BCFN(2+0,13-1,T)                R= +2.6  p = 0.141   normal
BCFN(2+1,13-1,T)                R= +2.1  p = 0.193   normal
BCFN(2+2,13-1,T)                R= -2.2  p = 0.811   normal
BCFN(2+3,13-1,T)                R= +2.7  p = 0.133   normal
BCFN(2+4,13-2,T)                R= -5.0  p = 0.983   normal
BCFN(2+5,13-3,T)                R= +3.8  p = 0.065   normal
BCFN(2+6,13-3,T)                R= +2.9  p = 0.120   normal
BCFN(2+7,13-4,T)                R= -1.4  p = 0.706   normal
BCFN(2+8,13-5,T)                R= -0.5  p = 0.552   normal
BCFN(2+9,13-5,T)                R= +0.8  p = 0.350   normal
BCFN(2+10,13-6,T)               R= +3.7  p = 0.071   normal
BCFN(2+11,13-6,T)               R= -2.1  p = 0.806   normal
BCFN(2+12,13-7,T)               R= -1.3  p = 0.683   normal
BCFN(2+13,13-8,T)               R= +3.4  p = 0.084   normal
BCFN(2+14,13-8,T)               R= +1.6  p = 0.208   normal
BCFN(2+15,13-9,T)               R= +0.1  p = 0.388   normal
BCFN(2+16,13-9,T)               R= -0.5  p = 0.509   normal
DC6-9x1Bytes-1                  R= -0.8  p = 0.753   normal
Gap-16:A                        R= +2.3  p = 0.096   normal
Gap-16:B                        R= +0.5  p = 0.366   normal
FPF-14+6/16:(0,14-0)            R= -1.1  p = 0.782   normal
FPF-14+6/16:(1,14-0)            R= +1.4  p = 0.158   normal
FPF-14+6/16:(2,14-0)            R= +0.0  p = 0.489   normal
FPF-14+6/16:(3,14-0)            R= -0.1  p = 0.524   normal
FPF-14+6/16:(4,14-0)            R= +0.7  p = 0.323   normal
FPF-14+6/16:(5,14-0)            R= +1.2  p = 0.210   normal
FPF-14+6/16:(6,14-1)            R= -0.1  p = 0.546   normal
FPF-14+6/16:(7,14-2)            R= -3.6  p =1-4.4e-3 normal
FPF-14+6/16:(8,14-2)            R= -0.3  p = 0.573   normal
FPF-14+6/16:(9,14-3)            R= -0.2  p = 0.568   normal
FPF-14+6/16:(10,14-4)           R= +2.0  p = 0.085   normal
FPF-14+6/16:(11,14-5)           R= -1.6  p = 0.871   normal
FPF-14+6/16:(12,14-5)           R= -1.1  p = 0.778   normal
FPF-14+6/16:(13,14-6)           R= -0.9  p = 0.739   normal
FPF-14+6/16:(14,14-7)           R= -1.3  p = 0.830   normal
FPF-14+6/16:(15,14-8)           R= +0.0  p = 0.475   normal
FPF-14+6/16:(16,14-8)           R= -2.1  p = 0.946   normal
FPF-14+6/16:(17,14-9)           R= -0.8  p = 0.701   normal
FPF-14+6/16:(18,14-10)          R= +1.1  p = 0.212   normal
FPF-14+6/16:(19,14-11)          R= -0.8  p = 0.679   normal
FPF-14+6/16:(20,14-11)          R= +0.6  p = 0.295   normal
FPF-14+6/16:all                 R= -0.3  p = 0.588   normal
FPF-14+6/16:cross               R= +0.0  p = 0.446   normal
BRank(12):128(8)                R= -0.3  p~= 0.500   normal
BRank(12):256(4)                R= -0.2  p~= 0.500   normal
BRank(12):384(1)                R= -0.7  p~= 0.689   normal
BRank(12):512(4)                R= -0.2  p~= 0.500   normal
BRank(12):768(1)                R= +1.8  p~= 0.146   normal
BRank(12):1K(2)                 R= -0.2  p~= 0.554   normal
BRank(12):1536(1)               R= -0.7  p~= 0.689   normal
BRank(12):2K(2)                 R= +0.6  p~= 0.322   normal
BRank(12):3K(1)                 R= +1.8  p~= 0.146   normal
mod3n(5):(0,9-0)                R= +4.1  p = 0.023   normal
mod3n(5):(1,9-0)                R= -1.5  p = 0.771   normal
mod3n(5):(2,9-1)                R= -5.8  p =1-1.6e-3 normalish
mod3n(5):(3,9-1)                R= -1.9  p = 0.834   normal
mod3n(5):(4,9-2)                R= -2.9  p = 0.932   normal
mod3n(5):(5,9-2)                R= -3.2  p = 0.947   normal
mod3n(5):(6,9-3)                R= +3.1  p = 0.064   normal
mod3n(5):(7,9-3)                R= +0.2  p = 0.459   normal
mod3n(5):(8,9-4)                R= +0.1  p = 0.452   normal
mod3n(5):(9,9-4)                R= +0.2  p = 0.441   normal
mod3n(5):(10,9-5)               R= +2.0  p = 0.146   normal
mod3n(5):(11,9-5)               R= -0.9  p = 0.646   normal
mod3n(5):(12,9-6)               R= +3.0  p = 0.070   normal
mod3n(5):(13,9-6)               R= +5.6  p = 9.3e-3  normal
mod3n(5):(14,9-6)               R= -1.0  p = 0.668   normal
mod3n(5):(15,9-6)               R= -1.7  p = 0.828   normal
TMFn(2+0):wl                    R= -0.1  p~= 0.5     normal
TMFn(2+1):wl                    R= -3.6  p~= 0.9     normal
TMFn(2+2):wl                    R= +0.0  p~= 0.5     normal
TMFn(2+3):wl                    R= +1.2  p~= 0.3     normal
TMFn(2+4):wl                    R= +0.7  p~= 0.4     normal
TMFn(2+5):wl                    R= +0.4  p~= 0.4     normal
[Low1/8]BCFN(2+0,13-3,T)        R= +2.1  p = 0.193   normal
[Low1/8]BCFN(2+1,13-3,T)        R= +1.0  p = 0.329   normal
[Low1/8]BCFN(2+2,13-3,T)        R= -3.6  p = 0.936   normal
[Low1/8]BCFN(2+3,13-3,T)        R= -2.5  p = 0.848   normal
[Low1/8]BCFN(2+4,13-4,T)        R= +6.2  p = 0.011   normal
[Low1/8]BCFN(2+5,13-5,T)        R= -0.6  p = 0.569   normal
[Low1/8]BCFN(2+6,13-5,T)        R= +2.3  p = 0.167   normal
[Low1/8]BCFN(2+7,13-6,T)        R= +3.3  p = 0.095   normal
[Low1/8]BCFN(2+8,13-6,T)        R= -0.3  p = 0.506   normal
[Low1/8]BCFN(2+9,13-7,T)        R= +0.3  p = 0.406   normal
[Low1/8]BCFN(2+10,13-8,T)       R= +4.8  p = 0.039   normal
[Low1/8]BCFN(2+11,13-8,T)       R= -0.3  p = 0.482   normal
[Low1/8]BCFN(2+12,13-9,T)       R= +2.3  p = 0.135   normal
[Low1/8]BCFN(2+13,13-9,T)       R= +1.1  p = 0.253   normal
[Low1/8]DC6-9x1Bytes-1          R= -1.1  p = 0.831   normal
[Low1/8]Gap-16:A                R= +2.3  p = 0.105   normal
[Low1/8]Gap-16:B                R= +2.4  p = 0.048   normal
[Low1/8]FPF-14+6/16:(0,14-0)    R= +2.1  p = 0.070   normal
[Low1/8]FPF-14+6/16:(1,14-0)    R= -0.7  p = 0.682   normal
[Low1/8]FPF-14+6/16:(2,14-0)    R= -0.5  p = 0.634   normal
[Low1/8]FPF-14+6/16:(3,14-1)    R= -0.5  p = 0.637   normal
[Low1/8]FPF-14+6/16:(4,14-2)    R= +0.4  p = 0.389   normal
[Low1/8]FPF-14+6/16:(5,14-2)    R= -0.0  p = 0.509   normal
[Low1/8]FPF-14+6/16:(6,14-3)    R= +1.6  p = 0.131   normal [Low1/8]FPF-14+6/16:(7,14-4)    R= +1.3  p = 0.178   normal [Low1/8]FPF-14+6/16:(8,14-5)    R= -2.0  p = 0.923   normal [Low1/8]FPF-14+6/16:(9,14-5)    R= -0.4  p = 0.620   normal [Low1/8]FPF-14+6/16:(10,14-6)   R= +2.1  p = 0.073   normal [Low1/8]FPF-14+6/16:(11,14-7)   R= +2.9  p = 0.029   normal [Low1/8]FPF-14+6/16:(12,14-8)   R= -1.6  p = 0.873   normal [Low1/8]FPF-14+6/16:(13,14-8)   R= +0.8  p = 0.267   normal [Low1/8]FPF-14+6/16:(14,14-9)   R= -0.3  p = 0.544   normal [Low1/8]FPF-14+6/16:(15,14-10)  R= -1.5  p = 0.866   normal [Low1/8]FPF-14+6/16:(16,14-11)  R= -1.3  p = 0.841   normal [Low1/8]FPF-14+6/16:(17,14-11)  R= +3.9  p = 0.016   normal [Low1/8]FPF-14+6/16:all         R= +0.8  p = 0.311   normal [Low1/8]FPF-14+6/16:cross       R= +0.4  p = 0.322   normal
[Low1/8]BRank(12):128(4)        R= -0.8  p~= 0.670   normal
[Low1/8]BRank(12):256(4)        R= -1.4  p~= 0.890   normal
[Low1/8]BRank(12):384(1)        R= -0.7  p~= 0.689   normal
[Low1/8]BRank(12):512(2)        R= -1.0  p~= 0.744   normal
[Low1/8]BRank(12):768(1)        R= -0.7  p~= 0.689   normal
[Low1/8]BRank(12):1K(2)         R= +0.6  p~= 0.322   normal
[Low1/8]BRank(12):1536(1)       R= +1.8  p~= 0.146   normal
[Low1/8]mod3n(5):(0,9-1)        R= +2.1  p = 0.145   normal
[Low1/8]mod3n(5):(1,9-2)        R= +4.2  p = 0.021   normal
[Low1/8]mod3n(5):(2,9-2)        R= +3.7  p = 0.035   normal
[Low1/8]mod3n(5):(3,9-3)        R= +2.6  p = 0.100   normal
[Low1/8]mod3n(5):(4,9-3)        R= +2.1  p = 0.151   normal
[Low1/8]mod3n(5):(5,9-4)        R= -1.5  p = 0.767   normal
[Low1/8]mod3n(5):(6,9-4)        R= -1.3  p = 0.732   normal
[Low1/8]mod3n(5):(7,9-5)        R= +2.2  p = 0.129   normal
[Low1/8]mod3n(5):(8,9-5)        R= -2.1  p = 0.866   normal
[Low1/8]mod3n(5):(9,9-6)        R= +0.2  p = 0.405   normal
[Low1/8]mod3n(5):(10,9-6)       R= -0.8  p = 0.633   normal
[Low1/8]mod3n(5):(11,9-6)       R= -0.5  p = 0.563   normal
[Low1/8]mod3n(5):(12,9-6)       R= +0.5  p = 0.352   normal
[Low1/8]mod3n(5):(13,9-6)       R= +2.6  p = 0.092   normal
[Low1/8]TMFn(2+0):wl            R= -1.1  p~= 0.7     normal
[Low1/8]TMFn(2+1):wl            R= +1.4  p~= 0.3     normal
[Low1/8]TMFn(2+2):wl            R= +1.9  p~= 0.3     normal
[Low4/32]BCFN(2+0,13-3,T)       R= +2.6  p = 0.142   normal
[Low4/32]BCFN(2+1,13-3,T)       R= +0.9  p = 0.344   normal
[Low4/32]BCFN(2+2,13-3,T)       R= +2.5  p = 0.151   normal
[Low4/32]BCFN(2+3,13-3,T)       R= +1.2  p = 0.297   normal
[Low4/32]BCFN(2+4,13-4,T)       R= +0.2  p = 0.449   normal
[Low4/32]BCFN(2+5,13-5,T)       R= -0.1  p = 0.491   normal
[Low4/32]BCFN(2+6,13-5,T)       R= +3.9  p = 0.064   normal
[Low4/32]BCFN(2+7,13-6,T)       R= +9.5  p = 1.1e-3  normal
[Low4/32]BCFN(2+8,13-6,T)       R= -3.9  p = 0.969   normal
[Low4/32]BCFN(2+9,13-7,T)       R= +5.3  p = 0.028   normal
[Low4/32]BCFN(2+10,13-8,T)      R= -0.8  p = 0.591   normal
[Low4/32]BCFN(2+11,13-8,T)      R= -1.6  p = 0.733   normal
[Low4/32]BCFN(2+12,13-9,T)      R= -2.4  p = 0.910   normal
[Low4/32]BCFN(2+13,13-9,T)      R= -2.3  p = 0.893   normal
[Low4/32]DC6-9x1Bytes-1         R= +1.4  p = 0.362   normal
[Low4/32]Gap-16:A               R= +0.8  p = 0.420   normal
[Low4/32]Gap-16:B               R= +0.8  p = 0.283   normal
[Low4/32]FPF-14+6/16:(0,14-0)   R= +0.0  p = 0.492   normal
[Low4/32]FPF-14+6/16:(1,14-0)   R= +0.5  p = 0.358   normal
[Low4/32]FPF-14+6/16:(2,14-0)   R= +2.8  p = 0.027   normal
[Low4/32]FPF-14+6/16:(3,14-1)   R= +2.0  p = 0.078   normal
[Low4/32]FPF-14+6/16:(4,14-2)   R= -0.1  p = 0.532   normal
[Low4/32]FPF-14+6/16:(5,14-2)   R= -0.9  p = 0.743   normal
[Low4/32]FPF-14+6/16:(6,14-3)   R= -1.3  p = 0.830   normal
[Low4/32]FPF-14+6/16:(7,14-4)   R= -0.1  p = 0.529   normal
[Low4/32]FPF-14+6/16:(8,14-5)   R= -0.8  p = 0.715   normal
[Low4/32]FPF-14+6/16:(9,14-5)   R= +1.1  p = 0.210   normal
[Low4/32]FPF-14+6/16:(10,14-6)  R= +1.3  p = 0.178   normal
[Low4/32]FPF-14+6/16:(11,14-7)  R= -0.9  p = 0.730   normal
[Low4/32]FPF-14+6/16:(12,14-8)  R= -2.0  p = 0.930   normal
[Low4/32]FPF-14+6/16:(13,14-8)  R= -1.6  p = 0.885   normal
[Low4/32]FPF-14+6/16:(14,14-9)  R= +1.7  p = 0.126   normal
[Low4/32]FPF-14+6/16:(15,14-10) R= -1.2  p = 0.798   normal
[Low4/32]FPF-14+6/16:(16,14-11) R= +0.3  p = 0.362   normal
[Low4/32]FPF-14+6/16:(17,14-11) R= +2.9  p = 0.039   normal
[Low4/32]FPF-14+6/16:all        R= +1.8  p = 0.118   normal
[Low4/32]FPF-14+6/16:cross      R= -0.1  p = 0.500   normal
[Low4/32]BRank(12):128(4)       R= -0.8  p~= 0.670   normal
[Low4/32]BRank(12):256(4)       R= -0.1  p~= 0.490   normal
[Low4/32]BRank(12):384(1)       R= -0.7  p~= 0.689   normal
[Low4/32]BRank(12):512(2)       R= +0.8  p~= 0.293   normal
[Low4/32]BRank(12):768(1)       R= +0.4  p~= 0.366   normal
[Low4/32]BRank(12):1K(2)        R= -1.0  p~= 0.744   normal
[Low4/32]BRank(12):1536(1)      R= +1.8  p~= 0.146   normal
[Low4/32]mod3n(5):(0,9-1)       R= +3.7  p = 0.032   normal
[Low4/32]mod3n(5):(1,9-2)       R= +3.4  p = 0.049   normal
[Low4/32]mod3n(5):(2,9-2)       R= -3.1  p = 0.946   normal
[Low4/32]mod3n(5):(3,9-3)       R= -0.4  p = 0.575   normal
[Low4/32]mod3n(5):(4,9-3)       R= +3.5  p = 0.043   normal
[Low4/32]mod3n(5):(5,9-4)       R= -0.9  p = 0.656   normal
[Low4/32]mod3n(5):(6,9-4)       R= -1.2  p = 0.725   normal
[Low4/32]mod3n(5):(7,9-5)       R= +1.5  p = 0.213   normal
[Low4/32]mod3n(5):(8,9-5)       R= -2.4  p = 0.905   normal
[Low4/32]mod3n(5):(9,9-6)       R= -1.0  p = 0.676   normal
[Low4/32]mod3n(5):(10,9-6)      R= +1.2  p = 0.232   normal
[Low4/32]mod3n(5):(11,9-6)      R= +1.6  p = 0.180   normal
[Low4/32]mod3n(5):(12,9-6)      R= -1.8  p = 0.836   normal
[Low4/32]mod3n(5):(13,9-6)      R= +0.3  p = 0.374   normal
[Low4/32]TMFn(2+0):wl           R= +1.0  p~= 0.4     normal
[Low4/32]TMFn(2+1):wl           R= -1.9  p~= 0.7     normal
[Low4/32]TMFn(2+2):wl           R= +0.8  p~= 0.4     normal
[Low1/32]BCFN(2+0,13-4,T)       R= +0.1  p = 0.462   normal
[Low1/32]BCFN(2+1,13-4,T)       R= +1.7  p = 0.230   normal
[Low1/32]BCFN(2+2,13-5,T)       R= +0.3  p = 0.422   normal
[Low1/32]BCFN(2+3,13-5,T)       R= -3.8  p = 0.957   normal
[Low1/32]BCFN(2+4,13-5,T)       R= +5.7  p = 0.018   normal
[Low1/32]BCFN(2+5,13-6,T)       R= -1.0  p = 0.641   normal
[Low1/32]BCFN(2+6,13-6,T)       R= -4.2  p = 0.979   normal
[Low1/32]BCFN(2+7,13-7,T)       R= -1.5  p = 0.711   normal
[Low1/32]BCFN(2+8,13-8,T)       R= -0.1  p = 0.444   normal
[Low1/32]BCFN(2+9,13-8,T)       R= +0.2  p = 0.407   normal
[Low1/32]BCFN(2+10,13-9,T)      R= +2.7  p = 0.111   normal
[Low1/32]BCFN(2+11,13-9,T)      R= -2.6  p = 0.933   normal
[Low1/32]DC6-9x1Bytes-1         R= +2.5  p = 0.182   normal
[Low1/32]FPF-14+6/16:(0,14-0)   R= +0.1  p = 0.476   normal
[Low1/32]FPF-14+6/16:(1,14-1)   R= -1.8  p = 0.908   normal
[Low1/32]FPF-14+6/16:(2,14-2)   R= -0.1  p = 0.528   normal
[Low1/32]FPF-14+6/16:(3,14-2)   R= +1.1  p = 0.227   normal
[Low1/32]FPF-14+6/16:(4,14-3)   R= -0.0  p = 0.507   normal
[Low1/32]FPF-14+6/16:(5,14-4)   R= +1.1  p = 0.212   normal
[Low1/32]FPF-14+6/16:(6,14-5)   R= +1.1  p = 0.223   normal
[Low1/32]FPF-14+6/16:(7,14-5)   R= -0.3  p = 0.594   normal
[Low1/32]FPF-14+6/16:(8,14-6)   R= -1.8  p = 0.897   normal
[Low1/32]FPF-14+6/16:(9,14-7)   R= -0.1  p = 0.512   normal
[Low1/32]FPF-14+6/16:(10,14-8)  R= -0.3  p = 0.565   normal
[Low1/32]FPF-14+6/16:(11,14-8)  R= -0.9  p = 0.727   normal
[Low1/32]FPF-14+6/16:(12,14-9)  R= -0.6  p = 0.648   normal
[Low1/32]FPF-14+6/16:(13,14-10) R= -0.0  p = 0.455   normal
[Low1/32]FPF-14+6/16:(14,14-11) R= +5.5  p = 3.5e-3  normal
[Low1/32]FPF-14+6/16:(15,14-11) R= -0.1  p = 0.471   normal
[Low1/32]FPF-14+6/16:all        R= -0.4  p = 0.627   normal
[Low1/32]FPF-14+6/16:cross      R= -0.1  p = 0.502   normal
[Low1/32]BRank(12):128(4)       R= +0.4  p~= 0.340   normal
[Low1/32]BRank(12):256(2)       R= -0.2  p~= 0.554   normal
[Low1/32]BRank(12):384(1)       R= -0.7  p~= 0.689   normal
[Low1/32]BRank(12):512(2)       R= +0.6  p~= 0.322   normal
[Low1/32]BRank(12):768(1)       R= +1.8  p~= 0.146   normal
[Low1/32]BRank(12):1K(1)        R= +0.4  p~= 0.366   normal
[Low1/32]mod3n(5):(0,9-2)       R= -0.7  p = 0.626   normal
[Low1/32]mod3n(5):(1,9-3)       R= +1.6  p = 0.206   normal
[Low1/32]mod3n(5):(2,9-3)       R= +2.8  p = 0.084   normal
[Low1/32]mod3n(5):(3,9-4)       R= -0.2  p = 0.530   normal
[Low1/32]mod3n(5):(4,9-4)       R= +3.5  p = 0.049   normal
[Low1/32]mod3n(5):(5,9-5)       R= -3.4  p = 0.977   normal
[Low1/32]mod3n(5):(6,9-5)       R= -0.3  p = 0.519   normal
[Low1/32]mod3n(5):(7,9-6)       R= +1.0  p = 0.257   normal
[Low1/32]mod3n(5):(8,9-6)       R= +1.6  p = 0.176   normal
[Low1/32]mod3n(5):(9,9-6)       R= +3.3  p = 0.057   normal
[Low1/32]mod3n(5):(10,9-6)      R= +4.3  p = 0.026   normal
[Low1/32]mod3n(5):(11,9-6)      R= +2.0  p = 0.136   normal
[Low1/32]TMFn(2+0):wl           R= -0.6  p~= 0.6     normal

PractRand performs a lot of tests, but none of the tests performed by PractRand failed. This result indicates that the TKey app can produce random numbers with a quality on par with that expected from a working random number generator capable of generating data that can be used for security-related use cases.

Conclusions

The TKey random number generator app is a high-quality generator based around the BLAKE2s hash function with a state updated using the TKey internal true random number source. The app can be used in systems that need access to cryptographically strong random numbers. And since the app is also able to sign the data (which we will cover in another blog post), it can be trusted to come from the TKey and the app described here.




Cover image: Gordon Johnson