FIPS Compliance

The Federal Information Processing Standards or FIPS are standards developed by the United States government for computer systems that sets requirements for, among other things, crytography.

Microsoft does not recommend enabling FIPS unless it is required by government regulations.

FIPS policy enforcement does not exist at all in .NET Core.

The Particular Software Platform is not FIPS compatible, and no testing is done to ensure components will work properly on FIPS-enabled hardware. In general, the platform uses System.Security.Cryptography classes only for hashing, and not for data security purposes.

There are workarounds that allow running NServiceBus and the Particular Service Platform on the .NET Framework on servers with FIPS enforcement enabled, but these workarounds are also not tested or verified in any way.

NServiceBus

NServiceBus uses the MD5 hash algorithm to generate deterministic unique identifiers for endpoints, also known as HostIds. MD5 is not FIPS compliant. Using a FIPS compliant hashing algorithm method to generate a HostId will allow an NServiceBus endpoint to run under a FIPS policy.

First a replacement for the MD5 based DeterministicGuid utility within the NServiceBus framework will have to be provided:

using System;
using System.Security.Cryptography;
using System.Text;

static class Sha1DeterministicGuid
{
    public static Guid Create(params object[] data)
    {
        var inputBytes = Encoding.UTF8.GetBytes(string.Concat(data));

        // Will create a FIPS-compliant provider when run on a FIPS-enabled system
        using (var sha1 = SHA1.Create())
        {
            var guidBytes = new byte[16];

            var hashBytes = sha1.ComputeHash(inputBytes);

            Array.ConstrainedCopy(hashBytes, 0, guidBytes, 0, 16);

            return new Guid(guidBytes);
        }
    }
}

Next set the HostId as part of the endpoint configuration:

7.x NServiceBus
endpointConfiguration.UniquelyIdentifyRunningInstance()
    .UsingNames(
        instanceName: "endpointName",
        hostName: Environment.MachineName);
// or
var hostId = CreateMyUniqueIdThatIsTheSameAcrossRestarts();
endpointConfiguration.UniquelyIdentifyRunningInstance()
    .UsingCustomIdentifier(hostId);
6.x NServiceBus
endpointConfiguration.UniquelyIdentifyRunningInstance()
    .UsingNames(
        instanceName: "endpointName",
        hostName: Environment.MachineName);
// or
var hostId = CreateMyUniqueIdThatIsTheSameAcrossRestarts();
endpointConfiguration.UniquelyIdentifyRunningInstance()
    .UsingCustomIdentifier(hostId);
5.x NServiceBus
public class HostIdFixer :
    IWantToRunWhenConfigurationIsComplete
{

    public HostIdFixer(UnicastBus bus, ReadOnlySettings settings)
    {
        var hostId = CreateGuid(Environment.MachineName, settings.EndpointName());
        var location = Assembly.GetExecutingAssembly().Location;
        var properties = new Dictionary<string, string>
        {
            {"Location", location}
        };
        bus.HostInformation = new HostInformation(
            hostId: hostId,
            displayName: Environment.MachineName,
            properties: properties);
    }

    static Guid CreateGuid(params string[] data)
    {
        using (var provider = new MD5CryptoServiceProvider())
        {
            var inputBytes = Encoding.Default.GetBytes(string.Concat(data));
            var hashBytes = provider.ComputeHash(inputBytes);
            return new Guid(hashBytes);
        }
    }

    public void Run(Configure config)
    {
    }
}
5.1 NServiceBus
var hostInfoSettings = busConfiguration.UniquelyIdentifyRunningInstance();
hostInfoSettings.UsingNames(
    instanceName: "endpointName",
    hostName: Environment.MachineName);
// or
var hostId = CreateMyUniqueIdThatIsTheSameAcrossRestarts();
hostInfoSettings.UsingCustomIdentifier(hostId);
4.x NServiceBus
public class HostIdFixer :
    IWantToRunWhenConfigurationIsComplete
{

    public HostIdFixer(UnicastBus bus)
    {
        var hostId = CreateGuid(Environment.MachineName, Configure.EndpointName);
        var identifier = Assembly.GetExecutingAssembly().Location;
        bus.HostInformation = new HostInformation(
            hostId: hostId,
            displayName: Environment.MachineName,
            displayInstanceIdentifier: identifier);
    }

    static Guid CreateGuid(params string[] data)
    {
        using (var provider = new MD5CryptoServiceProvider())
        {
            var inputBytes = Encoding.Default.GetBytes(string.Concat(data));
            var hashBytes = provider.ComputeHash(inputBytes);
            return new Guid(hashBytes);
        }
    }

    public void Run()
    {
    }
}

Component libraries

The following packages use MD5 and cannot be used with FIPS enforcement enabled:

  • NServiceBus.RavenDB - Uses MD5 to create create shortened keys for subscriptions and saga lookup properties.
  • NServiceBus.Gateway - Uses MD5 to ensure integrity of received data.
  • NServiceBus.Distributor.Msmq: Uses MD5 to shorten long queue names.

Disable enforcement of FIPS

ServiceControl, ServicePulse, and ServiceInsight also use MD5 internally and will require disabling FIPS enforcement to run properly. As these tools do not execute user code and can be audited as 100% open source, it is sometimes possible to obtain a waiver to run these tools with a configuration flag that instructs the .NET Framework to skip enforcement of FIPS even when configured to do so at the server level with group policy.

FIPS enforcement can be disabled by setting the runtime setting enforceFIPSPolicy to false in the application's app.config or web.config. See the MSDN article on how to change this setting.


Last modified