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
std.crypto.sha1— SHA-1-Hashing (für HMAC-Konstruktionen)std.crypto.md5— MD5-Hashingstd.hash— allgemeine Hash-Utilities (CRC32, FNV, …)std.net.tls— TLS/SSL (verwendet OpenSSL intern, nicht diese Unit)
Letzte Aktualisierung: 2026-06-05
