Zum Inhalt springen

Server-Integration

PoW-Verifizierungsprozess

Der Verifizierungsprozess basiert auf Berechnungsarbeit (SHA-Hashing) und umfasst folgende Schritte:

  1. Benutzer startet den Verifizierungsprozess.
  2. Das Widget sendet eine Anfrage an challengeurl, um die Herausforderungsdaten abzurufen.
  3. Das Widget verarbeitet und löst die Herausforderung basierend auf den abgerufenen Daten.
  4. Der Benutzer reicht das Formular ein, das die gelöste Herausforderung enthält.
  5. Der Server überprüft die Nutzlast in der Formularübermittlung, um sicherzustellen, dass sie mit der erwarteten Lösung der Herausforderung übereinstimmt.

Der Client-seitige Aspekt wird durch das ALTCHA-Widget verwaltet, während die Implementierung der serverseitigen Verifizierung erforderlich ist. Der Server-Submission-Handler (z.B. POST /form_submit) muss das ALTCHA-Payload bei der Formularübermittlung authentifizieren.

Lesen Sie die Proof-of-Work-Dokumentation, um mehr über den Mechanismus hinter ALTCHA zu erfahren.

Komplexität

Die Generierung einer neuen Challenge umfasst drei Durchläufe der SHA-Berechnung (einmal für die Challenge und zweimal für die HMAC-Signatur). Ebenso erfordert die Überprüfung einer Lösung drei Durchläufe.

Der Bereich der Zufallszahl passt die Schwierigkeit der Rechenaufgabe an, die vom Client erforderlich ist.

Für weitere Details siehe Anpassung der Komplexität.

Server

Der Server muss für jede ALTCHA-Verifizierung eine neue Challenge generieren. Es gibt zwei Methoden, um die Challenge an das Widget bereitzustellen:

  1. Verwendung von challengeurl: Wenn konfiguriert, holt das Widget die Challenge von der angegebenen URL. Der Server muss eine neue Challenge wie unten beschrieben zurückgeben.

  2. Verwendung von challengejson: Bieten Sie die Challenge direkt als JSON-kodierten String an. Diese Methode ist nützlich für serverseitig gerenderte Seiten.

Lesen Sie mehr über den Proof-of-Work-Mechanismus.

Erstellen einer Challenge

Hier ist ein Pseudocode-Beispiel für die Erstellung einer Challenge auf dem Server:

// Wählen Sie die Komplexität - die maximale Zufallszahl (siehe Komplexitätsdokumentation)
maxnumber = 100_000;
// Generieren Sie ein zufälliges Salt (empfohlene Länge: mindestens 10 Zeichen)
salt = random_string();
// Generieren Sie eine zufällige geheime Zahl (positive ganze Zahl)
// Bereich zwischen 0...maxnumber
// Achten Sie darauf, diese Zahl NICHT an den Client weiterzugeben
secret_number = random_int(maxnumber);
// Berechnen Sie den SHA-256-Hash des zusammengefügten Salts + secret_number (Ergebnis als HEX-String kodiert)
challenge = sha2_hex(concat(salt, secret_number));
// Erstellen Sie eine Serversignatur mit einem HMAC-Schlüssel (Ergebnis als HEX-String kodiert)
signature = hmac_sha2_hex(challenge, hmac_key);
// JSON-kodierte Daten zurückgeben
response = {
algorithm: 'SHA-256',
challenge,
maxnumber,
salt,
signature,
};

Wenn der Parameter maxnumber an den Client zurückgegeben wird, kann das ALTCHA-Widget die Arbeitslastverteilung zwischen mehreren Arbeitern besser optimieren, was zu einer schnelleren Ausführung führt. Die offiziellen Bibliotheken geben standardmäßig den Wert maxnumber zurück, da dies generell empfohlen wird. Abhängig von Ihrem Anwendungsfall könnte der Parameter maxnumber als geheimer Parameter betrachtet werden, der nicht an den Client weitergegeben werden sollte, da er den Bereich der Zahl offenlegt. In bestimmten Fällen, in denen Sie eine hohe Schwierigkeit wünschen, wie z.B. M2M oder benutzerdefinierte Integrationen, geben Sie maxnumber nicht zurück.

Salt-Parameter

Ab der Widget-Version v0.4 (Mai 2024) wird empfohlen, das expires-Flag und zusätzliche Parameter im salt als URL-kodierte Abfragezeichenfolgen einzuschließen. Dadurch können benutzerdefinierte Daten übergeben werden, die Teil der Signatur sind und auf dem Server überprüft werden können.

Das Widget erkennt automatisch den expires-Parameter, wenn er im Salz als Unix-Zeitstempel in Sekunden angegeben wird:

salt = '<random_salt>?expires=1715526540'

Um die Kompatibilität mit zukünftigen Versionen des Widgets sicherzustellen, wird empfohlen, benutzerdefinierte Parameter mit einem Unterstrich _ zu kennzeichnen.

Die altcha-lib-Bibliothek unterstützt bereits Salzparameter und überprüft automatisch das Ablaufdatum der Herausforderung ab Version v0.3.

Formularübermittlung

Bei der Übermittlung innerhalb eines <form> erhält der Server Daten, die als application/x-www-form-urlencoded oder multipart/form-data codiert sind, abhängig von der Formstruktur. Das ALTCHA-Payload wird als altcha-Feld eingebettet sein (anpassbar über das name-Attribut im Widget).

Verwenden Sie den Wert des altcha-Feldes als Payload in den untenstehenden Beispielen. Das Payload ist ein Base64-JSON-kodierter String.

Lösungsvalidierung

Hier ist ein Pseudocode-Beispiel zur Validierung einer Lösung auf dem Server:

// Das Payload ist ein BASE64-JSON-kodierter String
// Die dekodierten Daten sind ein Objekt, das { algorithm, challenge, number, salt, signature } enthält
data = json_decode(base64_decode(payload));
// Algorithmus validieren
alg_ok = equals(data.algorithm, 'SHA-256');
// Challenge validieren
challenge_ok = equals(data.challenge, sha2_hex(concat(data.salt, data.number)))
// Signatur validieren
signature_ok = equals(data.signature, hmac_sha2_hex(data.challenge, hmac_key))
// Als verifiziert betrachten, wenn alle Überprüfungen zutreffen
verified = alg_ok and challenge_ok and signature_ok

Beispiel

Die offizielle JS-lib funktioniert mit Node.js, Bun und Deno.

server.js
import { createChallenge, verifySolution } from 'altcha-lib';
const hmacKey = '$ecret.key'; // Ändern Sie den geheimen HMAC-Schlüssel
// Erstellen Sie eine neue Challenge und senden Sie sie an den Client:
const challenge = await createChallenge({
hmacKey,
});
// Bei Einreichung die Nutzlast überprüfen:
const ok = await verifySolution(payload, hmacKey);

Für weitere Beispiele und Integrationen, siehe die Community-Integrationen Seite.

Sicherheitsempfehlungen

  • Wiederholungsangriffe

    Um die Anfälligkeit von “Wiederholungsangriffen” zu verhindern, bei denen ein Client dieselbe Lösung mehrmals erneut einreicht, sollte der Server Maßnahmen ergreifen, die zuvor gelöste Challenges ungültig machen.

    Der Server sollte ein Register gelöster Challenges führen und jede Einreichung ablehnen, die versucht, eine Challenge wiederzuverwenden, die bereits erfolgreich gelöst wurde.

  • Ablauf der Challenge

    Durch die Begrenzung der Gültigkeitsdauer von Challenges können Sicherheitsmaßnahmen verstärkt werden, um sicherzustellen, dass Challenges nicht unbegrenzt ausgenutzt werden können. Die Implementierung des Ablaufs der Challenge beinhaltet die Festlegung eines Zeitlimits, innerhalb dessen eine Challenge gelöst und eingereicht werden muss.

    Eine effektive Methode zur Erreichung des Ablaufs der Challenge besteht darin, in die Erzeugung des Challenge-Salzes einen Server-Zeitstempel einzubeziehen.

    Ab Version 0.4 des Widgets können Sie Salt-parameter nutzen und den ?expires=<unix_ts>-Parameter im Salz einschließen. Das Widget erkennt automatisch den expires-Parameter. Ihr Server sollte dann das Ablaufdatum während des Überprüfungsprozesses überprüfen.