Good Cryptography Is Not Easy: Meet FIPS Integration

Today — at the IEEE CAMAD 2023 conference [here] — we are presenting a paper at a conference and which analyses flaws in the implementation…

Good Cryptography Is Not Easy: Meet FIPS Integration

Today — at the IEEE CAMAD 2023 conference [here] — we are presenting a paper at a conference and which analyses flaws in the implementation of the EdDSA signature [here]:

So, how could this flaw happen? Well, some of the implementations of cryptography are weak as they have not been implemented correctly, and where usability and getting the code working often come before security.

I may be wrong, but cryptography is one of the most challenging areas of cybersecurity, and it often takes a great deal of experience, diligence and knowledge to produce code which is robust and secure. This is one of the reasons that the Cryptography library in Python is known as HAZMAT (Hazardous Material).

The usage of random numbers is often critically important for the security of cryptography-focused applications. With this, the random oracle model defines that the security of the overall method is defined by the randomness of the oracle value that we use. The code used to create these programs must thus be free of flaws and often have to comply with the Federal Information Processing Standard (FIPS) standard. In this case, we will use the Bouncy Castle FIPS (FIPS) C# API. This needs the bc-fips-1.0.2.dll assembly and which integrates into the System.Security.Cryptography provider.

First we create a folder named “bc_fips01”, and then go into that folder.We can create a Dotnet console project for .NET 8.0 with:

dotnet new console --framework net8.0

Next we download the FIPS module (bc-fips-1.0.2.dll) from [here] and add it as a reference to the project:

This produces a Csproject file of [here]:

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<Reference Include="Org.BouncyCastle.Crypto">
<HintPath>bc-fips-1.0.2.dll</HintPath>
</Reference>


</ItemGroup>

</Project>

We can generate the random values in many ways, including with a random seed, or with integers and floating point values, and where the .next() method gives us the next random number [here]:

namespace Fips01
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Fips;
using Org.BouncyCastle.Crypto.Utilities;
using Org.BouncyCastle.Security;
class Program
{

static void Main(string[] args)
{
string size="32";

if (args.Length >0) size=args[0];

try {

var entSource = new BasicEntropySourceProvider (new SecureRandom(), true);
IDrbgBuilder
theDrbgBuilder = CryptoServicesRegistrar.CreateService(FipsDrbg.Sha512HMac).FromEntropySource(entSource);
theDrbgBuilder.SetSecurityStrength(256);
theDrbgBuilder.SetEntropyBitsRequired(256);
theDrbgBuilder.SetPersonalizationString(System.Text.Encoding.ASCII.GetBytes("The cat on the mat"));
byte[] nonce = new byte[Convert.ToInt16(size)];
var n=theDrbgBuilder.Build(nonce,false);
Console.WriteLine("Size: {0}",size);
Console.WriteLine("Random Seed: {0}",Convert.ToHexString(n.GenerateSeed(Convert.ToInt16(size))));
Console.WriteLine("Hash Code: {0}",(n.GetHashCode()));
for (int i=0;i<5;i++) {
Console.WriteLine("Random Int64: {0}",n.NextInt64());
}
for (int i=0;i<5;i++) {
n.NextBytes(nonce);
Console.WriteLine("Random Hex {0}",Convert.ToHexString(nonce));
}
for (int i=0;i<5;i++) {
Console.WriteLine("Random Double {0}",n.NextDouble());
}

} catch (Exception e) {
Console.WriteLine("Error: {0}",e.Message);
}
}
}
}
{

A sample run is [here]:

Size: 16
Random Seed: 77C2DDA2ED570FBA03CFA16824192698
Hash Code: 58225482
Random Int64: 2185014096620394652
Random Int64: 6547259502637679065
Random Int64: 6081615623724165065
Random Int64: 8531401192076663666
Random Int64: 8149660133904283657
Random Hex 5C667296AF1F89EE2488DCD583C31742
Random Hex 98D05CE2A4D68D981A6117A29C432302
Random Hex D2CAD8C50D15562E8C32B5353CCEA90E
Random Hex A1EFAAE9BAC9E8F947CD9093CF5F48D5
Random Hex A00B41BECCD445C9E1006DE280A0FE75
Random Double 0.9227581456101644
Random Double 0.7963939883459085
Random Double 0.6233004414069624
Random Double 0.11342376685574285
Random Double 0.303790433615841

and another run:

Size: 16
Random Seed: 7B9032B6BC57CE7AAF755B069A1A792D
Hash Code: 58225482
Random Int64: 7048896462485293653
Random Int64: 534441518009268538
Random Int64: 5485764435776354119
Random Int64: 5541028532111395291
Random Int64: 6078431120986501893
Random Hex F3B791FA0588AA7789E582B8903DED3A
Random Hex E0F08257401FCC9BAC748C724CEC7CCF
Random Hex A1F7F75481D0361B3FB1C7E566ABD621
Random Hex 7AF40799D3177554B07EBDB0A0583196
Random Hex D117C62065F245F31DA6231AAA381B9B
Random Double 0.3951819812521763
Random Double 0.9405280101977072
Random Double 0.8784901491148207
Random Double 0.47321478881809087
Random Double 0.8798897369784155

Conclusions

Don’t fall into the trap of producing bad crypto code.