Search code examples
c#fipsdevforce

Exception when using DevForce in a FIPS-compliant environment


We have some customers that want to run our software (which uses DevForce) with Windows in "FIPS Mode". It seems like most of the encryption done by DevForce is FIPS-compliant by default but we've run into problems with some of the hashing that DevForce does. Specifically, with code that calls down to AesCryptoProvider.CalcStringHash which looks like this:

/// <summary>
/// Returns a hash encoded as a string with the chars (A-Z,A-z,0-9,_) only.
/// </summary>
/// <remarks>
/// Under the covers this method returns an 128 bit hash code calculated
/// using SHA1.  This code is then encoded into an approx Base64 encode
/// of the chars listed above.  This will usually be approx 28 chars in length,
/// which may then be truncated based on the maxChars parameter. This
/// method can process approx 100K 300 char strings a second.
/// </remarks>
/// <param name="stringToHash"></param>
/// <param name="maxChars"></param>
/// <returns></returns>
public string CalcStringHash(string stringToHash, int maxChars)
{
  return CodingFns.EncodeBase64(new SHA1Managed().ComputeHash(Encoding.Unicode.GetBytes(stringToHash))).Substring(0, maxChars).Replace("=", "").Replace("/", "_d").Replace("+", "_p");
}

That method directly instantiates a SHA1Managed instance and unfortunately, that class is not FIPS compliant.

Here is the full stack trace for context:

Exception: System.InvalidOperationException: This implementation is not part of the Windows Platform FIPS validated cryptographic algorithms.
   at System.Security.Cryptography.SHA1Managed..ctor()
   at IdeaBlade.Core.PlatformServices.AesCryptoProvider.CalcStringHash(String stringToHash, Int32 maxChars)
   at IdeaBlade.Core.DynamicTypeInfo.GetUniqueToken()
   at IdeaBlade.Core.DynamicTypeInfo.BuildDynamicTypeName()
   at IdeaBlade.Core.DynamicTypeInfo..ctor(TypeShape typeShape)
   at IdeaBlade.Core.DynamicTypeInfo.FindOrCreate(IEnumerable`1 propertyNames, IEnumerable`1 propertyTypes)
   at IdeaBlade.Linq.AnonymousProjectionSelector.GetDynamicTypeInfo()
   at IdeaBlade.Linq.AnonymousProjectionSelector.ToLambdaExpression(Type delegateType)
   at IdeaBlade.Linq.QueryableExtensions.Select[TSource](IQueryable`1 source, IProjectionSelector selector)
   at My.Company.ServerClass.MyRemoteServerMethod(IPrincipal principal, EntityManager serverEm, Object[] rawArgs)

Is there any workaround to get DevForce to work under FIPS mode? Or is this something that could be added in a future release?

I noticed that the comments on that method talk about performance. If this is a performance-critical method and switching to a FIPS-complaint alternative would incur a performance hit, perhaps it could be a configurable option? We only have one customer complaining about FIPS but have many more that care about performance so I'd hate to make things slower for people that don't care about FIPS.


Solution

  • This is a bug and we can get this fixed (hopefully for the next release). This hashing logic is used only when generating the name for a "dynamic" type, which is used when working with anonymous types and also with dynamic queries. You might be able to work around this error by projecting into a custom type rather than an anonymous type, otherwise there's no workaround to avoid the problem.

    If performance is an issue, and it's likely not since this hashing is only now used for dynamic type names, we can look at a switch to choose between FIPS/non-FIPS compliant providers.