Skip to Content
Nueva versión 12 disponible 🎉
ObfuscatorConformidad con FIPS

Conformidad con FIPS

Los ensamblados protegidos con Babel Obfuscator se ejecutan en hosts en modo FIPS. Esta página explica cómo se comportan en esos hosts las funciones de protección que dependen del descifrado en tiempo de ejecución (cifrado de código (MSIL), cifrado de cadenas, cifrado de recursos y cifrado de valores y matrices), un problema de inicio que puede encontrar en los contenedores y cómo resolverlo, ya sea durante la ofuscación, protegiendo con el AES administrado autónomo de Babel, o en el entorno.

Contexto

Muchos clientes despliegan en hosts cuyo sistema operativo se ejecuta en modo FIPS; en Linux esto se expone como /proc/sys/crypto/fips_enabled = 1. En este modo se espera que el proveedor criptográfico de la plataforma (OpenSSL en Linux) atienda todas las operaciones criptográficas mediante un módulo FIPS certificado.

Un problema habitual aparece cuando un contenedor hereda el indicador FIPS del host pero su imagen base no incluye un proveedor FIPS de OpenSSL certificado. OpenSSL 3 intenta entonces entrar en modo FIPS, no consigue cargar el módulo del proveedor FIPS y queda en un estado defectuoso en el que fallan todas las operaciones de resumen y de cifrado, no solo las que FIPS normalmente no permitiría.

Se trata de una condición del entorno, no de un defecto del ensamblado ofuscado ni de Babel Obfuscator. Está documentada con independencia de Babel: consulte dotnet/dotnet-docker#5849  y dotnet/runtime#87884 . Afecta a cualquier criptografía de .NET basada en OpenSSL dentro del proceso, incluido TLS (HttpClient, gRPC), y no solo al código ofuscado.

Cómo puede manifestarse en los ensamblados ofuscados

Cuando un ensamblado se protege con una función que descifra contenido en tiempo de ejecución (sobre todo el cifrado de código y el cifrado de cadenas), Babel inyecta un pequeño entorno de ejecución que usa el proveedor criptográfico de la plataforma para descifrar los cuerpos de los métodos y las cadenas. En un host con FIPS defectuoso ese proveedor no se puede usar; el descifrado se ejecuta dentro de un inicializador de tipo y el ensamblado no consigue iniciarse antes de que se ejecute nada de su código:

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

Puede evitar este fallo de inicio durante la ofuscación protegiendo el ensamblado con el algoritmo AES administrado de Babel: el entorno de ejecución inyectado descifra entonces sin el proveedor criptográfico de la plataforma. Consulte Inicio en un host con FIPS defectuoso mediante AES administrado más abajo. Aun así, se recomienda corregir el entorno de OpenSSL (también descrito más abajo) cuando el contenedor está bajo su control, porque además resuelve otras operaciones del proceso basadas en OpenSSL, como TLS.

Inicio en un host con FIPS defectuoso mediante AES administrado

Babel Obfuscator puede incluir dentro del ensamblado protegido un descifrador AES administrado autónomo, de modo que el entorno de ejecución inyectado deja de depender del proveedor criptográfico de la plataforma. Proteja el ensamblado con el valor encryption=aesmanaged de la opción --use:

babel MyApp.dll --msilencryption --use encryption=aesmanaged

o, en un proyecto de MSBuild o .babel:

<Use>encryption=aesmanaged</Use>

El ofuscador sigue cifrando con el proveedor de la plataforma en el host de compilación (que funciona correctamente) y genera el mismo texto cifrado; solo cambia el descifrador incluido en el ensamblado protegido. Así el ensamblado puede iniciarse en un host con FIPS defectuoso sin ningún cambio en el entorno. Los ensamblados protegidos con una versión anterior de Babel deben volver a ofuscarse para incorporar el descifrador administrado.

Rendimiento. El descifrador administrado funciona a unos 40 MB/s, frente a varios GB/s del AES de la plataforma acelerado por hardware. Para el cifrado de cadenas, el de recursos y el cifrado de código habitual (con caché) se trata de un coste único en el inicio que no se nota. La excepción es el cifrado de código en un método marcado con cache=false, cuyo cuerpo se descifra en cada llamada: evite combinar cache=false con encryption=aesmanaged en los métodos de uso intensivo y mantenga activada la caché de métodos (el valor predeterminado) para que el descifrado se haga una sola vez.

Resolución en los contenedores

Haga que OpenSSL pueda usarse dentro del contenedor. Cualquiera de las dos opciones resuelve el síntoma del entorno de ejecución de la ofuscación y todas las demás operaciones de su proceso basadas en OpenSSL (por ejemplo, si el mismo ensamblado usa también Babel Licensing o TLS).

Opción 1: no entrar automáticamente en modo FIPS en el contenedor

En las imágenes de .NET basadas en Ubuntu, OpenSSL respeta la variable de entorno OPENSSL_FORCE_FIPS_MODE. Establézcala en 0 para que OpenSSL no intente entrar en modo FIPS con un proveedor que la imagen no incluye.

En un Dockerfile:

ENV OPENSSL_FORCE_FIPS_MODE=0

o en docker-compose.yml:

environment: OPENSSL_FORCE_FIPS_MODE: 0

Use esta opción cuando el contenedor en sí no necesita estar validado para FIPS: el host sigue en modo FIPS y solo el OpenSSL de este contenedor deja de seguir la ruta defectuosa de entrada automática en FIPS.

Opción 2: usar una imagen base con un proveedor FIPS certificado

Si se exige la conformidad con FIPS dentro del contenedor, use una imagen base que incluya un proveedor FIPS validado, para que la capa criptográfica se inicialice correctamente en lugar de fallar:

  • imágenes de .NET de Azure Linux 3.0 (mcr.microsoft.com/dotnet/aspnet:8.0-azurelinux3.0 y similares), que incluyen SymCrypt, el proveedor de Microsoft certificado para FIPS,
  • imágenes de .NET basadas en Red Hat UBI 9 (registry.access.redhat.com/ubi9/dotnet-90 y similares), o
  • Ubuntu Pro con los paquetes de OpenSSL certificados para FIPS.

Comprobar el entorno

Una comprobación rápida desde dentro del contenedor indica si OpenSSL funciona correctamente:

# Fails on a broken-FIPS host, succeeds once fixed echo test | openssl dgst -sha1
  • Un fallo con error:03000086 (o un mensaje que indica que fips.so no se puede cargar): OpenSSL está en el estado defectuoso; aplique la opción 1 o la 2.
  • Una línea normal SHA1(stdin)= ...: OpenSSL funciona correctamente y los ensamblados ofuscados se inician con normalidad.

Si no puede cambiar el entorno

Si no controla la imagen base ni las variables de entorno y el destino debe seguir estrictamente sujeto a FIPS, proteja el ensamblado con el algoritmo AES administrado descrito más arriba (--use encryption=aesmanaged) para que el descifrador inyectado no necesite el proveedor de la plataforma. Así un ensamblado protegido puede iniciarse incluso en un host con OpenSSL defectuoso sin tocar el entorno, y siguen disponibles todas las funciones de descifrado en tiempo de ejecución (cifrado de código, cifrado de cadenas, cifrado de recursos y cifrado de valores y matrices). Tenga en cuenta que las demás operaciones del mismo proceso basadas en OpenSSL (como TLS) seguirán fallando hasta que se corrija el entorno. Póngase en contacto con el soporte  si necesita orientación para un despliegue concreto.

Last updated on