This issue in the RavenDB Security Report is pretty simple, when we generate a certificate, we need to generate a certificate serial number. We were using a random number that is 64 bits in length, but that is too small. The problem is the birthday attack. For a 64 bits number, you only need about 5 billion attempts to generate a collision. In modern cryptography, that is actually a very low security threshold.

So we fixed it and used a random value that is 20 bytes in length. Or so we thought. This single issue is worth the trouble of publicly discussing the security report. As it turned out, I didn’t read the API docs properly and used this construction:

new BigInteger(20, random);

Where the random is a cryptographically secured random number generator. The problem here is that this BigInteger constructor uses bits length, not bytes length. And that resulted in a security “fix” that actually much worse than the previous situation (you only need a bit over a thousand tries to generate a collision). This has already been fixed, obviously, but I’m very happy that it was caught.

@svick
I agree. I always used named arguments for values like 0, 1, 20, etc, and true, false. Pretty much named arguments everywhere. R# makes it easy and it allows me more freedom when refactoring code. Reading code of the sort
MyFunc(20, 4, true, false)
is horrible compared to
MyFunc(start: 20, length: 4, inclusive: true, destroyTheWord: false)

Of course, an options object would be even better, but you can't always control the API you're having to call but you can at least control your code. Also helps if you have mean third parties that add optional parameters and pull other shenanigans that could result in subtle changes to which method overload you're actually calling.