# Wie KI-Agenten und Design by Contract Crypto-Bugs vor der Produktion abfangen
KI-Agenten verändern das Spiel bei der Entwicklung sicherer Systeme: Statt Code und Tests manuell zu schreiben, generieren sie Implementierungen basierend auf formalen Verträgen. Das eliminiert den Hauptgrund, warum Design by Contract scheiterte – die doppelte Arbeit. In einem Projekt mit Hardware-TRNG und PKI wurden zwei kritische Schwachstellen genau durch Vertrags-Tests entdeckt, die normale Unit-Tests übersehen hätten.
Warum Tests logische Fehler in der Kryptographie übersehen
Tests prüfen nur, was der Programmierer sich ausgedacht hat. Wenn niemand auf Padding in RSA oder die Entropiequalität vor der Verwendung in einem DRBG achtet – schreibt sich der Test nicht von allein. Genau so schlüpften ein 27 Jahre alter Bug in OpenBSD und eine 16 Jahre alte Schwachstelle in FFmpeg durch Millionen automatisierter Checks hindurch. Compiler und statische Analysatoren sind gegen logische Fehler machtlos: Falscher Verschlüsselungsmodus, ausgelassene Zertifikatsrevocation-Checks, veraltete Standards – all das entgeht ihnen.
Das Kernproblem: Tests reagieren auf die Implementierung, nicht auf die Absicht. Verträge erfassen die Absicht, bevor Code geschrieben wird. Sie definieren Grenzen: was das System tun muss (Postkonditionen), was verboten ist (Invariante) und unter welchen Bedingungen es aufgerufen werden darf (Präkonditionen). Das ist keine bloße Dokumentation – es ist eine ausführbare Spezifikation.
Hierin unterscheidet sich der Vertragansatz:
- Formalität: PRE/POST/INV werden maschinenlesbar formuliert, nicht als Kommentare.
- Frühe Erkennung: Vertragsverletzungen schlagen sofort fehl, nicht in der Produktion.
- Fokus auf Garantien: Statt „wie es funktioniert“ – „was garantiert ist“.
- Einzelne Wahrheitquelle: Der Vertrag ändert sich nicht während der Entwicklung; er wird nur bei Änderung der Anforderungen aktualisiert.
Wie der KI-Agent die zweite Hälfte der Arbeit übernimmt
Design by Contract scheiterte im Mainstream wegen der doppelten Belastung: Zuerst Vertrag schreiben, dann Code, dann Tests. Unter Zeitdruck fielen Verträge als Erstes weg. Heute übernimmt der KI-Agent Implementierung und Testgenerierung, sodass Menschen nur noch den Vertrag formulieren müssen. Das ändert die Ökonomie: Eine Zeile Vertrag ersetzt Hunderte Zeilen Code und Tests.
Der Prozess sieht so aus:
- Mensch schreibt Invariante:
padding == RSA-PSS | RSA-OAEP; PKCS#1 v1.5 == FORBIDDEN. - Agent generiert das CryptoEngine-Modul, das nur erlaubte Paddings verwendet.
- Gleichzeitig erzeugt der Agent einen Vertrags-Test, der PKCS#1 v1.5 ausprobiert und eine Exception erwartet.
- Scheitert der Test – behebt der Agent die Implementierung, ohne den Vertrag anzutasten.
- Mensch prüft nur 10 Zeilen Vertrag, nicht 1000 Zeilen Code.
Vorteile:
- Geschwindigkeit: 11 Tage aktive Arbeit für ein Fullstack-Embedded-Projekt statt Monate.
- Zuverlässigkeit: Der Vertrag ist der Mittelpunkt; Fehler darin fallen leichter auf als im Code.
- Skalierbarkeit: Eine Person steuert Agenten in verschiedenen Rollen (Coder, Tester, Architekt).
Realer Fall: PKI mit Hardware-TRNG und Vertrags-Tests
Das pki-on-box-Projekt umfasst fünf Module: STM32G431 (Hardware-TRNG), Python-Daemon (DRBG nach NIST SP 800-90A), CryptoEngine (Schlüsselerzeugung), KeyStorage (AES-256-GCM), CA-Service (X.509-Signierung). Jedes Modul hat formale Verträge an den Schnittstellen. Zwei kritische Schwachstellen wurden vor dem Deployment entdeckt:
- Falsches Padding: Implementierung nutzte versehentlich PKCS#1 v1.5 statt RSA-PSS. Bleichenbacher-Angriff erlaubt Plaintext-Wiederherstellung via Padding-Oracle – Vertrags-Test schlug sofort fehl.
- Falscher AES-Modus: ECB statt GCM gewählt. Vertrag forderte authentifizierte Verschlüsselung – Test schlug erneut fehl.
Projektmetriken:
- 131 Commits
- 62 Vertrags-Tests + 15 HW-Tests
- 3 MCU-Boards (STM32G474, G431, H750)
- Zielplattform: RK3328 ARM64
- KI-Kosten: 1780₽ für 30 Sessions
- Offenes Repository: github.com/vasilievsv/hw.pki-on-box
Verträge an Schnittstellen: Wo kritische Fehler entstehen
Logische Fehler entstehen an Modulgrenzen. DRBG liefert Bytes – CryptoEngine muss wissen, wie man sie verwendet. Ohne Vertrag wählt jemand Padding aus einem StackOverflow-Beispiel. Hier zwei Schlüsselverträge aus dem Projekt:
contract: key_generation
PRE:
- DRBG.seeded == true
- algorithm ∈ {RSA-2048, ECDSA-P384}
POST:
- private_key.encrypted(AES-256-GCM)
- public_key = derive(private_key)
INV:
- padding == RSA-PSS | RSA-OAEP
- PKCS#1 v1.5 == FORBIDDEN
contract: certificate_issuance
PRE:
- issuer_ca.valid() && !revoked()
- csr.signature.verify() == true
POST:
- cert.serial.unique()
- cert.signature.verify(issuer_ca.public_key) == true
INV:
- root_ca.offline == true
- cert_chain.depth <= max_path_length
Vertrags-Test für Padding:
def test_rejects_pkcs1v15_padding(self, crypto):
priv, pub = crypto.generate_rsa_keypair(bits=2048)
data = b"invariant check"
sig = crypto.sign_data(priv, data)
# PSS must rabotat
pub.verify(sig, data, padding.PSS(...))
# PKCS1v15 must slomatsya
with pytest.raises(Exception):
pub.verify(sig, data, padding.PKCS1v15(), hashes.SHA256())
Der Test prüft keine Funktionalität – er verifiziert die Einhaltung der Invariante. Ändert sich das Padding – schlägt der Test fehl, auch wenn die Signatur „technisch“ funktioniert.
Wichtige Erkenntnisse
- Verträge > Tests: Tests prüfen Implementierungen; Verträge prüfen Absichten. Logische Fehler werden nur durch formale Garantien gefasst.
- KI eliminiert doppelte Arbeit: Agent generiert Code und Tests aus dem Vertrag; Mensch konzentriert sich auf Spezifikation.
- Kritische Fehler an Grenzen: Padding, Verschlüsselungsmodi, Revocation-Checks – alles kontrolliert durch Invarianten an Modulschnittstellen.
- Offene Verifizierung: Projekt mit Hardware-TRNG und Vertrags-Tests im offenen Repository für Audit verfügbar.
- Zeitökonomie: 11 Tage für ein Fullstack-Embedded-System statt Monate – dank Rollenverteilung und Autogenerierung.
— Editorial Team
Noch keine Kommentare.