Pumpkin-MC/Pumpkin · error · AuthError

Invalid signature

Error message

Invalid signature

What it means

This variant indicates the ECDSA signature on a JWT is invalid — the signed data does not match the signature when verified with the token's key. It is raised during Mojang token verification when the cryptographic signature check fails, distinguishing signature corruption/forgery from key-trust failures (MojangKeyMismatch).

Solutions

  1. Reject the token and disconnect the client; an invalid signature cannot be retried or repaired
  2. Verify the signature bytes are decoded with URL-safe Base64 without padding before verification
  3. Confirm the exact signed message (header.payload concatenation) is passed to verification, not a re-serialized version
  4. Compare header/payload bytes received on the wire against what the client claims to send to rule out proxy modification

Example fix

// before
let sig = Signature::from_slice(&raw_sig).map_err(AuthError::from)?;
verify(msg, &sig)?;
// after
if let Err(e) = verifying_key.verify(msg, &sig) {
    log::warn!("invalid token signature: {e}; disconnecting client");
    return Err(AuthError::InvalidSignature);
}
Defensive patterns

Strategy: try-catch

Try / catch

match jwt::verify(&token) {
    Err(jwt::Error::InvalidSignature) => {
        log::warn!("token signature check failed; disconnecting client");
    }
    r => r?,
}

Prevention

When it happens

Trigger: Verifying a JWT whose signature bytes were decoded successfully but fail ecdsa::verify; tokens truncated mid-signature, tampered payloads, or signatures produced with a different key.

Common situations: Tampered tokens from modified clients; base64 padding/URL-safe alphabet mistakes that corrupt the signature bytes; proxies rewriting token bodies.

Related errors


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

Appendix: source

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

    #[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.
///
/// # Returns
///
/// A `Result` containing the decoded bytes or a `base64::DecodeError`.
pub fn decode_b64_url_nopad(s: &str) -> Result<Vec<u8>, base64::DecodeError> {
    general_purpose::URL_SAFE_NO_PAD.decode(s)
}

View on GitHub (pinned to 8d4639e25a)