I was using nunit to make sure a checkbits/signing algorithm was doing what it was supposed to do. Like everything in cryptography it was slow. The following loop took more than 16 seconds:
for (int i = 0; i < 10; i++)
{
var value = (UInt64)rng.Next((Int32)cipher.MaximumSequence);
ulong? lastHackedValue = null;
//for all the checkbit combinations...
for (int j = 1; j < Math.Pow(2, cipher.CheckBits) - 1; j++)
{
//move the checkbits over to the correct spot
var signature = (UInt64)j << cipher.SequenceBits;
var hackedValue = value + signature;
try
{
cipher.Unsign(hackedValue);
if (lastHackedValue == null)
lastHackedValue = hackedValue;
else
Assert.Fail("Too many successful cracks for value {0}. Hacked Value 1:{1}, Hacked Value 2:{2}",
i, lastHackedValue, hackedValue);
}
catch(ApplicationException ex)
{
Assert.That(ex.Message == "Invalid signature");
}
}
}
I tried using the Parallel class – sending my cpu utilization from 12 to 100% and I got it down to 5 seconds:
var parallelresult = Parallel.For(0, 10, i =>
{
//...same for loo
});
I noticed that assertion failures were not being displayed in nunit correctly. It turned out the .For call was wrapping them in an AggregateException so I wrapped the code like this:
try
{
var parallelresult = Parallel.For(0, 10, i =>
{
...
});
}
catch(AggregateException ex)
{
if(ex.InnerException is AssertionException)
{
throw ex.InnerException;
}
else
{
throw ex;
}
}