Authentication Tokens

AuthenticationTokenPair generates an Ed25519 client credential and a matching server verifier from an administrator-chosen identifier. The client credential is move-only and contains protected private material. The server credential is copyable and contains only a public verification key. ServerAuthenticationToken::matches() can check a pair cryptographically during setup; the visible identifier alone does not prove that two independently supplied keys match. See Authenticating with Tokens for the complete configuration and TCP workflow, security boundaries, and interoperable wire format.

Credential Text

elctk-<id>-c-<data> contains the private client seed; elctk-<id>-s-<data> contains the public server key. The ID matches [_a-z0-9]{1,64} and <data> is canonical, unpadded Base64url. Parsers reject noncanonical encodings and role mismatches.

Challenge Lifecycle

createChallenge() returns a PendingAuthenticationChallenge for one connection or request. The client returns a purpose-separated SignedByteBlock containing the exact challenge. Any verification attempt consumes pending state, including a failed attempt. The default lifetime is 60 seconds; a caller can request a shorter positive lifetime.

Interface

class AuthenticationTokenPair

A newly generated client credential and matching public server verifier.

See: Authentication Tokens

Public Functions

inline ClientAuthenticationToken &client() noexcept

Get the client credential, which may be moved out of this pair.

inline const ClientAuthenticationToken &client() const noexcept

Get the client credential without moving it.

inline ServerAuthenticationToken &server() noexcept

Get the server verifier, which may be copied or moved out of this pair.

inline const ServerAuthenticationToken &server() const noexcept

Get the server verifier without modifying it.

Public Static Functions

static AuthenticationTokenPair generate(const text::String &id)

Generate a new Ed25519 pair from secure randomness and an exact public identifier.

Parameters:

id – An identifier matching [_a-z0-9]{1,64}.

Returns:

Matching client and server credentials.

class ClientAuthenticationToken

A move-only client credential containing a protected Ed25519 private key.

Its text representation is sensitive and must not be transmitted during authentication.

See: Authentication Tokens

Public Functions

ClientAuthenticationToken() noexcept = default

Create an empty placeholder.

SignedByteBlock createResponse(mem::ConstByteSpan challenge) const

Sign a complete challenge using this client’s private key.

This client token must not be empty.

Parameters:

challenge – The exact challenge bytes supplied by the server.

Throws:

err::ParseError – If the challenge is malformed or addresses another identifier.

Returns:

A purpose-separated signed response.

inline bool isEmpty() const noexcept

Test whether this credential has no private key.

inline const text::String &id() const noexcept

Get the public identifier sent to the server for credential lookup.

text::String toString() const

Return the sensitive canonical elctk-<id>-c-<data> text.

Public Static Functions

static ClientAuthenticationToken fromString(const text::String &token) noexcept

Parse client credential text, returning an empty placeholder on failure.

static ClientAuthenticationToken fromStringOrThrow(const text::String &token)

Parse client credential text.

Throws:

err::ParseError – If the format, role, key, or encoding is invalid.

class PendingAuthenticationChallenge

One pending, one-use authentication attempt bound to one server credential.

An application must keep this state with the connection or request that issued its challenge.

See: Authentication Tokens

Public Functions

PendingAuthenticationChallenge() noexcept = default

Create an empty placeholder.

bool verify(mem::ConstByteSpan response)

Verify a signed response once, consuming this attempt even when verification fails.

Parameters:

response – The complete serialized signed response.

Returns:

true only for this challenge, credential, purpose, and an unexpired deadline.

inline bool isConsumed() const noexcept

Test whether the pending attempt is empty or has already been used.

inline mem::ByteBlock challengeBytes() const noexcept

Get the challenge bytes to send to the client.

class ServerAuthenticationToken

A copyable server credential containing only an Ed25519 public verifier.

Its -s- text is public verification data; it cannot answer a client challenge.

See: Authentication Tokens

Public Functions

ServerAuthenticationToken() = default

Create an empty placeholder.

auto createChallenge(time::TimeDelta lifetime = time::Seconds{60}) const -> PendingAuthenticationChallenge

Create one fresh challenge with a positive lifetime of at most 60 seconds.

Parameters:

lifetime – The monotonic lifetime. Must be positive and at most 60 seconds; defaults to 60 seconds.

Returns:

One-use pending verification state.

bool matches(const ClientAuthenticationToken &client) const

Check that this verifier matches a client credential, including its identifier.

inline bool isEmpty() const noexcept

Test whether this server verifier is empty.

inline const text::String &id() const noexcept

Get the public identifier used to select this verifier.

text::String toString() const

Return canonical public elctk-<id>-s-<data> text.

Public Static Functions

static ServerAuthenticationToken fromString(const text::String &token) noexcept

Parse server credential text, returning an empty placeholder on failure.

static ServerAuthenticationToken fromStringOrThrow(const text::String &token)

Parse server credential text.

Throws:

err::ParseError – If the format, role, public key, or encoding is invalid.