Zum Inhalt springen

Server-Integration

PoW-Verifizierungsprozess

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

  1. Abrufen der challenge auf der Clientseite.
  2. Lösung für die Challenge bestimmen.
  3. Einreichen der Lösung und Benutzerdaten auf dem Server.
  4. Überprüfen der Lösung und Signatur auf dem Server.

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:

// Generiere ein zufälliges Salt (empfohlene Länge: mindestens 10 Zeichen)
salt = random_string();
// Generiere eine zufällige Geheimzahl (positive Ganzzahl)
// Der Bereich hängt von der gewählten Komplexität ab (siehe Dokumentation)
// Stellen Sie sicher, dass diese Zahl nicht dem Client offengelegt wird
secret_number = random_int();
// Berechne den SHA256-Hash des konkatenierten Salt + secret_number (Ergebnis als HEX-String kodiert)
challenge = sha2_hex(concat(salt, secret_number));
// Erstelle eine Server-Signatur mit einem HMAC-Schlüssel (Ergebnis als HEX-String kodiert)
signature = hmac_sha2_hex(challenge, hmac_key);
// Gib JSON-kodierte Daten zurück
response = {
algorithm = 'SHA-256',
challenge,
salt,
signature,
};

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.