Threadsafe Bouncy Castle for (C# Lightweight API)


I leverage the Bouncy Castle cryptographic library to create tools that help me test the encryption management software we make at my day job. It is a robust library that comes in handy for generating all kinds of interesting data.

It came as a surprise to find that Bouncy Castle did not take to threading as well as I'd hoped. After implementing Threading in a few of my testing tools I found that Bouncy Castle would get stuck in an infinite loop while generating BigIntegers. I had to alter part the BC source code in order to solve my problem.

References:

 

Background

I had the need to generate over 100,000 certificates at work the other day for testing purposes. To accomplish this goal quickly I added threading to an existing certificate test data generation tool that I had alread put together. After verifying that certificates were being generated much more quickly I left the office for the evening and decided to check on it in the morning.

When I got back to work I noticed that around 24,000 certificates had been generated and that no new ones were being created even though the CPU was pegged at 100%. Something was wrong here- I'd never had this issue with my test tool before!

 

Troubleshooting

To get to the bottom of things I installed the MS Visual Studio Remote Debugger and did some debugging. As i drilled into the code I found that it was stuck in an infinite loop while generating BigIntegers. Upon closer examination I found that the loop was waiting for a non-zero BigInteger which was never happening. Digging deeper I found that the System.Random object used in the creation of the BigInteger was returning all 0's.

I'd never seen this before so I did some internet searching and ran across a couple of relevant questions on StackOverflow that helped me understand what was going on. As it turns out System.Random is not threadsafe! As I had threaded the certificate generation code I was running into a known issue where the shared Random object was returning all 0's when multiple threads use that object.

 

Solution

To solve the problem I made a couple of changes to the BigInteger.cs source file (found under bccrypto-net-1.7-src\csharp\crypto\src\math) to ensure that unique instances of System.Random were being used.

Original Source line #1342:

BigInteger a;
do
{
    a = new BigInteger(n.BitLength, random);
}
while (a.CompareTo(One) <= 0 || a.CompareTo(nMinusOne) >= 0);

 

Modified Source:

BigInteger a;
do{
        random = new Random(); // Added to uniqueness of Random object and prevent infinite loops
   a = new BigInteger(n.BitLength, random);
}
while (a.CompareTo(One) <= 0 || a.CompareTo(nMinusOne) >= 0);

 

Original Source line # 131

private static readonly Random RandomSource = new Random();

 

Modified Source:

private static Random RandomSource {
 get { return new Random(); // Ensures a unique Random }
}

 

Conclusion

It's great to have access to the BC Source code! If this were a proprietary library where I had no access to source I'd be really frustrated about now. As it stands now Bouncy Castle can be a bit hard to learn, but once you use it you have the satisfaction of knowing you can customize it to fit your needs.

Kudos to the BC Dev team for all their years of hard work!