CVE-2026-12860 Overview
CVE-2026-12860 is a signature verification flaw in Bouncy Castle for Java. The library skips the last two bytes of the hash when validating RSA PKCS#1 v1.5 signatures in the NULL-omitted DigestInfo code path. This defect weakens signature integrity checks and allows crafted signatures to pass validation. The issue affects Bouncy Castle for Java before 1.85 and Bouncy Castle for Java LTS before 2.73.12. The weakness is classified as [CWE-347: Improper Verification of Cryptographic Signature].
Critical Impact
An attacker can forge RSA PKCS#1 v1.5 signatures that pass verification, breaking the integrity guarantees of any protocol or application relying on Bouncy Castle for authentication, code signing, or message integrity.
Affected Products
- Bouncy Castle for Java versions prior to 1.85
- Bouncy Castle for Java LTS versions prior to 2.73.12
- Java applications using the RSADigestSigner class for PKCS#1 v1.5 signature verification
Discovery Timeline
- 2026-08-03 - CVE-2026-12860 published to NVD
- 2026-08-04 - Last updated in NVD database
Technical Details for CVE-2026-12860
Vulnerability Analysis
Bouncy Castle implements RSA PKCS#1 v1.5 signature verification in RSADigestSigner. The verifier compares the recovered signature payload against an expected DigestInfo encoding that contains an algorithm identifier followed by an OCTET STRING wrapping the message hash. In the NULL-omitted encoding path, the comparison loop iterates only hash.length bytes instead of covering the full trailing OCTET STRING region, which is hash.length + 2 bytes long. The two omitted bytes are the ASN.1 tag and length octets that precede the hash. Because these bytes are not verified, an attacker can substitute arbitrary values in that position while still producing a signature that verifies successfully. This breaks the collision resistance assumptions of the scheme and enables signature forgery against protocols using Bouncy Castle for RSA verification.
Root Cause
The defect is an off-by-two boundary error in the constant-time comparison loop of RSADigestSigner. The loop terminates before comparing the OCTET STRING tag and length prefix of the embedded hash, leaving two bytes of the expected structure unchecked.
Attack Vector
An attacker delivers a crafted RSA PKCS#1 v1.5 signature over a network protocol or file format that uses Bouncy Castle for verification. Because the skipped bytes sit inside the ASN.1 structure that immediately precedes the hash, the attacker gains additional freedom to construct forged signatures without knowing the private key. Exploitation requires no authentication and no user interaction.
int nonEqual = 0;
- for (int i = 0; i < hash.length; i++)
+ // Compare the whole trailing OCTET STRING - tag, length and every hash byte. That region
+ // is hash.length + 2 bytes
+ for (int i = 0; i < hash.length + 2; i++)
{
nonEqual |= (sig[sigOffset + i] ^ expected[expectedOffset + i]);
}
Source: Bouncy Castle security patch commit. The fix extends the byte comparison loop to cover the full trailing OCTET STRING, including the tag and length bytes that precede the hash.
Detection Methods for CVE-2026-12860
Indicators of Compromise
- Presence of bcprov-jdk*.jar files with version identifiers earlier than 1.85, or Bouncy Castle LTS artifacts earlier than 2.73.12, in application classpaths.
- Application logs showing successful RSA PKCS#1 v1.5 signature verifications from untrusted counterparties immediately followed by anomalous authenticated actions.
- Build manifests, SBOMs, or Maven or Gradle dependency reports listing org.bouncycastle:bcprov-jdk15on or org.bouncycastle:bcprov-jdk18on at vulnerable versions.
Detection Strategies
- Run software composition analysis across Java repositories and container images to flag Bouncy Castle versions below 1.85 or LTS below 2.73.12.
- Inventory runtime JVMs and inspect loaded JAR manifests to identify vulnerable Bouncy Castle providers registered via Security.addProvider.
- Review any custom code that invokes RSADigestSigner.verifySignature and flag pipelines that accept signatures from external parties.
Monitoring Recommendations
- Monitor endpoints and servers running Java workloads for the presence of unpatched Bouncy Castle libraries and alert on new deployments that reintroduce them.
- Correlate signature verification events with downstream privileged actions such as certificate issuance, JWT acceptance, or code execution from signed artifacts.
- Track outbound and inbound network flows carrying signed payloads to services identified as Bouncy Castle consumers.
How to Mitigate CVE-2026-12860
Immediate Actions Required
- Upgrade Bouncy Castle for Java to version 1.85 or later, or Bouncy Castle for Java LTS to version 2.73.12 or later, across all applications and container images.
- Rebuild and redeploy any shaded or fat JARs that embed Bouncy Castle to ensure the patched provider is loaded at runtime.
- Rotate keys and re-issue signatures for artifacts that were validated by systems exposed to untrusted signers during the vulnerable window.
Patch Information
The fix is committed in the Bouncy Castle repository under commit ea5970ea9b2fb91d763b904692fd21089ca3e396 and documented on the Bouncy Castle CVE-2026-12860 wiki page. The patch extends the verification loop in RSADigestSigner to include the ASN.1 tag and length bytes preceding the hash.
Workarounds
- Where upgrade is not immediately possible, disable acceptance of RSA PKCS#1 v1.5 signatures and require RSASSA-PSS or ECDSA in application configuration.
- Restrict signature verification paths to signers whose public keys are explicitly pinned, reducing the value of forged signatures from unknown issuers.
- Add an application-layer check that re-verifies the full DigestInfo ASN.1 encoding using an alternate cryptographic provider until the Bouncy Castle upgrade is completed.
# Maven dependency update to the patched release
mvn versions:use-dep-version -Dincludes=org.bouncycastle:bcprov-jdk18on -DdepVersion=1.85 -DforceVersion=true
# Verify runtime provider version
java -cp bcprov-jdk18on-1.85.jar org.bouncycastle.LICENSE | head -n 1
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

