Zurück zur Startseite

Python-Krypto für USB: SecureBytes und Streaming-Verschlüsselung

Der Artikel beschreibt eine Krypto-Engine für USB in Python mit der SecureBytes-Klasse für sichere Schlüsselspeicherung, Streaming-Verschlüsselung großer Dateien und Fehlertoleranz-Mechanismen. Unterstützung für AES-GCM, ChaCha20. Fokus auf die Beseitigung von Speicherschwachstellen und Stromausfall-Problemen.

Erstellen eines Krypto-Engines für Flash-Laufwerke: Python ohne Speicherlecks
Advertisement 728x90

Sichere USB-Verschlüsselung in Python: Speichermanagement und Stream-Verarbeitung

Für sichere Dateiübertragungen per USB gilt: Einfachheit ist entscheidend. Stecken Sie das Laufwerk ein, geben Sie ein Passwort ein und greifen auf verschlüsselte Daten zu. VeraCrypt nutzt Container-Dateien, was die direkte Verwendung über verschiedene Betriebssysteme erschwert. Die Hauptaufgabe? Der Schutz vor Datenkorruption bei plötzlichem Stromausfall, wenn ein Flash-Laufwerk während der Verschlüsselung herausgezogen wird.

Ein Krypto-Engine in Python nutzt AES-GCM und ChaCha20. Der Fokus liegt auf sicherer Speicherung von Schlüsseln im RAM, der Streaming-Verschlüsselung von Gigabyte-Dateien ohne Auslastung des Arbeitsspeichers und robusten Integritätsmechanismen.

Die SecureBytes-Klasse beseitigt eine kritische Schwachstelle in Python und Java: Die Garbage Collection (GC), die sensible Daten (Passwörter, Schlüssel) in neue Speicherbereiche kopiert und dadurch Spuren im RAM hinterlässt. So funktioniert es:

Google AdInline article slot
class SecureBytes:
    def __init__(self, data: Union[bytes, bytearray, int]):
        if isinstance(data, int):
            self._buffer = bytearray(data)
        else:
            self._buffer = bytearray(data)
        self._finalized = False
        # Schwachen Finalizer registrieren
        self._weak_ref = weakref.ref(self, self._cleanup_callback)

    def wipe(self, passes: int = 3):
        if self._finalized or len(self._buffer) == 0:
            return
        # Durchgang 1: Zufallsbytes
        self._buffer[:] = secrets.token_bytes(len(self._buffer))
        # Durchgang 2: Nullen
        self._buffer[:] = b'\x00' * len(self._buffer)
        self._finalized = True
        gc.collect()

    def __del__(self):
        if not self._finalized:
            self.wipe()

Wichtige Funktionen:

  • Nutzung von bytearray für In-Place-Überschreibungen – im Gegensatz zu unveränderlichen bytes.
  • Mehrfach-Wiping: Zuerst zufällige Daten, dann Nullen (gemäß NIST SP 800-88).
  • Entwickelt für den Einsatz mit Kontext-Managern (with secure_key(...)) zur sicheren Bereinigung auch bei Ausnahmen.

Dies minimiert die Exposition von Schlüsseln im Speicher und verhindert Lecks durch GC.

Streaming-Verschlüsselung: MemorySensitiveReader

Die Verschlüsselung einer 10-GB-Datei auf einem Gerät mit nur 4 GB RAM erfordert einen Streaming-Ansatz. Die MemorySensitiveReader-Klasse wechselt automatisch zwischen Modus je nach Dateigröße und verfügbarem Speicher:

Google AdInline article slot
class MemorySensitiveReader:
    def __init__(self, file_path: str, memory_threshold: int = 100 * 1024 * 1024):
        self.file_size = os.path.getsize(file_path)
        # Schwellenwert zum Wechsel in Streaming-Modus
        self.use_streaming = self.file_size > memory_threshold 

    def iter_chunks(self, chunk_size: int = 8192):
        # Lesen und Verschlüsseln in Blöcken
        ...

Lösung des Nonce-Problems: Die Wiederverwendung desselben Nonce mit einem einzigen Schlüssel in AES-GCM oder ChaCha20 ist katastrophal. Um dies zu verhindern, erhält jeder Block einen eindeutigen Nonce, abgeleitet aus einem Basis-Nonce und dem Blockindex:

def _derive_block_nonce_12bit(base_nonce: bytes, block_index: int) -> bytes:
    # Erste 8 Bytes = Präfix, letzte 4 = Block-Zähler
    prefix = base_nonce[:8]
    block_counter = block_index.to_bytes(4, byteorder='big')
    return prefix + block_counter

Blöcke werden in 8 KB-Chunks gelesen, Nonces aus Basiswert und Index generiert – garantiert kryptografische Stärke unabhängig von der Dateigröße.

Fehlerresistenz bei Operationen

Standard-Verschlüsselung, die die Originaldatei bei Fehlern löscht, führt zu dauerhafter Datenverlust. Dieses System beinhaltet:

Google AdInline article slot
  • Sperrdatei .encryption_lock.json: Verfolgt den Status als in_progress und listet verarbeitete Dateien auf.
  • Temporäre .tmp-Dateien: Verschlüsselt in eine Kopie; Original wird erst nach erfolgreicher Überprüfung gelöscht.
  • Integritätsprüfungen: Dekodieren eines Blocks, Vergleich von HMAC und SHA-256-Hashes.
  • Rollback-Mechanismus: Bei Unterbrechung wird automatisch das Original aus der verschlüsselten Datei wiederhergestellt.

Damit ist sichergestellt, dass nach einem Stromausfall die Daten entweder vollständig verschlüsselt sind oder völlig unberührt – keine halbverschlüsselten Zustände.

Unterstützte Algorithmen

  • AES-256-GCM: Nutzt Hardware-Beschleunigung via AES-NI.
  • ChaCha20-Poly1305: Optimaler Leistungsaufwand auf ARM-Geräten ohne AES-NI.
  • XChaCha20-Poly1305: 24-Byte-Nonce für großflächige Verschlüsselung.

Parallelisierung mittels ThreadPoolExecutor steigert die I/O-Leistung bei vielen kleinen Dateien und umgeht die GIL-Beschränkung.

Was zählt:

  • SecureBytes verhindert Schlüssel-Lecks durch GC mittels Mehrfach-Wiping.
  • Streaming-Verschlüsselung mit eindeutigen Nonces für Dateien ab 100 MB – keinerlei Kollisionsrisiko.
  • Vollständige Fehlerresistenz: Sperrdateien und automatischer Rollback bei Stromausfall.
  • Unterstützung für AES-GCM, ChaCha20, XChaCha20 – ohne Sicherheitsverlust.
  • Metadaten gespeichert in .usb_crypt_meta.json, Passwörter ≥12 Zeichen mit Validierung.

Einschränkungen & Bedrohungsmodell

Das Tool schützt vor verlorenen oder gestohlenen Laufwerken, verbirgt aber keine Dateinamen oder Verzeichnisstruktur. Es bietet keinen Schutz gegen Keylogger auf dem Host-System. Ideal für mittlere bis erfahrene Entwickler, die eine benutzerdefinierte USB-Verschlüsselung mit starkem Fokus auf Speichersicherheit und Robustheit benötigen.

— Editorial Team

Advertisement 728x90

Weiterlesen