Crate concrete_csprng
source ·Expand description
Cryptographically secure pseudo random number generator.
Welcome to the concrete-csprng
documentation.
This crate provides a fast cryptographically secure pseudo-random number generator, suited to work in a multithreaded setting.
§Random Generators
The central abstraction of this crate is the RandomGenerator
trait, which is implemented by different types, each supporting a different platform. In
essence, a type implementing RandomGenerator
is a type that
outputs a new pseudo-random byte at each call to
next_byte
. Such a generator g
can be seen as
enclosing a growing index into an imaginary array of pseudo-random bytes:
0 1 2 3 4 5 6 7 8 9 M-1 │
┏━┯━┯━┯━┯━┯━┯━┯━┯━┯━┯━━━┯━┓ │
┃ │ │ │ │ │ │ │ │ │ │...│ ┃ │
┗↥┷━┷━┷━┷━┷━┷━┷━┷━┷━┷━━━┷━┛ │
g │
│
g.next_byte() │
│
0 1 2 3 4 5 6 7 8 9 M-1 │
┏━┯━┯━┯━┯━┯━┯━┯━┯━┯━┯━━━┯━┓ │
┃╳│ │ │ │ │ │ │ │ │ │...│ ┃ │
┗━┷↥┷━┷━┷━┷━┷━┷━┷━┷━┷━━━┷━┛ │
g │
│
g.next_byte() │ legend:
│ -------
0 1 2 3 4 5 6 7 8 9 M-1 │ ↥ : next byte to be outputted by g
┏━┯━┯━┯━┯━┯━┯━┯━┯━┯━┯━━━┯━┓ │ │ │: byte not yet outputted by g
┃╳│╳│ │ │ │ │ │ │ │ │...│ ┃ │ │╳│: byte already outputted by g
┗━┷━┷↥┷━┷━┷━┷━┷━┷━┷━┷━━━┷━┛ │
g 🭭
While being large, this imaginary array is still bounded to M = 2¹³² bytes. Consequently, a
generator is always bounded to a maximal index. That is, there is always a max amount of
elements of this array that can be outputted by the generator. By default, generators created
via new
are always bounded to M-1.
§Tree partition of the pseudo-random stream
One particularity of this implementation is that you can use the
try_fork
method to create an arbitrary partition tree
of a region of this array. Indeed, calling try_fork(nc, nb)
outputs nc
new generators, each
able to output nb
bytes. The try_fork
method ensures that the states and bounds of the
parent and children generators are set so as to prevent the same substream to be outputted
twice:
0 1 2 3 4 5 6 7 8 9 M │
┏━┯━┯━┯━┯━┯━┯━┯━┯━┯━┯━━━┯━┓ │
┃P│P│P│P│P│P│P│P│P│P│...│P┃ │
┗↥┷━┷━┷━┷━┷━┷━┷━┷━┷━┷━━━┷━┛ │
p │
│
(a,b) = p.fork(2,4) │
│
0 1 2 3 4 5 6 7 8 9 M │
┏━┯━┯━┯━┯━┯━┯━┯━┯━┯━┯━━━┯━┓ │
┃A│A│A│A│B│B│B│B│P│P│...│P┃ │
┗↥┷━┷━┷━┷↥┷━┷━┷━┷↥┷━┷━━━┷━┛ │
a b p │
│ legend:
(c,d) = b.fork(2, 1) │ -------
│ ↥ : next byte to be outputted by p
0 1 2 3 4 5 6 7 8 9 M │ │P│: byte to be outputted by p
┏━┯━┯━┯━┯━┯━┯━┯━┯━┯━┯━━━┯━┓ │ │╳│: byte already outputted
┃A│A│A│A│C│D│B│B│P│P│...│P┃ │
┗↥┷━┷━┷━┷↥┷↥┷↥┷━┷↥┷━┷━━━┷━┛ │
a c d b p 🭭
This makes it possible to consume the stream at different places. This is particularly useful in a multithreaded setting, in which we want to use the same generator from different independent threads:
0 1 2 3 4 5 6 7 8 9 M │
┏━┯━┯━┯━┯━┯━┯━┯━┯━┯━┯━━━┯━┓ │
┃A│A│A│A│C│D│B│B│P│P│...│P┃ │
┗↥┷━┷━┷━┷↥┷↥┷↥┷━┷↥┷━┷━━━┷━┛ │
a c d b p │
│
a.next_byte() │
│
0 1 2 3 4 5 6 7 8 9 M │
┏━┯━┯━┯━┯━┯━┯━┯━┯━┯━┯━━━┯━┓ │
┃╳│A│A│A│C│D│B│B│P│P│...│P┃ │
┗━┷↥┷━┷━┷↥┷↥┷↥┷━┷↥┷━┷━━━┷━┛ │
a c d b p │
│ legend:
b.next_byte() │ -------
│ ↥ : next byte to be outputted by p
0 1 2 3 4 5 6 7 8 9 M │ │P│: byte to be outputted by p
┏━┯━┯━┯━┯━┯━┯━┯━┯━┯━┯━━━┯━┓ │ │╳│: byte already outputted
┃╳│A│A│A│C│D│╳│B│P│P│...│P┃ │
┗━┷↥┷━┷━┷↥┷↥┷━┷↥┷↥┷━┷━━━┷━┛ │
a c d b p 🭭
§Implementation
The implementation is based on the AES blockcipher used in counter (CTR) mode, as presented in the ISO/IEC 18033-4 document.
Modules§
- A module containing random generators objects.
- A module containing seeders objects.