std.crypto.ct
Constant-Time Utilities — timing-seitenkanal-freie Basisfunktionen für kryptographischen Code. Alle Operationen laufen in streng konstanter Zeit: keine datenbabhängigen Branches, kein datenabhängiges Memory-Access-Pattern. Intern genutzt von ML-KEM, ML-DSA und DADQ.
import std.crypto.ct;
→ std.crypto · Standard Library
Funktionen
Auswahl und Vergleich:
| Funktion | Signatur | Beschreibung |
|---|---|---|
CTSelect | (a, b, mask): int64 | Gibt a zurück wenn mask = 0xFFFF…FF, sonst b. Kein Branch. |
CTEqual | (a, b): int64 | Gibt 0xFFFF…FF zurück wenn a == b, sonst 0. |
CTIsZero | (x): int64 | Gibt 0xFFFF…FF zurück wenn x == 0, sonst 0. |
CTMemEqual | (a, b, len): int64 | Vergleicht len Bytes ohne Early-Exit. Gibt 1 zurück wenn gleich. |
Speicher:
| Funktion | Signatur | Beschreibung |
|---|---|---|
SecureZero | (ptr, len) | Überschreibt len Bytes mit 0. Nicht vom Compiler wegoptimiert (Barrier). |
Modulare Arithmetik:
| Funktion | Signatur | Beschreibung |
|---|---|---|
CTBarrettReduce | (a, q): int64 | Barrett-Reduktion: a mod q ohne Division in konstanter Zeit. Nutzt 2³²/q-Approximation. |
CTMontgomeryReduce | (a, q, qinv): int64 | Montgomery-Reduktion: a × R⁻¹ mod q. Erfordert qinv = q⁻¹ mod 2³². |
Verwendungsbeispiele
Constant-Time Vergleich (kein Early-Exit):
import std.crypto.ct;
// Sicher: MAC-Vergleich in konstanter Zeit (keine Timing-Leaks)
var mac1: int64 := alloc(32);
var mac2: int64 := alloc(32);
// ... beide MACs berechnen ...
var equal: int64 := CTMemEqual(mac1, mac2, 32); // 1 = gleich, 0 = verschieden
free(mac1, 32); free(mac2, 32);
CTSelect für branchlose Auswahl:
import std.crypto.ct;
// Wähle a oder b ohne if-Branch (wichtig in krypto-kritischen Schleifen):
var mask: int64 := CTEqual(condition, 1); // 0xFFFFFFFFFFFFFFFF wenn condition==1
var result: int64 := CTSelect(a, b, mask); // a wenn mask gesetzt, sonst b
SecureZero nach Schlüsselverwendung:
import std.crypto.ct;
import std.alloc;
var sk: int64 := alloc(576);
// ... Schlüssel verwenden ...
SecureZero(sk, 576); // Schlüsselmaterial sicher löschen (nicht wegoptimiert)
free(sk, 576);
Warum Constant-Time?
Normaler Code wie if a == b { … } läuft auf modernen CPUs unterschiedlich lang je nach Daten (Branch-Predictor, Cache). Ein Angreifer kann daraus Rückschlüsse auf geheime Daten ziehen (Timing-Angriff).
CTMemEqual verwendet XOR aller Bytes und gibt das Ergebnis erst am Ende zurück — kein Early-Exit, immer gleiche Laufzeit.
CTSelect nutzt bitweise Maskierung statt eines if-Branches:
CTSelect(a, b, mask) = (a & mask) | (b & ~mask)
Letzte Aktualisierung: 2026-06-08
