Skip to main content

Crate geronimo_captcha

Crate geronimo_captcha 

Source
Expand description

A JavaScript-free CAPTCHA. A speed bump for bulk automation, layered over server-side rate limiting. Not a wall.

A challenge is one to five rounds. Each round renders its own source image at nine orientations in a 3x3 grid, exactly one of them upright. The challenge id is an HMAC-SHA256 tag binding the length-prefixed correct tile numbers to a nonce and a timestamp. Verification recomputes the tag over the client’s guesses and compares it in constant time. No answer is stored server-side.

Replay and brute-force limiting live entirely in ChallengeRegistry. Without one, nothing limits guesses; a single round falls in nine.

The SampleSet is the security boundary. Supply your own corpus and rotate it.

use geronimo_captcha::{
    CaptchaManager, ChallengeInMemoryRegistry, GenerationOptions,
    NoiseOptions, SampleFormat, SampleSet, SpriteUri,
};
use std::sync::Arc;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let ttl_secs = 60;
    let registry = Arc::new(ChallengeInMemoryRegistry::new(ttl_secs, 3, 10_000)?);

    let images = std::fs::read_dir("/srv/captcha-corpus")?
        .filter_map(|e| std::fs::read(e.ok()?.path()).ok())
        .collect();
    let samples = SampleSet::new(SampleFormat::Jpeg, images)?;

    let mgr = CaptchaManager::new(
        "an-example-secret-key-of-32-bytes".to_string(),
        ttl_secs,
        NoiseOptions::default(),
        Some(registry),
        GenerationOptions::default(),
        &samples,
    )?;

    let challenge = mgr.generate_challenge::<SpriteUri>()?;

    // One sprite per round, rendered into the form
    let img_srcs: Vec<String> = challenge.sprites.into_iter().map(|s| s.0).collect();
    let challenge_id = challenge.challenge_id;

    // One index per round, in issue order
    let verified = mgr.verify_challenge(&challenge_id, &[5])?;

    Ok(())
}

Structs§

CaptchaChallenge
CaptchaManager
ChallengeInMemoryRegistry
DecodeLimits
Ceilings applied to a sample image before it is decoded.
GenerationOptions
Sprite geometry and encoding parameters.
NoiseOptions
Parameters for the noise watermark drawn over the composed sprite.
SampleSet
Source images a challenge draws its nine tiles from.
SpriteBinary
Sprite as raw encoded bytes plus its MIME type.
SpriteUri
Sprite as a data: URI, ready for <img src>.

Enums§

CaptchaError
NoisePattern
RegistryRejection
SampleFormat
Encoded format of every image in a SampleSet. The decoder is pinned to this rather than guessing from content.
SpriteFormat

Traits§

ChallengeRegistry
Implementations must make begin_attempt and mark_verified atomic per id.
SpriteTarget
Destination for the encoded sprite bytes.

Type Aliases§

Result