{"record":{"id":"9786c39ea4dbcbe5","repo":"Pumpkin-MC/Pumpkin","slug":"invalid-public-key-hex-encoding","errorCode":null,"errorMessage":"Invalid public key hex encoding","messagePattern":"Invalid public key hex encoding","errorType":"error_code","errorClass":"TelemetryVerificationError","httpStatus":null,"severity":"error","filePath":"crates/pumpkin/src/telemetry.rs","lineNumber":127,"sourceCode":"    body_bytes: &[u8],\n) -> (String, String) {\n    let signed_data = compute_signed_data(timestamp_str, body_bytes);\n    let signature = signing_key.sign(&signed_data);\n    let pubkey_hex = hex::encode(signing_key.verifying_key().to_bytes());\n    let sig_hex = hex::encode(signature.to_bytes());\n    (pubkey_hex, sig_hex)\n}\n\n/// Errors that can occur during telemetry request signature verification.\n#[derive(Debug, thiserror::Error, PartialEq, Eq)]\npub enum TelemetryVerificationError {\n    #[error(\"Invalid timestamp string format\")]\n    InvalidTimestamp,\n    #[error(\n        \"Timestamp drift exceeded: drift was {drift}s (max allowed is {MAX_CLOCK_DRIFT_SECS}s)\"\n    )]\n    ClockDriftExceeded { drift: u64 },\n    #[error(\"Invalid public key hex encoding\")]\n    InvalidPublicKeyHex,\n    #[error(\"Invalid public key bytes: {0}\")]\n    InvalidPublicKey(String),\n    #[error(\"Invalid signature hex encoding\")]\n    InvalidSignatureHex,\n    #[error(\"Invalid signature bytes: {0}\")]\n    InvalidSignature(String),\n    #[error(\"Signature verification failed: {0}\")]\n    VerificationFailed(String),\n}\n\n/// Verifies a signed telemetry request against an Ed25519 public key and timestamp.\n///\n/// Ensures clock drift between `current_time_secs` and `timestamp_str` does not exceed `±300` seconds.\npub fn verify_telemetry_request(\n    pubkey_hex: &str,\n    sig_hex: &str,\n    timestamp_str: &str,","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/Pumpkin-MC/Pumpkin/blob/8d4639e25a57c15e47448ec327c780d41bbf2356/crates/pumpkin/src/telemetry.rs#L109-L145","documentation":"TelemetryVerificationError::InvalidPublicKeyHex, produced by the telemetry signature verifier when the caller-supplied Ed25519 public key cannot be parsed as a hex string. The library expects the key to be encoded as lowercase/uppercase hexadecimal (64 hex chars for 32 bytes). It is thrown before any signature verification happens.","triggerScenarios":"Calling telemetry::verify with a public key string containing non-hex characters, an odd number of characters, or whitespace/prefixes like '0x'.","commonSituations":"Config file holds a base64 key instead of hex; key was copied with a '0x' prefix or surrounding quotes/whitespace; key truncated or from the wrong crypto system.","solutions":["Re-encode the public key as pure hex (e.g. `hex::encode([u8; 32])`) and pass exactly 64 hex characters","Strip any '0x' prefix, whitespace, or line breaks from the key string","Confirm the key source (config file, env var) actually holds an Ed25519 public key in hex format"],"exampleFix":"// before\nlet key = \"MCowBQYDK2VwAyEA...\"; // base64 PEM body\n// after\nlet key = \"d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a\"; // hex","handlingStrategy":"validation","validationCode":"fn is_hex(s: &str) -> bool { !s.is_empty() && s.len() % 2 == 0 && s.bytes().all(|b| b.is_ascii_hexdigit()) }\nif !is_hex(key.trim()) { return Err(\"public key must be pure hex\"); }","typeGuard":"fn valid_pubkey_hex(s: &str) -> bool {\n    let t = s.trim().trim_start_matches(\"0x\");\n    t.len() == 64 && t.bytes().all(|b| b.is_ascii_hexdigit())\n}","tryCatchPattern":"match telemetry::verify(&key, &sig, &msg, now) {\n    Err(TelemetryVerificationError::InvalidPublicKeyHex) => log::warn!(\"key is not hex: reject config\"),\n    Ok(()) => { /* proceed */ }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Store keys as hex in config and validate format at startup","Strip '0x' prefixes and whitespace at config load time","Add a unit test asserting your configured key passes hex decoding"],"tags":["rust","hex-decoding","ed25519","telemetry"],"backgroundTag":"invalid-argument-format","analyzedSha":"8d4639e25a57c15e47448ec327c780d41bbf2356","analyzedAt":"2026-09-09T15:32:22.916Z","contentChangedAt":"2026-09-09T15:32:22.916Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}