Skip to content

TLDR: ALTCHA Server Integration

This guide offers a concise overview of integrating ALTCHA on your server, covering both modes: with and without the spam filter. By following these steps, you’ll ensure secure and efficient verification of user submissions, whether you need basic challenge verification or advanced spam filtering.

For easy integration, consider using official libraries:

Setup Overview

  1. Retrieve Challenge:

    • Client-side fetches a challenge using the ALTCHA widget.
  2. Solve Challenge:

    • Client-side solves the challenge.
  3. Submit Solution:

    • Solution and user data are submitted to the server.
  4. Verify on Server:

    • Server validates the solution and, if using the spam filter, validates the spam classification.

Without Spam Filter

Full docs: Server Integration

Creating a Challenge (Server-side)

  • Generate Parameters:
    • maxnumber: Maximum random number (adjusts difficulty).
    • salt: Random string (≥10 characters).
    • secret_number: Random integer (0…maxnumber).
    • challenge: SHA-256 hash of salt + secret_number.
    • signature: HMAC-SHA-256 of challenge with a secret key.
maxnumber = 100_000;
salt = random_string();
secret_number = random_int(maxnumber);
challenge = sha2_hex(concat(salt, secret_number));
signature = hmac_sha2_hex(challenge, hmac_key);
response = {
algorithm: 'SHA-256',
challenge,
maxnumber,
salt,
signature,
};

Validating a Solution (Server-side)

  • Decode Payload:

    • Extract algorithm, challenge, number, salt, signature from Base64-JSON payload.
  • Validation Steps:

    • alg_ok: Check algorithm is ‘SHA-256’.
    • challenge_ok: Verify challenge matches sha2_hex(concat(salt, number)).
    • signature_ok: Verify signature matches hmac_sha2_hex(challenge, hmac_key).
data = json_decode(base64_decode(payload));
alg_ok = equals(data.algorithm, 'SHA-256');
challenge_ok = equals(data.challenge, sha2_hex(concat(data.salt, data.number)));
signature_ok = equals(data.signature, hmac_sha2_hex(data.challenge, hmac_key));
verified = alg_ok && challenge_ok && signature_ok;

With Spam Filter

Full docs: Server Integration

Using the API with the Widget

  • Widget Configuration:
    • Set challengeurl with your API key.
    • Enable spamfilter for spam classification.
<altcha-widget
challengeurl="https://eu.altcha.org/api/v1/challenge?apiKey=ckey_..."
spamfilter
></altcha-widget>

Server Verification

  • Payload Format:
    • You receive a base64-encoded JSON object with algorithm, signature, verificationData, and verified properties.
{
"algorithm": "SHA-256",
"signature": "71b86949a1a84595f71d8abd7bdef414e8b883247e30cba93f4946b028c4fbf1",
"verificationData": "classification=BAD&score=7.75&...&time=1713566250&verified=true",
"verified": true
}

Verifying the Signature

  1. Calculate the SHA hash of verificationData.
  2. Compute the HMAC signature using the secret part of your API key.

Example pseudo-code:

hash = sha2(payload.verificationData);
signature = hmac_sha2_hex(hash, hmac_key);
  • Verification:
    • The payload is verified if the computed signature matches the signature property.

Verifying Fields (Spam Filter)

  • Check fields and fieldsHash:
    • Concatenate field values with \n and compute the SHA hash.

Example pseudo-code:

hash = sha2_hex(field1_value + "\n" + field2_value + "\n" + field3_value);
  • Validation:
    • Data is correct if the computed hash matches the fieldsHash.

Example Code

  • Node.js Example:
import { createChallenge, verifySolution } from 'altcha-lib';
const hmacKey = '$ecret.key'; // Secret HMAC key
// Create a new challenge
const challenge = await createChallenge({ hmacKey });
// Verify the submitted payload
const ok = await verifySolution(payload, hmacKey);

Security Recommendations

  • Prevent Replay Attacks:

    • Invalidate previously solved challenges.
  • Challenge Expiration:

    • Include a timestamp in the salt to limit the validity period.
    • Use salt = '<random_salt>?expires=<unix_ts>'.

API Endpoints

  • Creating a New Challenge:

    • GET /api/v1/challenge
  • Verifying Solution:

    • POST /api/v1/challenge/verify
  • Validating Server Signature:

    • POST /api/v1/challenge/verify_server_signature