# STEP 4.2a – HASH-MIGRATION PROOF (AUDIT-NACHWEIS) # Status: PASS --- ## Test-Setup - **Datei:** `basis14.py` (Zeilen 1298–1316) - **Speicherort:** `kg_diktat_user_profile.json` (JSON, Feld `password_hash`) - **Testmethode:** Automatisiertes Python-Skript mit Backup/Restore des Original-Profils - **KDF:** bcrypt, cost=12, Salt eingebettet - **Legacy:** SHA-256, 64 Hex-Zeichen, kein Salt - **Testpasswörter:** `AuditTest2026!` (korrekt), `FalschesPasswort` (falsch) --- ## Test 1: Legacy-SHA-256-User anlegen ``` Passwort: AuditTest2026! SHA-256 Hash: e99f0f4a91440e4a7d89ebd1db548df0eed586dd16e1b3c0e9bb6356220e0f3b Speicherort: kg_diktat_user_profile.json ``` | Prüfung | Ergebnis | |---------|----------| | Profil gespeichert | PASS | | Hash ist Legacy (64 hex chars) | PASS | | Hash Länge = 64 | PASS | | Hash beginnt NICHT mit $2b$ | PASS | --- ## Test 2: Login mit falschem Passwort ``` Passwort: FalschesPasswort Ergebnis: REJECTED ``` | Prüfung | Ergebnis | |---------|----------| | Falsches PW abgelehnt | PASS | --- ## Test 3: Login mit korrektem Passwort + Rehash ### VORHER (Legacy SHA-256): ``` e99f0f4a91440e4a7d89ebd1db548df0eed586dd16e1b3c0e9bb6356220e0f3b ``` ### NACHHER (bcrypt): ``` $2b$12$mM1wNUuQJfYMZ23xJRfsJO/JVI0G4ucm9lT.BnTK/LVK8m/gw6CEK ``` | Prüfung | Ergebnis | |---------|----------| | Korrektes PW akzeptiert | PASS | | Hash hat sich geändert | PASS | | Neuer Hash beginnt mit $2b$ | PASS | | Neuer Hash ist NICHT Legacy | PASS | --- ## Test 4: Login nach Rehash (bcrypt-Hash) | Prüfung | Ergebnis | |---------|----------| | Korrektes PW nach Rehash | PASS | | Falsches PW nach Rehash abgelehnt | PASS | --- ## Test 5: Neue Registrierung → direkt bcrypt ``` Neues Passwort: NeuerUser2026! bcrypt Hash: $2b$12$MdhU4H6CihlPMecPxRGgHuZ0rRJw.QXd1B0tqr4A8xK... ``` | Prüfung | Ergebnis | |---------|----------| | Hash ist bcrypt | PASS | | Hash ist NICHT Legacy | PASS | | Verify korrekt | PASS | | Verify falsch abgelehnt | PASS | --- ## Test 6: Passwortänderung → bcrypt ``` Neuer Hash: $2b$12$62I3tJxk09DaPmmu.6SsEeTgSp6UJReaJtSzs57SFO6... ``` | Prüfung | Ergebnis | |---------|----------| | Hash ist bcrypt | PASS | | Altes PW abgelehnt | PASS | | Neues PW akzeptiert | PASS | --- ## Code-Verifikation ### _hash_password() – Zeile 1298–1301 ```python @staticmethod def _hash_password(pw: str) -> str: return bcrypt.hashpw(pw.encode("utf-8"), bcrypt.gensalt(rounds=12)).decode("utf-8") ``` → Erzeugt bcrypt-Hash mit cost=12 und eingebettetem Salt. ### _verify_password() – Zeile 1303–1309 ```python @staticmethod def _verify_password(pw: str, stored_hash: str) -> bool: if stored_hash.startswith("$2b$") or stored_hash.startswith("$2a$"): return bcrypt.checkpw(pw.encode("utf-8"), stored_hash.encode("utf-8")) legacy = hashlib.sha256(pw.encode("utf-8")).hexdigest() return legacy == stored_hash ``` → Erkennt bcrypt-Hashes am Prefix. Fällt auf SHA-256-Vergleich zurück. ### _is_legacy_hash() – Zeile 1311–1316 ```python @staticmethod def _is_legacy_hash(stored_hash: str) -> bool: if not stored_hash: return False return not stored_hash.startswith("$2") and len(stored_hash) == 64 ``` → Erkennt alte 64-Zeichen SHA-256-Hashes. ### Login mit Rehash – Zeile 1363–1367 ```python stored = self._user_profile.get("password_hash", "") if self._verify_password(pw, stored): if self._is_legacy_hash(stored): self._user_profile["password_hash"] = self._hash_password(pw) save_user_profile(self._user_profile) dlg.destroy() ``` → Bei erfolgreichem Login: Legacy-Hash automatisch durch bcrypt ersetzt. ### Registrierung – Zeile 1465 ```python "password_hash": self._hash_password(pw), ``` → Nutzt direkt bcrypt. ### Profiländerung (altes PW prüfen) – Zeile 1545 ```python if old_hash and not self._verify_password(pw_old_e.get(), old_hash): ``` → Verifiziert mit _verify_password (bcrypt + Legacy-kompatibel). ### Profiländerung (neues PW setzen) – Zeile 1554 ```python pw_hash = self._hash_password(new_pw) ``` → Nutzt direkt bcrypt. --- ## Gesamtergebnis | Nr | Testfall | Ergebnis | |----|----------|----------| | 1 | Legacy-Hash anlegen & erkennen | PASS | | 2 | Falsches PW → abgelehnt | PASS | | 3 | Korrektes PW → akzeptiert + Rehash | PASS | | 4 | Login nach Rehash funktioniert | PASS | | 5 | Registrierung schreibt bcrypt | PASS | | 6 | Passwortänderung schreibt bcrypt | PASS | **18/18 Einzelprüfungen: PASS** **0 Fixes notwendig** **Original-Profil wiederhergestellt** --- ## Bewertung: PASS Alle Anforderungen erfüllt: - Legacy SHA-256 wird erkannt - Login mit korrektem/falschem PW korrekt - Rehash passiert automatisch beim Login - Nach Rehash ist der gespeicherte Hash bcrypt - Neue Registrierungen und Passwortänderungen verwenden direkt bcrypt - Kein Forced Reset notwendig