1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
.. _random_number_generators:
Random Number Generators
========================================
The random number generators provided in Botan are meant for creating
keys, IVs, padding, nonces, and anything else that requires 'random'
data. It is important to remember that the output of these classes
will vary, even if they are supplied with the same seed (ie, two
``Randpool`` objects with similar initial states will not produce the
same output, because the value of high resolution timers is added to
the state at various points).
To create a random number generator, instantiate a ``AutoSeeded_RNG``
object. This object will handle choosing the right algorithms from the
set of enabled ones and doing seeding using OS specific
routines. The main service a RandomNumberGenerator provides is, of
course, random numbers:
.. cpp:function:: byte RandomNumberGenerator::random()
Generates a single random byte and returns it
.. cpp:function:: void RandomNumberGenerator::randomize(byte* data, size_t length)
Places *length* bytes into the array pointed to by *data*
To ensure good quality output, a PRNG needs to be seeded with truly
random data. Normally this is done for you. However it may happen that
your application has access to data that is potentially unpredictable
to an attacker. If so, use
.. cpp:function:: void RandomNumberGenerator::add_entropy(const byte* data, \
size_t length)
which incorporates the data into the current randomness state. Don't
worry about filtering the data or doing any kind of cryptographic
preprocessing (such as hashing); the RNG objects in botan are designed
such that you can feed them any arbitrary non-random or even
maliciously chosen data - as long as at some point some of the seed
data was good the output will be secure.
Implementation Notes
----------------------------------------
Randpool
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
``Randpool`` is the primary PRNG within Botan. In recent versions all
uses of it have been wrapped by an implementation of the X9.31 PRNG
(see below). If for some reason you should have cause to create a PRNG
instead of using the "global" one owned by the library, it would be
wise to consider the same on the grounds of general caution; while
``Randpool`` is designed with known attacks and PRNG weaknesses in
mind, it is not an standard/official PRNG. The remainder of this
section is a (fairly technical, though high-level) description of the
algorithms used in this PRNG. Unless you have a specific interest in
this subject, the rest of this section might prove somewhat
uninteresting.
``Randpool`` has an internal state called pool, which is 512 bytes
long. This is where entropy is mixed into and extracted from. There is also a
small output buffer (called buffer), which holds the data which has already
been generated but has just not been output yet.
It is based around a MAC and a block cipher (which are currently
HMAC(SHA-256) and AES-256). Where a specific size is mentioned, it
should be taken as a multiple of the cipher's block size. For example,
if a 256-bit block cipher were used instead of AES, all the sizes
internally would double. Every time some new output is needed, we
compute the MAC of a counter and a high resolution timer. The
resulting MAC is XORed into the output buffer (wrapping as needed),
and the output buffer is then encrypted with AES, producing 16 bytes
of output.
After 8 blocks (or 128 bytes) have been produced, we mix the pool. To
do this, we first rekey both the MAC and the cipher; the new MAC key
is the MAC of the current pool under the old MAC key, while the new
cipher key is the MAC of the current pool under the just-chosen MAC
key. We then encrypt the entire pool in CBC mode, using the current
(unused) output buffer as the IV. We then generate a new output
buffer, using the mechanism described in the previous paragraph.
To add randomness to the PRNG, we compute the MAC of the input and XOR
the output into the start of the pool. Then we remix the pool and
produce a new output buffer. The initial MAC operation should make it
very hard for chosen inputs to harm the security of ``Randpool``, and
as HMAC should be able to hold roughly 256 bits of state, it is
unlikely that we are wasting much input entropy (or, if we are, it
doesn't matter, because we have a very abundant supply).
ANSI X9.31
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
``ANSI_X931_PRNG`` is the standard issue X9.31 Appendix A.2.4 PRNG,
though using AES-256 instead of 3DES as the block cipher. This PRNG
implementation has been checked against official X9.31 test vectors.
Internally, the PRNG holds a pointer to another PRNG (typically
Randpool). This internal PRNG generates the key and seed used by the
X9.31 algorithm, as well as the date/time vectors. Each time an X9.31
PRNG object receives entropy, it passes it along to the PRNG it is
holding, and then pulls out some random bits to generate a new key and
seed. This PRNG considers itself seeded as soon as the internal PRNG
is seeded.
Entropy Sources
---------------------------------
An ``EntropySource`` is an abstract representation of some method of
gather "real" entropy. This tends to be very system dependent. The
*only* way you should use an ``EntropySource`` is to pass it to a PRNG
that will extract entropy from it -- never use the output directly for
any kind of key or nonce generation!
``EntropySource`` has a pair of functions for getting entropy from
some external source, called ``fast_poll`` and ``slow_poll``. These
pass a buffer of bytes to be written; the functions then return how
many bytes of entropy were gathered.
Note for writers of ``EntropySource`` subclasses: it isn't necessary
to use any kind of cryptographic hash on your output. The data
produced by an EntropySource is only used by an application after it
has been hashed by the ``RandomNumberGenerator`` that asked for the
entropy, thus any hashing you do will be wasteful of both CPU cycles
and entropy.
|