NOTAS DE LA VERSIÓN

Novedades de Babel.

Cambios en el motor, las herramientas de gestión de licencias y el espacio de trabajo de Desktop, según las notas de la versión del producto.

Publicado el 2 de agosto de 2026

Versión 11.8.0.0

Babel Obfuscator

Mejoras

  • Hosts con FIPS habilitado — cifrado AES gestionado: Se ha añadido un descifrador AES gestionado opcional que se selecciona con --use encryption=aesmanaged (o <Use>encryption=aesmanaged</Use> desde MSBuild). Los ensamblados protegidos con cifrado de código (MSIL), de cadenas, de valores y matrices o de recursos ahora arrancan en hosts donde el proveedor criptográfico de la plataforma no se puede usar, sobre todo en contenedores Linux con un estado FIPS de OpenSSL roto, donde el runtime de descifrado inyectado lanzaba antes un OpenSslCryptographicException dentro del inicializador de tipo, antes de que se ejecutara código de usuario. El ofuscador sigue cifrando con el proveedor de la plataforma en el host de compilación (sano) y emite el mismo texto cifrado; lo único que cambia es el descifrador autocontenido que lleva dentro el ensamblado. Compatible con .NET Framework y .NET (Core); netstandard y Mono mantienen su comportamiento actual. Consulte la página de documentación Cumplimiento de FIPS. Tenga en cuenta el rendimiento del descifrador gestionado, de unos 40 MB/s: evite combinarlo con cifrado de código con cache=false en métodos de rutas críticas.
  • Rendimiento — ensamblados grandes: Se han reescrito tres rutas críticas que dominaban la ofuscación de ensamblados muy grandes, con mucho código y muchos atributos, con una salida verificada como idéntica byte a byte a la de 11.7.0:
    • El renombrado de atributos personalizados (RenameTypeAttributes) ahora está indexado en lugar de ser O(tipos × atributos). Un ensamblado de 41 MB y unos 69.000 tipos con muchos atributos (por ejemplo, Microsoft.Graph) que antes no llegaba a terminar la fase de renombrado ahora la completa en unos 20 s.
    • El FindCallVertices del grafo de llamadas es O(vértices) en lugar de O(vértices × firmas): de 7 a 11 veces más rápido en DevExpress.XtraEditors y Spire.Pdf.
    • La agrupación de miembros virtuales en la fase de renombrado se reparte por nombre en cubos (de 2074 ms a 17 ms en DevExpress.XtraEditors). De principio a fin, esto redujo en torno a un 24 % la ofuscación con todas las características de un ensamblado de DevExpress de 7,9 MB.
  • Detección dinámica del runtime de destino: Se ha añadido la detección dinámica de la versión del runtime de destino para los ensamblados ofuscados.
  • Ejemplo de vinculación a dongle hardware: Se ha añadido una implementación de referencia multiplataforma y ejecutable que muestra cómo vincular una aplicación .NET protegida con cifrado de código a un dongle hardware de licencias (KEYLOK, SafeNet Sentinel, Wibu CodeMeter, Marx CrypToken, …) para que las DLL del dongle sustituidas o simuladas no puedan saltarse la protección.
  • [Nuevo] La advertencia OB0009 informa de un caso de modo demo que era imposible diagnosticar a partir de la salida: cuando se suministran archivos de mapa pero la ofuscación entre ensamblados no está licenciada, el mapa se omite y las referencias a símbolos externos renombrados conservan sus nombres originales, de modo que el ensamblado solo fallaba en tiempo de ejecución con un TypeLoadException. Ahora se informa en tiempo de compilación.

Correcciones de errores

  • Avalonia — cifrado de recursos: Se ha corregido el fallo de arranque de las aplicaciones Avalonia ofuscadas con FileNotFoundException en activos avares:// y XAML cuando el cifrado de recursos estaba activado. Avalonia guarda todo el XAML y los activos de un ensamblado en un único blob !AvaloniaResources que su cargador de activos lee directamente, saltándose el gancho de descifrado que inyecta Babel. Ese blob se deja ahora sin cifrar (el resto de recursos se siguen cifrando), de modo que las aplicaciones Avalonia son plenamente ofuscables con el cifrado de recursos activado. WPF no se ve afectado. Para distribuir una aplicación Avalonia en un solo archivo, use la incrustación de ensamblados (no la combinación).
  • WPF — combinación de diccionarios de temas: Se ha corregido la pérdida de los temas de los controles al combinar ensamblados que contienen un diccionario de recursos BAML en la misma ruta (normalmente themes/generic.baml). Los flujos ResourceDictionary de cultura neutra que colisionan se conservan ahora con nombres únicos y se enlazan mediante un diccionario sintetizado a través de MergedDictionaries, manteniendo la precedencia de búsqueda del ensamblado principal.
  • MAUI/XAML — primitivas de lenguaje x:: Se ha corregido que el renombrador de XAML eliminara el prefijo x: de las primitivas de lenguaje en x:TypeArguments (por ejemplo, x:Double → Double). Esto hacía fallar las compilaciones Release de .NET MAUI para iOS que cargan XAML en tiempo de ejecución, con XamlParseException ("Type Double not found").
  • Renombrado — referencias de tipo a sí mismo: Se ha corregido que un tipo renombrado dejara TypeReferences a sí mismo (con ámbito del propio módulo) con el nombre antiguo, lo que provocaba un System.TypeLoadException al inicializar el tipo. Los tejedores de IL como ArxOne.MrAdvice —y las instrucciones de nivel superior de C# a través del tipo interno Program— emiten alias ldtoken que entonces no se podían resolver. La corrección de la TypeRef del propio módulo se ejecuta ahora para cada tipo renombrado.
  • Renombrado — reescritura de cadenas de PropertyChanged: Se ha corregido que la reescritura de ldstr posterior al renombrado (que mantiene funcionando OnPropertyChanged("PropName") tras renombrar) reescribiera incorrectamente argumentos de otras API basadas en cadenas —búsquedas de controles XAML, claves de diccionario, registros propios— en cualquier tipo derivado de una base INotifyPropertyChanged. La reescritura se limita ahora a los destinos de PropertyChanged reconocidos. Notificado en 8.7, reproducido en 11.7.
  • Flujo de control — tipos anfitriones con dependencias externas: Se ha corregido un FileNotFoundException intermitente y aleatorio en tiempo de ejecución (por ejemplo, el 0xC0011008 de SSIS) provocado porque los métodos auxiliares del despachador de flujo de control y del aplanamiento de switch se alojaban en tipos que cargan un ensamblado externo al iniciarse. La selección del tipo anfitrión rechaza ahora los tipos con campos de tipo valor (comprobados de forma recursiva, incluidos los argumentos genéricos y los tipos valor anidados) o con tipos base o interfaces fuera del módulo o de la biblioteca base, y rechaza los tipos anfitriones genéricos.
  • Licencias — una licencia no válida recaía en modo demo en silencio: Se ha corregido que un archivo de licencia suministrado explícitamente pero no válido para la versión en ejecución no se respetara ni se comunicara: la ejecución continuaba en silencio en modo demo y producía un ensamblado con caducidad y sin las características licenciadas, algo que el usuario solía descubrir mucho después. Una licencia proporcionada explícitamente debe ser ahora válida para este producto y esta versión; de lo contrario, Babel se detiene con Error: the license provided is not valid for Babel Obfuscator <version>. y sale con LicensingFailure (1, o 40 con --strict-exit) sin producir ningún ensamblado. Ejecutar sin ninguna licencia sigue iniciando el modo demo con el conjunto de características reducido, como antes.
  • Licencias de prueba en Linux: Las licencias con una restricción de prueba por tiempo de ejecución o por número de instancias podían fallar la validación en hosts Linux, incluida la tarea NuGet de Babel Obfuscator en contenedores Linux. Consulte las notas de la versión 11.8.0.0 de Babel Licensing para más detalles.

Cambios

  • Cadena de herramientas de autoofuscación: El paquete NuGet de Babel Obfuscator (y los binarios babel, lic, HardwareId y Babel.Win) se ofuscan ahora a sí mismos con el algoritmo AES gestionado, de modo que las propias herramientas distribuidas arrancan en hosts con FIPS roto.

Babel Licensing

Mejoras

  • Hosts con FIPS habilitado — resistencia en el arranque: Babel Licensing sobrevive ahora en hosts con FIPS habilitado cuyo contenedor carece de un proveedor OpenSSL FIPS certificado (por ejemplo, un host RHEL ejecutando un contenedor .NET basado en Ubuntu, dotnet/dotnet-docker#5849), donde la validación de licencias fallaba antes con BabelLicenseException: Internal error: el hash de identidad de IsolatedStorage de .NET fallaba en SHA1.Create con error:03000086. El almacén de licencias recurre ahora a un almacén de archivos gestionado cuando IsolatedStorage no puede inicializarse, sustituye los cifradores AES/DES de la plataforma en el almacén de fechas cifrado por cifradores de BouncyCastle compatibles bit a bit (los archivos de almacén existentes siguen siendo legibles en ambos sentidos) y pasa a un seguimiento de fechas en memoria cuando no hay ningún almacenamiento utilizable, de modo que la validación de licencias ya no toca la pila criptográfica del sistema operativo. Cuando el servicio de Babel Licensing se ofusca con el algoritmo AES gestionado de Babel Obfuscator (--use encryption=aesmanaged), el servicio ofuscado también arranca en hosts con FIPS roto.
  • Licencias de activación — propagación de características al validar: Añadir una característica a una licencia de activación llega ahora a los clientes ya activados en la siguiente validación, en lugar de exigir una desactivación y reactivación completas. Tanto la ruta de activación como la de validación construyen y vuelven a firmar la licencia node-locked de cada máquina a partir de la licencia padre (características, campos, restricciones, fechas) más la vinculación al hardware, mediante un método auxiliar compartido.

Correcciones de errores

  • Autenticación gRPC con UserKey: Se han corregido todos los inicios de sesión gRPC con UserKey, que fallaban desde el refuerzo de seguridad de 11.7.0. GrpcAuthenticator.AuthenticateAsync ignoraba su parámetro de nombre de usuario y enviaba siempre el identificador de cliente capturado en el constructor, lo que encaminaba los inicios de sesión con UserKey por la ruta de inicio de sesión de identidad de dos argumentos. Un puente opcional EnableLegacyUserKeyFallback (desactivado de forma predeterminada) permite a los operadores con muchas aplicaciones cliente ya desplegadas recuperar la compatibilidad sin volver a desplegarlas, mientras que las instalaciones nuevas se quedan en la ruta corregida.
  • Claves JSON de las cargas de webhook: Se ha corregido que las cargas de webhook de licencias, pedidos e informes entregaran claves JSON de una sola letra (p, q, r, …) cuando el servicio de gestión de licencias se ofusca con renombrado de símbolos. Las cargas usan ahora DTO con nombres que fijan cada clave mediante [JsonPropertyName] (en camelCase), así que el contrato del webhook es inmune al renombrado de símbolos y al cifrado de cadenas.
  • Licencias de prueba — hosts Linux sin región de memoria compartida: Se ha corregido que una licencia con una restricción de prueba por tiempo de ejecución o por número de instancias fallara la validación con Object reference not set to an instance of an object, de modo que IsValid devolvía false mientras la misma licencia se validaba correctamente en Windows y macOS. Notificado en contenedores Linux. Application.StartTime y Application.InstanceCount leían la región de memoria compartida sin condiciones, pero la región solo se rellena cuando se puede abrir, así que donde no se podía crear ambos miembros lanzaban una excepción y TrialRestriction.Validate fallaba con un error opaco. La región se trata ahora como opcional y los dos valores degradan a valores por proceso —la hora de inicio del proceso y el recuento de procesos ya existente— en lugar de lanzar una excepción. Una hora de creación a cero se trata igual, ya que de lo contrario haría que cualquier tiempo de prueba pareciera ya consumido. No es una regresión: el comportamiento era idéntico en 11.6.0, 11.7.0, 11.7.0.3 y 11.8.0.
  • Linux — enlace con la biblioteca de semáforos POSIX: Se ha corregido la causa raíz del fallo anterior: la región de memoria compartida nunca se podía abrir en un host Linux con glibc. Los puntos de entrada sem_* que la protegen se importaban de librt, un nombre que el runtime de .NET busca como librt.so y liblibrt.so pero nunca como el soname instalado librt.so.1 —el enlace simbólico sin versión viene con el paquete de desarrollo, que las imágenes de contenedor no incluyen—, así que todas las llamadas fallaban al enlazar con un DllNotFoundException. Además de romper las restricciones de prueba, esto degradaba en silencio Application.StartTime y Application.InstanceCount a valores por proceso en todos los hosts Linux. La importación usa ahora el soname, y un DllImportResolver prueba además libpthread.so.0, libc.so.6 y los nombres de la libc de musl, cubriendo glibc antes y después de la fusión de sem_* en libc en la 2.34, así como musl. El recuento de instancias entre procesos y la hora de inicio compartida de la aplicación se comportan ahora en Linux como siempre lo han hecho en Windows. Los hosts Alpine/musl no estaban afectados. SharedMemory.Open también informa de que la región no está disponible en lugar de lanzar una excepción al llamador, así que los hosts sin semáforos con nombre siguen funcionando mediante la alternativa por proceso.
  • Servicio de Babel Licensing — clave de firma JWT generada automáticamente: Se ha corregido que todas las llamadas hechas con un token emitido fallaran con 401 —y que, por tanto, no se pudiera activar ninguna licencia— cuando Application:SigningKey se dejaba vacío. La clave aleatoria generada al arrancar se asignaba solo a una copia desacoplada de la sección de configuración Application, mientras que TokenService resuelve IOptionsSnapshot<ApplicationSettings> y vuelve a enlazar desde la configuración, así que los tokens se firmaban con una clave de espacios de relleno y se validaban contra la generada. El registro del servicio hacía difícil diagnosticarlo, porque informaba de una autenticación correcta justo antes del 401. La clave generada se aplica ahora mediante PostConfigure<ApplicationSettings>, de modo que todas las instancias de opciones enlazadas firman y validan con la misma clave. Configurar una clave explícita sigue siendo lo recomendado en producción: una clave generada cambia en cada reinicio y no se comparte entre instancias.