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=aesmanagedo, 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=0o en docker-compose.yml:
environment:
OPENSSL_FORCE_FIPS_MODE: 0Use 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.0y 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-90y 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 quefips.sono 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.