Read from the package's own PHP files at the commit 667269062ed9: its namespaces, classes, interfaces and enums, their public constants, properties and methods with their PHPDoc, and the options its factories take. Nothing of it is run.
AltchaGatewayclassAn ALTCHA challenge issued, solved by the visitor's browser, checked here: its signature (the site's key), its expiry, the solution, the action it was issued for - and, since ALTCHA itself cannot tell a solution it saw before, that it was not posted already (the replay store).
10 methods · 1 constant
AltchaGatewayFactoryclassALTCHA: a proof of work the site issues and checks itself - the visitor's browser derives keys until one starts as the challenge asks, the site checks the one it found. Nobody else is involved: no third party, no cookie.
13 options · 2 methods · 5 constants
Omnishield\Altcha
AltchaGateway class
final class AltchaGateway implements ChallengeIssuerInterface, LocalizableInterface AltchaGateway.php:27
An ALTCHA challenge issued, solved by the visitor's browser, checked here: its signature (the site's key), its expiry, the solution, the action it was issued for - and, since ALTCHA itself cannot tell a solution it saw before, that it was not posted already (the replay store).
The action is signed into the challenge's data with the time it was issued: {"action": "contact", "issued": 1791363600}.
const TEXTS = ['label', 'verifying', 'verified', 'verificationRequired', 'waitAlert', 'error', 'expired', 'footer', 'ariaLinkLabel', 'loading', 'reload', 'verify', 'cancel…The texts the widget shows (altcha 3.3.0's i18n keys).
AltchaGateway::__construct()
public function __construct(string $hmacKey, readonly DeriveKeyInterface $algorithm, readonly ReplayStoreInterface $replays, readonly int $cost = 5000, readonly string $keyPrefix = '00', readonly int $expires = 600, readonly ?string $challengeUrl = null, readonly string $field = 'altcha', readonly ?string $script = AltchaGatewayFactory::SCRIPT, readonly ?string $integrity = AltchaGatewayFactory::INTEGRITY, readonly array $attributes = [], readonly array $configuration = [], ?string $language = null, array $strings = [])$stringsthe widget's texts, by name (TEXTS)
AltchaGateway::texts()
public function texts(): arrayAltchaGateway::language()
public function language(): ?stringAltchaGateway::localized()
public function localized(string $language, array $strings = []): staticAltchaGateway::getName()
public function getName(): stringAltchaGateway::getTitle()
public function getTitle(): stringAltchaGateway::capabilities()
public function capabilities(): CapabilitiesAltchaGateway::issue()
public function issue(?string $action = null): arrayAltchaGateway::widget()
public function widget(?string $action = null): WidgetAltchaGateway::verify()
public function verify(Attempt $attempt): VerdictAltchaGatewayFactory class
final class AltchaGatewayFactory extends GatewayFactory AltchaGatewayFactory.php:42
ALTCHA: a proof of work the site issues and checks itself - the visitor's browser derives keys until one starts as the challenge asks, the site checks the one it found. Nobody else is involved: no third party, no cookie.
options: hmac_key: '%env(ALTCHA_HMAC_KEY)%' # required: signs the challenges - long, random, secret algorithm: PBKDF2/SHA-256 # or PBKDF2/SHA-384, PBKDF2/SHA-512, SHA-256, SHA-384, SHA-512 cost: 5000 # the key derivation's iterations: the work of one try key_prefix: '00' # what the derived key must start with: each hex pair, 256 times the tries expires: 600 # seconds a challenge may be solved and posted in challenge_url: ~ # where the widget fetches a challenge (the bridge's route); none: inline in the page field: altcha # the posted field script: https://cdn.jsdelivr.net/npm/altcha@3.3.0/dist/main/altcha.min.js # in PHP alone; the Symfony bridge serves the package's own copy (SCRIPT_PATH) integrity: sha256-... # the script's Subresource Integrity, set for the default address attributes: { auto: onsubmit, display: standard, language: fr } # <altcha-widget>'s own attributes configuration: { hideFooter: true } # its configuration attribute (JSON) language: fr # the widget's language (its language attribute) strings: { label: "Je ne suis pas un robot" } # its texts, by name (AltchaGateway::TEXTS); they win over the bridge's translations
Spent solutions are remembered in the ReplayStoreInterface given to the factory - the application's, shared by every request. Without one, this process's memory: right in a test or a worker, not behind PHP-FPM.
Options
| Option | Default | |
|---|---|---|
algorithm | 'PBKDF2/SHA-256' | |
cost | 5000 | |
key_prefix | '00' | |
expires | 600 | |
challenge_url | null | |
field | 'altcha' | |
script | self::SCRIPT | |
integrity | null | |
attributes | [] | |
configuration | [] | |
language | null | |
strings | [] | |
hmac_key | required |
const SCRIPT = 'https://cdn.jsdelivr.net/npm/altcha@3.3.0/dist/main/altcha.min.js'The widget, as published on npm (altcha 3.3.0, MIT) and served by jsDelivr.
const INTEGRITY = 'sha256-/CeoPc2Yo9is9tcPvkZD3L7lEqv7mIhu3Y7QRTUK2Ck='const SCRIPT_VERSION = '3.3.0'const SCRIPT_FILE = __DIR__ . '/public/altcha.min.js'The same file, shipped in this package (public/, MIT): for the site to serve it itself.
const SCRIPT_PATH = '/omnishield/altcha/' . self::SCRIPT_VERSION . '/altcha.min.js'Where omnishield's Symfony bridge serves that file, and the address its gateways use by default.
AltchaGatewayFactory::__construct()
public function __construct(readonly ?ReplayStoreInterface $replays = null)AltchaGatewayFactory::algorithm()
public static function algorithm(string $name): DeriveKeyInterface