Skip to content

HashWX ​

HashWX ist Caps Standard-Proof-of-Work. Während SHA-256 eine feste Hash-Funktion nutzt, erzeugt HashWX für jeden Nonce-Block eine neue, gebaut aus Integer-Operationen und Verzweigungen, die GPUs schlecht ausführen. Entworfen hat es tevador, von dem auch RandomX stammt. Sein Designdokument erklärt die Funktionsweise. Cap nutzt seinen WebAssembly-Referenz-Build.

Es ist der Standard in capd und in der Core-Bibliothek.

Warum nicht SHA-256 ​

Beim Bot-Schutz zählt, wie viele Challenges ein Angreifer pro Stunde löst, nicht wie lange eine einzelne dauert. Eine GPU führt eine feste Funktion wie SHA-256 gleichzeitig auf Tausenden Lanes aus. Vor HashWX nutzte Cap RSW-Time-Lock-Puzzles, die sich innerhalb eines Puzzles nicht parallelisieren lassen. Eine GPU rechnet aber trotzdem Tausende unabhängige Puzzles nebeneinander. Gemessen gegen eine Consumer-GPU:

AlgorithmusCPU, Ryzen 3700X, 16 ThreadsGPU, RTX 5060 TiGPU-Vorteil
SHA-25641 MH/s6150 MH/s~150x
RSW26 H/s4400 H/s~170x
HashWX2,8 MH/s5,8 MH/s~2x

Die Zahlen stammen von tevador und beruhen auf seiner eigenen, nicht veröffentlichten CUDA-Implementierung. Cap hat die RSW-Zeile nachgemessen. Ein M3 schafft 2,11 H/s pro Thread, was für 16 Ryzen-Threads auf 26 H/s hinausläuft.

RSW ist abgekündigt. capd liefert jetzt HashWX an Keys aus, die auf RSW eingestellt waren. Die Core-Bibliothek stellt auf Anfrage weiterhin RSW-Challenges aus, wähle es aber nicht für neue Setups.

Kosten ​

Serverzeit pro Challenge auf einem Kern eines Apple M3, Median über 200 Erzeugungen und 40 Verifizierungen:

ProtokollErzeugungVerifizierungGesamt
HashWX, 1 Challenge14 µs40 µs54 µs
HashWX, 4 Teil-Challenges (Standard)20 µs129 µs149 µs
SHA-256, 50 Challenges mit Schwierigkeit 44 µs83 µs87 µs
RSW, t = 75.0001522 µs14 µs1536 µs

Die Schwierigkeit ändert an diesen Zahlen nichts. Verifizieren ist ein Hash pro Teil-Challenge, egal wie lange es gedauert hat, ihn zu finden.

Auf dem Client hat eine einzelne Challenge eine zufällige Lösungszeit. Dieselbe Schwierigkeit kann bei einem Besucher 30 ms und beim nächsten 3 s dauern. Cap teilt die Schwierigkeit standardmäßig auf vier Teil-Challenges auf, was die Lösungszeit gleichmäßiger macht. Gemessen durch das Widget in Chrome auf einem M3 mit 8 Kernen, je 72 Lösungen, beide Schwierigkeiten auf ungefähr denselben Median abgestimmt:

1 Challenge, d = 1.330.0004 Teil-Challenges, d = 1.000.000
Median536 ms490 ms
p901447 ms778 ms
Langsamste von 722378 ms1490 ms

Die rechte Spalte ist der Standard. Gegen einen capd-Key ergab er einen Median von 578 ms und ein p90 von 0,9 s. Das Aufteilen ändert nichts daran, was ein Angreifer bezahlt, denn die erwartete Arbeit bleibt in beiden Fällen d Hashes.

Browser ​

Der WebAssembly-Build läuft mit etwa 60% der nativen Geschwindigkeit. Gemessen auf demselben M3:

Browser1 Worker8 WorkerInterpretierter Fallback
Chrome 153440 KH/s2050 KH/s94 KH/s
Firefox 156420 KH/s1850 KH/s105 KH/s
Safari 27.2410 KH/s1480 KH/s105 KH/s

Safari erreicht auf allen Kernen etwa 70% der Geschwindigkeit von Chrome. Stimme die Schwierigkeit also auf Safari ab. Beim Standard sind das etwa 0,5 s auf Chrome und 0,7 s auf Safari.

Wenn du selbst misst, nutze Release-Builds und lass den Tab im Vordergrund. Playwrights Firefox führt WebAssembly drei- bis sechsmal langsamer aus als echtes Firefox, und ein Tab im Hintergrund kann auf den Effizienzkernen laufen.

Smartphones ​

Die Standardschwierigkeit auf echten Smartphones über BrowserStack, je 15 Lösungen, jeweils mit einer frisch geladenen Seite:

GerätSystemAlle KerneMedianLangsamste
Galaxy S24Android 141238 KH/s1,1 s1,8 s
Pixel 9Android 15837 KH/s1,4 s2,0 s
Pixel 6Android 12746 KH/s1,9 s2,4 s
iPhone 15iOS 17nicht gemessen1,9 s4,3 s
iPhone 12iOS 17620 KH/s2,0 s3,3 s
iPhone 13iOS 15678 KH/s2,2 s4,1 s
iPhone SE 2022iOS 15588 KH/s2,4 s4,0 s
Redmi Note 11Android 11456 KH/s2,4 s4,8 s

Jede Lösung enthält zwei Roundtrips zum Testserver von je 80 bis 190 ms. Eine Seite, auf der HashWX bereits eine Minute lief, löste 24% bis 29% schneller. Benchmarks mit Aufwärmphase sehen also besser aus als das, was Besucher erleben.

Kommt der Großteil deines Traffics von Mobilgeräten, senke die Schwierigkeit. Die Lösungszeit skaliert mit ihr. 500.000 halbiert also ungefähr den Rechenanteil dieser Zahlen.

HashWX braucht WebAssembly und auf iPhones iOS 15 oder neuer. Für Browser ohne WebAssembly nutze SHA-256, das einen JavaScript-Fallback hat.

Grenzen ​

Spezialhardware würde eine CPU weiterhin schlagen. Ein für HashWX gebauter FPGA oder ASIC kostet Millionen in der Entwicklung, was sich fürs CAPTCHA-Lösen nicht rechnet. Das ist aber ein wirtschaftliches Argument und kein kryptografisches.

Menschen, die fürs manuelle Lösen von Challenges bezahlt werden, hält es ebenfalls nicht auf. Kombiniere es mit Instrumentation, damit zusätzlich ein echter Browser erforderlich ist.