Vor etwa vier Monaten sitze ich beim Geschäftsführer eines mittelständischen Lohnbuchhaltungs-Dienstleisters. 140 Mitarbeitende, .NET-Backend, Azure-Hosting, SQL Server. Der CTO zeigt mir stolz ihre neue „Datenschutz-Architektur": Jede Gehaltsangabe wird beim Serialisieren in JSON verschlüsselt, bevor sie in die Datenbank geht. Custom-Attribute, eigener Konverter, gut 600 Zeilen Code, drei Monate Entwicklungszeit.
Ich frage: „Wer hat Zugriff auf den Encryption Key?" — „Der Connection String liegt in der appsettings.json. Den Key haben wir da auch reingepackt." Der Key, mit dem die sensiblen Daten verschlüsselt sind, liegt unverschlüsselt neben den verschlüsselten Daten. Auf demselben Server. Im selben Repository. Drei Monate Arbeit, die bei einem echten Breach exakt nichts bringt.
Das ist kein Einzelfall. Das ist ein Muster.
Was Steve Gordon beschreibt
Steve Gordon baut in seiner zweiteiligen Serie eine elegante Lösung für automatische Eigenschaftsverschlüsselung während der JSON-Serialisierung. Teil 2 — darum geht es hier — implementiert den AesGcmDataEncryptor: eine Wrapper-Klasse um Microsofts eigene Kryptographie-API, die AES-GCM mit 128- oder 256-Bit-Keys, Nonce-Generierung via RandomNumberGenerator und Tag-Validation bereitstellt. Der Code ist allokationsarm durch konsequente Nutzung von Span<T> und ArrayPool<T>, und die Architektur ist sauber in einen KeyStore-Abstraktionslayer und den eigentlichen Encryptor getrennt. Gordon selbst betont explizit: Das ist Demo-Code, nicht production-ready, nicht battle-hardened.
Das ist ehrlich — und wichtig. Aber es fehlt der dritte Satz, den ich in Beratungen immer ergänze.
Wie das im KMU landet
Wenn du ein .NET-Haus mit 30 bis 300 Mitarbeitenden führst oder verantwortest, dann ist Gordons Artikel technisch korrekt und praktisch gefährlich — nicht wegen dem, was er sagt, sondern wegen dem, was er weglässt.
Das Schlüsselmanagement ist das Problem. Nicht die Verschlüsselung.
AES-GCM ist stark. Die .NET-Implementierung ist gut. Gordons Code für den Encryptor selbst — solide. Aber ein AesGcmDataEncryptor ohne gelösten KeyStore ist wie ein Tresor ohne Schlosspolitik. Du kannst noch so hochwertigen Stahl verbauen, wenn der Schlüssel unter der Fußmatte liegt, hilft das nichts.
In der Praxis sehe ich bei KMU drei Varianten, wie Gordons Pattern umgesetzt wird — und zwei davon machen die Sache aktiv schlechter:
Variante 1 (häufigste, schlechteste): Key in appsettings.json oder als Environment Variable auf dem Server. Der Applikations-Code, der liest, und der Key, der entsperrt, liegen auf derselben Maschine. Bei einem Servercompromiss ist alles weg. Overhead: 0 Euro, Sicherheitsgewinn: ebenfalls 0 Euro.
Variante 2 (teuer, halbgut): Key in Azure Key Vault oder AWS KMS, aber ohne Key Rotation, ohne Audit Log auswerten, ohne klares Zugriffskonzept. Kostet 50-150 Euro pro Monat, schützt gegen externe Angreifer, aber der eigene Entwickler hat über die Service Principal-Credentials trotzdem Vollzugriff. Ich habe das in drei von fünf Azure-KMU-Projekten der letzten zwei Jahre so vorgefunden.
Variante 3 (selten, richtig): Key Vault mit RBAC, Managed Identity für die App, keine menschlichen Zugriffsrechte auf den Key selbst, automatische Rotation alle 90 Tage, Alert bei ungewöhnlichen Decrypt-Zugriffen. Aufwand für die Einrichtung: ein bis zwei Tage. Monatliche Kosten: unter 30 Euro.
Der Unterschied zwischen Variante 1 und 3 ist nicht die Verschlüsselung. Der Encryptor-Code ist in beiden Fällen derselbe.
Was in Gordons Artikel fehlt — aus Mittelstandsperspektive
Gordons Architektur plant einen KeyStore-Abstraktionslayer ein. Das ist gut. Aber er liefert noch keine Implementierung — die kommt laut seiner Ankündigung in späteren Teilen der Serie. Das Problem: Die meisten Entwickler, die ich kenne, bauen los, sobald der Encryptor läuft, und ergänzen den KeyStore nie mit der nötigen Sorgfalt. Sie bauen Gordons grünen Block im Architektur-Diagramm nach — und lassen den orangefarbenen Block als TODO stehen.
Zweiter blinder Fleck: Wo wird verschlüsselt? Gordons Ansatz verschlüsselt beim JSON-Serialisieren. Das klingt logisch, hat aber eine Konsequenz, die für viele KMU-Szenarien falsch ist: Die Daten liegen im Arbeitsspeicher des Application Servers im Klartext. Bei einem Heap Dump, einer Memory-Analyse, einem Debug-Attach durch einen zu freizügigen Admin — Klartext. Für echte Datenschutzanforderungen (DSGVO, Health-Data, Lohnbuchhaltung, Vertragsmanagement) ist Column-Level Encryption auf Datenbankebene oft die bessere Schicht.
SQL Server bietet seit 2016 Always Encrypted — auch in der Express-Variante. Der Schlüssel verlässt nie die Applikationsschicht, der Datenbankserver sieht nur Ciphertext. Das funktioniert ohne eigenen Serialisierungscode, ohne Custom Attributes, ohne TypeInfoResolver. Für ein KMU mit einem kleinen Entwicklungsteam ist das der weniger fehlerträchtige Weg.
Meine konkrete Empfehlung
Wenn du .NET einsetzt und sensible Felder in JSON verschlüsseln willst — zum Beispiel für Event-Sourcing, Message Queues, API-Responses an externe Partner — dann ist Gordons Ansatz eine solide Basis. Aber bevor du eine Zeile Encryptor-Code schreibst, beantworte diese drei Fragen schriftlich:
-
Wo lebt der Key, und wer hat Zugriff darauf? Wenn die Antwort „appsettings.json" oder „ich weiß nicht" ist, fang mit Azure Key Vault und Managed Identity an. Erst dann Code.
-
Auf welcher Schicht soll verschlüsselt werden? Serialisierung (Gordons Ansatz) eignet sich für Transit-Encryption zwischen Services. Für Daten at rest in einer relationalen Datenbank ist immer zuerst Column-Level Encryption auf Datenbankebene zu prüfen.
-
Hast du einen Decrypt-Audit-Trail? Wenn jemand tausend Datensätze in einer Stunde entschlüsselt, willst du das wissen. Das ist keine Kryptographie-Frage, sondern eine Monitoring-Frage — aber ohne die macht das ganze Verschlüsselungs-Projekt wenig Sinn.
Gordons Code kommt dann ins Spiel, wenn alle drei Fragen beantwortet sind. Dann ist er wirklich nützlich: sauber, allokationsarm, gut abstrahiert. Als erster Schritt gebaut, bevor das Schlüsselkonzept steht, ist er eine elegante Lösung für das falsche Problem.
Der vollständige Original-Beitrag von Steve Gordon: Encrypting Properties with System.Text.Json and a TypeInfoResolver Modifier (Part 2)
Wenn du dir nicht sicher bist, auf welcher Schicht du verschlüsseln sollst, oder wenn dein Team gerade dabei ist, Gordons Pattern zu bauen und du einen zweiten Blick auf die Key-Management-Strategie brauchst — dann ist das genau das Gespräch für ein 30-Minuten-Sparring.
— Bernhard