{"record":{"id":"ee391af162c6dad8","repo":"elastic/elasticsearch","slug":"signature-verification-for-failed","errorCode":null,"errorMessage":"signature verification for [{}] failed","messagePattern":"signature verification for \\[(.+?)\\] failed","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"critical","filePath":"distribution/tools/plugin-cli/bc/src/main/java/org/elasticsearch/plugins/cli/bc/PgpSignatureVerifier.java","lineNumber":69,"sourceCode":"            InputStream fin = pluginZipInputStream;\n            InputStream sin = ascInputStream;\n            InputStream ain = new ArmoredInputStream(publicKeyInputStream) // input stream to the public key in ASCII-Armor format (RFC4880)\n        ) {\n            final JcaPGPObjectFactory factory = new JcaPGPObjectFactory(PGPUtil.getDecoderStream(sin));\n            final PGPSignature signature = ((PGPSignatureList) factory.nextObject()).get(0);\n\n            // validate the signature has key ID matching our public key ID\n            final String keyId = Long.toHexString(signature.getKeyID()).toUpperCase(Locale.ROOT);\n            if (publicKeyId.equals(keyId) == false) {\n                throw new IllegalStateException(\"key id [\" + keyId + \"] does not match expected key id [\" + publicKeyId + \"]\");\n            }\n\n            // compute the signature of the downloaded plugin zip\n            computeSignatureForDownloadedPlugin(fin, ain, signature);\n\n            // finally we verify the signature of the downloaded plugin zip matches the expected signature\n            if (signature.verify() == false) {\n                throw new IllegalStateException(\"signature verification for [\" + urlString + \"] failed\");\n            }\n        } catch (PGPException e) {\n            throw new IOException(\"PGP exception during signature verification for [\" + urlString + \"]\", e);\n        }\n    }\n\n    private static void computeSignatureForDownloadedPlugin(InputStream fin, InputStream ain, PGPSignature signature) throws PGPException,\n        IOException {\n        final PGPPublicKeyRingCollection collection = new PGPPublicKeyRingCollection(ain, new JcaKeyFingerprintCalculator());\n        final PGPPublicKey key = collection.getPublicKey(signature.getKeyID());\n        signature.init(new JcaPGPContentVerifierBuilderProvider(), key);\n        final byte[] buffer = new byte[1024];\n        int read;\n        while ((read = fin.read(buffer)) != -1) {\n            signature.update(buffer, 0, read);\n        }\n    }\n","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/distribution/tools/plugin-cli/bc/src/main/java/org/elasticsearch/plugins/cli/bc/PgpSignatureVerifier.java#L51-L87","documentation":"IllegalStateException (unchecked) thrown after `signature.verify()` returns false — meaning the computed hash of the downloaded plugin ZIP bytes did not validate against the detached PGP signature using the public key. The key ID matched (passed the earlier guard) but the content does not verify, indicating corruption or tampering of either the ZIP or the `.asc`. No exit code; runtime exception.","triggerScenarios":"Truncated or corrupted plugin ZIP (partial download); a `.asc` that belongs to a different build of the same plugin; CDN/cache serving a stale ZIP with the current signature; deliberate tampering that changes bytes but keeps the old signature.","commonSituations":"Flaky downloads leaving a truncated file; mirror desync; version skew between cached ZIP and freshly fetched signature.","solutions":["Re-download both the plugin ZIP and its `.asc` from the official source and retry.","Clear any local/corporate-proxy cache that may have served a stale copy.","Verify checksums of both files against the published release manifest.","If persistently failing on a specific version, check Elastic's advisories for a known bad artifact."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    PgpSignatureVerifier.verifySignature(publicKeyId, url, zip, asc, pubKey);\n} catch (IllegalStateException e) {\n    // signature verify=false: re-download both ZIP and .asc, then retry once; never proceed unsigned\n    redownloadAndRetry();\n}","preventionTips":["Re-download the ZIP and `.asc` together; do not mix versions.","Clear caches (local + proxy) that may serve stale artifacts.","Compare checksums against the published release manifest before installing."],"tags":["elasticsearch","plugin-cli","pgp","security","signature","integrity"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:17:08.281Z"}