altcha-org / altcha
A lightweight PHP library for creating and verifying ALTCHA challenges.
Requires
- php: >=8.2
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.72
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^2.1
- phpstan/phpstan-phpunit: ^2.0
- phpunit/phpunit: ^11.5.50
README
A lightweight PHP library for creating and verifying ALTCHA challenges using key derivation functions (PBKDF2, Argon2id, Scrypt).
Compatibility
- PHP 8.2+
Migrating from V1 to V2
Example
Installation
composer require altcha-org/altcha
Usage
<?php require 'vendor/autoload.php'; use AltchaOrg\Altcha\Altcha; use AltchaOrg\Altcha\CreateChallengeOptions; use AltchaOrg\Altcha\SolveChallengeOptions; use AltchaOrg\Altcha\VerifySolutionOptions; use AltchaOrg\Altcha\Payload; use AltchaOrg\Altcha\Algorithm\Pbkdf2; $pbkdf2 = new Pbkdf2(); $altcha = new Altcha( hmacSignatureSecret: 'secret', hmacKeySignatureSecret: 'key-secret', // optional, enables fast verification path ); // Create a new challenge // Modify the cost and counter depending on the algorithm $challenge = $altcha->createChallenge(new CreateChallengeOptions( algorithm: $pbkdf2, cost: 5000, counter: random_int(5000, 10000), expiresAt: time() + 600, )); // Solve the challenge (client-side in production) $solution = $altcha->solveChallenge(new SolveChallengeOptions( algorithm: $pbkdf2, challenge: $challenge, )); // Verify the solution (server-side) if ($solution !== null) { $payload = new Payload($challenge, $solution); $result = $altcha->verifySolution(new VerifySolutionOptions( algorithm: $pbkdf2, payload: $payload, )); if ($result->verified) { echo "Solution verified!\n"; } }
API
Altcha
$altcha = new Altcha( hmacSignatureSecret: 'secret', hmacKeySignatureSecret: 'key-secret', // enables fast verification path hmacAlgorithm: HmacAlgorithm::SHA256, // default );
Altcha::createChallenge(CreateChallengeOptions $options): Challenge
Creates a new challenge.
CreateChallengeOptions
| Parameter | Type | Default | Description |
|---|---|---|---|
algorithm |
DeriveKeyInterface |
required | Key derivation algorithm |
cost |
int |
required | Iterations/time cost |
counter |
?int |
null |
Counter for deterministic mode |
data |
?array |
null |
Custom metadata |
expiresAt |
?int |
null |
Unix timestamp for expiration |
keyLength |
int |
32 |
Derived key length in bytes |
keyPrefixLength |
int |
keyLength / 2 |
Key prefix length in bytes |
memoryCost |
?int |
null |
Memory cost (Argon2id/Scrypt) |
nonce |
?string |
null |
Custom nonce (hex) |
parallelism |
?int |
null |
Parallelism factor (Scrypt) |
salt |
?string |
null |
Custom salt (hex) |
When counter is provided and hmacKeySignatureSecret is set, the challenge includes a keySignature for fast verification (skips re-derivation).
Returns: Challenge with parameters (ChallengeParameters) and signature.
Altcha::solveChallenge(SolveChallengeOptions $options): ?Solution
Iterates counter values to find a derived key matching the challenge prefix.
SolveChallengeOptions
| Parameter | Type | Default | Description |
|---|---|---|---|
algorithm |
DeriveKeyInterface |
required | Key derivation algorithm |
challenge |
Challenge |
required | The challenge to solve |
start |
int |
0 |
Initial counter value |
step |
int |
1 |
Counter increment per iteration |
timeout |
float |
30.0 |
Timeout in seconds |
Returns: Solution with counter, derivedKey (hex), and time (seconds). Returns null if no match is found.
Altcha::verifySolution(VerifySolutionOptions $options): VerifySolutionResult
Verifies a solution against its challenge.
VerifySolutionOptions
| Parameter | Type | Default | Description |
|---|---|---|---|
algorithm |
DeriveKeyInterface |
required | Key derivation algorithm |
payload |
Payload |
required | Challenge + solution pair |
VerifySolutionResult
| Property | Type | Description |
|---|---|---|
verified |
bool |
Whether the solution is valid |
expired |
bool |
Whether the challenge has expired |
invalidSignature |
?bool |
Whether the challenge signature is invalid |
invalidSolution |
?bool |
Whether the derived key doesn't match |
time |
float |
Verification time in seconds |
Key Derivation Algorithms
All algorithms implement DeriveKeyInterface.
PBKDF2
use AltchaOrg\Altcha\Algorithm\Pbkdf2; use AltchaOrg\Altcha\HmacAlgorithm; new Pbkdf2(); // PBKDF2/SHA-256 new Pbkdf2(HmacAlgorithm::SHA384); // PBKDF2/SHA-384 new Pbkdf2(HmacAlgorithm::SHA512); // PBKDF2/SHA-512
Argon2id
Requires ext-sodium (typically bundled with PHP).
use AltchaOrg\Altcha\Algorithm\Argon2id; new Argon2id();
Uses memoryCost from challenge options.
Scrypt
Requires ext-scrypt (php-scrypt).
use AltchaOrg\Altcha\Algorithm\Scrypt; new Scrypt();
Uses memoryCost (r, default: 8) and parallelism (p, default: 1) from challenge options.
HmacAlgorithm
Enum used for HMAC signing and PBKDF2 hash selection:
HmacAlgorithm::SHA256-SHA-256HmacAlgorithm::SHA384-SHA-384HmacAlgorithm::SHA512-SHA-512
ServerSignature::verifyServerSignature(string|array $data, string $hmacKey, HmacAlgorithm $hmacAlgorithm = HmacAlgorithm::SHA256): ServerSignatureVerification
Verifies a server signature payload.
ServerSignatureVerification
| Property | Type | Description |
|---|---|---|
verified |
bool |
Whether the signature is valid, not expired, and solution verified |
expired |
bool |
Whether the verification data has expired |
invalidSignature |
bool |
Whether the HMAC signature is invalid |
invalidSolution |
bool |
Whether the solution was not verified |
time |
float |
Verification time in seconds |
verificationData |
?ServerSignatureVerificationData |
Parsed verification data |
Verification data is parsed generically from URL-encoded params with auto-detected types (bool, int, float, string, array for fields/reasons). Access values via property or array syntax:
use AltchaOrg\Altcha\ServerSignature; $result = ServerSignature::verifyServerSignature($payload, 'server-secret'); if ($result->verified) { $result->verificationData->expire; // int $result->verificationData->score; // float $result->verificationData->verified; // bool $result->verificationData->fields; // array $result->verificationData->classification; // string $result->verificationData['email']; // array access also works }
ServerSignature::verifyFieldsHash(array $formData, array $fields, string $fieldsHash, HmacAlgorithm $hmacAlgorithm = HmacAlgorithm::SHA256): bool
Verifies the hash of specific form fields.
$isValid = ServerSignature::verifyFieldsHash( formData: ['name' => 'John', 'email' => 'john@example.com'], fields: ['name', 'email'], fieldsHash: hash('sha256', "John\njohn@example.com"), );
Payload
Wraps a Challenge and Solution pair for verification and serialization.
$payload = new Payload($challenge, $solution); $payload->toArray(); // array $payload->toJson(); // JSON string $payload->toBase64(); // base64-encoded JSON
V1 API
The V1 API is available under the AltchaOrg\Altcha\V1 namespace. It uses simple hash-based challenges (SHA-1, SHA-256, SHA-512) instead of key derivation functions.
Tests
vendor/bin/phpunit tests
License
MIT