{"record":{"id":"8e1541b3fe91898b","repo":"elastic/elasticsearch","slug":"key-id-does-not-match-expected-key-id","errorCode":null,"errorMessage":"key id [{}] does not match expected key id [{}]","messagePattern":"key id \\[(.+?)\\] does not match expected key id \\[(.+?)\\]","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":61,"sourceCode":"        String publicKeyId,\n        String urlString,\n        InputStream pluginZipInputStream,\n        InputStream ascInputStream,\n        InputStream publicKeyInputStream\n    ) throws IOException {\n\n        try (\n            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());","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/distribution/tools/plugin-cli/bc/src/main/java/org/elasticsearch/plugins/cli/bc/PgpSignatureVerifier.java#L43-L79","documentation":"IllegalStateException (unchecked) thrown by PgpSignatureVerifier.verifySignature when the key ID embedded in the detached `.asc` signature does not equal the expected `publicKeyId`. This is a trust/integrity guard: the signature must have been produced by Elastic's published signing key, and a mismatch means either the signature file is for a different key or the expected key id is wrong. There is no exit code — it propagates as a runtime exception.","triggerScenarios":"Installing a plugin whose `.asc` was signed by a different key than the one bundled/expected; a stale `publicKeyId` after Elastic rotated signing keys; a man-in-the-middle or tampered artifact replacing the signature; mismatched `--plugin-certificate`/key configuration.","commonSituations":"Elastic rotating its plugin signing key between versions; third-party plugins signed by their own key; mirrors/CDNs serving a mismatched `.asc`.","solutions":["Update to a build that knows the current Elastic signing key id (upgrade the distribution), or supply the correct public key.","Confirm the `.asc` and the ZIP come from the same release (re-download both from the official source).","For third-party plugins, install from the author's documented key, not Elastic's.","If the key rotation is legitimate and verified, update the configured `publicKeyId` accordingly."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    PgpSignatureVerifier.verifySignature(publicKeyId, url, zip, asc, pubKey);\n} catch (IllegalStateException | IOException e) {\n    // treat as untrusted artifact: abort install, do not fall back to unsigned\n    throw e;\n}","preventionTips":["Always download plugins and their `.asc` from the official Elastic source in lockstep.","Keep the bundled Elastic signing key current by staying on a supported build.","Never downgrade trust on failure — investigate the key-id mismatch before proceeding."],"tags":["elasticsearch","plugin-cli","pgp","security","signature","trust"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}