Das Rätsel
Ein Rätsel besteht aus einem 32-Byte-Kopf und einer 32-Byte-HMAC-SHA256-Signatur mit dem Serverschlüssel.
Der Kopf enthält Version, Anzahl der verlangten Null-Bits, Anzahl der Teilrätsel, Ausgabe- und Ablaufzeit, die Sitekey-ID und eine zufällige 16-Byte-Rätsel-ID.
Für jedes Teilrätsel i sucht der Browser eine 8-Byte-Nonce, sodass SHA-256(Kopf || i || Nonce) mit der verlangten Anzahl Null-Bits beginnt.
Der erwartete Aufwand je Teilrätsel sind 2^Bits Hashes;
die acht Teilrätsel glätten die Streuung, damit die Lösungszeiten berechenbar sind.
Schwierigkeitsstufen
| Stufe | Null-Bits | Erwartete Hashes |
|---|---|---|
| 1 | 11 | 16,384 |
| 2 | 12 | 32,768 |
| 3 | 13 | 65,536 |
| 4 | 14 | 131,072 |
| 5 | 15 | 262,144 |
| 6 | 16 | 524,288 |
| 7 | 17 | 1,048,576 |
| 8 | 18 | 2,097,152 |
| 9 | 19 | 4,194,304 |
| 10 | 20 | 8,388,608 |
Die Standardstufe steht in der .env-Datei (DIFFICULTY_DEFAULT) und lässt sich je Sitekey überschreiben.
Ein Desktop-Browser rechnet im Worker etwa ein bis zwei Millionen Hashes pro Sekunde: Stufe 4 dauert etwa 0,1 s, Stufe 7 etwa 1 bis 2 s, Stufe 10 etwa 3 bis 8 s.
Handys sind 2- bis 5-mal langsamer.
Anpassbare Schwierigkeit und Ratenbegrenzung
Der Server zählt Rätsel je Client-Adresse (als gesalzenen Hash) in einem Zeitfenster (RATE_WINDOW, Standard 10 Minuten).
Adressen, die die Schwellen in RATE_STEPS überschreiten (Standard 10, 30, 100, 300 Rätsel), bekommen eine, zwei, drei oder vier Stufen mehr.
Über RATE_PUZZLES_MAX (Standard 600) antwortet die API mit 429.
Geteilte Adressen (Büros, Mobilfunk-NAT) bekommen also schwerere Rätsel, aber bis zur Obergrenze nie eine Sperre.
Was der Server prüft
- Format und Version des Tokens.
- HMAC-Signatur (Vergleich in konstanter Zeit).
- Ablauf (PUZZLE_TTL, Standard 30 Minuten) mit kleiner Toleranz für Uhrenabweichungen.
- Das Rätsel steht in der Datenbank und wurde noch nicht benutzt.
- Jede Nonce löst ihr Teilrätsel.
- Das Rätsel wird mit einem atomaren Update als benutzt markiert; eine gleichzeitige Wiederholung verliert.
Was gespeichert wird
Je Rätsel: ID, Sitekey-ID, gesalzener Adress-Hash, Bits, Anzahl, Ausgabe- und Ablaufzeit, Lösungszeit.
Die Einträge werden eine Stunde nach Ablauf bei normalen API-Aufrufen gelöscht (kein Cronjob).
Tageszähler je Sitekey (ausgegeben, geprüft, abgelehnt) bleiben für die Statistik erhalten;
sie enthalten keine personenbezogenen Daten.
Grenzen eines Proof of Work
Ein Proof of Work macht Missbrauch teuer, aber nicht unmöglich.
Ein entschlossener Angreifer mit vielen Rechnern kann weiterhin Rätsel lösen.
Kombinieren Sie CDPCaptcha mit den üblichen Maßnahmen: einer Ratenbegrenzung am Formular selbst, einem Honeypot-Feld und Plausibilitätsprüfungen des Inhalts.
Unsere eigenen Kontakt- und Registrierungsformulare machen genau das.
