Files
onyx/Spikes/password-check-probe.swift
ScarriffleandClaude Opus 5 e3b215a1dd Ein eigener Sperrbildschirm — und ohne gespeichertes Passwort
Kameraaufnahme, Anlernen über drei Posen, Fenster je Bildschirm auf
Bildschirmschoner-Ebene, Passwortrückfall.

**Das Anmeldepasswort wird nicht gespeichert.** Ein Spike hat den Weg
freigeräumt: `ODRecord.verifyPassword` ist öffentliche API, die Eingabe geht
direkt hinein, das Ergebnis ist ein `Bool`, danach ist die Zeichenkette wieder
weg. Damit fällt der Grund weg, aus dem vergleichbare Programme sich das
Passwort geben lassen und in die Keychain legen.

Angelernt wird über drei Posen mit je fünf Aufnahmen. Der Merkmalsvektor ist ein
allgemeiner Bildmerkmalsvektor und kein Gesichtsmerkmal — er reagiert auf
Kopfhaltung und Beleuchtung mit. Eine einzige Aufnahme beschreibt genau eine
Haltung bei genau einem Licht.

Die Vektoren liegen in der Keychain, nicht in einer Datei: aus ihnen lässt sich
kein Bild zurückgewinnen, aber wer sie hat, kann prüfen, ob eine bestimmte
Person vor der Kamera stand.

Die Einschränkung steht auf dem Sperrbildschirm selbst und nicht im
Kleingedruckten: Bequemlichkeit, keine Sicherheitsgrenze; der Vergleich läuft
über die Webcam und lässt sich mit einem Foto täuschen. Wer sich darauf
verlässt, tut es dort.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-05 21:22:32 +02:00

41 lines
1.7 KiB
Swift

import Foundation
import OpenDirectory
// Lässt sich ein eingegebenes Passwort gegen die echte Anmeldung prüfen, ohne
// es je zu speichern?
//
// Sapphire lässt sich das Anmeldepasswort geben und legt es in die Keychain.
// Das ist nicht nötig — und ein gespeichertes Anmeldepasswort ist genau die
// Sorte Sicherheitsschuld, die man nicht aufnehmen sollte, wenn es auch ohne
// geht.
//
// **Hier wird ausdrücklich KEIN Passwort geprüft.** Der Spike stellt nur fest,
// ob der Weg zum Benutzerdatensatz offensteht. Fehlversuche gegen ein echtes
// Konto können Sperrfristen auslösen; das ist nichts, was ein Spike anrichten
// darf.
let user = NSUserName()
print("Benutzer: \(user)")
do {
let node = try ODNode(session: ODSession.default(), type: ODNodeType(kODNodeTypeAuthentication))
print("Knoten: erreichbar")
let record = try node.record(withRecordType: kODRecordTypeUsers, name: user, attributes: nil)
print("Datensatz: gefunden")
// Genau diese Methode würde die Prüfung machen — sie wird hier nicht gerufen.
let selector = NSSelectorFromString("verifyPassword:error:")
print("verifyPassword(_:): \(record.responds(to: selector) ? "vorhanden" : "FEHLT")")
let names = try record.values(forAttribute: kODAttributeTypeFullName) as? [String]
print("Vollständiger Name lesbar: \(names?.first != nil ? "ja" : "nein")")
print("\nBefund: Der Weg steht offen. Ein eingegebenes Passwort lässt sich")
print("gegen die echte Anmeldung prüfen, ohne es irgendwo abzulegen.")
} catch {
print("FEHLER: \(error.localizedDescription)")
print("Dann bliebe nur Authorization Services — oder, schlimmstenfalls, das")
print("Speichern des Passworts. Letzteres wäre ein Grund, die Funktion zu lassen.")
}