entropy-auth 2026.7.31

Authentication and authorization for Entropy Softworks server and API projects
docs.rs failed to build entropy-auth-2026.7.31
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

entropy-auth

Authentication and authorization primitives for Entropy Softworks Rust projects. Crypto, encoding, and protocol logic is implemented from specifications, leaning only on well-audited, idiomatic crates.io dependencies (such as argon2, aes-gcm, webauthn-rs, the RustCrypto curve crates, serde/serde_json, rand_core, and tracing — see the dependency table in the API docs for the full set) — no internal-only dependencies. Logging is emitted through the tracing facade, so consumers wire up whatever subscriber they like. Thread-safe (Send + Sync).

Installation

Releases use CalVer (YYYY.M.D), stamped at publish from the build date, so pin to the year-and-month series you want:

[dependencies]
entropy-auth = "2026.6"

# Optional protocol modules
# entropy-auth = { version = "2026.6", features = ["oidc", "saml"] }

Quick Start

Password Hashing

use entropy_auth::{PasswordHash, PasswordConfig};

let config = PasswordConfig::default();
let hash = PasswordHash::generate(b"my-secret-password", &config).unwrap();
assert!(hash.verify(b"my-secret-password"));
assert!(!hash.verify(b"wrong-password"));

// Serialize for storage
let stored = hash.to_phc_string();
let loaded = PasswordHash::parse(stored).unwrap();
assert!(loaded.verify(b"my-secret-password"));

API Key Authentication

use entropy_auth::{ApiKey, ApiKeyHash};

let (key, hash) = ApiKey::generate().unwrap();
println!("Give to client: {}", key.as_str());
println!("Store in DB: prefix={}", hash.prefix());

// Later, verify:
assert!(key.verify(&hash));

OAuth 2.0 Flow

use entropy_auth::oauth::{OAuthConfig, AuthorizationRequest};

let config = OAuthConfig::builder("client-id", "client-secret")
    .authorization_endpoint("https://auth.example.com/authorize")
    .token_endpoint("https://auth.example.com/token")
    .redirect_uri("https://myapp.com/callback")
    .scope("openid")
    .scope("profile")
    .scope("email")
    .build()
    .unwrap();

let auth_req = AuthorizationRequest::build(&config).unwrap();
println!("Redirect user to: {}", auth_req.url());
// After callback, exchange code for tokens...

Feature Flags

Security-related capabilities are always on per the project's "no feature flags for core security" policy. The remaining flags gate optional protocol or use-case modules:

Feature Default Description
saml no SAML 2.0 support (includes XML parser)
oidc no OpenID Connect support (enables asym-jwt)
asym-jwt no Asymmetric JWT: EdDSA/ES256 signing + verification, RS256/RS512 verification (RFC 7518 §3.3), and JWKS (RFC 7515/7517/7518/7638/8037); pulls in the RustCrypto curve crates plus rsa + sha2
ssh-keys no SSH public key parsing and fingerprinting

Always-on capabilities (no flag required): local auth, OAuth 2.0, API auth, sessions, JWT (HMAC HS256/HS512), TOTP / MFA, HIBP password breach checking, AES-GCM secret-box, WebAuthn / passkey ceremonies. Build dependencies include argon2, tracing, aes-gcm, rand_core, webauthn-rs (transitively openssl-sys — consumers need openssl-devel or equivalent at build time), serde, serde_json. Enabling asym-jwt (or oidc) additionally pulls in the optional ed25519-dalek and p256 crates for EdDSA/ES256 (the ecdsa and signature traits arrive transitively via p256), plus rsa + sha2 for verifying RSA-signed (RS256/RS512) ID tokens from external OIDC providers (Google, Microsoft, Okta). RSA is verify-only — the crate validates RSA-signed tokens but never mints them — so the rsa private-key path (and RUSTSEC-2023-0071's Marvin timing concern, which is specific to private-key operations) is never exercised.

Passkeys / WebAuthn

The crate wraps webauthn-rs in the same trait-and-builder shape used by the rest of the crate. Always available — no feature flag required:

[dependencies]
entropy-auth = "2026.6"

This pulls in webauthn-rs (and its transitive dependencies, including OpenSSL). All consumers of entropy-auth get passkey support out of the box.

Public surface

  • RelyingParty / RelyingPartyBuilder — RP-ID, RP-name, and origin allowlist; builder validation rejects empty RP-IDs, missing origins, and unparseable origin URLs at build time.
  • PasskeyCredential — stored credential record (credential ID, embedded Passkey, sign-count, transports, AAGUID, label, PRF flag and salt, timestamps).
  • PasskeyCredentialStore — trait that mirrors CredentialStore: one associated type Error: std::error::Error, pluggable persistence methods (lookup_by_user, lookup_by_credential_id, store, update_sign_count, update_last_used, remove).
  • InMemoryPasskeyStoreVec-backed implementation for tests and prototypes (uses constant_time_eq for all credential-ID / user-handle comparisons).
  • RegistrationCeremony::begin / RegistrationCeremony::finish — two-step registration; returns a RegistrationOutcome carrying prf_supported: bool.
  • AuthenticationCeremony::begin / AuthenticationCeremony::finish — two-step authentication; returns an AuthenticationOutcome with the new sign-count and PRF flag.
  • WebAuthnError — private-enum + public-struct error wrapper with is_* query methods (is_origin_mismatch, is_rp_id_mismatch, is_sign_count_rollback, is_credential_not_found, …).
  • prf module — PrfSalt, PrfRegistrationRequest, PrfAuthenticationRequest, PrfClientResult, inspect_registration_response, inspect_authentication_response.

PRF (prefer-not-require)

The W3C WebAuthn Level 3 prf extension is requested at registration but never required. The authenticator may decline; that is not an error. The flag is surfaced on RegistrationOutcome::prf_supported, persisted on PasskeyCredential::prf_supported, and re-checked on every authentication.

  • PRF-capable credentials carry a 32-byte salt; the same salt is replayed on every authentication, the authenticator derives the same 32-byte PRF output, and the client uses it as a key-encryption key for the symmetric vault key. The server never sees the PRF output or the unwrapped key — the zero-knowledge property is preserved.
  • Non-PRF credentials are still valid auth factors; the client falls back to a master-password unlock after the session is established.

Because webauthn-rs 0.5.x does not expose the W3C prf extension directly (it surfaces only the lower-level CTAP2 hmac-secret), this module layers PRF on top of the upstream challenge JSON. The documented happy-path API is RegistrationChallenge::merged_challenge_json() / AuthenticationChallenge::merged_challenge_json() — both return the webauthn-rs JSON with the PRF extension already spliced under publicKey.extensions.prf. The raw accessors challenge_json() and prf_extension_json() remain available for callers that need to perform the splice manually. On the response side, the consumer extracts the clientExtensionResults.prf block and passes it back via client_extension_results: Option<&Value>. See the module docs for the wire-format contract.

Security notes

  • deny(unsafe_code) crate-wide; the webauthn module adds no new unsafe blocks.
  • PrfSalt is wrapped in Zeroizing<Vec<u8>> and redacted in Debug output.
  • Sign-count rollback is rejected with WebAuthnError::is_sign_count_rollback; the in-crate unit tests pin the variant.
  • Origin and RP-ID mismatches surface as distinct WebAuthnError variants so the consumer's HTTP error mapper can produce specific error codes for operator telemetry. Callers MUST collapse all WebAuthn failures into a single opaque "authentication failed" response over the wire to prevent credential enumeration.
  • Missing PRF support is a flag, never an error. There is no is_prf_not_supported predicate by design — see the rollout plan §2.2 for the prefer-not-require rationale.

Security

All cryptographic implementations are tested against published test vectors (NIST CAVP, RFC 4231, RFC 6238). Security-relevant design decisions:

  • Secret material is stored in Zeroizing<T> wrappers that clear memory on drop.
  • All secret comparisons use constant_time_eq to prevent timing side-channel attacks.
  • deny(unsafe_code) crate-wide. The only unsafe is core::ptr::write_volatile for secret-scrubbing in crypto/zeroize.rs, crypto/sha1.rs, and crypto/sha2.rs (scoped #[allow(unsafe_code)]); the CSPRNG goes through rand_core::OsRng, which contains no unsafe.
  • AuthError::InvalidCredentials is a single opaque variant for all authentication failures, preventing user enumeration.
  • PKCE uses S256 only (plain is rejected).
  • Minimum Argon2id parameters (memory, iterations, parallelism) are enforced by PasswordConfig.
  • No secrets appear in Debug or Display output.

See SECURITY.md for the full security policy.

Public API

Commonly-used exports, grouped by area. This is a curated selection, not the complete surface — run cargo doc --all-features --open for everything (including the oauth::server IdP types and the asym-jwt JWKS surface). Items marked core are always available; others require the listed feature.

Export Kind Feature Description
Sha256 struct core SHA-256 digest.
Sha512 struct core SHA-512 digest.
Sha1 struct core SHA-1 digest (legacy interop; used by HIBP).
HmacSha256 struct core HMAC-SHA256.
HmacSha512 struct core HMAC-SHA512.
HmacSha1 struct core HMAC-SHA1.
SecretBox struct core AES-256-GCM authenticated secret-box for data at rest.
SecretBoxError struct core Secret-box encrypt/decrypt error.
fill_random fn core Fill a buffer from the platform CSPRNG.
random_token_hex fn core Generate a hex-encoded random token.
random_token_base64url fn core Generate a base64url-encoded random token.
RandomError struct core CSPRNG failure error.
base64_encode fn core Standard base64 encoding.
base64_decode fn core Standard base64 decoding.
base64url_encode fn core URL-safe base64 encoding.
base64url_decode fn core URL-safe base64 decoding.
base32_encode fn core RFC 4648 base32 encoding (TOTP secrets).
base32_decode fn core RFC 4648 base32 decoding.
Base32DecodeError struct core Base32 decode error.
hex_encode fn core Hex encoding.
hex_encode_upper fn core Uppercase hex encoding.
hex_decode fn core Hex decoding.
url_encode fn core URL percent-encoding.
url_decode fn core URL percent-decoding.
url_encode_component fn core URL component encoding.
Base64DecodeError struct core Base64 decode error.
HexDecodeError struct core Hex decode error.
UrlDecodeError struct core URL decode error.
xml_escape fn saml Escape special characters for XML embedding.
constant_time_eq fn core Timing-safe byte comparison.
Zeroizing struct core Wrapper that clears memory on drop.
ZeroizeOnDrop trait core Trait for types that zeroize on drop.
Timestamp struct core UTC timestamp via Hinnant civil-date algorithm.
is_valid_username fn core Username validation.
is_valid_name fn core Name validation.
is_valid_client_id fn core OAuth client ID validation.
is_valid_redirect_uri fn core Redirect URI validation.
is_valid_scope fn core OAuth scope validation.
PasswordHash struct core Argon2id memory-hard password hashing.
PasswordConfig struct core Password hashing configuration.
PasswordError struct core Password hashing error.
Session struct core Session token with expiry and idle timeout.
SessionConfig struct core Session configuration.
SessionError struct core Session error.
SessionValidation enum core Session validation result.
generate_token fn core Generate a random opaque token.
generate_token_with_hash fn core Generate a token and its SHA-256 hash.
hash_token_for_lookup fn core Re-derive a minted token's SHA-256 storage hash for server-side lookup.
Username struct core Validated username wrapper.
Credentials struct core Username + password pair.
StoredCredential struct core Stored credential (hash + metadata).
CredentialStore trait core Trait for credential storage backends.
InMemoryCredentialStore struct core In-memory credential store.
InMemoryStoreError struct core Error type for InMemoryCredentialStore.
ApiKey struct core API key (cleartext, for client).
ApiKeyHash struct core API key hash (for server-side storage).
ApiKeyError struct core API key error.
HmacRequestSigner struct core HMAC request signing.
HmacRequestVerifier struct core HMAC request verification.
HmacAuthError struct core HMAC auth error.
BearerError struct core Bearer token extraction error.
extract_bearer_token fn core Extract bearer token from Authorization header.
JsonValue enum core Minimal JSON value (RFC 8259).
JsonParseError struct core JSON parse error.
JwtAlgorithm enum core JWT algorithm (HS256, HS512).
JwtHeader struct core JWT header.
JwtHeaderError struct core JWT header parse error.
JwtClaims struct core JWT claims.
JwtClaimsError struct core JWT claims parse error.
JwtSignatureError struct core JWT signature error.
JwtEncoder struct core Mint (sign) a JWT.
JwtSigningAlgorithm enum core Algorithm for minting a JWT (HS256/HS512).
IntoCustomClaim trait core Convert a value into a custom JWT claim.
verify_jwt fn core Verify a JWT string.
OAuthConfig struct core OAuth 2.0 client configuration.
OAuthConfigBuilder struct core Builder for OAuthConfig.
OAuthConfigError struct core OAuth config validation error.
PkceChallenge struct core PKCE S256 challenge + verifier.
OAuthState struct core CSRF state parameter.
AuthorizationRequest struct core OAuth authorization URL builder.
TokenExchangeRequest struct core OAuth code-for-token exchange.
TokenResponse struct core Parsed token endpoint response.
TokenResponseError struct core Token response parse error.
RefreshRequest struct core OAuth refresh token request.
OidcDiscovery struct oidc OpenID Connect discovery document.
OidcDiscoveryError struct oidc Discovery document parse error.
IdTokenClaims struct oidc ID token claims.
IdTokenClaimsError struct oidc ID token claims error.
IdTokenValidator struct oidc ID token validator.
IdTokenError struct oidc ID token validation error.
UserInfo struct oidc UserInfo endpoint response.
UserInfoError struct oidc UserInfo parse error.
SamlConfig struct saml SAML SP configuration.
SamlResponse struct saml Parsed SAML response.
SamlResponseError struct saml SAML response parse error.
SamlStatus enum saml SAML status code.
SamlAssertion struct saml SAML assertion.
SamlSubject struct saml SAML subject (NameID).
SamlConditions struct saml SAML conditions (audience, time).
SamlAttribute struct saml SAML attribute name/value.
generate_sp_metadata fn saml Generate SP metadata XML.
XmlElement struct saml Parsed XML element.
XmlParseError enum saml XML parse error.
parse_xml fn saml Parse an XML document.
TotpSecret struct core TOTP shared secret (RFC 6238).
TotpConfig struct core TOTP parameters (digits, period, algorithm).
TotpAlgorithm enum core TOTP HMAC algorithm (SHA-1/256/512).
TotpError struct core TOTP error.
totp_generate fn core Generate the current TOTP code.
totp_verify fn core Verify a TOTP code within a skew window.
totp_verify_step fn core Verify and return the matched step (replay guarding).
generate_recovery_codes fn core Generate zeroizing MFA recovery codes.
HibpPrefix struct core Have-I-Been-Pwned k-anonymity SHA-1 prefix.
HibpResponse struct core Parsed HIBP range response.
BreachResult enum core HIBP breach lookup result.
HibpError struct core HIBP error.
hibp_sha1_hex fn core SHA-1 hex of a password for HIBP range queries.
RelyingParty struct core WebAuthn relying party / ceremony entry point.
RelyingPartyBuilder struct core Builder for RelyingParty.
Passkey struct core A registered passkey credential.
RegistrationCeremony struct core WebAuthn registration ceremony.
AuthenticationCeremony struct core WebAuthn authentication ceremony.
InMemoryPasskeyStore struct core In-memory passkey store.
PrfSalt struct core WebAuthn PRF extension salt.
PrfClientResult enum core Whether the client honored the PRF extension.
WebAuthnError struct core WebAuthn error (opaque over the wire).
SshPublicKey struct ssh-keys Parsed SSH public key (fingerprint/classification).
SshKeyAlgorithm enum ssh-keys SSH key algorithm.
SshKeyError struct ssh-keys SSH key parse error.
AuthProviderKind enum core Authentication provider discriminant.
AuthIdentity struct core Authenticated identity from any provider.
AuthResult struct core Unified authentication result.
AuthError struct core Top-level error type.

Full API docs: cargo doc --all-features --open

Development

git clone git@gitlab.com:entropysoftworks/crates/auth.git
cd auth
cargo test --all-features
cargo clippy --all-features -- -D warnings -W clippy::pedantic
cargo doc --all-features --no-deps

License

MIT -- see LICENSE.