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
- Log the wrapped String message to see which key-construction step failed
- Ensure the key bytes are extracted from the correct Base64 URL-safe field (x5u) before key construction
- Use the matching decoder for the key format (SEC1/DER/PEM) expected by the crypto crate version
- 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
- Decode the x5u header field with URL-safe Base64 before key construction
- Match the decoder to the key format expected by your crypto crate version
- Never accept hand-crafted tokens; reject clients whose embedded key cannot be built
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
- Invalid token format
- x5u not found in header
- JSON parse error
- Token not signed by trusted Mojang key
- Invalid signature
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)