#challenge-response #validation #applications #create-and-validate #salt #sha-256 #sha-384 #sha-512 #sha-1 #altcha

altcha-lib-rs

Community implementation of the Altcha library in Rust for your own server application to create and validate challenges and responses

6 releases

0.3.1 Jan 8, 2026
0.3.0 Dec 20, 2025
0.2.0 Aug 23, 2025
0.1.3 Apr 18, 2025
0.1.1 Aug 21, 2024

#595 in Cryptography

Download history 70/week @ 2025-10-16 124/week @ 2025-10-23 101/week @ 2025-10-30 29/week @ 2025-11-06 77/week @ 2025-11-13 1/week @ 2025-11-20 9/week @ 2025-11-27 4/week @ 2025-12-04 14/week @ 2025-12-11 135/week @ 2025-12-18 42/week @ 2025-12-25 58/week @ 2026-01-01 27/week @ 2026-01-08 87/week @ 2026-01-15 30/week @ 2026-01-22 23/week @ 2026-01-29

172 downloads per month

Apache-2.0

27KB
457 lines

Community ALTCHA Rust Library   Build & test

Community implementation of the ALTCHA library in Rust for your own server application to create and validate challenges and responses.

For more information about ALTCHA https://altcha.org/docs


Features

  • Compatible with the ALTCHA client-side widget
  • Generates and validates self-hosted challenges
  • Expiring challenges option
  • Supports the algorithms SHA256, SHA384, SHA512, and SHA1 (via optional feature flag)
  • With v0.3, enforces delimited salt to prevent replay attacks; see https://altcha.org/security-advisory/

Not part of this library:

  • Methods to call ALTCHA's spam filter API
  • machine-to-machine ALTCHA
  • Store previously verified challenges to prevent replay attacks

Setup

[dependencies]
altcha-lib-rs = { version = "0", features = ["json"] } # with SHA1: ["json", "sha1"]

Example

use altcha_lib_rs::{create_challenge, verify_json_solution, 
                    Payload, Challenge, ChallengeOptions};

fn main() {
    // create a challenge
    let challenge = create_challenge(ChallengeOptions {
        hmac_key: "super-secret",
        expires: Some(Utc::now() + chrono::TimeDelta::minutes(1)),
        ..Default::default()
    }).expect("should be ok");

    // transmit the challenge to the client and let the client solve it
    let res = solve_challenge(&challenge.challenge, &challenge.salt, None, None, 0)
        .expect("need to be solved");
    // pack the solution into a json string
    let payload = Payload {
        algorithm: challenge.algorithm,
        challenge: challenge.challenge,
        number: res,
        salt: challenge.salt,
        signature: challenge.signature,
        took: None,
    };
    let string_payload = serde_json::to_string(&payload).unwrap();

    // receive the solution from the client and verify it
    verify_json_solution(&string_payload, "super-secret", true).expect("should be verified");
}

See example server

Dependencies

~2.2–3.5MB
~67K SLoC