Standard-Bibliothek — `hash`
Verfügbar — implementiert in Phase B.7.3. Vollständige Spec in
docs/hash.md.
Hash-Funktionen verwandeln beliebige Daten in einen kurzen, deterministischen Fingerabdruck. Der gleiche Input ergibt immer den gleichen Hash. Ein einziges Bit Unterschied im Input ergibt einen komplett anderen Hash.
25.1 Aktivieren und einfache Hashes
nutze hash
sag hash.md5("Hallo") // 32-stelliger Hex-String
sag hash.sha256("Hallo") // 64-stelliger Hex-String — der Standard
sag hash.sha512("Hallo") // 128-stelliger Hex-String
25.2 Sicherheits-Einordnung — sehr wichtig
Nicht alle Hashes sind gleich gut. Das ist die Realität:
| Algorithmus | Status | Wofür benutzen? |
|---|---|---|
| MD5 | kryptographisch gebrochen | Caching, ETags, Identifiers — nie für Sicherheit |
| SHA-1 | kryptographisch gebrochen | Git-Kompatibilität, Legacy — nie für neue Sicherheit |
| SHA-256 | sicher | Datei-Hashes, Inhalts-Verifikation, Standard-Wahl |
| SHA-512 | sicher | Wie SHA-256, längerer Output |
| HMAC-SHA256 | sicher | API-Tokens, Webhook-Signaturen |
Faustregel: Wenn du nicht weißt was du brauchst, nimm SHA-256.
25.3 Was hash NICHT ist
Hash-Funktionen sind nicht für Passwörter gedacht!
// FALSCH — niemals so Passwörter speichern!
nimm gehasht = hash.sha256(passwort)
datei.schreibe("benutzer.txt", gehasht)
Warum nicht? SHA-256 ist zu schnell. Ein Angreifer kann Milliarden Hashes pro Sekunde durchprobieren (Brute-Force). Für Passwörter braucht man absichtlich langsame Funktionen wie Bcrypt, Argon2 oder scrypt. Die kommen später mit dem passwort-Modul.
Auch nicht in hash:
- Verschlüsselung (AES, RSA) → kommt mit
krypto-Modul - Sichere Zufallszahlen für Salts/Tokens → kommt mit
krypto.zufall_bytes
25.4 Datei-Hashes (Inhalts-Verifikation)
nutze datei
nutze hash
// Hinweis: setzt eine vorhandene Datei voraus (sonst Fehler).
nimm fingerabdruck = hash.sha256(datei.inhalt("./readme.md"))
sag "Datei-Hash: {fingerabdruck}"
// Später: prüfen, ob die Datei sich geändert hat
nimm aktueller = hash.sha256(datei.inhalt("./readme.md"))
wenn aktueller == fingerabdruck {
sag "Datei unverändert"
}
Heute funktioniert das nur für Text-Dateien, weil datei.inhalt UTF-8 verlangt. Binär-Hashes (Bilder, ZIP, etc.) kommen mit dem bytes-Modul.
25.5 HMAC — authentifiziertes Hashing
HMAC ist wie ein normaler Hash, aber mit einem geheimen Schlüssel. Nur jemand, der den Schlüssel kennt, kann den HMAC reproduzieren — perfekt für API-Tokens und Webhook-Signaturen.
nutze umgebung
// Schlüssel aus Umgebung holen — NIEMALS im Quellcode hartcodieren!
nimm geheim = umgebung.wert_oder("API_SECRET", "")
wenn geheim == "" {
sag "API_SECRET nicht gesetzt!"
umgebung.beende(1)
}
nimm payload = "user_id=42&action=transfer"
nimm signatur = hash.hmac_sha256(payload, geheim)
// Ein Angreifer ohne den Schlüssel kann diese Signatur nicht erzeugen.
// Server prüft mit derselben Funktion, ob die Signatur stimmt:
sag hash.hmac_sha256(payload, geheim) == signatur // wahr
25.6 Base64 und Hex — Encoding
// Base64 — gut für JSON-Übertragung von „beliebigen" Bytes
sag hash.base64_kodiert("Hallo") // "SGFsbG8="
sag hash.base64_dekodiert("SGFsbG8=") // "Hallo"
// Hex — gut für menschen-lesbare Hash-Ausgaben (deshalb sind Hash-Funktionen
// ohnehin Hex-formatiert)
sag hash.hex_kodiert("ABC") // "414243"
sag hash.hex_dekodiert("414243") // "ABC"
Roundtrip funktioniert garantiert für UTF-8-Text: dekodiert(kodiert(x)) == x.
Caveat: Beim Dekodieren erwartet Kiste, dass die dekodierten Bytes gültiges UTF-8 sind — sonst Fehler. Wer beliebige Bytes braucht, wartet auf das bytes-Modul.
25.7 Was nicht in hash ist
- Streaming-Hashing für sehr große Dateien — kommt mit
bytes/Streaming. - URL-Safe-Base64 — kommt später falls Bedarf.
- Konstanten-Zeit-Vergleich für HMAC-Tags — kommt mit
krypto.gleich_konstant_zeit. - Bcrypt/Argon2/scrypt/PBKDF2 — eigenes Modul
passwort/krypto. - Verschlüsselung, Signaturen, Key-Derivation —
krypto-Modul.