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 — either at obfuscation time, by protecting with Babel’s self-contained managed AES, or at the environment level.
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(...)You can prevent this startup failure at obfuscation time by protecting the assembly with Babel’s managed AES algorithm: the injected runtime then decrypts without the platform cryptographic provider — see Starting on a broken-FIPS host with managed AES below. Fixing the OpenSSL environment (also described below) is still recommended when you control the container, because it additionally resolves other OpenSSL-backed operations in the process, such as TLS.
Starting on a broken-FIPS host with managed AES
Babel Obfuscator can carry a self-contained managed AES decryptor
inside the protected assembly, so the injected runtime no longer depends
on the platform cryptographic provider. Protect the assembly with the
encryption=aesmanaged value of the
--use
switch:
babel MyApp.dll --msilencryption --use encryption=aesmanagedor, in an MSBuild / .babel project:
<Use>encryption=aesmanaged</Use>The obfuscator still encrypts with the platform provider on the build host (which is healthy) and produces the same ciphertext; only the decryptor carried inside the protected assembly changes. This lets the assembly start on a broken-FIPS host without any environment change. Assemblies protected with an earlier Babel release must be re-obfuscated to pick up the managed decryptor.
Performance. The managed decryptor runs at roughly 40 MB/s, versus
several GB/s for the hardware-accelerated platform AES. For string,
resource and the common (cached) code encryption this is a one-time cost
at startup and is not noticeable. The exception is Code Encryption on
a method marked cache=false, whose body is decrypted on every call:
avoid combining cache=false with encryption=aesmanaged on hot-path
methods, and keep the method cache enabled (the default) so decryption
happens once.
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=0or in docker-compose.yml:
environment:
OPENSSL_FORCE_FIPS_MODE: 0Use 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 FIPS provider so the crypto layer initializes correctly instead of failing:
- Azure Linux 3.0 .NET images
(
mcr.microsoft.com/dotnet/aspnet:8.0-azurelinux3.0and similar), which ship Microsoft’s FIPS-certified SymCrypt provider, - Red Hat UBI 9 based .NET images
(
registry.access.redhat.com/ubi9/dotnet-90and 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 aboutfips.sonot 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 you have no control over the base image or environment variables and
the target must remain strictly FIPS constrained, protect the assembly
with the managed AES algorithm described above
(--use encryption=aesmanaged) so the injected decryptor does not need
the platform provider. This lets a protected assembly start even on a
broken-OpenSSL host without touching the environment, and keeps all the
runtime-decryption features — Code Encryption, String
Encryption, Resource Encryption and Value and Array Encryption
— available. Note that other OpenSSL-backed operations in the same
process (such as TLS) will still fail until the environment is fixed.
Contact support if you need guidance for a
specific deployment.