Skip to Content
New release 11.7 available 🎉
ObfuscatorFIPS Compliance

FIPS Compliance

Assemblies protected with Babel Obfuscator run on FIPS-enabled hosts. This page explains how the protection features that rely on runtime decryption — Code Encryption (MSIL), String Encryption, Resource Encryption and Value and Array Encryption — behave on such hosts, a startup issue you may encounter in containers, and how to resolve it.

Background

Many customers deploy on hosts where the operating system runs in FIPS mode — on Linux this is exposed as /proc/sys/crypto/fips_enabled = 1. In this mode the platform crypto provider (OpenSSL on Linux) is expected to service every cryptographic operation through a certified FIPS module.

A common problem arises when a container inherits the host’s FIPS flag but its base image does not ship a certified OpenSSL FIPS provider. OpenSSL 3 then tries to enter FIPS mode, fails to load the FIPS provider module, and ends up in a broken state where every digest and cipher operation fails — not only the ones FIPS would normally disallow.

This is an environment condition, not a defect in the obfuscated assembly or in Babel Obfuscator. It is documented independently of Babel — see dotnet/dotnet-docker#5849  and dotnet/runtime#87884 . It affects any OpenSSL-backed .NET cryptography in the process, including TLS (HttpClient, gRPC), not just obfuscated code.

How it can surface in obfuscated assemblies

When an assembly is protected with a feature that decrypts content at runtime — most notably Code Encryption and String Encryption — Babel injects a small runtime that uses the platform’s cryptographic provider to decrypt method bodies and strings. On a broken-FIPS host that provider is unusable, so the decryption runs inside a type initializer and the assembly fails to start before any of your code runs:

System.TypeInitializationException: The type initializer for '...' threw an exception. ---> Interop+Crypto+OpenSslCryptographicException: error:0308010C:digital envelope routines::unsupported at System.Security.Cryptography.AesImplementation.CreateTransform(...)

There is no in-assembly workaround for this condition: modern .NET no longer provides a pure-managed cipher in the base class library, so the injected runtime depends on the platform provider being functional. The fix is applied at the environment level, as described below. This does not require re-obfuscating your assemblies.

Resolving it in containers

Make OpenSSL usable inside the container. Either option resolves the obfuscation-runtime symptom and every other OpenSSL-backed operation in your process (for example, if the same assembly also uses Babel Licensing or TLS).

Option 1 — Do not auto-enter FIPS in the container

On Ubuntu-based .NET images, OpenSSL honors the OPENSSL_FORCE_FIPS_MODE environment variable. Set it to 0 so OpenSSL does not try to enter FIPS mode with a provider the image does not ship.

In a Dockerfile:

ENV OPENSSL_FORCE_FIPS_MODE=0

or in docker-compose.yml:

environment: OPENSSL_FORCE_FIPS_MODE: 0

Use this when the container itself does not need to be FIPS-validated: the host stays FIPS-enabled and only this container’s OpenSSL opts out of the broken auto-FIPS path.

Option 2 — Use a base image with a certified FIPS provider

If FIPS compliance is required inside the container, run on a base image that ships a validated OpenSSL FIPS provider so OpenSSL initializes correctly instead of failing:

  • Red Hat UBI 9 based .NET images (registry.access.redhat.com/ubi9/dotnet-90 and similar), or
  • Ubuntu Pro with the FIPS-certified OpenSSL packages.

Verifying the environment

A quick check from inside the container tells you whether OpenSSL is healthy:

# Fails on a broken-FIPS host, succeeds once fixed echo test | openssl dgst -sha1
  • Failure with error:03000086 (or a message about fips.so not being loadable) — OpenSSL is in the broken state; apply Option 1 or 2.
  • A normal SHA1(stdin)= ... line — OpenSSL is healthy and obfuscated assemblies start normally.

If you cannot change the environment

If the target environment cannot be adjusted (no control over the base image or environment variables) and it must remain strictly FIPS constrained, avoid the protection features that decrypt content at runtime on that target — Code Encryption and String Encryption in particular — and rely on the obfuscation techniques that do not perform runtime decryption (symbol renaming, control flow obfuscation, and similar). Contact support  if you need guidance for a specific deployment.

Last updated on