OpenWebAuth: PKCS#1 v1.5 zelf uitpakken, met een grens op het aantal pogingen
Node weigert privateDecrypt met RSA_PKCS1_PADDING sinds de mitigatie voor
CVE-2023-46809 (Marvin). Daarmee was gastlogin stuk: vier tests rood, en
in bedrijf een geworpen TypeError midden in de inlogstroom.
De revert-vlag was geen uitweg. Die bestaat alleen op de lijnen 18/20/21
-- Node voegt een security-revert alleen toe aan wat ondersteund was toen
de fix kwam -- en 20 is sinds 30 april 2026 EOL. Node 22+ heeft hem nooit
gehad. FEP-61cf schrijft v1.5 voor, dus OAEP repareert de test en breekt
de interop met Hubzilla. Blijft over: het omhulsel zelf afhalen via
RSA_NO_PADDING.
Dat is precies het stuk dat de CVE veroorzaakte, dus met de zorg erbij:
- Geen vroege uitgang en geen worp. De scan loopt altijd het hele blok af.
Dat is geen echte constant-time -- die krijg je in JavaScript met JIT en
GC niet -- maar het haalt het waarneembare verschil weg.
- Implicit rejection: bij een ongeldig omhulsel een afgeleide waarde in
plaats van een fout. DETERMINISTISCH, uit sleutel + ciphertext. Vers
willekeurig zou slechter zijn: dezelfde ciphertext twee keer aanbieden
gaf dan twee antwoorden, en juist dat verschil wilden we verbergen.
- Een teller van 20/uur op POST /magic, per SITE-SLUG want daar hangt het
sleutelpaar aan. Hij telt ALLE pogingen, niet alleen de mislukte: een
teller die alleen faalt meetelt is zelf weer een orakel, en dan staat de
vertakking die we bij de ontsleuteling weghaalden aan de achterdeur
terug. Een orakel heeft honderdduizenden pogingen nodig; twintig per uur
is voor een mens onzichtbaar.
Onderweg bleek een aanname in de bestaande code niet te kloppen: het
commentaar bij decryptToken en bij de test leunden op OpenSSL's eigen
implicit rejection. Die kwam pas in 3.2; Node 20 brengt 3.0.19 mee en
daar WERPT hij. Die meting was dus op een andere machine gedaan dan waar
het draait. Nu maken we het zelf, dus de eigenschap staat vast ongeacht
de OpenSSL eronder.
Suite 1160/1160. Van de drie eigenschappen bijten er twee bij een
controleproef (de PS-ondergrens en het determinisme); de nep-uitkomst
niet, want de andere tak geeft dan een lege string die net zo goed
sneuvelt. Dat staat zo in het commentaar in plaats van dat ik doe alsof
alle drie dragend zijn.
Co-Authored-By: Claude Opus 5 <noreply@…>