std.crypto.aes

AES (Advanced Encryption Standard, NIST FIPS 197) ist der weltweit meistgenutzte symmetrische Blockverschlüsselungsalgorithmus. Die Unit implementiert AES-128 (16-Byte-Schlüssel, 10 Runden) und AES-256 (32-Byte-Schlüssel, 14 Runden) im CBC-Modus (Cipher Block Chaining) mit PKCS#7-Padding. Der CBC-Modus verkettet aufeinanderfolgende Blöcke, sodass identische Klartextblöcke zu unterschiedlichen Chiffretextblöcken führen. Ein zufälliger Initialisierungsvektor (IV) muss für jede Verschlüsselung neu generiert werden.

Standard Library · std.crypto.md5 · std.crypto.sha1


Konstanten

Konstante Wert Beschreibung
AES_BLOCK_SIZE 16 Blockgröße in Bytes (immer 16, unabhängig vom Schlüssel)
AES_128_KEY_SIZE 16 Schlüssellänge AES-128 in Bytes
AES_256_KEY_SIZE 32 Schlüssellänge AES-256 in Bytes
AES_128_ROUNDS 10 Anzahl Verschlüsselungsrunden AES-128
AES_256_ROUNDS 14 Anzahl Verschlüsselungsrunden AES-256

Funktionen

Signatur Beschreibung
AES128CBCEncrypt(key: pchar, iv: pchar, input: pchar, input_len: int64, output: pchar): int64 AES-128-CBC-Verschlüsselung mit PKCS#7-Padding. Gibt Länge des Chiffretexts zurück.
AES128CBCDecrypt(key: pchar, iv: pchar, input: pchar, input_len: int64, output: pchar): int64 AES-128-CBC-Entschlüsselung mit PKCS#7-Entfernung. Gibt Länge des Klartexts zurück.
AES256CBCEncrypt(key: pchar, iv: pchar, input: pchar, input_len: int64, output: pchar): int64 AES-256-CBC-Verschlüsselung mit PKCS#7-Padding. Gibt Länge des Chiffretexts zurück.
AES256CBCDecrypt(key: pchar, iv: pchar, input: pchar, input_len: int64, output: pchar): int64 AES-256-CBC-Entschlüsselung mit PKCS#7-Entfernung. Gibt Länge des Klartexts zurück.
AESEncryptOutputSize(input_len: int64): int64 Berechnet die benötigte Puffergröße für die Verschlüsselung (PKCS#7 rundet auf nächstes 16-Byte-Vielfaches auf).
AESDecryptOutputSize(input_len: int64): int64 Berechnet die maximale Puffergröße für die Entschlüsselung.
AES128KeyExpand(key: pchar, expanded_key: pchar): int64 Schlüsselexpansion für AES-128 (für Low-Level-Nutzung, z.B. mehrfache Blockverschlüsselung mit gleichem Schlüssel).
AES256KeyExpand(key: pchar, expanded_key: pchar): int64 Schlüsselexpansion für AES-256.
AESEncryptBlockWithKey(block: pchar, expanded_key: pchar, rounds: int64): pchar Verschlüsselt einen einzelnen 16-Byte-Block mit vorexpandiertem Schlüssel.
AESDecryptBlockWithKey(block: pchar, expanded_key: pchar, rounds: int64): pchar Entschlüsselt einen einzelnen 16-Byte-Block mit vorexpandiertem Schlüssel.

Verwendung

Nachricht verschlüsseln und entschlüsseln (AES-128)

import std.crypto.aes;
import std.alloc;
import std.string;
import std.io;

fn main(): int64 {
    var key: pchar := "0123456789abcdef";   // 16 Bytes für AES-128
    var iv:  pchar := "abcdef0123456789";   // 16 Bytes IV — für jede Nachricht neu generieren!

    var plaintext: pchar := "Geheime Nachricht!!";
    var ptLen: int64 := StrLen(plaintext);

    // Ausgabepuffer berechnen und allozieren
    var encLen: int64 := AESEncryptOutputSize(ptLen);   // Aufgerundet auf 16er-Vielfaches
    var ciphertext: pchar := alloc(encLen) as pchar;

    // Verschlüsseln
    var actualLen: int64 := AES128CBCEncrypt(key, iv, plaintext, ptLen, ciphertext);
    PrintLn("Verschlüsselt: " + IntToStr(actualLen) + " Bytes");

    // Entschlüsseln
    var decBuf: pchar := alloc(AESDecryptOutputSize(actualLen)) as pchar;
    var decLen: int64 := AES128CBCDecrypt(key, iv, ciphertext, actualLen, decBuf);

    // Ergebnis prüfen
    PrintLn("Entschlüsselt: " + decBuf);
    // Ausgabe: Geheime Nachricht!!

    free(ciphertext as int64, encLen);
    free(decBuf as int64, AESDecryptOutputSize(actualLen));
    return 0;
}

AES-256 für höhere Sicherheit

import std.crypto.aes;
import std.alloc;

fn Encrypt256(key32: pchar, iv16: pchar, data: pchar, dataLen: int64): int64 {
    // key32: 32 Bytes für AES-256
    var outLen: int64 := AESEncryptOutputSize(dataLen);
    var out: int64 := alloc(outLen);
    if (out == 0) { return 0; }
    AES256CBCEncrypt(key32, iv16, data, dataLen, out as pchar);
    return out;   // Aufrufer: free(out, outLen)
}

fn Decrypt256(key32: pchar, iv16: pchar, cipher: pchar, cipherLen: int64): int64 {
    var outLen: int64 := AESDecryptOutputSize(cipherLen);
    var out: int64 := alloc(outLen);
    if (out == 0) { return 0; }
    AES256CBCDecrypt(key32, iv16, cipher, cipherLen, out as pchar);
    return out;   // Aufrufer: free(out, outLen)
}

Dateiverschlüsselung

import std.crypto.aes;
import std.alloc;
import std.fs;
import std.io;

fn EncryptFile(inPath: pchar, outPath: pchar, key: pchar, iv: pchar): bool {
    // Eingabedatei lesen
    var inFd: int64 := open(inPath, 0, 0);
    if (inFd < 0) { return false; }

    var fileSize: int64 := lseek(inFd, 0, 2);   // Größe ermitteln
    lseek(inFd, 0, 0);

    var inBuf: int64 := alloc(fileSize);
    read(inFd, inBuf as pchar, fileSize);
    close(inFd);

    // Verschlüsseln
    var encSize: int64 := AESEncryptOutputSize(fileSize);
    var outBuf: int64 := alloc(encSize);
    var written: int64 := AES128CBCEncrypt(key, iv, inBuf as pchar, fileSize, outBuf as pchar);

    // Ausgabedatei schreiben
    var outFd: int64 := open(outPath, 577, 0644);   // O_WRONLY|O_CREAT|O_TRUNC
    if (outFd < 0) {
        free(inBuf, fileSize);
        free(outBuf, encSize);
        return false;
    }
    write(outFd, outBuf as pchar, written);
    close(outFd);

    free(inBuf, fileSize);
    free(outBuf, encSize);
    return true;
}

Vorexpandierter Schlüssel (Performance)

Wenn viele Blöcke mit demselben Schlüssel verschlüsselt werden, lohnt sich die einmalige Schlüsselexpansion:

import std.crypto.aes;
import std.alloc;

fn EncryptManyBlocks(key: pchar, blocks: int64, count: int64): void {
    // Einmalige Schlüsselexpansion: AES-128 → 176 Bytes expanded key
    var expKey: int64 := alloc(176);
    AES128KeyExpand(key, expKey as pchar);

    var i: int64 := 0;
    while (i < count) limit(1000000) {
        var block: int64 := blocks + i * 16;
        AESEncryptBlockWithKey(block as pchar, expKey as pchar, AES_128_ROUNDS);
        i := i + 1;
    }

    free(expKey, 176);
}


Hinweise

  • Der IV muss für jede Verschlüsselung zufällig und einmalig sein — niemals denselben IV mit demselben Schlüssel für zwei verschiedene Nachrichten verwenden. Ein vorhersehbarer IV macht CBC anfällig gegen Chosen-Plaintext-Angriffe.
  • Der IV ist kein Geheimnis und wird typischerweise zusammen mit dem Chiffretext übertragen (die ersten 16 Bytes der Nachricht).
  • PKCS#7-Padding: Der Chiffretext ist immer ein Vielfaches von 16 Bytes. AESEncryptOutputSize(n) gibt die korrekte Puffergröße zurück: (n / 16 + 1) * 16.
  • Für AES-128 den Schlüssel exakt 16 Bytes lang wählen; für AES-256 exakt 32 Bytes.
  • AES-CBC ist nicht authentifiziert — es schützt gegen passive Abhörung, nicht gegen aktive Manipulation. Für Integrität zusätzlich einen MAC (HMAC-SHA256) verwenden.
  • Die Unit ist eine reine Software-Implementierung — kein AES-NI. Auf Systemen mit AES-NI-Unterstützung (x86_64 ab Westmere, ARM Cortex-A) ist die Leistung dadurch geringer als eine hardwarebeschleunigte Implementierung.

Verwandte Units

Letzte Aktualisierung: 2026-06-05