NAME

Uniform::HTTP::Auth::Digest - HTTP Digest authentication calculations and state

SYNOPSIS

use Uniform::HTTP::Auth::Digest;

my $digest = Uniform::HTTP::Auth::Digest->new;

my $value = $digest->authorization(
    challenge      => $challenge,
    origin         => 'https://example.com:443',
    username       => 'user',
    password       => 'secret',
    method         => 'GET',
    request_target => '/private',
);

DESCRIPTION

Uniform::HTTP::Auth::Digest implements the Digest calculation and client state used by Uniform::HTTP::Auth. It does not send requests or perform HTTP retries.

The module supports MD5, SHA-256, and SHA-512/256, including their -sess variants, plus qop=auth and qop=auth-int. MD5 is provided for legacy interoperability; modern applications should prefer stronger algorithms when servers offer them.

METHODS

new

my $digest = Uniform::HTTP::Auth::Digest->new;

Creates a stateful Digest calculator. Nonce-count and cnonce state are retained across calls.

validate_challenge

my $error = Uniform::HTTP::Auth::Digest->validate_challenge($challenge);

Returns undef when the parsed challenge has the required Digest structure, or a diagnostic string when it does not.

select_challenge

my $challenge = $digest->select_challenge(\@digest_challenges);

Returns the first usable Digest challenge in wire order. Challenges with an unsupported algorithm or no supported qop are skipped.

authorization

my $value = $digest->authorization(
    challenge      => $challenge,
    origin         => 'https://example.com:443',
    username       => 'user',
    password       => 'secret',
    method         => 'GET',
    request_target => '/resource',
    entity_body    => $body,
);

Returns a complete Digest authentication field value.

challenge, username, password, method, and request_target are required. entity_body is required only when qop=auth-int is selected and must be a defined plain scalar.

origin is optional for direct use but is supplied automatically by Uniform::HTTP::Auth. When present, it is included in the internal Digest state key so identical nonce strings from unrelated HTTP protection spaces do not share nonce counts or cnonces. Direct users that omit origin should keep a Digest object scoped appropriately for their endpoint.

If a challenge lists both auth and auth-int, version 0.02 prefers auth. If no supported qop can be satisfied, the method returns undef so a caller can try another challenge or authentication scheme.

DIGEST STATE

State is isolated by origin, realm, username, and nonce. The first use of a nonce with qop sends nc=00000001; subsequent uses increment the count. A new nonce naturally starts a new sequence. Client nonces are generated from Crypt::SysRandom.

A stale=true challenge is accepted so a calling HTTP implementation can retry with existing credentials. Uniform still does not own the request retry itself.

CHARACTER ENCODING

When charset=UTF-8 is present, username and password are normalized to NFC and encoded as UTF-8 for the Digest calculation. userhash=true and username* are supported as defined by RFC 7616.

Without a charset indication, version 0.02 accepts ASCII username/password credentials only rather than guessing an encoding.

LEGACY INTEROPERABILITY

Digest challenges without qop are accepted for compatibility. Session algorithms still generate and send a cnonce when qop is absent.

SECURITY NOTES

Digest does not make an insecure transport confidential, and legacy MD5 Digest should not be treated as a modern cryptographic choice. Scheme policy belongs to the caller or the configured Uniform::HTTP::Auth scheme order.

SEE ALSO

Uniform::HTTP::Auth, RFC 7616.

AUTHOR

Joshua S. Day, <HAX@cpan.org>

LICENSE

This software is released under the MIT License.