One of the big items I learned is: Very simple whitening methods together with very biased inputs can give output streams that readily pass statistical randomness tests like dieharder (i.e., “my PRNG/TRNG passes DieHarder” doesn’t mean much). Only analysis like we see in this paper can really give you confidence that your outputs are unguessable by an adversary with specific capabilities.

So while the math is way over my head I say: I hope that my favorite operating systems will take lessons from it as soon as possible to improve their cryptographic-quality random number generation.

]]>I have all the code I used to generate them. The sboxes are 8 8×64 bit sboxes, which is about 4x the memory as you can expect in most software implementations and AES. And yeah, timing attacks are a possibility.

The sboxes in f.c were found via a pseudorandom search. I basically seeded xorshift with constants I copied from sha512 (entirely for convenience), randomly sorted an array with the numbers 0-255, and ran for a few weeks until I found sboxes with suitable cryptographic properties: nonlinearity 98, max value of 8 in xor table, and a generalization of the bit independence/avalanche/completeness criterion in which for every input differential and every combination of output bits, I check that the parity is 1 with a probability of 0.5 +/- 40/256 (extremely difficult to find good numbers for that property randomly, but for comparison AES sbox has a bias of 16/256).

The sboxes in t.c are computed from f.c; I’d have to check the code to generate it, but IIRC each byte is basically computed by nesting functions in f.c a number of times depending on the position, with a constant 0x00-0x07 xord depending on the position. You can see that the least significant byte for t[m][n] is f[m][n]-n.

]]>(1) HUGE s-boxes. You will probably be vulnerable to time based side channel attacks.

(2) Where does the constants in t.c and f.c come from? You should document that so anybody can replicate it. Even you. ðŸ˜‰

]]>Sounds good. I’m all for people tinkering around, learning, and having fun. It’s the very essence of hacking in the old meaning of the term.

]]>It’s just something I’ve done for fun and educational reasons. Something people could check out for the hell of it as a curiosity. Of course I would disclose that to people. I don’t advocate anybody actually use it for anything important. I always use AES and Twofish for real projects. ]]>

I wrote about 2**out in Figure 8 to an author of the paper, and they were kind enough to write back:

…

In the constant-rate regime, there’s a very clear way to judge a scheme: You simply compute what we call the competitive ratio, r, which is just the ratio of the maximum entropy that we need to receive to be secure relative to an idealized scheme that knows everything about the system (e.g., how much entropy it’s received, when it’s been compromised, etc.). In this regime, our best scheme is about twice as efficient as the original Fortuna with the numbers that Ferguson and Schneier suggest, and it uses a base of 3. See Theorem 5, and in particular note the parameter b and the parametrized competitive ratio r_b. Intuitively, we achieve a competitive ratio proportional to roughly (b+1/b)/\log(b), and it turns out that that’s minimized at b=3. (It happens that base 4 is almost as good, which might be convenient for practitioners.)

In the non-constant-rate regime the situation is a bit complicated. In particular, our security definition is slightly subtle, with two parameters, \alpha and \beta. If we receive some amount of entropy proportional to \alpha in time T, then we guarantee security at time \beta*T. Intuitively, once we’ve received sufficient entropy, we need to take some sufficient additional time to get that entropy into the register, the time that this takes is proportional to the amount of time that it took us to get the entropy in the first place. \alpha defines “sufficient entropy” and \beta defines “sufficient additional time” (multiplicatively).

The scheme from Figure 8 in base b achieves \beta = b^2 and \alpha proportional to 1/\log(b). So, in theory, there’s just a tradeoff between \alpha and \beta and no real way to define an optimal base. However, note that in the constant-rate case, the competitive ratio r just corresponds to \alpha * \beta, so a natural thing to do is simply to extend this and minimize \alpha * \beta, which gives b = 2. (We can argue more rigorously that this parameter makes sense.) But, it’s worth noting that these parameters necessarily come from a fairly extreme worst-case analysis that, in particular, assumes that our entropy source gives us just enough entropy and then stops providing any more. We could define a model in which we ask our entropy source to be “roughly constant” over “long” periods of time, and depending on the definitions of “roughly constant” and “long”, b = 3 might give a better competitive ratio than b = 2.

Given all of this ambiguity and how complex the paper already was, we just fixed b = 2 in the non-constant-rate regime.

…

Just on instinct, I had used 3 in my adaptation of Fortuna to Keccak last year.

Another issue I was going to raise, namely that Figure 4 passes skey to attacker A but not to adversarial entropy supplier E, is addressed in section 7.

]]>ELSE out<–max{out: tau = 0 mod 2**out*P/wmax}

when I looked at the equivalent part of Fortuna, some time ago, my first thought was that the 2 was arbitrary, and that 3 or 4 (or 1.5) might be better. Now Dodis, Shamir, Stephens-Davidowitz and Wichs have agreed with Ferguson and Schneier, and put their imprimatur on 2. Ugh. It would probably take me weeks to work out a proof that 2 either is or isn’t better than alternatives.

]]>