CVE-2026-71887 in BC-JAVAinfo

Summary

by MITRE • 10/03/2026

In Bouncy Castle for Java before 1.86, the high-level OpenPGP API accepted a data signature made by a signing subkey whose Subkey Binding signature carried no embedded Primary Key Binding (cross-certification) signature, in the case where that binding omits a Key Flags subpacket. RFC 9580 sec. 5.2.1.8 and sec. 10.1.3 require the embedded Primary Key Binding signature on any subkey that can issue signatures; it is the subkey's own statement that it belongs to the primary key it is bound under. OpenPGPCertificate resolved the subkey's key flags two different ways. isSigningKey() goes through getKeyFlags() and getApplyingSubpacket(), which falls back to the primary key's direct-key or primary User ID self-signature when the binding signature omits the subpacket, so the subkey inherited the primary's SIGN_DATA and counted as signing-capable; verifyEmbeddedPrimaryKeyBinding(), which enforces the requirement, reads the binding signature's own hashed subpackets, found no SIGN_DATA there, and returned early as a non-signing key without ever demanding the back signature. The same subkey was therefore signing-capable - so its signatures were attributed to the certificate and OpenPGPSignature.OpenPGPDocumentSignature.isValid() returned true - while being exempt from cross-certification, where GnuPG refuses the identical certificate and message. An attacker needs only the victim's public signing subkey, which is public material: they bind it to their own primary key with a Subkey Binding signature they are able to make, carrying no Key Flags and no embedded Primary Key Binding signature, which they cannot make without the subkey's private key, and a relying party verifying one of the victim's genuinely signed messages against that certificate is told the signature is valid and given the attacker's certificate as its issuer. Because a certificate's User IDs are self-asserted, a verifier that pins on the subkey's fingerprint or key ID while taking the identity from the enclosing certificate reports a real signature under an attacker-chosen identity. This is misattribution of a genuine signature rather than forgery of a new one: no private key is recovered, and the signature must be one the grafted subkey actually made. The low-level PGPSignature / PGPPublicKeyRing API performs no binding checks by design and is unaffected. Key Flags are a statement about the key the carrying signature refers to (RFC 9580 sec. 5.2.3.29), so a subkey no longer inherits them from the certificate-wide signatures of the primary key: a Subkey Binding signature that omits the subpacket now leaves the subkey with no capabilities rather than the primary's, which makes the flags the cross-certification check consults the same flags every other decision consults. Preferences and the other subpackets a direct-key signature carries are inherited as before, and the primary key itself, whose flags legitimately come from its own direct-key or User ID self-signature, is unaffected.

Once again VulDB remains the best source for vulnerability data.

Analysis

by VulDB Data Team • 10/03/2026

The vulnerability in Bouncy Castle for Java prior to version 1.86 represents a critical logic flaw within the high-level OpenPGP API regarding the validation of subkey binding signatures and key capabilities. The core issue stems from an inconsistency in how the library determines whether a specific public subkey is authorized to perform cryptographic signing operations. According to RFC 9580, specifically sections 5.2.1.8 and 10.1.3, any subkey capable of issuing signatures must carry an embedded Primary Key Binding signature, also known as cross-certification. This binding serves as the definitive statement that the subkey belongs to the primary key it is bound under. However, Bouncy Castle exhibited divergent behavior when processing these bindings if the Subkey Binding signature omitted the Key Flags subpacket. In such cases, one method of determining signing capability incorrectly allowed the subkey to inherit flags from the primary key's self-signature, while another validation path strictly enforced RFC requirements by rejecting keys without explicit cross-certification. This discrepancy created a state where a certificate could be simultaneously considered valid for signature verification and invalid due to missing binding structures.

The operational impact of this flaw is severe because it enables misattribution attacks rather than direct key forgery. An attacker possessing only the victim's public signing subkey can create a malicious OpenPGP certificate by binding that subkey to their own primary key. Because the attacker does not need the victim's private key, they simply generate a Subkey Binding signature that lacks both Key Flags and the required embedded Primary Key Binding signature. When a relying party verifies a message genuinely signed by the victim using this manipulated certificate, the Bouncy Castle API incorrectly accepts the signature as valid. The verification process attributes the genuine cryptographic proof to the attacker's chosen identity within their malicious certificate. Consequently, users are misled into believing that the communication originated from or was authorized by the entity holding the attacker-controlled primary key, despite the digital signature itself being mathematically authentic and generated by the victim’s actual private key.

This vulnerability aligns with CWE-20 Improper Input Validation, as the library failed to correctly validate the structural integrity of OpenPGP packets against established standards. It also relates to CWE-345 Insufficient Verification of Data Authenticity because the system accepted a signature that was cryptographically valid but contextually fraudulent due to incorrect identity binding. From an ATT&CK perspective, this flaw facilitates Identity Impersonation and potentially Supply Chain Compromise if used in automated systems that trust signed artifacts without rigorous cross-certification checks. The attack vector relies on the public nature of OpenPGP keys, allowing adversaries to graft legitimate signing capabilities onto malicious identities without breaking encryption or forging signatures from scratch.

The root cause lies in the inconsistent application of RFC 9580 rules regarding Key Flags inheritance. In earlier versions and non-compliant implementations, subkeys were often assumed to inherit all capabilities defined in the primary key’s self-signature if not explicitly overridden. However, RFC 9580 section 5.2.3.29 clarifies that Key Flags are statements about the specific key referenced by the signature carrying them. Therefore, a Subkey Binding signature without explicit flags should result in the subkey having no capabilities, rather than inheriting those of the primary key. The fix ensures that all decision paths within the API consistently consult the same source for capability information and strictly enforce the presence of cross-certification signatures for signing keys. This alignment with industry standards prevents the ambiguity that allowed attackers to exploit the gap between signature validity checks and identity binding validation, ensuring that only properly bound subkeys are recognized as authoritative sources for signed data.

Responsible

Bcorg

Reservation

08/08/2026

Disclosure

10/03/2026

Moderation

accepted

EPSS

0.00090

KEV

no

Activities

very low

Sources

Do you need the next level of professionalism?

Upgrade your account now!