{"record":{"id":"d399679ab7b91982","repo":"Pumpkin-MC/Pumpkin","slug":"signature-verification-failed-0","errorCode":null,"errorMessage":"Signature verification failed: {0}","messagePattern":"Signature verification failed: (.+?)","errorType":"error_code","errorClass":"TelemetryVerificationError","httpStatus":null,"severity":"error","filePath":"crates/pumpkin/src/telemetry.rs","lineNumber":135,"sourceCode":"\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,\n    body_bytes: &[u8],\n    current_time_secs: u64,\n) -> Result<(), TelemetryVerificationError> {\n    let ts: u64 = timestamp_str\n        .parse()\n        .map_err(|_| TelemetryVerificationError::InvalidTimestamp)?;\n\n    let drift = current_time_secs.abs_diff(ts);","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/Pumpkin-MC/Pumpkin/blob/8d4639e25a57c15e47448ec327c780d41bbf2356/crates/pumpkin/src/telemetry.rs#L117-L153","documentation":"TelemetryVerificationError::VerificationFailed(String), produced when the Ed25519 cryptographic signature does not verify against the given public key and message. The key and signature parsed fine, but the signature was not made by the matching secret key over the exact verified payload.","triggerScenarios":"Calling telemetry::verify with a signature produced over different bytes than what the server verifies (e.g. different timestamp string, reordered fields, different serialization), a mismatched key/signature pair, or an attacker-tampered payload.","commonSituations":"Client and server canonicalize the payload differently (whitespace, field order, timestamp normalization); key rotation on the server without updating clients; MITM/replay attempts on telemetry endpoints.","solutions":["Ensure the client signs the exact byte string the server verifies — agree on a canonical payload (timestamp included)","Confirm the verifying key corresponds to the client's current signing key (sync key rotation)","Log which payload bytes were verified on both sides and diff them","Check that proxies/gateways are not rewriting the request body or timestamp before verification"],"exampleFix":"// before\nlet msg = format!(\"{payload}{timestamp}\"); // client order differs from server\n// after\nlet msg = format!(\"{timestamp}{payload}\"); // use one agreed canonical format on both sides","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match telemetry::verify(&key, &sig, &msg, now) {\n    Err(TelemetryVerificationError::VerificationFailed(m)) => {\n        log::warn!(\"telemetry signature mismatch: {m}\");\n        // reject request / rotate keys if this spikes\n    }\n    Ok(()) => { /* proceed */ }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Pin one canonical payload format shared by signer and verifier (include the timestamp string verbatim)","Keep client signing keys in sync with server verifying keys; document key rotation","Alert on spikes of VerificationFailed — it may indicate tampering or a botched deploy"],"tags":["rust","ed25519","signature-verification","security"],"backgroundTag":"signature-verification-failed","analyzedSha":"8d4639e25a57c15e47448ec327c780d41bbf2356","analyzedAt":"2026-09-09T15:32:22.916Z","contentChangedAt":"2026-09-09T15:32:22.916Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}