Pumpkin-MC/Pumpkin · error · AuthError

Public key build failed

Error message

Public key build failed: {0}

What it means

This variant indicates the library failed to construct a public key (e.g. an RSA or EC point) from its encoded representation while validating a Mojang-signed JWT. Unlike the #[from] variants, it carries a manually supplied String, meaning code explicitly chose this error when key-building (e.g. p256/rsa decoding) failed. It signals the token's embedded key material is invalid or unsupported.

Solutions

  1. Log the wrapped String message to see which key-construction step failed
  2. Ensure the key bytes are extracted from the correct Base64 URL-safe field (x5u) before key construction
  3. Use the matching decoder for the key format (SEC1/DER/PEM) expected by the crypto crate version
  4. Reject authentication for the client; an unparseable embedded key means the token cannot be trusted

Example fix

// before
let key = VerifyingKey::<NistP256>::from_sec1_bytes(&bytes)
    .map_err(|e| AuthError::PublicKeyBuild(e.to_string()))?;
// after
if bytes.len() != 65 || bytes[0] != 0x04 {
    return Err(AuthError::PublicKeyBuild("unexpected key encoding".into()));
}
let key = VerifyingKey::<NistP256>::from_sec1_bytes(&bytes)
    .map_err(|e| AuthError::PublicKeyBuild(e.to_string()))?;
Defensive patterns

Strategy: validation

Validate before calling

// check expected raw SEC1 P-256 point encoding (0x04 || 32 || 32 = 65 bytes)
fn key_bytes_look_valid(bytes: &[u8]) -> bool {
    bytes.len() == 65 && bytes[0] == 0x04
}

Try / catch

match jwt::parse(&token) {
    Err(jwt::Error::PublicKeyBuild(msg)) => {
        log::warn!("client sent unparseable public key: {msg}; rejecting");
    }
    r => r?,
}

Prevention

When it happens

Trigger: Decoding the x5u/encoded public key from a JWT header and calling key-construction APIs (e.g. VerifyingKey::from_sec1_bytes, RsaPublicKey::new) on bytes that are not a valid key encoding.

Common situations: Forged or modified clients embedding garbage in the token header; a Mojang crypto format change; feeding DER bytes where raw SEC1 point bytes are expected (or vice versa).

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of Pumpkin-MC/Pumpkin@8d4639e25a (2026-09-09). Data as JSON: /api/errors/6c93d6c1152c6be6. Report an issue: GitHub.

Appendix: source

Thrown at crates/pumpkin-auth/src/jwt/mod.rs:45

}

/// Represents the possible errors that can occur during JWT verification.
#[derive(Debug, Error)]
pub enum AuthError {
    /// Indicates that a JWT token has an invalid format (not enough parts).
    #[error("Invalid token format")]
    InvalidTokenFormat,
    /// Indicates that the 'x5u' (X.509 URL) header parameter is missing from a token.
    #[error("x5u not found in header")]
    MissingX5U,
    /// Indicates a failure in Base64 decoding.
    #[error("Base64 decoding failed: {0}")]
    Base64Decode(#[from] base64::DecodeError),
    /// Indicates a failure in parsing JSON data.
    #[error("JSON parse error: {0}")]
    JsonParse(#[from] serde_json::Error),
    /// Indicates a failure in building a public key from its representation.
    #[error("Public key build failed: {0}")]
    PublicKeyBuild(String),
    /// Indicates that the token was not signed by the trusted Mojang public key.
    #[error("Token not signed by trusted Mojang key")]
    MojangKeyMismatch,
    /// Indicates that the token's signature is invalid.
    #[error("Invalid signature")]
    InvalidSignature,
    /// Indicates an error related to ECDSA signature operations.
    #[error("ECDSA signature error: {0}")]
    Ecdsa(#[from] ecdsa::Error),
}

/// Decodes a Base64 URL-safe encoded string with no padding.
///
/// # Arguments
///
/// * `s` - The Base64 URL-safe encoded string to decode.
///

View on GitHub (pinned to 8d4639e25a)