Pumpkin-MC/Pumpkin · error · TelemetryVerificationError

Invalid signature hex encoding

Error message

Invalid signature hex encoding

What it means

TelemetryVerificationError::InvalidSignatureHex, produced when the caller-supplied signature cannot be parsed as a hex string. The signature must be hex-encoded (128 hex chars for a 64-byte Ed25519 signature). Thrown before verification runs.

Solutions

  1. Encode the signature as pure hex (`hex::encode`) on the client side
  2. Normalize the transport (header/query) so it does not alter the signature string
  3. Strip whitespace, quotes, and prefixes from the signature before calling verify

Example fix

// before
let sig = base64::engine::general_purpose::STANDARD.encode(signature_bytes);
// after
let sig = hex::encode(signature_bytes);
Defensive patterns

Strategy: validation

Validate before calling

fn is_hex(s: &str) -> bool { !s.is_empty() && s.len() % 2 == 0 && s.bytes().all(|b| b.is_ascii_hexdigit()) }
if !is_hex(sig.trim()) { return Err("signature must be pure hex"); }

Type guard

fn valid_signature_hex(s: &str) -> bool {
    let t = s.trim().trim_start_matches("0x");
    t.len() == 128 && t.bytes().all(|b| b.is_ascii_hexdigit())
}

Try / catch

match telemetry::verify(&key, &sig, &msg, now) {
    Err(TelemetryVerificationError::InvalidSignatureHex) => log::warn!("client sent non-hex signature; check client encoding"),
    Ok(()) => { /* proceed */ }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling telemetry::verify with a signature string containing non-hex characters, odd length, base64 content, or extra whitespace/prefixes.

Common situations: Client sends the signature base64-encoded while the server expects hex; signature URL-decoded/mangled in transit; signature copied with surrounding quotes or a '0x' prefix.

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/85d7c9d637d38759. Report an issue: GitHub.

Appendix: source

Thrown at crates/pumpkin/src/telemetry.rs:131

    let pubkey_hex = hex::encode(signing_key.verifying_key().to_bytes());
    let sig_hex = hex::encode(signature.to_bytes());
    (pubkey_hex, sig_hex)
}

/// Errors that can occur during telemetry request signature verification.
#[derive(Debug, thiserror::Error, PartialEq, Eq)]
pub enum TelemetryVerificationError {
    #[error("Invalid timestamp string format")]
    InvalidTimestamp,
    #[error(
        "Timestamp drift exceeded: drift was {drift}s (max allowed is {MAX_CLOCK_DRIFT_SECS}s)"
    )]
    ClockDriftExceeded { drift: u64 },
    #[error("Invalid public key hex encoding")]
    InvalidPublicKeyHex,
    #[error("Invalid public key bytes: {0}")]
    InvalidPublicKey(String),
    #[error("Invalid signature hex encoding")]
    InvalidSignatureHex,
    #[error("Invalid signature bytes: {0}")]
    InvalidSignature(String),
    #[error("Signature verification failed: {0}")]
    VerificationFailed(String),
}

/// Verifies a signed telemetry request against an Ed25519 public key and timestamp.
///
/// Ensures clock drift between `current_time_secs` and `timestamp_str` does not exceed `±300` seconds.
pub fn verify_telemetry_request(
    pubkey_hex: &str,
    sig_hex: &str,
    timestamp_str: &str,
    body_bytes: &[u8],
    current_time_secs: u64,
) -> Result<(), TelemetryVerificationError> {
    let ts: u64 = timestamp_str

View on GitHub (pinned to 8d4639e25a)