FIPS-Konformität
Mit Babel Obfuscator geschützte Assemblys laufen auf Hosts im FIPS-Modus. Diese Seite erklärt, wie sich die Schutzfunktionen, die auf Entschlüsselung zur Laufzeit beruhen, also Codeverschlüsselung (MSIL), Zeichenfolgenverschlüsselung, Ressourcenverschlüsselung und Wert- und Arrayverschlüsselung, auf solchen Hosts verhalten, welches Startproblem in Containern auftreten kann und wie Sie es beheben: entweder bei der Verschleierung, indem Sie mit dem eigenständigen verwalteten AES von Babel schützen, oder auf der Ebene der Umgebung.
Hintergrund
Viele Kunden stellen auf Hosts bereit, deren Betriebssystem im
FIPS-Modus läuft. Unter Linux ist das an
/proc/sys/crypto/fips_enabled = 1 zu erkennen. In diesem Modus soll
der Kryptografieanbieter der Plattform (OpenSSL unter Linux) jede
kryptografische Operation über ein zertifiziertes FIPS-Modul ausführen.
Ein häufiges Problem entsteht, wenn ein Container das FIPS-Flag des Hosts erbt, sein Basisimage aber keinen zertifizierten OpenSSL-FIPS-Anbieter enthält. OpenSSL 3 versucht dann, in den FIPS-Modus zu wechseln, kann das Modul des FIPS-Anbieters nicht laden und gerät in einen fehlerhaften Zustand, in dem jede Hash- und Verschlüsselungsoperation fehlschlägt, nicht nur die, die FIPS normalerweise nicht zulässt.
Das ist ein Zustand der Umgebung, kein Fehler in der verschleierten
Assembly oder in Babel Obfuscator. Er ist unabhängig von Babel
dokumentiert, siehe
dotnet/dotnet-docker#5849
und dotnet/runtime#87884 .
Er betrifft jede auf OpenSSL gestützte .NET-Kryptografie im Prozess,
einschließlich TLS (HttpClient, gRPC), nicht nur verschleierten Code.
Wie sich das Problem in verschleierten Assemblys zeigt
Wenn eine Assembly mit einer Funktion geschützt ist, die Inhalte zur Laufzeit entschlüsselt, vor allem Codeverschlüsselung und Zeichenfolgenverschlüsselung, fügt Babel eine kleine Laufzeitkomponente ein, die Methodenrümpfe und Zeichenfolgen mit dem Kryptografieanbieter der Plattform entschlüsselt. Auf einem Host mit defektem FIPS ist dieser Anbieter unbrauchbar. Die Entschlüsselung läuft in einem Typinitialisierer, und die Assembly startet deshalb nicht, noch bevor Ihr Code ausgeführt wird:
System.TypeInitializationException: The type initializer for '...' threw an exception.
---> Interop+Crypto+OpenSslCryptographicException:
error:0308010C:digital envelope routines::unsupported
at System.Security.Cryptography.AesImplementation.CreateTransform(...)Sie können diesen Startfehler bei der Verschleierung verhindern, indem Sie die Assembly mit dem Algorithmus verwaltetes AES von Babel schützen: Die eingefügte Laufzeitkomponente entschlüsselt dann ohne den Kryptografieanbieter der Plattform, siehe Mit verwaltetem AES auf einem Host mit defektem FIPS starten weiter unten. Die OpenSSL-Umgebung zu reparieren (ebenfalls unten beschrieben) empfiehlt sich dennoch, wenn Sie den Container kontrollieren, weil dadurch auch andere auf OpenSSL gestützte Operationen im Prozess wie TLS wieder funktionieren.
Mit verwaltetem AES auf einem Host mit defektem FIPS starten
Babel Obfuscator kann eine eigenständige verwaltete
AES-Entschlüsselungsroutine in der geschützten Assembly mitliefern,
sodass die eingefügte Laufzeitkomponente nicht mehr vom
Kryptografieanbieter der Plattform abhängt. Schützen Sie die Assembly
mit dem Wert encryption=aesmanaged des Schalters
--use:
babel MyApp.dll --msilencryption --use encryption=aesmanagedoder in einem MSBuild- oder .babel-Projekt:
<Use>encryption=aesmanaged</Use>Der Obfuscator verschlüsselt weiterhin mit dem Anbieter der Plattform auf dem Buildhost (der intakt ist) und erzeugt denselben Chiffretext. Es ändert sich nur die Entschlüsselungsroutine, die in der geschützten Assembly mitgeliefert wird. So startet die Assembly auf einem Host mit defektem FIPS ohne jede Änderung an der Umgebung. Assemblys, die mit einer früheren Babel-Version geschützt wurden, müssen neu verschleiert werden, um die verwaltete Entschlüsselungsroutine zu erhalten.
Leistung. Die verwaltete Entschlüsselungsroutine arbeitet mit etwa
40 MB/s, das hardwarebeschleunigte AES der Plattform dagegen mit
mehreren GB/s. Bei der Zeichenfolgen-, der Ressourcen- und der üblichen
(zwischengespeicherten) Codeverschlüsselung fallen diese Kosten einmalig
beim Start an und sind nicht spürbar. Die Ausnahme ist die
Codeverschlüsselung einer Methode mit cache=false, deren Rumpf bei
jedem Aufruf entschlüsselt wird: Kombinieren Sie cache=false bei
häufig durchlaufenen Methoden nicht mit encryption=aesmanaged, und
lassen Sie den Methodencache eingeschaltet (die Standardeinstellung),
damit die Entschlüsselung nur einmal stattfindet.
Lösung in Containern
Machen Sie OpenSSL im Container nutzbar. Jede der beiden Optionen behebt das Symptom in der Laufzeitkomponente der Verschleierung und das Problem bei jeder anderen auf OpenSSL gestützten Operation in Ihrem Prozess (zum Beispiel, wenn dieselbe Assembly auch Babel Licensing oder TLS verwendet).
Option 1: FIPS im Container nicht automatisch aktivieren
In .NET-Images auf Basis von Ubuntu beachtet OpenSSL die Umgebungsvariable
OPENSSL_FORCE_FIPS_MODE. Setzen Sie sie auf 0, damit OpenSSL nicht
versucht, mit einem Anbieter in den FIPS-Modus zu wechseln, den das
Image nicht enthält.
In einem Dockerfile:
ENV OPENSSL_FORCE_FIPS_MODE=0oder in docker-compose.yml:
environment:
OPENSSL_FORCE_FIPS_MODE: 0Verwenden Sie diese Option, wenn der Container selbst nicht FIPS-validiert sein muss: Der Host bleibt im FIPS-Modus, und nur OpenSSL in diesem Container verzichtet auf den fehlerhaften automatischen Wechsel in den FIPS-Modus.
Option 2: Basisimage mit zertifiziertem FIPS-Anbieter verwenden
Wenn die FIPS-Konformität im Container verlangt wird, verwenden Sie ein Basisimage mit einem validierten FIPS-Anbieter, damit die Kryptografieschicht korrekt initialisiert wird und nicht fehlschlägt:
- .NET-Images für Azure Linux 3.0
(
mcr.microsoft.com/dotnet/aspnet:8.0-azurelinux3.0und ähnliche), die den FIPS-zertifizierten Anbieter SymCrypt von Microsoft enthalten, - .NET-Images auf Basis von Red Hat UBI 9
(
registry.access.redhat.com/ubi9/dotnet-90und ähnliche) oder - Ubuntu Pro mit den FIPS-zertifizierten OpenSSL-Paketen.
Umgebung prüfen
Eine kurze Prüfung im Container zeigt, ob OpenSSL intakt ist:
# Fails on a broken-FIPS host, succeeds once fixed
echo test | openssl dgst -sha1- Ein Fehler mit
error:03000086(oder eine Meldung, dassfips.sonicht geladen werden kann): OpenSSL ist im fehlerhaften Zustand. Wenden Sie Option 1 oder 2 an. - Eine normale Zeile
SHA1(stdin)= ...: OpenSSL ist intakt, und verschleierte Assemblys starten normal.
Wenn Sie die Umgebung nicht ändern können
Wenn Sie weder das Basisimage noch die Umgebungsvariablen beeinflussen
können und die Zielumgebung strikt an FIPS gebunden bleiben muss,
schützen Sie die Assembly mit dem oben beschriebenen Algorithmus
verwaltetes AES (--use encryption=aesmanaged), damit die
eingefügte Entschlüsselungsroutine den Anbieter der Plattform nicht
benötigt. So startet eine geschützte Assembly auch auf einem Host mit
defektem OpenSSL ohne Eingriff in die Umgebung, und alle
Funktionen mit Entschlüsselung zur Laufzeit bleiben verfügbar:
Codeverschlüsselung, Zeichenfolgenverschlüsselung,
Ressourcenverschlüsselung und Wert- und Arrayverschlüsselung.
Beachten Sie, dass andere auf OpenSSL gestützte Operationen im selben
Prozess (etwa TLS) weiterhin fehlschlagen, bis die Umgebung repariert
ist. Wenden Sie sich an den Support , wenn
Sie Unterstützung für eine bestimmte Bereitstellung benötigen.