The default constructor of SecureRandom uses GetSeed(8), which is only 64 bits, but worse yet, GetSeed seeds itself from the system clock Ticks.
There are 10million ticks per second, and a single laptop CPU core can perform between 10million and 200million AES operations per second, depending on hardware acceleration, clock speed, and how efficient the software library is. This means, suppose you used SecureRandom() to generate an AES key, a completely unsophisticated brute force attacker could guess your key in a period of time that's less than the precision he has on guessing *when* you created your key. If he knows when you generated it +/- 12 hours, then he would expect to require something between 0.5 and 12 hours to guess your key, divided by the number of CPU cores he has available. Even if an attacker had no idea when you generated some key, it's still limited to 64 bits, which is just nowhere near good enough. Even if you're aware of this, and you painstakingly and consistently use things like ThreadedSeedGenerator to seed the SecureRandom, there are tons of places where SecureRandom() is used *internally* by Bouncy Castle. By searching code, I see 526 references. I discovered this today, because I painstakingly created strong random to seed my ECKeyPairGenerator, and then signed & verified data, only to discover that the insecure SecureRandom() is used internally by ECDSASigner. So the questions I have are ... What to do about it. Option 1: More education to the users. Response: I see code examples all over the internet, where people advise each other to use SecureRandom and expect it to be secure, as the name implies. So the idea of just educating people on proper usage and expectations is unrealistic. The name "SecureRandom" in a widely trusted crypto library such as Bouncy Castle is important and meaningful. More importantly, SecureRandom() is used *internally* by Bouncy Castle. Which underscores the futility of "user education" as the solution. As described above, I painstakingly ensured I used good random, only to find it undermined internally by ECDSASigner. Option 2: Instead of seeding SecureRandom from system time, seed it from ThreadedSeedGenerator, or better yet, a combination of the two, or better yet, pull from both of those sources plus the OS crypto API and everything else available to provide seed material. In fact, that's what we're doing in TinHat Random. http://tinhatrandom.org If the solution is to seed SecureRandom from a bunch of different sources, then I would like to see TinHat Random folded into the source of Bouncy Castle. Which might be easier said than done, given the Java / C# duality. Also, there might be some logistical difficulties, compatibility with different system types, different OSes with different threading models, etc. I would be brazen to assume there always exists an OS crypto API on every platform where BC gets used. Not to mention, the assumption that ThreadedSeedGenerator is valid to use. Which is another big assumption. Option 3: I am rather expecting to hear a lot of "can't" in response to Option 2. But I am working for an employer who is planning to use BC for secure communications, and I cannot afford to deliver "can't" as my answer. So I am estimating probably my response will be forced, to fork BC, and fold TinHat Random into it, to make it suitable for my employer's purposes. And I'll have to go around promoting my fork to application developers, etc. But I'm hoping for a more graceful integration process somehow that doesn't result in fragmentation of community or development efforts. Other options? Ideas? Comments? Thanks... PS, I love BC and as always, thanks to everyone who contributed and contributes to it.