[Botan-devel] Desiring comments on RNG design changes
lloyd at randombit.net
Tue Jun 24 15:47:01 EDT 2008
I'm contemplating some design alternatives/problems, and thought I
would see if anyone had suggestions/comments.
So, as background, in 1.7.7 the global RNG object is (hopefully) going
away completely. That's mostly accomplished already (but not quite
yet, hoping to get that part completed and 1.7.7 released sometime in
July). Where the global RNG was used, instead the user has to pass in
an RNG object (a RandomNumberGenerator&, to be specific). This is good
for a few reasons:
- It makes it much easier to test (previously the test suite did
hackish things like replace the RNG object, run some tests that
relied on a certain fixed RNG output, then replaced it back with a
real RNG). Now it just passes the fixed-output RNG object directly
to the operation being tested.
- It reduces thread contention. Obviously as a global resource, the
global RNG has to be locked. This requires overhead that is either
(in single threaded programs) unnecessary or that serializes
threads, reducing the level of concurrency (and thus, presumably
performance) in multithreaded programs. Now each thread can
maintain its own RNG object (or the application can maintain an
app-wide RNG that uses whatever locking scheme it prefers).
- It minimizes data races. Frankly MT-safe code is hard to write (at
least for me, maybe there are people who can write 100% correct
concurrent shared memory code but I am not among them), and it
seems like the easiest way to do it is avoid mutable shared
state. So where that is feasiable I'm trying to point Botan in
that direction (viz botan.remove-libstate branch, etc).
OK. So taking the global PRNG going away as a given, how does the
application create an RNG to use? We could make each application
figure out which entropy sources were available, create a Randpool,
maybe pass the Randpool pointer to an X9.31 PRNG, seed the RNG,
etc. However that seems silly for multiple reasons (code duplication
across projects (nearly any code using Botan would have similar code),
bug prone (hard to write, and if you do it wrong your RNG is broken
which is not good), not extensible (ideally adding a new entropy
source to the library would be easy and applications would benefit
with just a recompile at most)).
Solution? New interface
[As a static RandomNumberGenerator method? As freestanding? Other?]
which is implemented as something like:
RandomNumberGenerator* rng = new ANSI_X931_PRNG("AES-256", new Randpool);
// collect list of available EntropySources into sources
// [code from Builtin_Modules::entropy_sources()]
// seed rng with sources?
So what I'm contemplating but am unsure about:
Does it make sense to remove the EntropySource handling entirely from
the base RNG class and just have that be more or less and Randpool
specific thing? For instance, have the Randpool maintain a
std::vector<> of the entropy sources; periodically (using some logic
only known to it), it would poll some or all the sources and use it to
add entropy to its internal state. So the //...s above would be
With no explicit seeding step; when the Randpool is first asked for
output it would realize it had not been seeded and run a poll.
Pro: This lets make_rng() return a singular object that will just work
Pro: Applications don't have to know about/configure entropy sources
Pro: Randpool can repoll for more entropy when it wants to (which
could give it /dev/random like semantics where it blocks to
repoll if it thinks it does not have enough entropy in its pool
(I'm not sure if that is a good idea or not, but certainly
automatic repolls would be nice for long-lived apps).
Con: Makes it hard to add application-specific entropy data (does
anyone do this, though?). Also makes it hard to use
application-specific entropy source classes (again, does anyone
Con: Maybe causes too tight a cohesion between Randpool and
Con: It's not clear how one signals a top level RNG sitting on top of
a Randpool that it should reseed itself. Currently X9.31 will do
it anytime new randomness is added to the pool. But when the
Randpool itself is doing the repolling, that indicator goes away.
More information about the botan-devel