elastic/elasticsearch · critical · IllegalStateException
signature verification for [{}] failed
Error message
signature verification for [{}] failed What it means
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.
Source
Thrown at distribution/tools/plugin-cli/bc/src/main/java/org/elasticsearch/plugins/cli/bc/PgpSignatureVerifier.java:69
InputStream fin = pluginZipInputStream;
InputStream sin = ascInputStream;
InputStream ain = new ArmoredInputStream(publicKeyInputStream) // input stream to the public key in ASCII-Armor format (RFC4880)
) {
final JcaPGPObjectFactory factory = new JcaPGPObjectFactory(PGPUtil.getDecoderStream(sin));
final PGPSignature signature = ((PGPSignatureList) factory.nextObject()).get(0);
// validate the signature has key ID matching our public key ID
final String keyId = Long.toHexString(signature.getKeyID()).toUpperCase(Locale.ROOT);
if (publicKeyId.equals(keyId) == false) {
throw new IllegalStateException("key id [" + keyId + "] does not match expected key id [" + publicKeyId + "]");
}
// compute the signature of the downloaded plugin zip
computeSignatureForDownloadedPlugin(fin, ain, signature);
// finally we verify the signature of the downloaded plugin zip matches the expected signature
if (signature.verify() == false) {
throw new IllegalStateException("signature verification for [" + urlString + "] failed");
}
} catch (PGPException e) {
throw new IOException("PGP exception during signature verification for [" + urlString + "]", e);
}
}
private static void computeSignatureForDownloadedPlugin(InputStream fin, InputStream ain, PGPSignature signature) throws PGPException,
IOException {
final PGPPublicKeyRingCollection collection = new PGPPublicKeyRingCollection(ain, new JcaKeyFingerprintCalculator());
final PGPPublicKey key = collection.getPublicKey(signature.getKeyID());
signature.init(new JcaPGPContentVerifierBuilderProvider(), key);
final byte[] buffer = new byte[1024];
int read;
while ((read = fin.read(buffer)) != -1) {
signature.update(buffer, 0, read);
}
}
View on GitHub (pinned to db6a809a66)
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.
Defensive patterns
Strategy: try-catch
Try / catch
try {
PgpSignatureVerifier.verifySignature(publicKeyId, url, zip, asc, pubKey);
} catch (IllegalStateException e) {
// signature verify=false: re-download both ZIP and .asc, then retry once; never proceed unsigned
redownloadAndRetry();
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Flaky downloads leaving a truncated file; mirror desync; version skew between cached ZIP and freshly fetched signature.
Related errors
- key id [{}] does not match expected key id [{}]
- PGP exception during signature verification for [{}]
- 64
- Cannot combine trust configurations [{}]
- failed to initialize a TrustManager for the system keystore
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/ee391af162c6dad8.
Report an issue: GitHub.