update
This commit is contained in:
194
AzA march 2026/security/handovers/STEP_4_2a_HASHING_PROOF.md
Normal file
194
AzA march 2026/security/handovers/STEP_4_2a_HASHING_PROOF.md
Normal file
@@ -0,0 +1,194 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user