ALTCHA Go Library

May 12, 2026 ยท View on GitHub

The ALTCHA Go Library is a lightweight library for creating and verifying ALTCHA challenges in Go applications. It implements the ALTCHA v2 proof-of-work protocol based on key derivation functions (KDF).

Compatibility

  • Go 1.22+

Installation

go get github.com/altcha-org/altcha-lib-go/v2

Packages

PackageImport pathDescription
v2 (default)github.com/altcha-org/altcha-lib-go/v2ALTCHA v2 PoW protocol
v1 (legacy)github.com/altcha-org/altcha-lib-goLegacy ALTCHA v1 protocol

Usage

Create a challenge

import altcha "github.com/altcha-org/altcha-lib-go/v2"

challenge, err := altcha.CreateChallenge(altcha.CreateChallengeOptions{
    Algorithm:           "PBKDF2/SHA-256",
    DeriveKey:           altcha.DeriveKeyPBKDF2(),
    HMACSignatureSecret: "your-secret",
    Cost:                5000,
    KeyLength:           32,
})

Solve a challenge

solution, err := altcha.SolveChallenge(altcha.SolveChallengeOptions{
    Challenge: challenge,
    DeriveKey: altcha.DeriveKeyPBKDF2(),
})

Verify a solution

result, err := altcha.VerifySolution(altcha.VerifySolutionOptions{
    Challenge:           payload.Challenge,
    Solution:            payload.Solution,
    DeriveKey:           altcha.DeriveKeyPBKDF2(),
    HMACSignatureSecret: "your-secret",
})

if result.Verified {
    // valid
}

HTTP server example

See examples/server for a minimal HTTP server with GET /challenge and POST /submit endpoints.

Key derivation algorithms

Choose the algorithm that fits your performance and security requirements. All algorithms accept a Cost parameter that controls the work factor.

PBKDF2 (DeriveKeyPBKDF2)

Recommended. Password-Based Key Derivation Function 2. Moderate cost, widely supported.

AlgorithmDescription
PBKDF2/SHA-256PBKDF2 with SHA-256, default
PBKDF2/SHA-384PBKDF2 with SHA-384
PBKDF2/SHA-512PBKDF2 with SHA-512
altcha.CreateChallenge(altcha.CreateChallengeOptions{
    Algorithm: "PBKDF2/SHA-256",
    DeriveKey: altcha.DeriveKeyPBKDF2(),
    Cost:      5000, // iterations
})

Scrypt (DeriveKeyScrypt)

Memory-hard KDF. Cost maps to N, MemoryCost to r, Parallelism to p.

altcha.CreateChallenge(altcha.CreateChallengeOptions{
    Algorithm:   "Scrypt",
    DeriveKey:   altcha.DeriveKeyScrypt(),
    Cost:        65536,
    MemoryCost:  8,
    Parallelism: 1,
})

Argon2id (DeriveKeyArgon2id)

Memory-hard KDF, winner of the Password Hashing Competition. Cost maps to time (iterations), MemoryCost to memory in KiB, Parallelism to threads.

altcha.CreateChallenge(altcha.CreateChallengeOptions{
    Algorithm:   "Argon2id",
    DeriveKey:   altcha.DeriveKeyArgon2id(),
    Cost:        1,
    MemoryCost:  65536,
    Parallelism: 1,
})

SHA (DeriveKeySHA)

Legacy algorithm. Iterated SHA hashing - fast, suitable for low-friction challenges.

AlgorithmDescription
SHA-256SHA-256, default
SHA-384SHA-384
SHA-512SHA-512
altcha.CreateChallenge(altcha.CreateChallengeOptions{
    Algorithm: "SHA-256",
    DeriveKey: altcha.DeriveKeySHA(),
    Cost:      5000, // number of iterations
})

API

CreateChallenge(options CreateChallengeOptions) (Challenge, error)

Creates a new v2 challenge.

FieldTypeDescription
AlgorithmstringKDF algorithm name (required)
DeriveKeyDeriveKeyFuncKey derivation function (required when Counter is set)
HMACSignatureSecretstringSecret used to sign the challenge
HMACKeySignatureSecretstringOptional secret to sign the derived key separately
HMACAlgorithmAlgorithmHMAC algorithm (SHA-256 default)
CostintWork factor / iterations (required)
KeyLengthintDerived key length in bytes (default: 32)
KeyPrefixstringExpected key prefix the solver must match
KeyPrefixLengthintRandom prefix length when Counter is not set (default: KeyLength/2)
Counter*intDeterministic counter; when set, derives the key prefix from this counter
MemoryCostintMemory cost (Scrypt r / Argon2id KiB)
ParallelismintParallelism (Scrypt p / Argon2id threads)
ExpiresAt*time.TimeOptional challenge expiry
Datamap[string]interface{}Optional arbitrary data embedded in the challenge

SolveChallenge(options SolveChallengeOptions) (*Solution, error)

Brute-forces counter values until the derived key matches the challenge prefix. Returns nil if stopped via StopChan.

FieldTypeDescription
ChallengeChallengeThe challenge to solve
DeriveKeyDeriveKeyFuncKey derivation function (must match the one used to create the challenge)
CounterStartintStarting counter value (default: 0)
CounterStepintCounter increment per iteration (default: 1)
StopChan<-chan struct{}Optional channel to abort solving

VerifySolution(options VerifySolutionOptions) (VerifySolutionResult, error)

Verifies a submitted solution against a challenge.

FieldTypeDescription
ChallengeChallengeThe original challenge
SolutionSolutionThe submitted solution
DeriveKeyDeriveKeyFuncKey derivation function
HMACSignatureSecretstringSecret used when the challenge was signed
HMACKeySignatureSecretstringSecret used for key signature verification
HMACAlgorithmAlgorithmHMAC algorithm (SHA-256 default)

Result fields:

FieldTypeDescription
Verifiedbooltrue if the solution is valid
Expiredbooltrue if the challenge has expired
InvalidSignature*boolnil if not checked; true if signature is invalid
InvalidSolution*boolnil if not checked; true if derived key does not match
Timeint64Verification time in milliseconds

Types

type Challenge struct {
    Parameters ChallengeParameters `json:"parameters"`
    Signature  string              `json:"signature,omitempty"`
}

type ChallengeParameters struct {
    Algorithm    string                 `json:"algorithm"`
    Nonce        string                 `json:"nonce"`
    Salt         string                 `json:"salt"`
    Cost         int                    `json:"cost"`
    KeyLength    int                    `json:"keyLength"`
    KeyPrefix    string                 `json:"keyPrefix"`
    KeySignature string                 `json:"keySignature,omitempty"`
    MemoryCost   int                    `json:"memoryCost,omitempty"`
    Parallelism  int                    `json:"parallelism,omitempty"`
    ExpiresAt    int64                  `json:"expiresAt,omitempty"`
    Data         map[string]interface{} `json:"data,omitempty"`
}

type Solution struct {
    Counter    int    `json:"counter"`
    DerivedKey string `json:"derivedKey"`
    Time       int64  `json:"time,omitempty"`
}

type Payload struct {
    Challenge Challenge `json:"challenge"`
    Solution  Solution  `json:"solution"`
}

type DeriveKeyFunc func(params ChallengeParameters, salt []byte, password []byte) ([]byte, error)

v1 (legacy)

The original ALTCHA v1 protocol (SHA-based hash challenge) is available at github.com/altcha-org/altcha-lib-go (no version suffix):

import altcha "github.com/altcha-org/altcha-lib-go"

challenge, err := altcha.CreateChallenge(altcha.ChallengeOptions{
    HMACKey:   "secret",
    MaxNumber: 100000,
})

ok, err := altcha.VerifySolution(payload, "secret", true)

License

MIT