Skip to Content
Neue Version 12 verfügbar 🎉
ObfuscatorNuGet-PaketSchutz von Geheimnissen

Geheimnisse mit Zeichenfolgen- und Wertverschlüsselung schützen

Fast jede Anwendung liefert in ihrem Code Geheimnisse aus: API-Schlüssel, Endpunkte, Verbindungszeichenfolgen, Lizenzparameter, „magische“ Zahlen und Nachschlagetabellen. Ein Decompiler liest sie in Sekunden. Dieses Beispiel entfernt mit dem NuGet-Paket von Babel Obfuscator diese Literale aus der ausgelieferten Assembly, und zwar mit Zeichenfolgenverschlüsselung und Wert- und Arrayverschlüsselung, ohne eine Zeile Code zu ändern.

Für dieses Beispiel brauchen Sie eine Standortlizenz für Babel Obfuscator (Edition Ultimate, Server oder Data Center). Der Quellcode ist auf GitHub verfügbar:

git clone https://github.com/babelfornet/secret-protection-nuget-example.git

Das Konsolenprojekt SecretApp referenziert das NuGet-Paket von Babel Obfuscator (nur für den Build) und schaltet in Release die beiden Verschlüsselungsebenen ein:

<ItemGroup Condition="'$(Configuration)' == 'Release'"> <PackageReference Include="Babel.Obfuscator" Version="12.0.0"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> </ItemGroup> <PropertyGroup Condition="'$(Configuration)' == 'Release'"> <StringEncryption>stream</StringEncryption> <ValueEncryption>int32=true;int64=true;single=true;double=true;array=true;true</ValueEncryption> <ControlFlowObfuscation>if=true;switch=true;case=true;chain=true;true</ControlFlowObfuscation> <BabelWarningsAsErrors>W00000</BabelWarningsAsErrors> </PropertyGroup>

Der Zeichenfolgenalgorithmus stream verschiebt jedes Zeichenfolgenliteral in eine verschlüsselte Tabelle, während die Wert- und Arrayverschlüsselung numerische Konstanten und Inline-Arrays aus dem IL-Code entfernt. Beides wird zur Laufzeit bei Bedarf entschlüsselt. Das Programm verhält sich also genau wie zuvor, während die Konstanten aus der Binärdatei verschwinden. Wird BabelWarningsAsErrors auf W00000 gesetzt, wird ein Build im Evaluierungsmodus zum Fehler, sodass eine ungeschützte Binärdatei nie versehentlich ausgeliefert wird.

Die Geheimnisse selbst stehen in src/SecretApp/Secrets.cs:

internal static class Secrets { // Strings -> removed by String Encryption (stream) public static readonly string ApiKey = "DEMO-API-KEY-0000-1111-2222-3333-4444-5555"; public static readonly string ServiceEndpoint = "https://api.internal.example.com/v3/ingest"; public static readonly string ConnectionString = "Server=db.internal;Database=Orders;User Id=svc;Password=__DEMO_PLACEHOLDER__;"; // Numbers -> removed by Value Encryption public static readonly int ApiPort = 8443; public static readonly double RiskThreshold = 0.8734; // Lookup table -> removed by Array Encryption public static readonly int[] RolloutBuckets = { 12, 47, 63, 88, 91, 128, /* … */ 8192, 9001 }; }

Das Beispiel zeigt außerdem ein wichtiges Detail: Die Geheimnisse sind als static readonly deklariert, nicht als const. Ein const-Wert wird in die Metadaten der Assembly geschrieben und an jeder Verwendungsstelle inline eingesetzt. Er übersteht daher die Verschleierung und bleibt lesbar. Ein static readonly-Feld wird dagegen mit einer Anweisung ldstr/ldc zugewiesen, die von der Zeichenfolgen- und Wertverschlüsselung umgeschrieben wird. Ein Build des Beispiels in Release und eine Suche in den beiden Assemblys bestätigen den Unterschied: API-Schlüssel, Endpunkt und Verbindungszeichenfolge sind im Debug-Build vorhanden und im Release-Build verschwunden, bei identischer Programmausgabe.

Last updated on