# Bouncy Castle Crypto Package - Release Notes

## 1.0 Introduction

The Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. The package is organised so that it contains a light-weight API suitable for use in any environment (including the J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.

## 2.0 Release History

### 2.1.1 Version

Release: 1.85
Date: 2026, TBD

### 2.1.2 Defects Fixed

- The streaming S/MIME writers SMIMEEnvelopedWriter.Builder and SMIMESignedWriter.Builder (org.bouncycastle.mime.smime) let a caller set an arbitrary MIME header through withHeader(name, value) and emitted that name and value verbatim, each terminated by CRLF, when the message headers were written (Headers.dumpHeaders). A name or value carrying an embedded CRLF - the natural case when an application populates a header such as Subject from user input - was therefore folded into the produced message as extra header lines and, with a trailing CRLFCRLF, a forged body, i.e. a MIME/e-mail header injection (CWE-93). withHeader now rejects a header name or value containing CR or LF with an IllegalArgumentException; the internally generated headers (including the RFC 5322 folded multipart Content-Type boundary) are set directly and are unaffected, as are well-formed caller headers (github #2348).
- A version 6 OnePassSignature packet (org.bouncycastle.bcpg.OnePassSignaturePacket) generated for emission defaulted to the Legacy (old) OpenPGP packet format, so under the default ROUNDTRIP encoding a v6 OPS packet built via PGPSignatureGenerator was written with a Legacy header - breaking interoperability with strict RFC 9580 consumers (RFC 9580 sec. 4.2 states the Legacy packet format "SHOULD NOT be used to generate new data"). The v6 generating constructor now defaults to the new packet format, mirroring the v6 SignaturePacket constructor; the high-level OpenPGP message API was unaffected as it already forces the new format. Version 3 OPS packets retain the Legacy default, and a Legacy header can still be forced via a BCPGOutputStream opened with PacketFormat.LEGACY (github #2347).
- OpenPGPCertificate (org.bouncycastle.openpgp.api) derived a key's expiration from the most recent applicable self-signature/binding without verifying it, so an attacker who could tamper with a transferable public key (keyserver upload, mail attachment, MITM of a key fetch) could append a later-dated subkey-binding signature advertising KeyExpirationTime = 0 ("never expires"); getExpirationTime() / OpenPGPComponentKey.getKeyExpirationDate() then reported the key as non-expiring, overriding the owner's genuine expiry. Expiry is now taken only from the most recent self-signature/binding that is cryptographically valid, so a forged or otherwise invalid binding is skipped in favour of the genuine one. The legacy org.bouncycastle.openpgp.PGPPublicKey.getValidSeconds()/getValidDays() accessors remain unverified by design (that class has no handle on the issuing key); their javadoc now points callers making trust decisions at OpenPGPCertificate.
- The OpenPGP NotationData signature subpacket parser (org.bouncycastle.bcpg.sig.NotationData) miscounted its own header when bounds-checking the body: a notation header is 8 octets (4 flag octets, a 2-octet name length and a 2-octet value length), but verifyData reserved only 4, so a (critical) notation subpacket declaring more name/value data than it carried slipped past the length guard and then overran with an ArrayIndexOutOfBoundsException when getNotationName() / getNotationValueBytes() were read during signature verification, rather than being cleanly rejected at parse time. The guard now accounts for the full 8-octet header, matching the truncation checks on the Features, TrustSignature, SignatureTarget, RevocationKey and RevocationReason subpackets (issue #2346).
- The soft-fail hard limit in org.bouncycastle.pkix.jcajce.X509RevocationChecker (Builder.setSoftFailHardLimit) compared the elapsed downtime against the limit with a strict "<", so a failure occurring exactly at maxTime was still treated as soft rather than hard - contrary to the javadoc ("At maxTime any failures will be treated as hard"). With maxTime = 0 this meant the second failure only hard-failed once a full millisecond had elapsed since the first, so on a fast machine two revocation checks within the same millisecond both soft-passed. The comparison is now inclusive ("<="), so the limit fires at maxTime as documented and the maxTime = 0 case deterministically hard-fails the second failure regardless of sub-millisecond timing.
- KMIPInputStream (org.bouncycastle.kmip.wire) built its XMLEventReader from a bare XMLInputFactory, so a KMIP XML message carrying a DOCTYPE was processed and external SYSTEM entities were resolved during parsing - an XML External Entity (XXE) exposure permitting local file disclosure via file:// URIs, outbound requests (SSRF) via http:// URIs, and information disclosure through parse error messages. The factory is now configured with SUPPORT_DTD = false (which rejects any DOCTYPE outright) and IS_SUPPORTING_EXTERNAL_ENTITIES = false before the reader is created. KMIP messages without a DOCTYPE parse exactly as before (github #2315).
- Reading a GnuPG keybox (org.bouncycastle.gpg.keybox.KeyBox / BcKeyBox / JcaKeyBox) stopped at the first EMPTY_BLOB, treating that free/deleted slot as end-of-file: Blob.getInstance() fell through to returning null (the caller's end-of-file signal) for a BlobType.EMPTY_BLOB, so any key blobs following an empty blob were silently dropped - a keybox laid out as OpenPGP, OpenPGP, OpenPGP, EMPTY_BLOB, OpenPGP returned only three key blobs where gnupg reads four. An empty blob is now skipped by advancing past its declared length and parsing continues with the following blobs (including a header-only empty blob whose declared length is exactly the 6-octet header); only a malformed empty-blob length that would move the read position backwards (shorter than its own header) or point beyond the buffer still terminates the read (issue #2343).
- The CMS SignerInfo decoder org.bouncycastle.asn1.cms.SignerInfo cast the version element directly to ASN1Integer and the trailing unsignedAttrs element directly to ASN1TaggedObject, so a malformed-but-parseable SignerInfo whose first element is not an INTEGER, or whose trailing element is not a [1] tagged object, leaked an unchecked ClassCastException instead of the documented IllegalArgumentException. This could escape the throws-CMSException contract of code reaching the SignerInfo decode via getSignerInfos() / getCounterSignatures() outside the getSignedData() cast guard. Both elements now decode via ASN1Integer.getInstance / ASN1TaggedObject.getInstance, matching org.bouncycastle.asn1.pkcs.SignerInfo; well-formed messages are unaffected (issue #2342).
- The CMS attribute decoder org.bouncycastle.asn1.cms.Attribute cast the first two elements of its SEQUENCE directly to ASN1ObjectIdentifier / ASN1Set, so an attribute whose type element is not an OBJECT IDENTIFIER (or whose value is not a SET) - for example a tagged object - leaked an unchecked ClassCastException instead of the documented IllegalArgumentException. This escaped the throws-CMSException contract of SignerInformation.verify() / getSignedAttributes(), which build an AttributeTable over the parsed signed-attribute SET, when verifying a malformed-but-parseable CMS signed message. Attribute now decodes both elements via ASN1ObjectIdentifier.getInstance / ASN1Set.getInstance, rejecting a bad element with IllegalArgumentException. Well-formed attributes are unaffected.
- Materializing a definite-length ASN.1 object through DefiniteLengthInputStream.toByteArray() allocated the full declared length up front (new byte[length]) before reading any content. When ASN1InputStream wraps a raw InputStream (a socket, a decompressed payload, etc.) the per-object length limit falls back to Runtime.maxMemory() in StreamUtil.findLimit(), so a short crafted header - for example a 6-byte OCTET STRING declaring a near-heap length with no body - could drive an OutOfMemoryError before a single content byte was read (CWE-789, memory allocation with excessive size value; reported by Michał Majchrowicz and Marcin Wyczechowski of AFINE). The buffer is now grown incrementally as bytes actually arrive (capped initial allocation, doubling towards the declared length), so the allocation a short input can force is bounded: a truncated stream fails with the same "DEF length ... object truncated by ..." EOFException as before, and a well-formed object of any size still materializes correctly. Callers wrapping a raw stream should still set an explicit limit via the ASN1InputStream(InputStream, int) constructor or the org.bouncycastle.asn1.max_limit property; this change removes the small-input-to-large-allocation amplification but the declared length remains bounded only by that limit.
- The SP 800-208 XMSS / XMSS^MT parameter sets (SHA-256/192, SHAKE256/256, SHAKE256/192) could not be carried through a PKCS#8 PrivateKeyInfo: PrivateKeyInfoFactory always encoded XMSS / XMSS^MT private keys as the legacy PQCObjectIdentifiers.xmss / xmss_mt form with an XMSSKeyParams / XMSSMTKeyParams carrying only the tree height and tree-digest OID, which cannot express these sets. Encoding a SHAKE256/256 or SHAKE256/192 private key threw IllegalArgumentException ("unknown tree digest: SHAKE256-LEN"), and a SHA-256/192 private key (which shares id-sha256 with the RFC 8391 SHA-256/256 set, differing only in the security parameter n=24) encoded losslessly to the wrong OID and round-tripped through PrivateKeyFactory to a different, n=32 parameter set. Separately, the matching public key already encoded in the RFC 9802 id-alg-xmss-hashsig / id-alg-xmssmt-hashsig form for every standard set, so a keypair's private and public halves carried different algorithm OIDs. XMSS / XMSS^MT private keys for all standard (RFC 8391 and SP 800-208) parameter sets are now encoded in the same RFC 9802 form as the public key (id-alg-xmss-hashsig / id-alg-xmssmt-hashsig, with the 4-octet parameter-set identifier carried ahead of the raw key), so the private and public halves share one OID and a private key round-trips losslessly to its exact parameter set. Keys generated for non-standard tree heights (which have no RFC 8391 parameter-set identifier) continue to use the legacy PQCObjectIdentifiers.xmss / xmss_mt form, and that legacy form is still read on decode (issue #2176).
- The BouncyCastle X.509 value objects returned by CertificateFactory ("X.509", "BC") deferred X.500 subject/issuer name validation to their lazy getSubjectX500Principal() / getIssuerX500Principal() accessors, which build a javax.security.auth.x500.X500Principal from the DER-encoded name. A distinguished name that decodes structurally under BC's lenient X500Name but is rejected by the stricter X500Principal constructor therefore parsed cleanly at generateCertificate() / generateCRL() and then threw an unchecked IllegalArgumentException ("improperly specified input name") the first time the name was read. For a certificate this escaped java.security.cert.CertPathValidator.validate() as an unchecked exception rather than the declared CertPathValidatorException (the issuer is read by CertPathValidatorUtilities.findTrustAnchor before signature verification, so an attacker-supplied leaf could trigger it). X509CertificateObject and X509CRLObject (org.bouncycastle.jcajce.provider.asymmetric.x509) now validate the name(s) in their constructor and reject a malformed name at parse time with a checked CertificateParsingException / CRLException, so the object is never constructed. Well-formed certificates and CRLs are unaffected.
- During PKIX revocation checking against an indirect CRL, CertPathValidatorUtilities.getCertStatus (org.bouncycastle.jce.provider and org.bouncycastle.pkix.jcajce) and RevocationUtilities.getCertStatus (org.bouncycastle.pkix.jcajce) read the CRL entry's certificateIssuer through X509CRLEntry.getCertificateIssuer(), whose own try/catch guards only the IOException from X500Name.getEncoded() and lets the IllegalArgumentException from the X500Principal constructor escape on a structurally-decodable-but-invalid name. A malformed certificateIssuer in a (validly signed) indirect CRL therefore leaked an unchecked IllegalArgumentException out of getCertStatus rather than the declared AnnotatedException. All three getCertStatus consumers now wrap the getCertificateIssuer() read and fail closed with AnnotatedException ("CRL entry certificate issuer could not be parsed.") - the exception is not swallowed to null, which would fail revocation open. Revocation checking of well-formed CRLs is unaffected.
- The JCE parameter-set classes KyberParameterSpec, SABERParameterSpec, HQCParameterSpec and SnovaParameterSpec (org.bouncycastle.pqc.jcajce.spec) built their static fromName(String) lookup map with keys that never matched the value getName() returns, so fromName(spec.getName()) returned null for every parameter set: KyberParameterSpec was keyed "kyber512".."kyber1024" but getName() yields the ML-KEM name "ML-KEM-512".."ML-KEM-1024"; HQCParameterSpec was keyed "hqc128".."hqc256" but getName() yields "hqc-128".."hqc-256"; SnovaParameterSpec was keyed with the upper-case parameter names while fromName looks up the lower-cased argument; and SABERParameterSpec had no static initializer at all, leaving its map permanently empty. Because the BCPQC key classes implement getParameterSpec() as fromName(params.getParameters().getName()), every BCKyber/BCSABER/BCHQC/BCSnova public and private key returned null from getParameterSpec(), so a caller doing key.getParameterSpec().getName() got a NullPointerException. Each map is now keyed by the (lower-cased) getName() value — Kyber additionally retains the legacy "kyber*" aliases and HQC the un-dashed "hqc*" aliases — so fromName(spec.getName()) round-trips and getParameterSpec() returns the correct spec for all parameter sets.
- Decrypting a CMS/S-MIME EnvelopedData (or AuthEnvelopedData) addressed to a password recipient derived the key-encryption key by running PBKDF2 with the iteration count taken straight from the PBKDF2Params in the recipient's keyDerivationAlgorithm, with no upper bound. That count travels in the unauthenticated PasswordRecipientInfo (RFC 3211), and CMS EnvelopedData has no integrity gate before content decryption, so an attacker-supplied message could specify an iteration count up to Integer.MAX_VALUE and make a single decryption attempt spin for tens of minutes - a CPU denial of service. Both password-recipient derivation paths (org.bouncycastle.cms.bc.BcPasswordRecipient and org.bouncycastle.cms.jcajce.EnvelopedDataHelper, used by BcPasswordEnvelopedRecipient / JcePasswordEnvelopedRecipient) now bound the count by Properties.PBE_MAX_ITERATION_COUNT (default 10,000,000, the same ceiling the PBES2 PKCS#8/PEM decrypt path applies) and throw a CMSException before deriving the key when it is exceeded. Legitimately generated password-enveloped messages are unaffected.
- The X.509 NameConstraints parser (org.bouncycastle.asn1.x509.NameConstraints / GeneralSubtree) did not reject structurally invalid empty sequences: an empty permittedSubtrees [0] or excludedSubtrees [1] was accepted even though RFC 5280 sec. 4.2.1.10 defines GeneralSubtrees as SEQUENCE SIZE (1..MAX) OF GeneralSubtree, and an empty GeneralSubtree (which is missing its mandatory base GeneralName) parsed with an unchecked ArrayIndexOutOfBoundsException escaping the IllegalArgumentException-declared parse path. Both now reject the empty sequence with "sequence may not be empty", matching the existing behaviour of AuthorityInformationAccess and the other SEQUENCE SIZE (1..MAX) extension types. Well-formed name constraints are unaffected.
- Five more X.509 extension value parsers that are defined as SEQUENCE SIZE (1..MAX) by RFC 5280 - CertificatePolicies (sec. 4.2.1.4), PolicyMappings (sec. 4.2.1.5), ExtendedKeyUsage (sec. 4.2.1.12), CRLDistPoint / CRLDistributionPoints (sec. 4.2.1.13) and SubjectDirectoryAttributes (sec. 4.2.1.8), all in org.bouncycastle.asn1.x509 - accepted a structurally invalid empty SEQUENCE, yielding a degenerate empty extension rather than failing the parse. Each now rejects an empty sequence with "sequence may not be empty" in its parse constructor, matching AuthorityInformationAccess, NameConstraints and the other SEQUENCE SIZE (1..MAX) types. Well-formed extensions are unaffected (issue #2331).
- The GPG S-expression parser (org.bouncycastle.gpg.SExpression, reached via SExprParser.parseSecretKey / PGPSecretKey.parseSecretKeyFromSExpr) allocated the buffer for a canonical string directly from the attacker-declared length before reading any data: a canonical token such as "(67108864:)" declares a 64 MiB (up to Integer.MAX_VALUE) string from a handful of input bytes, so "new byte[len]" drove a large heap allocation - and on a short stream the two-argument Streams.readFully silently left the buffer zero-padded rather than failing. The declared length is now read incrementally in bounded increments, so the allocation tracks the bytes the stream actually delivers and a truncated canonical string is rejected with an EOFException at the genuine end of input rather than driving an out-of-memory denial of service. Well-formed secret keys are unaffected (github #2338).
- org.bouncycastle.openpgp.PGPObjectFactory.nextObject() (the standard entry point for reading a PGP object stream, declared to throw only IOException) leaked an unchecked ClassCastException on a stream presenting a top-level SECRET_SUBKEY packet. SECRET_SUBKEY (packet type 7) is not one of the tags handled by the nextObject() switch, so it fell through to the default tail, which blindly cast the result of BCPGInputStream.readPacket() to UnknownPacket; but readPacket() decodes a SECRET_SUBKEY into a typed SecretSubkeyPacket, so the cast threw "SecretSubkeyPacket cannot be cast to UnknownPacket" past the declared contract (a caller catching only IOException crashed). The default tail now rejects any packet that readPacket() decodes into a concrete type but the switch does not handle with an IOException ("unexpected packet in stream: ..."), covering SECRET_SUBKEY and any other typed tag missing from the switch now or later; the genuine unknown-packet path (USER_ID, MOD_DETECTION_CODE, unrecognised tags, etc.) is unchanged. (PUBLIC_SUBKEY was already handled by the switch and never leaked.) Normal key-ring and message parsing are unaffected.
- The BC provider aliased the ARIA-CCM content-encryption OIDs (id-aria128-ccm/192/256, 1.2.410.200046.1.1.37/38/39) to the AES "CCM" Cipher rather than to ARIA-CCM, so a Cipher or AlgorithmParameters obtained by ARIA-CCM OID silently ran AES-CCM. The ARIA-CCM OIDs now resolve to the ARIA CCM Cipher and a dedicated ARIA-CCM AlgorithmParameters/AlgorithmParameterGenerator (the ARIA-GCM OID aliases were already correct). ARIA-CCM is thus now usable through the standard OID-addressed JCE path; the previously registered ARIA "ARIAGCM"/"ARIACCM" ciphers are unaffected.
- The RFC 3029 DVCS request builder DVCSRequestInformationBuilder, when seeded from an existing request through its DVCSRequestInformationBuilder(DVCSRequestInformation) constructor, silently dropped the requester ([0] GeneralNames) and extensions ([4] Extensions) fields: only seven of the nine DVCSRequestInformation fields were carried forward, so build() re-emitted the request without the original requester identity and without any extensions. The loss was also unrecoverable for extensions, since setExtensions() throws on a seeded builder. This is exactly the seed-and-re-issue path RFC 3029 sec. 9.1 describes for a DVCS modifying a received request. The constructor now copies requester and extensions alongside the other fields, so rebuilding a parsed request is byte-for-byte faithful.
- BCJSSE's established session (ProvSSLSession) threw UnsupportedOperationException from getRequestedServerNames(); only the transient handshake session implemented it, so a server (e.g. Jetty) could not read the SNI the client requested once the handshake had completed. The requested server names are now captured from the handshake and retained on the established session, so getRequestedServerNames() returns them (an empty list when no SNI was sent, per the ExtendedSSLSession contract) on both the client and server side (issue #1773).
- BCJSSE endpoint identification for the HTTPS algorithm matched a dNSName SAN wildcard in any label of the certificate name rather than only in the complete left-most label: ProvX509TrustManager.checkEndpointID dispatched the HTTPS case to HostnameUtil.checkHostname with the all-labels wildcard mode. A certificate whose SAN was "foo.*.com" therefore matched the host "foo.evil.com", and "*.*.com" matched any two-label .com host -- a weakening of TLS hostname verification (the client's defence against an impersonating server) and more permissive than both SunJSSE (sun.security.util.HostnameChecker uses matchLeftmostWildcard for TYPE_TLS) and RFC 6125 sec. 6.4.3 / RFC 9525 sec. 6.3, which require the wildcard to appear only as the complete content of the left-most label. The HTTPS path now performs left-most-label-only wildcard matching, matching the LDAP/LDAPS path (which was already correct) and SunJSSE. A wildcard forming the complete left-most label ("*.example.com" matching "a.example.com") and exact SAN matches are unaffected; only a certificate carrying a wildcard in a non-left-most label -- which no publicly-trusted CA will issue -- changes outcome (it is now rejected).
- A parameter-set-locked HQC KeyGenerator threw a NullPointerException when initialised with a KEMGenerateSpec/KEMExtractSpec — a consequence of the HQCParameterSpec fromName() mis-keying covered in the parameter-spec entry above; HQCKeyGeneratorSpi now compares against the upper-cased parameter name (matching the key's getAlgorithm()) as the other KEMs do. The dash form (e.g. "HQC-128") is now the primary registered KeyFactory/KeyPairGenerator/KeyGenerator/Cipher/KEM algorithm name, matching getName()/getAlgorithm() and the pre-existing KEM registrations, with the non-hyphenated names ("HQC128" etc.) retained as aliases. The equivalent name handling in the NTRU+ KEM KeyGenerator (which was already correct because its names are upper-case) was aligned to the same pattern.
- The lightweight cert-path validation rule org.bouncycastle.cert.path.validations.CRLValidation selected a CRL from the supplied Store by matching the issuer DN only and then consulted its revoked list without ever verifying the CRL signature. Code that populated the Store from an attacker-influenceable feed could therefore be given a forged CRL bearing the CA's issuer DN (an empty list to suppress a real revocation, or a fabricated entry to deny a valid certificate) and have it trusted. CRLValidation now verifies each matched CRL's signature against the issuing CA's public key before it can affect revocation status, mirroring ParentCertIssuedValidation; a new constructor takes the trust anchor's SubjectPublicKeyInfo and an X509ContentVerifierProviderBuilder, and the previous (X500Name, Store) constructor is deprecated and fails closed (a matched CRL is rejected rather than trusted) because it cannot verify signatures. The full JCA RFC3280CertPathUtilities.processCRLG path already verified CRL signatures and was unaffected.
- The default BC "BKS" keystore would silently load a legacy version 0/1 store. Those formats derive the HMAC integrity key at only the digest size in bits rather than bytes (a 16-bit key for the SHA-1 HMAC), which is brute-forceable offline, so an attacker able to supply or tamper with a keystore file could downgrade the on-disk version field, forge a valid integrity MAC over modified contents (e.g. injecting a rogue trusted certificate) and have it accepted (CVE-2018-5382). The version 2 format introduced for that CVE writes a full-length integrity key, but the load path still honoured the unauthenticated version field; loading a version 0/1 store through the default "BKS" type now throws an IOException unless the caller opts in via the system/security property "org.bouncycastle.bks.enable_v1" (also exposed as Properties.BKS_ENABLE_V1), which already gated creation of such stores and the separate "BKS-V1" keystore type. The default type continues to read and write the version 2 format unchanged.
- The default BC "BKS" keystore (and the legacy "BKS-V1" type) derived its integrity-MAC key using the PBE iteration count read from the keystore header with no upper bound. KeyStore.load(stream, password) runs that derivation -- iterationCount rounds of the PKCS#12 PBKDF -- before the HMAC integrity check, so an attacker able to supply the keystore file (the caller supplies the password, the normal load shape) could set the count near 2^31 and pin a CPU core for minutes per load() call: a pre-integrity-check CPU-exhaustion denial of service. The store salt length was already bounded, but the iteration count was not. BcKeyStoreSpi.engineLoad now rejects an out-of-range count up front with an IOException, bounded by the new system/security property Properties.BKS_MAX_IT_COUNT ("org.bouncycastle.bks.max_it_count", default 1048576), mirroring the existing caps on the sibling "UBER" store (MIN_ITERATIONS << 6) and the PKCS12 / BCFKS keystores (Properties.PKCS12_MAX_IT_COUNT / Properties.BCFKS_MAX_IT_COUNT). The same bound is applied to the per-entry iteration count read when decrypting a sealed key (KeyStore.getKey). The BKS writer emits a count of ~1024-2047, so normally written stores are far below the cap and unaffected. The same unbounded read exists in bc-csharp's BcKeyStoreSpi and should be corrected too.
- ArmoredInputStream mishandled dash-escaping in cleartext-signed (CSF) messages. RFC 4880 7.1 requires every cleartext line beginning with a dash to be prefixed with "- " (dash, space); the reader instead dropped the two leading characters of any line starting with a dash, so a signature computed over "payload" also verified against a tampered "-Xpayload" line. The reader now treats a leading dash that is neither a "-----" armor header nor a "- " escape as malformed and, by default, rejects it with an ArmoredInputException. RFC-conformant messages (including everything written by ArmoredOutputStream) are unaffected; the new ArmoredInputStream.Builder.setRejectPrefixedDashesInCSFMessages(false) restores a lenient mode that surfaces the offending bytes verbatim (so the signature check fails) rather than silently dropping them. (github #2329)
- KGCMBlockCipher (DSTU 7624 GCM mode, and the KGMac built on it) did not detect nonce reuse: re-initialising the same instance for encryption with an identical key and nonce was silently accepted. As with any GCM-family mode, encrypting two messages under the same key and nonce is catastrophic (it leaks the authentication key and the XOR of the plaintexts). KGCMBlockCipher.init now rejects this with an IllegalArgumentException ("cannot reuse nonce for KGCM encryption"), matching the existing GCMBlockCipher guard. reset()-based reuse, a fresh nonce, a fresh key, and re-initialisation for decryption are all unaffected.
- KGCMBlockCipher (DSTU 7624 GCM mode) applied the AEADParameters initial associated text to its associated-text accumulator on init() but did not first clear the accumulator, so re-initialising an instance carried the previous operation's associated data (left in the buffer by the prior doFinal's reset()) into the next authentication tag: a re-init with a fresh AAD produced a tag over the old AAD concatenated with the new, differing from a freshly constructed cipher. init() now resets the associated-text buffer in both the AEADParameters and ParametersWithIV branches, so a re-initialised cipher behaves exactly like a new one; reset()-based reuse was already correct and is unaffected (github PR #2349).
- The AEAD block-cipher modes EAXBlockCipher, CCMBlockCipher, OCBBlockCipher and KCCMBlockCipher (DSTU 7624 CCM mode) did not detect nonce reuse on re-initialisation for encryption -- the same catastrophic footgun the KGCMBlockCipher guard above, and the long-standing GCMBlockCipher and ChaCha20Poly1305 guards, already reject. Re-initialising the same instance for encryption with an identical key and nonce was silently accepted, even though encrypting two messages under one key and nonce leaks the authentication/MAC key and the XOR of the plaintexts (CTR keystream reuse for EAX/CCM/KCCM; offset and keystream reuse for OCB). RFC 5116 (the IETF AEAD interface) sec. 2.1 requires every nonce supplied to an AEAD encryption operation to be distinct for a given key, and RFC 7253 sec. 5.1 states the same for OCB; that obligation falls on the caller, so this is a defensive guard (turning a silent violation into a fail-fast error) rather than a conformance change. Each mode's init now throws an IllegalArgumentException ("cannot reuse nonce for EAX encryption", and likewise for CCM/OCB/KCCM) when the new nonce equals the previous one under the same key; CCM and OCB additionally catch the null-key (explicit key-reuse) form. reset()-based reuse, a fresh nonce, a fresh key, and re-initialisation for decryption are all unaffected, so the normal "encrypt many messages with rotating nonces" pattern is unchanged. GCMSIVBlockCipher (AES-GCM-SIV is nonce-misuse-resistant by design, RFC 8452) and KXTSBlockCipher (not a nonce-AEAD) are deliberately not guarded. The same modes in bc-csharp (EaxBlockCipher / CcmBlockCipher / OcbBlockCipher / KCcmBlockCipher) should be corrected too.
- CCM (CCMBlockCipher) released unverified plaintext on a failed authentication check. Decryption CTR-decrypted the whole payload straight into the caller-supplied output buffer and only then compared the MAC; on a tag mismatch it threw InvalidCipherTextException but left the unverified plaintext (AES-CTR(key, nonce) XOR ciphertext) in that buffer, never zeroed. A caller that exposes the buffer on the failure path -- through pooled-buffer reuse, logging, or memory inspection -- could thereby use forged ciphertexts as an unauthenticated CTR decryption oracle, contrary to NIST SP 800-38C 6.2 (return FAIL without revealing the payload). CCM is non-streaming, so decryption now produces the plaintext into a private buffer, verifies the MAC, and copies to the caller's output only on success (clearing the private buffer on failure), matching the pattern already used by GCMSIVBlockCipher. Output for valid ciphertexts is unchanged.
- The DSTU 7624 (Kalyna) AEAD modes KCCMBlockCipher and KGCMBlockCipher released unverified plaintext on the same failure path as CCM (above): decryption wrote the recovered plaintext into the caller-supplied output buffer before the authentication tag was compared, so a forged ciphertext left unverified plaintext there when InvalidCipherTextException was thrown. KGCM authenticates the ciphertext, so it now verifies the tag before decrypting; KCCM authenticates the plaintext, so it now decrypts into a private buffer and copies the plaintext to the caller's output only once the MAC verifies, clearing the private buffer on failure. Output for valid ciphertexts is unchanged.
- KCCMBlockCipher (DSTU 7624 CCM mode) no longer appends the authentication tag to the recovered plaintext on decryption. Decryption previously wrote plaintext || MAC into the caller's output buffer and reported only the plaintext length, leaving the verified MAC sitting past the returned length, and getOutputSize() returned len + macSize for decryption as well as encryption. KCCM decryption now writes the plaintext alone (the MAC is consumed for verification and remains available via getMac()) and getOutputSize() returns len - macSize on decryption, matching the standard AEAD contract followed by CCMBlockCipher, GCMBlockCipher and KGCMBlockCipher. The output-buffer length check was made mode-specific (encryption requires len + macSize, decryption requires len - macSize) so a caller may now pass a plaintext-sized output buffer on decryption, and getOutputSize() now accounts for buffered data so the multi-part update/doFinal path is sized correctly. The MAC verification itself is unchanged (a forged ciphertext is still rejected with InvalidCipherTextException and no unverified plaintext is released); callers that relied on reading the tag from the output buffer should use getMac() instead.
- BIKE KEM decapsulation hardened the Fujisaki-Okamoto implicit-rejection step. The decoder (BGFDecoder) returned null on a decoding failure, which the decapsulation path then dereferenced, raising a NullPointerException before the implicit-rejection branch could run; this both crashed on malformed ciphertext and acted as a decryption-failure oracle (return-key vs. throw). The decoder now always returns the recovered error vector and the re-encryption check rejects a bad decode. Separately, the final select between the genuine seed and the secret-key rejection seed sigma was written as a data-dependent if/else on the (constant-time) comparison result, so the branch direction leaked the FO oracle bit; the select is now a branchless constant-time move (Bytes.cmov), matching FrodoEngine and defending against the Guo-Johansson-Nilsson (CRYPTO 2020) FO-transform timing key-recovery attack. Output for valid ciphertexts is unchanged (KAT vectors byte-identical).
- Salsa20Engine, ChaChaEngine and ChaCha7539Engine detected the carry out of the low 32-bit counter word in advanceCounter(long) with a signed comparison (engineState[i] < oldState) where an unsigned comparison is required. A skip() from a non-zero counter by a distance whose low counter word crosses the 0x80000000 boundary therefore mis-set the high counter word: for Salsa20 / ChaCha this silently desynced the 64-bit block counter (wrong keystream and getPosition() after a large random-access seek), and for the 32-bit ChaCha7539 counter it both threw "attempt to increase counter past 2^32" on a valid skip and could miss a genuine 2^32 wrap. The carry is now computed with an unsigned comparison, matching the existing retreatCounter(long). Sequential encryption (which uses the no-argument advanceCounter()) and seekTo() from reset were already correct and are unchanged, so all KAT vectors are byte-identical.
- The lazy ASN.1 SEQUENCE parse path (ASN1InputStream constructed with lazyEvaluate=true, used by the CMS and X509CRLHolder stream parsers) did not enforce the nested-construction depth guard that the eager path applies. A lazily parsed SEQUENCE captured its contents as raw bytes and LazyEncodedSequence.force() re-parsed them through a fresh ASN1InputStream, which reset the depth budget (org.bouncycastle.asn1.max_cons_depth, default 64) to its maximum on every level. A whole-tree operation (re-encoding, hashCode, equals, iteration) on a crafted deeply nested DER/BER blob therefore recursed without bound and could raise a StackOverflowError -- a denial of service on a consumer parsing untrusted CRLs/CMS/certificates. The remaining depth budget is now threaded into LazyEncodedSequence and LazyConstructionEnumeration so forcing keeps decrementing the guard, raising the same "maximum nested construction level reached" ASN1Exception the eager path raises. Depths within the limit are unaffected.
- The OER decoder (OERInputStream), which parses IEEE 1609.2 / ETSI TS 103 097 (V2X) structures before any signature verification, was hardened against three denial-of-service vectors reachable from a small crafted input. (1) parse() recursed with no nesting-depth bound, and the IEEE 1609.2 schema is cyclic (an Ieee1609Dot2Data can nest inside its own SignedData payload), so a few KB repeatedly selecting the signedData CHOICE drove recursive descent into a StackOverflowError; a hard depth cap (default 256, threaded across the parseOpenType open-type boundary) now rejects over-deep input with an IOException. (2) A SEQUENCE-OF decoded its element count from a few attacker-controlled bytes and looped that many times allocating objects without first checking the count against the remaining input, so a count such as a long-form 7F FF FF FF drove roughly 2^31 allocations; the count is now bounded by the bytes available, and the fixed-width INTEGER and BOOLEAN element decoders now fail on a short read instead of silently yielding 0 / TRUE at end of input. (3) The open-type EXTENSION branch allocated new byte[length] directly from an attacker-controlled long-form length, bypassing the maxByteAllocation cap every other branch honours and allowing an immediate OutOfMemoryError; it now allocates through the same bounded helper. Valid 1609.2 messages parse unchanged.
- IETFUtils.valueToString (reached from X500Name.toString() / equals() / hashCode() via AbstractX500NameStyle, and from java.security X509Certificate.getSubjectX500Principal().toString()) escaped RFC 4514 special characters and leading/trailing spaces by inserting a backslash into the StringBuilder it was scanning. Because each insert shifts the remainder of the buffer, escaping a value of n special characters (or n leading/trailing spaces) cost O(n^2) character moves, so a single large attacker-supplied RDN -- e.g. a long PrintableString of commas in a certificate, CSR, CRL or CMS SignerIdentifier -- could pin a CPU core when the resulting X500Name was logged, compared, hashed or pretty-printed (a denial-of-service amplification on otherwise in-spec ASN.1 string sizes). The escaping now runs in a single linear pass into a fresh builder; the produced string is unchanged.
- The jdk1.4 build variant of LDAPStoreHelper (org.bouncycastle.x509.util, used by the bcprov-jdk14 distribution) did not escape DN-derived values before concatenating them into an LDAP search filter, so the CVE-2023-33201 LDAP filter-injection fix -- which added filter escaping to the main-Java LDAPStoreHelper (via LDAPUtils.parseDN) and to both X509LDAPCertStoreSpi variants -- never reached bcprov-jdk14: the jdk14 Ant build overlays this jdk1.4 file, which carries its own private parseDN, over the patched main-Java one. A certificate whose Subject/Issuer CN embedded LDAP filter metacharacters (e.g. "a)(userPassword=*") could therefore rewrite the DirContext.search() filter when certification-path building or CRL lookup invoked the helper. parseDN now applies the same RFC 2254 filter escaping as the other three variants. This affects the jdk1.4/legacy distribution only; the Gradle-built jars were already fixed.
- Importing a Diffie-Hellman or DSA public key validated the key by computing a modular exponentiation (and, for DH safe primes, a Legendre symbol) modulo the supplied prime p, with no bound on the size of p. A crafted DH/DSA SubjectPublicKeyInfo (via KeyFactory import or certificate parsing through the BC provider) carrying a multi-million-bit p therefore forced a very expensive computation at import time -- an import-time CPU-exhaustion denial of service of the same class as CVE-2024-29857 (explicit EC parameters). DHPublicKeyParameters and DSAPublicKeyParameters now reject a modulus whose bit length exceeds a configurable bound before performing the exponentiation, mirroring the existing RSA modulus cap (org.bouncycastle.rsa.max_size). The bounds default to 16384 bits (well above any standardised DH/DSA group) and are controlled by the new Properties.DH_MAX_SIZE (org.bouncycastle.dh.max_size) and Properties.DSA_MAX_SIZE (org.bouncycastle.dsa.max_size).
- ArmoredOutputStream sanitized armor header values against the line feed (\n) only: the additive (addComment / setComment / setMessageId / setCharset) paths split values on \n, and the singleton (setVersion) path rejected \n, but neither handled a bare carriage return (\r). A header value carrying an embedded CR -- for example a parsed User-ID re-armored as a Comment via OpenPGPCertificate.toAsciiArmoredString() -- therefore survived into a single physical header line, which a reader treating a lone CR as end-of-line (including BouncyCastle's own ArmoredInputStream) splits into a forged extra header or armor boundary (armor header injection / round-trip denial of service). The split paths now split on CR, LF and CRLF, and the singleton path rejects CR as it rejects LF.
- The ArmoredOutputStream CR/LF hardening above covered only the Builder paths; the deprecated setHeader(name, value) / addHeader(name, value) methods and the ArmoredOutputStream(OutputStream, Hashtable) constructor still stored a header name or value verbatim, so a CR or LF embedded in one (for example an application armoring a user-supplied Comment through the legacy API) survived into a single physical header line and could inject an extra armor header, or -- via a blank line -- terminate the header block early with the remainder parsed as base64 body (armor header injection). The rejection has been moved to the single sink every path funnels through, writeHeaderEntry, which now throws IllegalArgumentException("armor header must not contain CR/LF") when a header name or value contains CR or LF; this covers the deprecated setters, the Hashtable constructor and the Builder at once (the Builder's pre-split, well-formed values pass through unchanged). The analogous PEM header writer org.bouncycastle.util.io.pem.PemWriter (the parent of the openssl PEMWriter / JcaPEMWriter) had the same gap -- it emitted PemHeader name/value pairs without sanitization -- and now rejects a CR or LF in a PemHeader name or value the same way. BouncyCastle's own headers (the constant Version, and the standardised PEM Proc-Type / DEK-Info) are unaffected.
- OpenPGPMessageInputStream.OnePassSignatures.verify() (the inline one-pass-signature verification path of the high-level OpenPGP API) caught the PGPSignatureException thrown by OpenPGPSignature.sanitize() -- which enforces the OpenPGPPolicy (rejecting weak hashes such as MD5/SHA-1/RIPEMD-160, unacceptable keys, unknown critical subpackets, pre-dated signatures) -- in a catch block whose body was an empty "// continue" comment with no statement, so execution fell through to the cryptographic verify() and the signature was added to the results as tested/correct. A one-pass signature that fails policy (e.g. a collision-prone hash on an otherwise trusted key) was therefore reported as valid through getSignatures() / isTestedCorrect(). The catch now reports the exception via the processor and skips the signature, matching the detached- and prefixed-signature paths.
- OpenPGP SEIPD v1 decryption from a public-key (PKESK) or other already-recovered session key still performed the legacy CFB "quick check" on the two repeated prefix bytes and threw PGPDataValidationException("data check failed.") before the MDC was verified. PGPPublicKeyEncryptedData has long suppressed this check to avoid the Mister-Zuccherato adaptive-chosen-ciphertext oracle, but the session-key path (PGPSessionKeyEncryptedData, reached by the high-level OpenPGP API after unwrapping a PKESK session key) did not, re-exposing a distinguishable early failure that an attacker with a decryption oracle could use to recover plaintext. The quick check is now suppressed on the public-key / session-key path (the SEIPD v1 MDC is the integrity check there); it is retained on the password-based (PBE) path, where its failure and stream reset are what let the decryptor detect a wrong passphrase and rewind to try the next SKESK packet in a multi-passphrase message.
- Loading a BCFKS keystore (BcFKSKeyStoreSpi) derived the integrity-MAC key from the scrypt or PBKDF2 cost parameters carried in the keystore before verifying that MAC, with no bound on those parameters. A crafted .bcfks declaring, for example, a scrypt cost of N=2^28 (≈68 GiB working memory) or a PBKDF2 iteration count near 2^31 therefore forced unbounded memory or CPU consumption at load time, before any password or integrity check -- a pre-authentication denial of service for any application that loads untrusted BCFKS keystores. Unlike the PKCS#12 keystore (which caps iteration counts via PKCS12_MAX_IT_COUNT) BCFKS applied no bound. The MAC-key derivation now rejects a scrypt working-memory estimate (≈128·N·r) above Properties.BCFKS_MAX_SCRYPT_MEMORY (default 1 GiB) or an oversized scrypt block size, and a PBKDF2 iteration count above Properties.BCFKS_MAX_IT_COUNT (default 5,000,000), before running the KDF. The BCFKS writer's own parameters (PBKDF2 ≈51,200 iterations, scrypt N=16384/r=8) are well within the defaults.
- Decrypting a PBES2-protected PKCS#8 / PEM private key (JcePKCSPBEInputDecryptorProviderBuilder and JceOpenSSLPKCS8DecryptorProviderBuilder) derived the key from the scrypt or PBKDF2 cost parameters carried in the encrypted-key container with no bound on those parameters. The container is not integrity-protected, so importing an attacker-supplied encrypted key (a routine operation) could be driven into multi-gigabyte scrypt memory or billions of PBKDF2 iterations -- a decryption-time denial of service. Both builders now reject a scrypt working-memory estimate (≈128·N·r) above Properties.PBE_MAX_SCRYPT_MEMORY (default 1 GiB) or an oversized scrypt block size, and a PBKDF2 iteration count above Properties.PBE_MAX_ITERATION_COUNT (default 10,000,000), before running the KDF. The defaults are generous enough for deliberately strong settings and are configurable for callers needing higher costs.
- Completing the cost-parameter bounding above for the PBES2 / scrypt path, the legacy PKCS#5 v1.5 PBES1 branch of those same two builders (JcePKCSPBEInputDecryptorProviderBuilder and JceOpenSSLPKCS8DecryptorProviderBuilder) still fed the PBKDF1 iteration count carried in the encrypted-key AlgorithmIdentifier straight into key derivation with no bound. That parameter is unauthenticated and reachable through the routine PKCS8EncryptedPrivateKeyInfo.decryptPrivateKeyInfo / InputDecryptorProvider.get(algId) import path (pbeWithMD5AndDES-CBC, pbeWithSHA1AndDES-CBC and the related PKCS#5 v1.5 PBE OIDs), so a crafted key declaring a count near 2^31 drove a long PBKDF1 hash loop -- a decryption-time CPU-exhaustion denial of service. Both PBES1 branches now reject an iteration count above Properties.PBE_MAX_ITERATION_COUNT (default 10,000,000) before deriving the key, matching the PBES2 / PBKDF2 branch in the same builders; legitimate PBES1 counts are far smaller and unaffected.
- The RFC 4211 PKMAC / CMP password-based-MAC builder (PKMACBuilder) ran its iterated hash for the iteration count carried in the (unauthenticated) PBMParameter with no upper bound unless the caller had constructed the builder with an explicit maxIterations ceiling. Verifying a passwordBasedMac-protected CMP message (ProtectedPKIMessage.verify(PBEMacCalculatorProvider, char[])) feeds the incoming message's iteration count straight into that loop, so an attacker-supplied message declaring a count near 2^31 could drive the recipient into billions of hash iterations -- a CPU-exhaustion denial of service. PKMACBuilder now applies a default ceiling (Properties.PKMAC_MAX_ITERATION_COUNT, org.bouncycastle.pkmac.max_iteration_count, default 10,000,000) when no explicit maxIterations was supplied, rejecting an oversized count with an IllegalArgumentException before the loop runs; an explicitly configured maxIterations still takes precedence. Legitimate CMP iteration counts are far smaller and unaffected.
- The EST client (DefaultESTClient) followed an HTTP 3xx redirect whose Location pointed to any host, rebuilding the request -- including its headers (any Authorization credential) and body (the enrolment CSR) -- against the redirect target. A malicious or compromised EST server could therefore redirect an enrolment or otherwise authenticated request to an attacker-chosen origin and have the client replay those credentials and the CSR there (cross-origin credential / request-body disclosure). redirectURL now follows only same-origin redirects (matching scheme, host and port) and refuses a redirect to a different origin with an ESTException. Relative-Location redirects, which reuse the original origin by construction, are unaffected.
- DTLS handshake reassembly (DTLSReliableHandshake) sized each reassembly buffer from the full-message length declared in a handshake fragment header (a uint24, up to ~16 MiB), with no bound, and created one reassembler per message_seq across the receive-ahead window -- all at epoch 0, before any signature or Finished verification. A handful of small datagrams carrying minimal fragments with large declared lengths could therefore commit hundreds of MiB of attacker-controlled heap per peer, a pre-authentication denial of service. The non-DTLS path already rejected handshake messages exceeding the peer's getMaxHandshakeMessageSize() (default 32768); the DTLS reassembler now applies the same bound (max(1024, peer.getMaxHandshakeMessageSize())) before allocating, ignoring an over-sized fragment as it already ignores a malformed one.
- The JCE private-key classes BCMLDSAPrivateKey (ML-DSA), BCMLKEMPrivateKey (ML-KEM) and BCSLHDSAPrivateKey (SLH-DSA) compared their secret-bearing encodings in equals() with the variable-time Arrays.areEqual, whereas the secret-bearing private-key path should use the constant-time comparison (as the other BC private-key classes do). The comparison now uses Arrays.constantTimeAreEqual; the boolean result is unchanged.
- NTRU+ KEM decapsulation (NTRUPlusEngine) computed its re-encryption equality check in a constant-time loop but then converted the accumulated difference to the fail flag with a data-dependent branch (acc != 0 ? 1 : 0), despite the method's "constant time" contract and the branchless form documented in its own comment. Because the fail flag drives a constant-time cmov of the shared secret, the branch reintroduced a Fujisaki-Okamoto decryption-failure timing oracle. The conversion is now branchless ((-acc) >>> 31); the returned 0/1 value (and therefore the KEM output) is unchanged.
- NTRU LPRime KEM decapsulation (NTRULPRimeKEMExtractor) recomputed the re-encrypted ciphertext components encBnew = Encode(Round(bG)) and encTnew = Encode(Top(bA)) but then assembled the candidate ciphertext for the Fujisaki-Okamoto re-encryption check from the input ciphertext's own encB / encT bytes (and encoded the input T rather than the recomputed Tnew), so encBnew / encTnew were discarded. The constant-time comparison against the supplied encapsulation therefore compared the B and T components against themselves and only meaningfully checked the hc confirmation hash, so the implicit-rejection step never verified that the recovered message actually re-encrypts to the supplied ciphertext. Since the rounded B/T encoding is malleable, this weakened the IND-CCA2 guarantee the FO transform provides. The check now rebuilds the candidate ciphertext from the re-encrypted encBnew / encTnew, matching the encapsulator (NTRULPRimeKEMGenerator) and the sibling Streamlined NTRU Prime extractor. Decapsulation of valid ciphertexts is unchanged (KAT vectors byte-identical).
- Several post-quantum KEM decapsulators did not validate the length of the supplied ciphertext (encapsulation) before decoding it, so a malformed or truncated ciphertext from the wire crashed decapsulation with an uncaught ArrayIndexOutOfBoundsException / NegativeArraySizeException -- or, for Frodo, NTRU LPRime and Streamlined NTRU Prime, a ciphertext one byte short of the expected length was silently accepted and decapsulated to a wrong shared secret -- instead of being cleanly rejected. This is a robustness / denial-of-service defect on the attacker-supplied ciphertext, reachable wherever a KEM ciphertext is decapsulated. The lightweight extractors SABERKEMExtractor, FrodoKEMExtractor (the legacy NIST round 3 / eFrodoKEM implementation), CMCEKEMExtractor, HQCKEMExtractor, NTRUPlusKEMExtractor, NTRULPRimeKEMExtractor and SNTRUPrimeKEMExtractor (org.bouncycastle.pqc.crypto.*), and the legacy BIKEKEMExtractor (org.bouncycastle.pqc.legacy.bike), now reject an encapsulation whose length is not the parameter set's expected ciphertext length with an IllegalArgumentException ("encapsulation wrong length") before any decoding, matching the existing guard in MLKEMExtractor / NTRUKEMExtractor and the standardised org.bouncycastle.crypto.kems extractors. Decapsulation of valid (correct-length) ciphertexts is unchanged (KAT vectors byte-identical).
- The NTRU+ KEM JCE wiring in the BCPQC provider was only partially functional. NTRUPlusParameterSpec.fromName() keyed its lookup map on strings ("ntruplus-768"/"ntruplus-864") that getName() never produces (getName() returns "NTRU+KEM768"/"NTRU+KEM864"/"NTRU+KEM1152"), duplicated the 864 entry and omitted ntruplus_1152 altogether, so fromName() returned null for every parameter set: BCNTRUPlusPublicKey.getParameterSpec() and BCNTRUPlusPrivateKey.getParameterSpec() returned null for all NTRU+ keys, and a parameter-locked KeyGenerator raised a NullPointerException from engineInit. The map is now keyed by the lower-cased canonical name and includes all three parameter sets. The per-parameter-set KeyGenerator and Cipher aliases also registered class names (NTRUPLUSKeyGeneratorSpi / NTRUPLUSCipherSpi) that did not match the actual classes (NTRUPlusKeyGeneratorSpi / NTRUPlusCipherSpi), so KeyGenerator.getInstance / Cipher.getInstance for "NTRU+KEM-768", "NTRU+KEM-864" and "NTRU+KEM-1152" failed with a NoClassDefFoundError; the registrations now name the real classes. Finally, two parameter-set mix-ups were corrected: the NTRUPlus768 Cipher SPI was constructed with the 864 parameters (so the "NTRU+KEM-768" Cipher alias rejected genuine 768 keys), and the NTRUPlus1152 KeyPairGenerator SPI was constructed with the 864 parameters (so the "NTRU+KEM-1152" alias generated 864-sized keys and rejected an explicit ntruplus_1152 initialisation). The lightweight org.bouncycastle.pqc.crypto.ntruplus API, OID-based key decoding, and the base "NTRUPLUS" KeyPairGenerator / Cipher / KeyGenerator were unaffected; key encodings are unchanged.
- The RFC 9579 PBMAC1 PKCS#12 keystore SPI (PKCS12PBMAC1KeyStoreSpi) read the outer authSafe ContentInfo's content with ASN1OctetString.getInstance(info.getContent()).getOctets(). A crafted PKCS#12 whose ContentInfo omits the OPTIONAL [0] EXPLICIT content field -- and which carries no MacData, so the MAC block that would otherwise touch the content is skipped -- left info.getContent() null and the subsequent getOctets() raised a NullPointerException during engineLoad, a parse-time denial of service triggerable before any MAC/password check. The legacy PKCS12KeyStoreSpi already routes the same outer-content access through PKCS12Util.getContentOctets (which raises a diagnosable ASN1ParsingException("ContentInfo content missing")); its SPI-pair sibling PKCS12PBMAC1KeyStoreSpi did not, so the CVE-2024-0727 hardening was incomplete. The PBMAC1 SPI now uses the same helper, completing the fix across the PKCS#12 SPI pair. (The PKCS12PBMAC1StoreTest regression suite, previously not referenced by the package AllTests, is now wired in.)
- PKIX certification-path validation built the RFC 5280 valid-policy-tree with no bound on its size. Certificate policy mapping combined with the anyPolicy expansion (RFC 5280 6.1.3 (d)(2) / 6.1.4) makes the tree grow multiplicatively per certificate, so a crafted chain that still chains to a trusted anchor (for example an attacker-controlled sub-CA, or an mTLS client-supplied chain) and carries policies plus policy mappings at every level could drive the validator into exponential memory/CPU consumption -- a denial of service of the class of CVE-2023-0464. (Unlike OpenSSL, whose certificate-policy processing is disabled by default, BC builds the policy tree unconditionally on every validation.) The valid-policy-tree node count is now bounded: validation aborts with a CertPathValidatorException once the live node count (summed across all depth levels, checked once per certificate) exceeds Properties.X509_MAX_POLICY_NODES (org.bouncycastle.x509.max_policy_nodes), which defaults to 8192 -- far above any legitimate policy tree, which contains a handful of nodes -- and is configurable. The bound is applied to every copy of the policy-tree-building logic: the org.bouncycastle.jce.provider CertPathValidator / CertPathBuilder (the BouncyCastle provider path), and the PKIXCertPathReviewer diagnostic classes in org.bouncycastle.x509 and org.bouncycastle.pkix.jcajce (which build the same tree and report a "policy checking failed" finding when the bound is exceeded).
- X.509 name-constraint enforcement (PKIXNameConstraintValidator, used by the BouncyCastle PKIX CertPathValidator / CertPathBuilder) was tightened against two bypasses by which a compromised or mis-issuing name-constrained intermediate CA could escape its constraints. (1) directoryName matching searched for the constraint's first RDN at an arbitrary offset in the subject and matched the remaining RDNs from there, so a subject such as C=FR,O=Attacker,C=US,O=TrustedOrg,CN=victim was accepted under a permittedSubtree of C=US,O=TrustedOrg; RFC 5280 sec. 4.2.1.10 / 7.1 require the constraint to be an initial prefix of the subject, and matching now starts at the first RDN only. (The relaxed GSMA SGP.22 anywhere-match stays available behind Properties.X509_SGP22_NAME_CONSTRAINTS.) (2) rfc822Name and uniformResourceIdentifier host comparisons used an exact case-insensitive compare while the dNSName path strips an RFC 1034 root-label trailing dot, so an excluded subtree of bank.com / competitor.example could be evaded with a trailing dot (user@bank.com., https://competitor.example./); the email and URI host forms now apply the same trailing-dot canonicalisation before comparison. Names that obey the constraints, and certificates without prepended-RDN or trailing-dot tricks, are unaffected.
- X.509 name-constraint enforcement (PKIXNameConstraintValidator, used by the BouncyCastle PKIX CertPathValidator / CertPathBuilder) was tightened against a further rfc822Name bypass of the same class as the trailing-dot issue above. When matching a certificate's rfc822Name against an email name constraint, the validator derived the mailbox host by splitting the address at its first '@'. RFC 5321 sec. 4.1.2 allows a quoted local part to contain '@', so the domain of a mailbox is the text after its last '@', not its first: a tested rfc822Name such as "victim@evil.example"@bank.com is a mailbox in bank.com, but the first-'@' split yielded the host evil.example"@bank.com and so slipped past an excluded (or failed a permitted) subtree of bank.com that a correctly-parsing relying party would enforce, letting a compromised or mis-issuing name-constrained intermediate CA escape an email-domain constraint. Because a quoted local part cannot be split unambiguously by simple string slicing, a tested rfc822Name containing more than one '@' is now rejected when rfc822Name constraints are in force, rather than guessing a host from the wrong '@'. This is deliberately stricter than RFC 5321 (a quoted-local-part address carrying an embedded '@' is a valid, if vanishingly rare, mailbox), so a new property Properties.X509_ALLOW_LENIENT_RFC822_NAME (org.bouncycastle.x509.allow_lenient_rfc822_name) restores the previous lenient parsing for any deployment that needs it; it defaults to off (validation is strict by default) and is the general opt-out for rfc822Name conformance strictness as the validator moves toward a full RFC 5321 mailbox parse. Ordinary single-'@' email addresses, and certificates validated where no rfc822Name name constraints apply, are unaffected.
- CMS AuthenticatedData verification did not bind the content to the MAC when authenticated attributes were present. With authAttrs, RFC 5652 sec. 9.3 computes the MAC over DER(authAttrs) -- which carries a messageDigest attribute -- so content integrity depends on the recipient additionally comparing that attribute against the digest computed over the content. RecipientInformation exposed the computed digest via getContentDigest() but never performed the comparison, and the documented verification pattern (and most of the AuthenticatedData test suite) checked only Arrays.equals(ad.getMac(), recipient.getMac()); since AuthenticatedData authenticates but does not encrypt the content, an attacker could replace encapContentInfo.eContent with arbitrary bytes, leave authAttrs and the mac untouched, and the recipient MAC comparison would still succeed. RecipientInformation.getMac() now verifies the recovered content digest against the messageDigest authenticated attribute and throws a CMSRuntimeException on mismatch (binding the content for both the in-memory CMSAuthenticatedData and streaming CMSAuthenticatedDataParser paths). getContentDigest() is also now idempotent -- it caches the computed digest, which the underlying DigestCalculator.getDigest() otherwise finalises on first read. Messages without authenticated attributes MAC the content directly and are unaffected.
- CMSSignedData.verifySignatures(...) returned true for a SignedData carrying no SignerInfos. RFC 5652 permits a degenerate (certs-only) SignedData with an empty signerInfos SET, and the verification loop simply falls through to "return true" when there are no signers -- so an application using verifySignatures() as its top-level authenticity check would accept arbitrary attacker-supplied content wrapped in a zero-signer SignedData envelope (a fail-open / vacuous success). verifySignatures() now throws a CMSException ("no signers present in SignedData") when the signer set is empty. Counter-signature verification is unaffected (a signer with no counter-signatures remains valid - the check applies only to the top-level signer set); applications expecting a certs-only structure should use getCertificates().
- BcRSAAsymmetricKeyUnwrapper (the lightweight CMS / PKIX RSA PKCS#1 v1.5 key-transport unwrapper) now carries a class-level javadoc note documenting that PKCS#1 v1.5 RSA decryption is subject to Bleichenbacher / Marvin adaptive chosen-ciphertext attacks: the unwrapper signals a padding failure by throwing rather than returning a random key of the expected length, so a service that decrypts attacker-supplied key-transport blobs with a static RSA private key and exposes the outcome (a distinguishable error, or a response-time difference) can act as a padding oracle. BC deliberately leaves the constant-time random-fallback mitigation to the protocol layer -- the TLS stack wires PKCS1Encoding's fallback mode for the RSA key exchange -- and the javadoc now points callers exposing an online decryption oracle at RSA-KEM or RSA-OAEP key transport instead. Documentation only; no behaviour change.
- The composite (draft-ietf-lamps-pq-composite-kem / -sig) KEM and signature parsers split attacker-controlled key and signature bytes at fixed component offsets without first checking the input was long enough. A crafted composite public key, private key or signature with a truncated body therefore raised an uncaught NegativeArraySizeException / ArrayIndexOutOfBoundsException / IllegalArgumentException out of KeyFactory.generatePublic / generatePrivate (reachable via BouncyCastleProvider.getPublicKey / getPrivateKey when parsing a certificate or PKCS#8) and out of Signature.verify -- a parse-time denial of service on untrusted input that escaped the methods' declared IOException / SignatureException contracts. compositekem.KeyFactorySpi (public- and private-key paths), compositesignatures.SignatureSpi.engineVerify and CompositeMLKEMEngine decapsulation now bound-check the input length first and reject a too-short body with a diagnosable IOException / SignatureException, matching the strict-parse hardening applied elsewhere (e.g. the CVE-2024-0727 PKCS#12 fix).
- Three further secret-comparison sites were switched from the variable-time Arrays.areEqual to the constant-time Arrays.constantTimeAreEqual, matching the bc-java convention for secret-bearing comparisons: the DSTU 7624 (Kalyna) key-unwrap integrity check in DSTU7624WrapEngine (the only wrap engine still using the variable-time compare; RFC3394WrapEngine / RFC5649WrapEngine / DESedeWrapEngine / RC2WrapEngine / RFC3211WrapEngine already use the constant-time form), and the legacy stateful-hash PQC private-key equals() implementations in BCXMSSPrivateKey, BCXMSSMTPrivateKey and BCSphincs256PrivateKey (the un-migrated siblings of the ML-DSA / ML-KEM / SLH-DSA private-key equals() hardened earlier in this release). The boolean / thrown results are unchanged.
- The remaining secret-bearing private-key equals() implementations were likewise switched from the variable-time Arrays.areEqual to the constant-time Arrays.constantTimeAreEqual, completing the migration begun earlier in this release. On the lightweight side, LMSPrivateKeyParameters now compares its RFC 8554 master secret (the seed from which every LM-OTS private key is derived) in constant time; HSSPrivateKeyParameters compares its component LMS keys and so inherits the change. On the JCE side, the BCPQC private-key wrappers BCLMSPrivateKey, BCDilithiumPrivateKey, BCKyberPrivateKey, BCFalconPrivateKey, BCNTRUPrivateKey, BCNTRULPRimePrivateKey, BCSNTRUPrimePrivateKey, BCNTRUPlusPrivateKey, BCSABERPrivateKey, BCFrodoPrivateKey, BCBIKEPrivateKey, BCCMCEPrivateKey, BCHQCPrivateKey, BCSPHINCSPlusPrivateKey, BCPicnicPrivateKey, BCMayoPrivateKey, BCMQOMPrivateKey, BCSDitHPrivateKey, BCSnovaPrivateKey and BCNHPrivateKey each compared their secret-bearing encoded private key with the variable-time form and now use the constant-time comparison. (BCNHPrivateKey's secret is exposed as a short[], for which there is no constant-time primitive, so it now compares its PKCS#8 encoding in constant time as its siblings already do.) The public LMS I identifier comparison is deliberately left variable-time, and the boolean result of every equals() is unchanged.
- The classic JCA private-key classes likewise had their secret-scalar equals() comparisons made constant-time, matching the earlier BCECPrivateKey / BCEdDSAPrivateKey / BCXDHPrivateKey hardening: BCRSAPrivateKey and BCRSAPrivateCrtKey (the private exponent, and for the CRT key the primes p and q, the two CRT exponents and the CRT coefficient), BCDSAPrivateKey, BCDHPrivateKey, BCElGamalPrivateKey and BCGOST3410PrivateKey (the secret value x), and BCDSTU4145PrivateKey, BCECGOST3410PrivateKey and BCECGOST3410_2012PrivateKey (the EC private scalar d) now compare the secret BigInteger through the new BigIntegers.constantTimeAreEqual helper (a constant-time comparison of the toByteArray() form) instead of the variable-time BigInteger.equals; the public modulus, public exponent and domain parameters continue to use the ordinary comparison. Separately, the HSS private-key regeneration path in HSSPrivateKeyParameters compared a freshly-derived child seed against the stored master secret with the variable-time Arrays.areEqual and now uses Arrays.constantTimeAreEqual. The boolean result of every comparison is unchanged.
- X509CertificateHolder and X509CRLHolder, when constructed from a byte[] / InputStream, caught only ClassCastException and IllegalArgumentException from the ASN.1 decode and wrapped them in a CertIOException; other RuntimeExceptions thrown on malformed input -- ASN1ParsingException / IllegalStateException from the lazy-sequence and tagged-object decoders, and a NullPointerException reachable in the certificate path -- escaped a constructor that declares only IOException, so a caller catching IOException on untrusted input could still receive an uncaught RuntimeException (a parse-time robustness failure surfaced by fuzzing). Both parse helpers now treat any RuntimeException from the decode as malformed input and wrap it in a CertIOException carrying the same "malformed data: ..." message. Valid encodings are unaffected (80,000 mutated CRL/certificate inputs all surfaced as IOException).
- PKCS12KeyStoreSpi.engineLoad and its RFC 9579 PBMAC1 SPI pair (PKCS12PBMAC1KeyStoreSpi) parsed the (untrusted) PKCS#12 safe contents -- AuthenticatedSafe / SafeBag / CertBag decode, ASN1OctetString.getInstance, embedded certificate generation -- without catching the RuntimeExceptions those ASN.1 operations throw on malformed input, so a crafted .p12 could surface an uncaught IllegalArgumentException (e.g. "illegal object in getInstance") or a bare RuntimeException out of KeyStore.load, escaping the method's declared IOException contract (a parse-time robustness failure for callers catching IOException; the same class as the X509CertificateHolder / X509CRLHolder fix above). The safe-contents processing in both SPIs is now wrapped so any RuntimeException from the decode is re-thrown via Exceptions.ioException as an IOException. Valid keystores are unaffected.
- BCPBEKey.destroy() -- the JCE PBEKey returned by the BC SecretKeyFactory PBE / PBKDF2 / scrypt key factories -- zeroized the password and salt but left the derived key bytes, the actual secret, in memory: the derived key is held in the CipherParameters param field (a KeyParameter, or a KeyParameter wrapped in ParametersWithIV) and was never cleared, so a heap dump taken after a caller had dutifully called destroy() still contained the derived key. destroy() now also overwrites the derived key held in param (recursing through ParametersWithIV to reach the wrapped KeyParameter), honouring the Destroyable contract; behaviour before destroy() and the post-destroy IllegalStateException from getEncoded()/getParam() are unchanged.
- Three provider / cache data races were closed. BouncyCastleProvider.getKeyInfoConverter and BouncyCastlePQCProvider.getKeyInfoConverter read the shared static keyInfoConverters HashMap with no synchronization, while addKeyInfoConverter and the sibling getAsymmetricKeyInfoConverter both hold the map's monitor; a getKeyInfoConverter call racing an addKeyInfoConverter (for example a second provider construction, which re-runs the converter registration, concurrent with a key decode on another thread) could observe a partially-rehashed table and return a wrong or null converter. Both reads now take the same monitor as the write. Separately, OcspCache.getOcspResponse mutated its per-responder inner HashMap (get / put / remove) with no synchronization, so two threads validating certificates from the same OCSP responder could structurally corrupt that map; the method is now static synchronized, matching its sibling CrlCache.getCrl. No behavioural change for single-threaded callers.
- MLS (RFC 9420) external-proposal verification (Group.verifyExternal) looked up the sender's signature key as senders.get(sender_index).getSignatureKey() from the group's external_senders extension with no null-check on the extension and no bounds-check on the wire-controlled sender_index, before verifying the signature. A PublicMessage carrying an EXTERNAL sender therefore crashed message processing with an uncaught NullPointerException (when the group has no external_senders extension) or IndexOutOfBoundsException (when sender_index is out of range or negative) -- a pre-verification denial of service on untrusted input. verifyExternal now rejects a missing external_senders extension and an out-of-range sender_index with a diagnosable Exception, matching the sibling verifyInternal's "Signature from blank node" rejection, before the lookup. A well-formed external proposal from an authorized sender is unaffected.
- MLS (RFC 9420) external-join verification (Group.verifyNewMemberCommit and Group.verifyNewMemberProposal) dereferenced optional, wire-controlled message fields with no guard -- the missed siblings of the verifyExternal fix above. Group.handle dispatches signature verification on sender type via verifyAuth before any content-type or path validation, and the membership tag is not checked for a NEW_MEMBER_COMMIT / NEW_MEMBER_PROPOSAL sender, so a PublicMessage carrying either sender type reached these two methods on untrusted input. A Commit whose updatePath is absent (a legal decode -- readOptional) crashed verifyNewMemberCommit with a NullPointerException at commit.getUpdatePath().getLeafNode(), and a NewMemberProposal carrying any non-Add proposal crashed verifyNewMemberProposal at proposal.getAdd().keyPackage -- a pre-verification, remote, unauthenticated denial of service. Both methods now reject the malformed message with a diagnosable Exception ("malformed NewMemberCommit" / "malformed NewMemberProposal") before the dereference, matching verifyExternal and completing the malformed-external-message hardening begun for external senders. A well-formed external commit (carrying an UpdatePath) or external Add proposal from an authorized joiner is unaffected.
- MLS (RFC 9420) message-key derivation (GroupKeySet.HashRatchet.get) advanced the per-sender hash ratchet by one HKDF-derivation step for every generation between the ratchet's current position and the generation requested by an incoming message, with no bound on the gap. The generation is carried in the (authenticated, sender-supplied) message, so a group member could request a generation up to ~2^31 and force every recipient into billions of key derivations -- a CPU-exhaustion denial of service (insider-reachable, the generation being inside the AEAD-protected sender data). get now rejects a forward gap exceeding HashRatchet.MAX_FORWARD_RATCHET_STEPS (65536) with an InvalidParameterException before advancing, matching the existing expired-key rejection. Legitimate generation gaps (message reordering/loss within an epoch) are far smaller and unaffected.
- MLS (RFC 9420) PrivateMessage.protect left the per-message reuse_guard -- the 4-byte value XORed into the AEAD nonce to guard against nonce reuse (RFC 9420 sec. 6.3.1) -- all-zero on the send path, never randomizing it. With a constant guard the nonce for a given (key, generation) is fixed, removing the defense-in-depth the guard is meant to provide; two protections of the same content under the same key state produced byte-identical ciphertext. protect now fills reuse_guard with fresh bytes from a SecureRandom per message, as the spec requires. The guard is carried in the encrypted sender data and applied by the receiver, so interop and decryption are unaffected.
- SExprParser.parseSecretKey() now auto-detects the GnuPG "Extended Private Key Format" (a set of "Name: value" header lines followed by the key S-expression under a "Key:" field), which has been the gpg-agent default since 2.2.20. Previously this entry point assumed a bare canonical S-expression and failed on the leading header character ("unknown character encountered" for on-disk private-keys-v1.d key files written by modern GnuPG); it now routes an extended-format stream through PGPSecretKeyParser / OpenedPGPKeyData while leaving the canonical-format path unchanged (issue #794).
- The BC provider's BKS and UBER keystores (BcKeyStoreSpi) read length-prefixed certificate-chain, key, secret, sealed and salt fields from the stream and allocated arrays of the declared size before reading the data, with no upper bound. A crafted keystore of a few dozen bytes declaring an Integer.MAX_VALUE length could therefore drive an immediate OutOfMemoryError on KeyStore.load() regardless of the configured heap size - and, because loadStore() runs ahead of the integrity-MAC comparison, regardless of the password supplied (CWE-789 / CWE-400). The certificate chain is now decoded incrementally instead of pre-allocating a Certificate array from the declared count, and every length-prefixed block read from a store stream is now read through a fixed-size buffer (2 MiB) rather than allocating the declared length up front: a declared length up to the buffer size is allocated directly, while a larger length is accumulated incrementally, so a stream that does not actually carry the declared number of bytes fails with an EOFException after a bounded allocation instead of an OutOfMemoryError. Store-header salt lengths are bounds-checked before allocation. Both the BKS and UBER load paths, the per-entry certificate/key decode helpers and the sealed-key retrieval path are covered.
- LMS / HSS public key parsing (LMSPublicKeyParameters.getInstance / HSSPublicKeyParameters.getInstance, and hence X.509 SubjectPublicKeyInfo decoding for id-alg-hss-lms-hashsig keys) now enforces the RFC 8554 well-formedness rules on untrusted encodings: an unknown LMS typecode is rejected with an IOException rather than surfacing as a NullPointerException, an unknown LM-OTS typecode is rejected rather than silently producing a public key carrying null OTS parameters (which would only fail later, at verification time), the HSS level count L must lie in the range 1 to 8 inclusive (RFC 8554 sec. 6 — the key generation side already enforced this), and a byte[] / SubjectPublicKeyInfo encoding carrying trailing data after the key is rejected (sec. 5.3 requires the public key be exactly 24 + m bytes). The stream-based entry points used to read public keys embedded in HSS signature chains are unchanged apart from the typecode checks — they still leave trailing stream data in place.
- RSADigestSigner.verifySignature, when accepting the legacy DigestInfo encoding that omits the (RFC 8017 sec. 9.2-required) NULL AlgorithmIdentifier parameter, compared the recovered DigestInfo against the expected one with a loop that ran only digest-length times over the trailing region. That region begins at the OCTET STRING tag two bytes ahead of the hash, so the loop stopped two bytes short and never compared the final two bytes of the message hash: a signature whose recovered DigestInfo matched in its header and in all but the last two hash bytes was accepted as valid, weakening PKCS#1 v1.5 signature verification (and widening the search space for a Bleichenbacher-style low-public-exponent forgery). The comparison now covers the entire trailing OCTET STRING -- tag, length and every hash byte. The strict NULL-present DigestInfo path (the common case, a full constant-time array compare) and verification with org.bouncycastle.pkcs1.strict_digestinfo set (which rejects the NULL-omitted form outright) were never affected.
- BCJSSE per-connection server logging (ProvTlsServer) and property-discovery logging (PropertyUtils) were emitted at INFO; they have been moved to FINE to match the level ProvTlsClient already used for the equivalent events (issues #2235 / #1705).
- KGCMBlockCipher (DSTU 7624 GCM mode), and hence KGMac built on it, authenticated a trailing partial block (associated data or payload whose length is not a multiple of the block size) by reading a full block out of the backing buffer; the bytes past the message length are not zeroed by reset(), so the GF(2^n) MAC depended on what the instance had previously processed and a partial-block MAC was non-deterministic across reuse. The trailing partial block is now explicitly zero-padded, matching the generic GCM/GMAC construction (the true bit-length is bound by the trailing lambda field) and making the result deterministic. Block-aligned input and the first use of a fresh instance are unaffected (issue #287).
- KCCMBlockCipher (DSTU 7624 CCM mode) advanced its gamma (counter) keystream with an independent per-byte add that dropped the carry between bytes; since the counter has only its lowest byte set to 1, only the low byte of the counter state ever changed, so the keystream block repeated every 256 blocks and any message longer than 255 blocks was encrypted with a repeating keystream (a two-time pad), allowing recovery of XORed plaintext-block pairs from the ciphertext alone. The counter advance now propagates the carry across the whole block (matching the generic CCM counter and the sibling KCTR / KGCM modes), so the keystream no longer repeats. The published DSTU 7624 KAT vectors are short enough that their keystream never wrapped, so they are unaffected; only messages exceeding 255 blocks change. This is the same defect class as CVE-2025-14813 (GOST CTR). The same per-byte counter is present in bc-csharp's KCcmBlockCipher and should be corrected there too (issue #287).
- UserAttributeSubpacketInputStream allocated the subpacket body buffer (new byte[bodyLen - 1]) directly from the wire length header, guarded only by StreamUtil.findLimit(). For the BCPGInputStream used during packet parsing findLimit() returns close to the JVM heap size rather than the bytes actually available, so the guard was ineffective and a crafted User Attribute subpacket header declaring a ~2 GiB length forced a multi-gigabyte allocation before any body byte was read -- a pre-authentication memory-exhaustion denial of service against any consumer importing untrusted OpenPGP certificates (the sibling of CVE-2026-3505). The reader now rejects a body length exceeding an absolute 2 MiB cap (UserAttributeSubpacketInputStream.MAX_SUBPACKET_LEN, matching SignaturePacket.MAX_SUBPACKET_LEN and PublicKeyPacket.MAX_LEN) independently of the findLimit() hint, before allocating.
- The MLS API compared received membership and confirmation tags against the locally computed HMAC values using early-exit array comparisons, giving a byte-by-byte timing oracle on secret-keyed MACs. The three verification sites (PublicMessage.unprotect, the Group external-join constructor and Group commit handling) now use Arrays.constantTimeAreEqual, and as defense-in-depth the secret-bearing equals() implementations on the MLS Secret and KeyGeneration classes now also compare their key material in constant time (PR #2316).
- PKIXCertPathReviewer.processQcStatements() only recognised the legacy ETSI TS 101 862 / RFC 3739 QC statements (QcCompliance, QcSSCD, QcLimitValue, pkixQCSyntax-v1), so a qualified certificate carrying the modern ETSI EN 319 412-5 statements (QcType, QcRetentionPeriod, QcPDS, QcCClegislation) or pkixQCSyntax-v2 in a critical qcStatements extension was reported as having an "unknown critical extension". These statements are now recognised and surfaced as notifications (QcType additionally lists the declared esign / eseal / web type(s)), so the reviewer no longer flags such certificates. Applied to both the org.bouncycastle.pkix.jcajce and org.bouncycastle.x509 copies (issue #1239).
- An ECGOST3410-2012 key pair generated on one of the (256-bit) GOST R 34.10-2001 named curves (e.g. "GostR3410-2001-CryptoPro-A") was stamped with the legacy GOST R 34.11-94 digest OID (1.2.643.2.2.30.1) instead of the GOST R 34.11-2012-256 digest OID (id-tc26-gost3411-12-256, 1.2.643.7.1.1.2.2). The shared GOST3410ParameterSpec(String) constructor defaults those curves to the 94 digest (correct for an ECGOST3410-2001 key but wrong for a 2012 key); the 2012 key-pair generator now remaps a 94 digest to the 2012-256 digest, so the public key, private key and their encodings all report the correct OID. The native 2012 curves are unaffected (issue #611).
- KeyFactory.getInstance("RSASSA-PSS") shared the generic RSA KeyFactorySpi, so keys built from the raw RSAPublicKeySpec / RSAPrivateKeySpec / RSAPrivateCrtKeySpec were stamped with the rsaEncryption AlgorithmIdentifier (1.2.840.113549.1.1.1) rather than id-RSASSA-PSS (1.2.840.113549.1.1.10, RFC 8017 A.2.3). The resulting keys reported "RSA" from getAlgorithm() and encoded with the wrong OID, even though the equivalent KeyPairGenerator.getInstance("RSASSA-PSS") and the encoded-spec (X509EncodedKeySpec / PKCS8EncodedKeySpec) paths already produced id-RSASSA-PSS keys. The RSASSA-PSS KeyFactory now stamps id-RSASSA-PSS on keys generated from the raw RSA key specs; the plain RSA KeyFactory is unchanged (issue #1474).
- The "No CRLs found for issuer ..." exception thrown by BC's CertPathValidator (and X509RevocationChecker) when a revocation check came back empty gave callers no clue about why the lookup failed. The message now also lists the certificate's CDP URIs, the number of PKIXCRLStores / CertStores consulted, and the state of the network-fetch toggle (with a hint pointing at the property or at registering a store). When the toggle is on and every CDP URI fails, the per-URI causes are now propagated up instead of being silently swallowed. The "org.bouncycastle.x509.enableCRLDP" system property is now exposed as the Properties.X509_ENABLE_CRLDP constant (issue #1309).
- GOST3410ParametersGenerator's Procedure A'/B' inner loops resampled candidate values via `init_random.nextInt() * 2` / `init_random.nextInt() * 2 + 1`; the multiplication was evaluated in int arithmetic (wrapping modulo 232) before being widened to the surrounding `long`. The multiplications are now evaluated in `long` arithmetic (`* 2L` / `* 2L + 1`), so a large sampled value no longer wraps before the candidate is formed (issue #813).
- CertificateFactory ("BC", "X.509") returned null from generateCertificate(InputStream) / generateCRL(InputStream) for empty input or an empty PKCS#7 SignedData wrapper, contrary to the java.security.cert.CertificateFactory contract that mandates throwing CertificateException / CRLException when no certificate / CRL can be parsed (PR #459 already covered the garbage-PEM / garbage-DER cases; this fix completes the empty-input residual). The single-value methods now throw a CertificateException / CRLException naming the failure; the collection-returning generateCertificates / generateCRLs continue to return a (possibly-empty) Collection per their separate contract. Internal callers in PKIXCertPath that previously walked the multi-cert stream by looping on generateCertificate until null have been switched to a single generateCertificates call, which is the spec-compliant pattern (issue #457).
- LocalizedMessage.getEntry (both org.bouncycastle.i18n and org.bouncycastle.pkix.util copies) called ResourceBundle.getBundle(name, locale) without an override, so Java's default candidate-locale chain — which falls back to Locale.getDefault() when the requested locale has no matching properties file — would return a JVM-default-locale bundle to a caller who had explicitly requested a different locale. On a German system, SignedMailValidatorTest.testKeyUsage (and the other testKeyUsage / testExtKeyUsage cases) requesting Locale.ENGLISH thus received the German message from SignedMailValidatorMessages_de.properties and failed the literal-text assertion. Both LocalizedMessage classes now use ResourceBundle.Control.getNoFallbackControl(FORMAT_DEFAULT) so the lookup chain falls through to the base bundle (English) rather than to the JVM default when no _en file is shipped (issue #2249).
- The BC provider's ML-DSA Signature implementation resolved a public key supplied by another provider through the legacy PQC PublicKeyFactory rather than org.bouncycastle.crypto.util.PublicKeyFactory, so initVerify with a non-BC ML-DSA public key failed with an exception. The conversion now goes through the correct factory (issue #2287).
- FalconKeyPairGeneratorSpi.getNameFromParams was inconsistent: FalconParameterSpec returned an upper-cased name while NamedParameterSpec was lower-cased, leaving NamedParameterSpec inputs unable to resolve any Falcon variant. FalconParameterSpec now preserves the canonical lower-case algorithm name, so both spec types now work (issue #2194).
- ProvOcspRevocationChecker was silently ignoring OCSP response signature verification failures when an OCSP response was supplied via PKIXRevocationChecker.setOcspResponses(). The checker now raises a CertPathValidatorException when the response signature fails to validate.
- The streaming ASN.1 generators (BERSequenceGenerator, BEROctetStringGenerator, DERSequenceGenerator) wrote the tagged-object identifier as a single octet, so a tag number greater than 30 silently produced a corrupt encoding (the low five bits collided with the X.690 8.1.2.4 high-tag-number escape). The tagged header is now emitted through the same identifier encoding used by ASN1OutputStream, so high tag numbers encode correctly in both the explicit and implicit (X.690 8.14.2 / 8.14.3) forms. Output for tag numbers 0 to 30 — including all the CMS uses — is unchanged.
- The public ECJPAKECurve constructor documented that "n*h must equal the order of the curve" but performed no such check, so a user-supplied group with a wrong order or cofactor was accepted. Since computing the exact point count is impractical, the constructor now checks the implied order n*h against the Hasse bound for the field size ((q + 1 - n*h)2 <= 4q), rejecting wildly wrong n or h values; the pre-approved ECJPAKECurves groups are unaffected.
- RFC3394WrapEngine.init and RFC5649WrapEngine.init (the base engines behind AESWrap / AESWrapPad / ARIAWrap / CamelliaWrap / SEEDWrap) silently ignored a CipherParameters argument that was neither a KeyParameter nor a ParametersWithIV, leaving the engine unkeyed so the next wrap/unwrap failed later with an opaque NullPointerException. They now reject an unrecognised parameter type up front with "invalid parameter passed to <cipher> init - <class>", matching the behaviour of the other org.bouncycastle.crypto.engines block ciphers.
- X509CertificateFormatter was indenting the basicConstraints pathLenConstraint line incorrectly, dropping the 23-space prefix shared with other extension lines. The line now uses the same pad as the surrounding output (issue #2214).
- A wide audit of catch-and-rethrow sites that dropped the original cause when rewrapping as IllegalArgumentException, IllegalStateException, or IOException has been carried out across core, prov, pkix, pg, mail/jmail, mls and tls. The affected sites now chain the cause via org.bouncycastle.util.Exceptions so the full stack trace is preserved, while keeping the existing message text unchanged (issue #2239 / PR #2250).
- PGPPublicKey.getValidSeconds() returned a stale expiration time when an earlier self-signature carried a Key Expiration Time subpacket and a more recent self-signature omitted it; per RFC 4880 5.2.4.1 the latest self-signature wins, so the absence of the subpacket on the newer signature now correctly cancels the expiry and the method returns 0 (issue #1749).
- The Argon2 memory size exponent bounds check (capped by the "org.bouncycastle.argon2.max_memory_exp" property) is now applied at key-derivation time (PGPUtil.makeKeyFromPassPhrase) rather than during S2K packet parsing, so an out-of-range exponent in one ESK packet no longer makes a whole stream unparseable - decryption fails with a PGPException ("memory size exponent out of range") instead, and other ESK packets can still be attempted; the check covers both the SKESK and the secret-key decryption paths. The enforced lower bound now also matches RFC 9106 sec. 3.1, which requires the memory size m to be at least 8*p kibibytes, i.e. memorySizeExponent ≥ 3 + ceil(log2(parallelism)) = 3 + bitLen(parallelism - 1); previously only memorySizeExponent < 3 was rejected, so an Argon2 S2K with, for example, parallelism 4 and memorySizeExponent 4 (m = 16 KiB < 8*p = 32 KiB) was accepted and used at this layer. The bound now equals the floor the S2K.Argon2Params constructor already enforces for programmatically built specifiers, so the two paths agree (issue #2283 / PR #2322).
- ArmoredInputStream's base64 decoder defeated its own invalid-character check in the two-pad ("XX==") group: the two decoding-table lookups were masked to unsigned values before the "< 0" guard, so the 0xff sentinel for a non-alphabet character became 255 and the guard never fired. A final armor group such as "!!==" was decoded to a junk byte rather than rejected, while the one-pad ("XXX=") and no-pad ("XXXX") groups (and Base64Encoder) already rejected it. The mask has been removed so all three groups validate consistently.
- S/MIME signing of an attachment-only MimeMessage produced a signed body with empty content. SMIMEGenerator.makeContentBodyPart(MimeMessage) rebuilt the content body part with new DataHandler(message.getDataHandler().getDataSource()) (a workaround for a javax.mail change affecting stream-backed attachments); for an object-backed message whose content type has no object DataContentHandler (e.g. a body set via setContent(byte[], "application/octet-stream")), getDataSource() returns a synthetic DataHandlerDataSource and re-wrapping it yields a body part that writes nothing - writeTo() throws "no object DCH" and the signature is computed over empty content. The re-wrap is now applied only to a genuine DataSource; an object-backed DataHandler is carried through unchanged, so attachment-only messages sign correctly again on both javax.mail and jakarta.mail (issue #1432).
- PEMParser failed to parse a "BEGIN PRIVATE KEY" block carrying OpenSSL-legacy encryption headers (Proc-Type: 4,ENCRYPTED / DEK-Info), throwing "corrupted stream" while ASN.1-decoding the ciphertext. The PRIVATE KEY parser now honours those headers and returns a PEMEncryptedKeyPair whose decryptKeyPair() yields a PEMKeyPair holding the decrypted PKCS#8 PrivateKeyInfo (issue #1238).
- PKIXCertPathValidatorSpi (and its JDK 8+ revocation-checker-aware variant) threw a NullPointerException when validating against a TrustAnchor constructed with (caName, caPublicKey, nameConstraints) instead of an X509Certificate, because the trust anchor's certificate encoding was always validated up front. The check is now skipped when no certificate is supplied, allowing name-and-key trust anchors to validate as expected (issue #1420).
- PKCS12PfxPdu.isMacValid threw ClassCastException when the PFX used PBMAC1 (id-PBMAC1) for integrity, because JcePKCS12MacCalculatorBuilderProvider tried to parse the algorithm parameters as PKCS12PBEParams. The provider now dispatches to JcePBMac1CalculatorBuilder for id-PBMAC1, and isMacValid compares only the inner MAC digest bytes for PBMAC1 (RFC 9579 sec. 6 leaves the MacData salt and iterations unused, so producers may write arbitrary placeholder values) — PBMAC1 PFX files written by OpenSSL and BCJSSE now verify correctly.
- JcaPGPKeyConverter.getPublicKey threw "InvalidParameterSpecException: Not a supported curve" on JDK 11 when the underlying JCE provider was Sun's, because the converter unconditionally fed the X9.62 OID-encoded form to AlgorithmParameters and Sun's CurveDB couldn't resolve it. The converter now resolves the curve name first via ECNamedCurveTable.getName(...) and only falls back to the OID encoding when the provider doesn't recognise the name (issue #1230).
- CertPathBuilder could recurse without bound (StackOverflowError on small stacks) when CRL revocation was enabled and a CRL had multiple candidate signers, e.g. several trust-anchor roots sharing the issuer DN. A re-entry guard in RFC3280CertPathUtilities.processCRLF now breaks the cycle, and candidates whose path can't be built are skipped instead of aborting the whole check. As a follow-up, when the CRL carries an authorityKeyIdentifier with a keyIdentifier field, processCRLF now narrows the candidate signer set by SubjectKeyIdentifier (RFC 5280 sec. 5.2.1) — without this the wall time grew O(N^depth) across N roots sharing the issuer DN, which was reported on the issue (e.g. ~7 minutes for N=6!) (issue #2291).
- OpenSSHPrivateKeyUtil.encodePrivateKey now wraps ECDSA keys in the openssh-key-v1 envelope (matching the Ed25519 path) instead of emitting a raw RFC 5915 ECPrivateKey SEQUENCE, so the output is loadable by OpenSSH and JSCH (issue #2240).
- X500Name string parsing rejected RDNs whose attributeValue contained an unescaped '=', e.g. "CN==^_^=" or "CN=foo=bar", with "badly formatted directory string". RFC 4514 sec. 3 lists '=' (0x3D) as a valid stringchar, so only the FIRST '=' separates the attributeType from the attributeValue. IETFUtils now rejoins any subsequent '='-split tokens, matching the behaviour of javax.security.auth.x500.X500Principal (issue #2226).
- AuthorityKeyIdentifier (id-ce 35) construction and parsing now enforce the RFC 5280 sec. 4.2.1.1 constraint that authorityCertIssuer and authorityCertSerialNumber MUST both be present or both be absent. The ASN1Sequence parse path and the (byte[], GeneralNames, BigInteger), (SubjectPublicKeyInfo, GeneralNames, BigInteger) and (GeneralNames, BigInteger) public constructors all throw IllegalArgumentException when only one of the two fields is supplied (issue #2036).
- TBSCertList, TBSCertificate and AttributeCertificateInfo parsing, plus the V1/V3 TBSCertificate, V2 TBSCertList and V2 AttributeCertificateInfo generators, now enforce the RFC 5280 sec. 4.1.2.4 / 5.1.2.3 and RFC 3281 sec. 4.2.3 requirement that the issuer field contain a non-empty identifier. Empty X.500 issuer names, empty v1 GeneralNames AttCertIssuer values, and V2Form AttCertIssuer values lacking issuerName / baseCertificateID / objectDigestInfo are now rejected with an Illegal{Argument,State}Exception instead of being silently accepted. As a side fix, V2Form parsing no longer throws ArrayIndexOutOfBoundsException on an empty SEQUENCE input (issue #2010).
- JndiDANEFetcherFactory now uses DirContext.list() rather than listBindings() to enumerate _smimecert entries, so each result is delivered as a NameClassPair (string-only) instead of a Binding whose getObject() materialises a Java object from the directory's reply. The factory only ever consumed the entry's name from the binding; switching to list() preserves identical behaviour for legitimate DNS responses while removing the JNDI-deserialisation attack surface that would otherwise apply if the API were redirected at a hostile JNDI provider (issue #239).
- BcRSAContentSignerBuilder and BcRSAContentVerifierProviderBuilder unconditionally instantiated RSADigestSigner (PKCS#1 v1.5) regardless of the supplied signature algorithm OID, so when an id-RSASSA-PSS AlgorithmIdentifier was passed in the lightweight Bc* operator path produced and verified PKCS#1 v1.5 bytes — wire-incompatible with the JCE RSASSA-PSS path and rejected by external validators (e.g. EU DSS). Both builders now detect id-RSASSA-PSS and construct a PSSSigner from the RSASSAPSSparams (hashAlgorithm / mgf1 hash / saltLength / trailerField=1) so Bc-side signing and verification round-trip correctly with the JCE side and with RFC 8017 PSS implementations generally (issue #721).
- BCStyle and RFC4519Style now reject countryName (BCStyle.C / RFC4519Style.c) and, for BCStyle, jurisdictionCountry (JURISDICTION_C) attribute values whose length is not exactly 2 when constructing a new X500Name (via X500NameBuilder.addRDN or the X500Name(String) constructor). RFC 5280 sec. 4.1.2.4 / X.520 specify countryName as PrintableString (SIZE (2)) and CAB Forum Baseline Requirements 7.1.4.2.1 narrows it to a valid ISO 3166-1 alpha-2 code, so values such as "USA" now throw IllegalArgumentException at build time rather than encoding a non-spec value that downstream consumers would reject. Parsing of existing DER-encoded names containing a non-conforming country code is deliberately still permitted, so already-issued certificates in the wild remain readable (issue #2011).
- BCStyle and RFC4519Style now reject commonName (BCStyle.CN / RFC4519Style.cn) attribute values longer than 64 characters when constructing a new X500Name (via X500NameBuilder.addRDN or the X500Name(String) constructor). RFC 5280 sec. A.1 / X.520 specify commonName as DirectoryString { ub-common-name } with ub-common-name = 64, and OpenSSL / Microsoft CryptoAPI / GnuTLS / CAB Forum BR-aware validators all reject longer values. Names whose CN exceeds 64 characters now throw IllegalArgumentException at build time rather than encoding a value that downstream consumers will reject. Parsing of existing DER-encoded names containing an over-length CN is deliberately still permitted, matching the leniency split applied to countryName (issue #750).
- DefaultDigestAlgorithmIdentifierFinder.find(AlgorithmIdentifier) returned the wrong digest for the IANA-namespaced composite ML-DSA + classical signature OIDs: every entry mapped to SHA-512 regardless of the scheme's actual prehash. The mappings now reflect the per-scheme prehash that the composite SignatureSpi feeds the inner signers (the OID name suffix): SHA-256 for *_SHA256 variants, SHAKE-256 for id_MLDSA87_Ed448_SHAKE256, SHA-512 for *_SHA512 variants.
- The class-level javadoc around CMS parsers and streaming generators has been updated to explicitly describe how it treats the underlying streams passed in.
- X509CertificateImpl.hasUnsupportedCriticalExtension() reported a critical extendedKeyUsage (id-ce 37) extension as unsupported, so loading such a certificate through the BC CertificateFactory returned true where the JDK provider returned false. RFC 5280 sec. 4.2.1.12 explicitly permits extendedKeyUsage to be marked critical, and the BC X509Certificate implementation fully recognises it (getExtendedKeyUsage()); the OID has been added to the skip list in hasUnsupportedCriticalExtension() so the BC and JDK providers now agree (issue #1796).
- The BC X.509 CertificateFactory (Provider "BC", "X.509"/"X509") previously recognised only the RFC 2315 PKCS#7 SignedData ContentType OID (1.2.840.113549.1.7.2) when extracting embedded certificates and CRLs from a SignedData wrapper, so generateCertificate{s} / generateCRL{s} returned nothing (or threw "sequence wrong size for a certificate") for a GM/T 0010-2012 SM2 SignedData wrapper (ContentType 1.2.156.10197.6.1.4.2.2). Both SignedData ASN.1 structures are identical apart from the outer ContentType OID, so the factory now treats the SM2 OID equivalently and walks the embedded certificate / CRL sets the same way. New ASN.1 constants for the full GM/T 0010 SM2 content-type arc (1.2.156.10197.6.1.4.2.{1..6}) have been added to GMObjectIdentifiers (issue #1355).
- ESTService.getCSRAttributes treated a server response of 204 No Content or 404 Not Found as "no attributes available" and returned null, but did not drain the response body before letting the surrounding finally block close it. When the server attached a body to the 404 (e.g. a JSON error message), ESTResponse's underlying LimitedInputStream then threw "Stream closed before limit fully read" on close and the caller saw an opaque IOException-wrapping ESTException instead of the 404 status they could act on. The 204 / 404 branches now drain the body via Streams.drain before returning, so the close path completes cleanly and the call returns a null CSRAttributesResponse as documented (issue #781).
- JceOpenSSLPKCS8DecryptorProviderBuilder cast the PBES2 key-derivation-function parameters blind to PBKDF2Params, so an EncryptedPrivateKeyInfo whose KDF inside PBES2 was scrypt (RFC 7914, e.g. anything produced by "openssl pkcs8 -topk8 -scrypt") failed to decrypt with "DLSequence cannot be cast to PBKDF2Params". The builder now dispatches on the KDF algorithm OID: id-PBKDF2 takes the existing PBKDF2 path, id-scrypt parses the parameters as ScryptParams and derives the key via SCrypt.generate (the password is encoded as UTF-8 to match OpenSSL's raw-bytes treatment). PBKDF2-based PBES2, PKCS#5 PBES1 and PKCS#12 PBE paths are unchanged (issue #400).
- RFC3280CertPathUtilities.processCRLB2 (in both prov and pkix) emitted an opaque AnnotatedException "No match for certificate CRL issuing distribution point name to cRLIssuer CRL distribution point." when the CRL's issuingDistributionPoint did not match the cert's CRL distribution point names, with no way for an operator to tell which CRL had been returned for which DP. The message now appends both name lists, e.g. ". cert DP names: [6: http://crl3.example/foo.crl, 6: http://crl4.example/foo.crl]; CRL IDP names: [6: http://crl4.example/bar.crl]", letting the cause of the mismatch be diagnosed without re-running with extra logging. Existing assertion sites in NistCertPathTest / NistCertPathTest2 / PKITSTest were updated to use prefix-matching against the original message (issue #800).
- JceInputDecryptorProviderBuilder previously assumed the supplied AlgorithmIdentifier parameters were either an ASN1OctetString (raw IV) or GOST28147Parameters, so init() failed with "DLSequence cannot be cast to ASN1ObjectIdentifier" (via the GOST fallback) on an AES-GCM (or AES-CCM) AlgorithmIdentifier carrying GCMParameters / CCMParameters. The builder now dispatches on the algorithm OID: id-aes{128,192,256}-GCM and id-aes{128,192,256}-CCM parse the parameters as GCMParameters / CCMParameters and init the cipher via GCMParameterSpec(icvLen*8, nonce); the existing IV and GOST paths are unchanged (issue #1510).
- BCStyle and RFC4519Style now accept "DN", "DNQ" and "dnQualifier" as parser aliases for the dnQualifier attribute (OID 2.5.4.46), so new X500Name(principal.toString()) round-trips when the underlying JDK stringifies the attribute using any of those short forms (issue #1622).
- BCStyle and RFC4519Style now accept "S" as a parser alias for the stateOrProvinceName attribute (OID 2.5.4.8), in addition to the RFC 2253/4514 short form "ST". Microsoft's CertNameToStr emits "S=" for 2.5.4.8 (its documentation notes this differs from the RFC 1779 key name "ST"), so DN strings produced by Windows tooling previously failed to parse with "Unknown object id - S - passed to distinguished name". Encoding is unchanged — BC still emits the canonical "ST" symbol on output (issue #1301).
- Six S/MIME content-handler classes in the bcjmail tree (org.bouncycastle.mail.smime.handlers.{multipart_signed, PKCS7ContentHandler, pkcs7_mime, pkcs7_signature, x_pkcs7_mime, x_pkcs7_signature}) each carried a leftover "import java.awt.datatransfer.DataFlavor;" line that survived the migration to Jakarta Activation 2.x. The import was unused — every reference in the migrated code routes through jakarta.activation.ActivationDataFlavor, which in Jakarta Activation 2.x is a standalone class that no longer extends java.awt.datatransfer.DataFlavor. The stale imports nevertheless forced Android (and other awt-less JVMs) to pull a non-existent class onto the classpath at load time. The imports have been removed; the bcjmail tree now has zero java.awt references across both main and test sources, so Android consumers using bcjmail with a Jakarta Activation 2.x runtime (e.g. Eclipse Angus Activation) no longer need a DataFlavor shim. Note that the legacy bcmail tree (javax.mail / javax.activation 1.x) cannot be cleaned up the same way: legacy javax.activation.ActivationDataFlavor extends java.awt.datatransfer.DataFlavor by upstream contract and the javax.activation.DataContentHandler interface methods take DataFlavor parameters — Android users should consume bcjmail, not bcmail (issue #242).
- CMS EnvelopedData with a BSI TR-03111 ECKA-EG-X963KDF key agreement (BSIObjectIdentifiers.ecka_eg_X963kdf_SHA1/SHA224/SHA256/SHA384/SHA512/RIPEMD160) failed both encode and decode: JceKeyAgreeRecipientInfoGenerator threw "Unknown key agreement algorithm" on generate, and JceKeyAgreeRecipient's parallel branch silently fell through to a null UserKeyingMaterialSpec, producing the wrong shared secret and "checksum failed" on the AES key unwrap. The underlying agreement (ECDHBasicAgreement + KDF2BytesGenerator) is structurally identical to dhSinglePass_stdDH_*kdf_scheme, and BSI TR-03109-3 / ICAO 9303-11 — the canonical consumers of ECKA-EG-in-CMS — specify the RFC 5753 ECC-CMS-SharedInfo format for the KDF input. The six BSI ecka_eg_X963kdf_* OIDs have been added to the EC dispatch table in CMSUtils so both encode and decode route through the existing RFC 5753 KeyMaterialGenerator (issue #790).
- The package-private org.bouncycastle.pkix.ASN1PKIXNameConstraintValidator carried a near-verbatim copy of org.bouncycastle.asn1.x509.PKIXNameConstraintValidator in core. The pkix-side org.bouncycastle.pkix.PKIXNameConstraintValidator facade now delegates directly to the core class — matching the pattern already used by org.bouncycastle.jce.provider.PKIXNameConstraintValidator in prov — and the duplicate has been removed.
- SMIMESignedGenerator.generate(MimeBodyPart) producing a multipart-signed message containing a nested multipart subpart (e.g. multipart/mixed wrapping a multipart/alternative) could not be verified in-process: SMIMESigned.getSignerInfos().verify(...) threw CMSSignerDigestMismatchException "message-digest attribute value does not match calculated value" because SMIMEUtil.outputBodyPart's verify-side writer skipped the CRLF separator the signer had emitted between an inner multipart's closing boundary and the next outer boundary. The verify side delegated that separator to SMIMEUtil.outputPostamble which reads from parent.getRawInputStream() — only available once the part has been serialized to bytes — and silently emitted nothing for in-memory parts. outputPostamble now emits a single CRLF when the raw stream is unavailable, matching SMIMESignedGenerator.ContentSigner.writeBodyPart on the signing side; the postamble-preservation path for parsed-from-bytes parts is unchanged so existing inter-op verification (foreign signers that include extra postamble lines in the digest) continues to work (issue #542).
- PKIXCertPath.sortCerts — the convenience reorder used by CertificateFactory.getInstance("X.509", "BC").generateCertPath(List) when the supplied collection is not already in end-entity-to-root order — fell back to the unsorted input for certain orderings (e.g. [end-entity, root, intermediate]) where it should have produced [end-entity, intermediate, root]. The end-entity-detection loop mutated its working list while iterating: the inner "is anyone's issuer == this cert's subject?" scan walked the mutating list, so once an end-entity was removed its parent intermediate had nothing pointing to it and was misclassified as a second end-entity; and the outer index incremented past the element that had shifted down, skipping it. The fix snapshots the input as an unchanging list for the inner scan and decrements the outer index after a remove, restoring intended best-effort ordering for inputs the algorithm previously gave up on (issue #1269).
- DefaultAlgorithmNameFinder.getAlgorithmName had no mappings for the four EdEC OIDs (id_Ed25519, id_Ed448, id_X25519, id_X448), so callers got the bare OID string (e.g. "1.3.101.112") instead of the algorithm name. This was out of step with DefaultSignatureNameFinder and DefaultSignatureAlgorithmIdentifierFinder which both map the signature OIDs to their names. ED25519 / ED448 / X25519 / X448 have been added to DefaultAlgorithmNameFinder's static table (issue #2306).
- The published Maven Central jars (main, -sources, -javadoc) for every Gradle-built subproject (bcprov, bcpkix, bcutil, bcpg, bctls, bcmls, bcmail, bcjmail) now embed the project's LICENSE.md at META-INF/LICENSE.md so automated OSS compliance scanners (ScanCode, FOSSology, etc.) can recover the license terms from the artifact alone — previously the -sources.jar in particular carried no license information and was flagged as "Unlicensed" / "Unknown License" by CI scanners (issue #2303).
- ECIESKEMExtractor.extractSecret crashed with a NullPointerException ("Cannot invoke ECFieldElement.getEncoded() because getAffineXCoord() is null") when the supplied encapsulation decoded to the point at infinity — the SEC1 / X9.62 single-byte 0x00 encoding — because the subsequent hTilde.getAffineXCoord() returned null on the infinity point. The extractor now routes any infinity hTilde (whether reached directly from a 0x00 encapsulation or indirectly via a low-order ephemeral that collapses under the static-ephemeral scalar multiplication) to an all-zero implicit-rejection key of the configured key length, so a hostile encapsulation produces a key that won't decrypt the subsequent payload rather than crashing the decapsulation service.
- IETFUtils.rDNsFromString (and thus the new X500Name(String) constructor) treated each \HH escape inside a DN attributeValue as an independent Java char, so a multi-byte UTF-8 character spelled out as consecutive hex escapes — e.g. "CN=Lu\C4\8Di\C4\87" for "CN=Lučić" — produced a 7-char String (one char per byte) that was then DER-encoded as a malformed UTF8String. RFC 4514 sec. 2.4 lets any byte be escaped as \HH and RFC 5280 sec. 4.1.2.4 mandates UTF-8 for the underlying directoryString, so a \HH run is a UTF-8 byte sequence. IETFUtils.unescape now accumulates consecutive \HH escapes as bytes and decodes the run via Strings.fromUTF8ByteArray when the run ends, producing the correct Java String and the correct wire encoding. Relatedly, unescape previously dropped a backslash escape that began a hex pair but was not completed by a second hex digit — e.g. "CN=a\Cz" parsed to "az" — and the abandoned half-pair could leak into and corrupt a following valid \HH escape; since RFC 4514 sec. 2.4 defines a backslash escape as ESC followed by ESC, a special character, or a two-digit hexpair, a lone hex digit (whether followed by a non-hex character, a quote, or end of input) is now rejected with IllegalArgumentException, matching the existing rejection of an incomplete UTF-8 hex sequence such as "CN=Lu\C4" (issue #1061).
- SignerInformation.verify failed to verify a GOST signature whose signedAttributeSet was null when the SignerInformation came from CMSSignedDataParser (the parser path leaves the SignerInformation with a pre-computed resultDigest and a null content). JcaContentVerifierProviderBuilder.createRawSig built the NONE-prefixed signature algorithm name (e.g. NONEWITHECGOST3410-2012-256) and asked the JCE for a matching Signature service so it could expose a RawContentVerifier; BC registered no such service, so the verifier degraded to a plain SigVerifier, and the doVerify path fed it no bytes — returning false. The BC JCE provider now registers NONEWITHECGOST3410, NONEWITHECGOST3410-2012-256 and NONEWITHECGOST3410-2012-512 as NullDigest-backed siblings of the existing SignatureSpi classes, so the raw-verify path applies the pre-computed GOST3411 / GOST3411-2012-256 / GOST3411-2012-512 hash directly through ECGOST3410Signer.verifySignature and CMSSignedDataParser-driven direct-signature verification succeeds (issue #1501).
- ASN1UTCTime and ASN1GeneralizedTime now reject structurally malformed content on decode (non-digit or out-of-range fields, illegal lengths, missing/garbage terminators) rather than parsing it into a time object whose getDate() returns a nonsensical date or throws. ASN1UTCTime.createPrimitive / ASN1GeneralizedTime.createPrimitive validate well-formedness via the new org.bouncycastle.asn1.ASN1TimeFormat helper; legal-but-non-DER formatting (missing seconds, "+hhmm" offset, trailing-zero fraction, local-time GeneralizedTime) is still parsed leniently and the write-side DER gate (Properties.ASN1_ALLOW_NON_DER_TIME) is unchanged. Among other things this rejects a UTCTime-shaped (13-character, 2-digit-year) value smuggled inside a GeneralizedTime, as seen in CRL thisUpdate/nextUpdate fields in the wild (issues #1973, #2040, #2321).
- PKCS12KeyStoreSpi.processKeyBag and PKCS12PBMAC1KeyStoreSpi.processKeyBag threw a NullPointerException when loading a keystore containing an RFC 7292 sec. 4.2.1 keyBag (unencrypted PrivateKeyInfo) that either carried no bagAttributes or carried bagAttributes without a localKeyId — getBagAttributes() and the recovered localId were dereferenced unconditionally, unlike the sibling processShroudedKeyBag / processSecretBag which already guard both. Both keyBag handlers now skip the attribute scan when bagAttributes is absent and stash a localKeyId-less key under the "unmarked" alias, matching the shrouded-key-bag path, so such a keystore loads instead of failing on parse.
- OtherName (RFC 5280 sec. 4.2.1.6), SafeBag (RFC 7292 sec. 4.2) and SignerInfo (RFC 2315 sec. 9.2, the legacy PKCS#7 type) getInstance now validate the decoded SEQUENCE length — exactly 2 for OtherName, 2 or 3 for SafeBag, 5 to 7 for SignerInfo — and route element extraction through the typed getInstance helpers. A structurally invalid SEQUENCE (wrong element count, or an element of the wrong ASN.1 type) now fails fast with "Bad sequence size: <n>" / an IllegalArgumentException, rather than leaking an ArrayIndexOutOfBoundsException or ClassCastException out of the parse, matching the strict-parse behaviour of the neighbouring x509 / pkcs ASN.1 types.
- The OpenSSL PEM parsing path hardened its handling of malformed encryption metadata. A PEM block whose "Proc-Type: 4,ENCRYPTED" header was present but whose "DEK-Info" header was missing, or whose DEK-Info value lacked the IV component, previously leaked a NullPointerException (KeyPairParser) or NoSuchElementException out of PEMParser; both the "RSA/DSA/EC PRIVATE KEY" (KeyPairParser) and "PRIVATE KEY" (PrivateKeyParser) paths now reject such input with a PEMException ("malformed PEM data: missing or invalid DEK-Info header"). Separately, PemReader.readPemObject wrapped a malformed base64 body in a DecoderException (a RuntimeException) that escaped the method's declared IOException contract; the Base64 decode is now caught and re-thrown as an IOException with the original cause attached.
- The OpenSSL PEMParser path for the traditional "DSA PRIVATE KEY" format silently ignored the version field of the DSAPrivateKey SEQUENCE, so a key whose version was any value other than 0 parsed without complaint. The sibling RSA path already rejects an out-of-range version ("wrong version for RSA private key") and BC's own writer always emits version 0, so the DSA parser now likewise rejects a non-zero version with "wrong version for DSA private key", bringing it into line with the RSA/EC traditional-key parsers (issue #2319).
- Follow-up to CVE-2026-5588: the legacy id_alg_composite CompositeVerifier (org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder, used by X509CertificateHolder.isSignatureValid, CMS and TSP) iterated the component count from the supplied signature sequence rather than from the key, so although the earlier fix rejected an empty signature sequence, a composite signature truncated to a verifying prefix (e.g. stripped of its post-quantum or its classical component) still verified. The verifier now requires the signature to carry exactly one component for every component key, rejecting both under- and over-length composite signatures. The final-draft (IANA-OID) composite path was unaffected — it parses a fixed-length concatenation and already verifies every component.
- The XMSS and XMSS^MT public-key converters in PublicKeyFactory (the raw RFC 9802 / RFC 8391 SubjectPublicKeyInfo form, which prefixes the key material with a 4-octet parameter-set OID) leaked a RuntimeException out of the createKey / BouncyCastleProvider.getPublicKey decode path on a malformed key: a public key shorter than the 4-octet OID prefix threw ArrayIndexOutOfBoundsException, and one carrying a valid parameter-set OID but truncated root/seed material threw IllegalArgumentException ("public key has wrong size"). Both are reachable when decoding an untrusted certificate, PKCS#8 or SubjectPublicKeyInfo through the BC provider. The converters now reject such input with an IOException, matching the declared contract and the strict-parse behaviour of the neighbouring stateful-hash converters.
- BouncyCastleProvider.getPublicKey(SubjectPublicKeyInfo) and getPrivateKey(PrivateKeyInfo) — the provider's internal entry points for turning a decoded key into a JCA PublicKey / PrivateKey, reached when parsing an untrusted certificate, PKCS#12 / BCFKS keystore entry or wrapped key — could leak a RuntimeException (typically a NullPointerException from a key-info converter handed a structurally degenerate SubjectPublicKeyInfo / PrivateKeyInfo, for example one with empty or truncated key material) out of their declared IOException contract. Both methods now catch a converter's RuntimeException and re-throw it as an IOException with the original cause attached, so a malformed key surfaces as the checked exception callers already handle rather than an uncaught crash. The per-algorithm converters are unchanged; this is a defence-in-depth guard at the shared decode boundary.
- S/MIME streaming operations buffer decrypted, decompressed and signed plaintext to backing temp files. These were created with File.createTempFile, which honours the process umask and so typically leaves the files world-readable (mode 0644) on POSIX systems, allowing other local users on a shared host to read the plaintext before cleanup. The temp files created by SMIMEUtil and SMIMESignedParser are now created through Files.createTempFile, which restricts them to the owner (0600 on POSIX, owner-only ACL on Windows). The java.nio.file call is isolated in a package-private TempFileFactory, so the legacy pre-Java-7 builds - where java.nio.file is unavailable - fall back to the historical File.createTempFile via jdk1.4 / jdk1.5 source overrides (issue #2326).
- HQCEngine.decaps bounded its Fujisaki-Okamoto implicit-rejection conditional-move by the Reed-Solomon message length k (16 bytes for HQC-128, 24 for HQC-192) rather than by the full 32-byte shared secret. On a re-encryption mismatch this left the trailing bytes ss[k..31] holding K' = G(H(pk) || m' || salt), a deterministic function of the decoder output m' of the attacker-supplied ciphertext, rather than the rejection secret. That gave an adaptive attacker with a decapsulation oracle a plaintext-checking / decoding-result oracle on the underlying PKE, defeating the implicit-rejection property and breaking IND-CCA2 for HQC-128 and HQC-192 (HQC-256 was unaffected, as k == 32 there). The conditional-move now covers all 32 bytes of the shared secret, so on re-encryption failure every output byte depends only on the rejection PRF and the ciphertext; the success path is unchanged.
- OpenPGP AEAD decryption (SEIPDv2 / OpenPGP v6 and the v5 AEAD packet) skipped verification of the trailing message tag for chunk-aligned messages. RFC 9580 5.13.2 ends an AEAD message with a final authentication tag that authenticates the total plaintext length, so that truncation at a chunk boundary is detectable. The decrypting stream in BcAEADUtil / JceAEADUtil verified that final tag only when the last data chunk was shorter than chunkLength; when the plaintext was an exact multiple of chunkLength every chunk was full-size, the final tag was pre-read into the look-ahead but never passed to doFinal, and the stream returned a clean EOF without checking it. As PGPEncryptedData.verify() returns true unconditionally for AEAD, there was no backstop, so an attacker who could tamper with the ciphertext could strip trailing chunks plus the final tag (fixing up the un-authenticated outer packet length) and have the recipient accept the truncated plaintext as authentic. The final tag is now always verified before EOF is signalled, in both the Bc and Jce decryptors; surviving chunks were already individually authenticated, so this only ever affected truncation at a chunk boundary.
- The X-Wing hybrid KEM lightweight implementation (`org.bouncycastle.pqc.crypto.xwing`) shipped in the bcprov jar but was missing from the JPMS module descriptor, so module-path consumers (JDK 9+) could not reference it even though class-path consumers could. The package is now exported.
- The vestigial round-3 "Dilithium-AES" OIDs (`dilithium2_aes` / `dilithium3_aes` / `dilithium5_aes`) were registered in `PublicKeyFactory` and the `BouncyCastleProvider` key-info converter bridge but not in `PrivateKeyFactory`, so `BouncyCastleProvider.getPublicKey()` decoded such a public key to one carrying null parameters while `getPrivateKey()` rejected it. There is no lightweight Dilithium-AES parameter set (the variants were dropped in the ML-DSA migration), so these converters have been removed and both key-factory paths now consistently reject the OIDs. The remaining vestigial references have been removed as well: the never-registered `Base2_AES`/`Base3_AES`/`Base5_AES` subclasses of `DilithiumKeyFactorySpi` (which could no longer decode a key in any case), the DILITHIUM2/3/5-AES name mappings in the pkix `DefaultSignatureAlgorithmIdentifierFinder` / `DefaultDigestAlgorithmIdentifierFinder`, and the matching converter registrations in the legacy pre-1.5 `PublicKeyFactory` source trees. The OID constants themselves remain in `BCObjectIdentifiers`.
- IESEngine stream mode (IES/ECIES/DHIES with no backing block cipher) derived the encryption keystream K1 and the MAC key K2 from the key-derivation output using two different layouts: the ephemeral-sender path (standard ECIES) took K2 from a fixed prefix and K1 from the remainder, but the static-key path (the four-argument init, with no ephemeral component) took K1 first and K2 from a message-length-dependent offset behind it. Because the static-key mode reuses the same derivation input for every message, a single known-plaintext recovery of K1 (= plaintext XOR ciphertext) then also exposed the MAC key of any shorter message, letting an attacker forge a ciphertext+tag the recipient accepts from one observation. Both paths now use the fixed K2-first layout, so the MAC key is never covered by the keystream and the forgery is closed. The ephemeral ECIES wire format is unchanged; only the static-static stream-mode encoding changes (ciphertext produced by earlier versions in that specific mode will no longer decrypt). Note that static-key stream mode remains deterministic - the keystream repeats across messages under one key pair (a many-time pad) - so it is unsuitable for encrypting more than one message; callers needing confidentiality should use the ephemeral sender-key (standard ECIES) mode, as now noted in the IESEngine javadoc.
- SignedMailValidator used the CMS signingTime signed attribute as the certificate-path validation date, and a signer-supplied signingTime took precedence over any date set on the caller's PKIXParameters. Because signingTime is asserted by the signer and is unauthenticated in the absence of a trusted timestamp, certificate expiry and revocation were evaluated at a signer-chosen instant: a message back-dated to before the signing certificate's expiry or revocation would validate as if the certificate were still good (a revocation dated after the asserted time is only a notification, not an error). A date explicitly set on the supplied PKIXParameters now takes precedence over signingTime, so a caller can pin a trusted validation instant (e.g. the current time) and have a back-dated signature made with a since-expired or since-revoked key rejected; with no date set the behaviour is unchanged (the chain is validated as of the signing time, so legitimately old signatures still verify). The security note has been added to the SignedMailValidator constructor javadoc.
- The PKIXRevocationChecker OCSP path accepted a stapled OCSP response (supplied via PKIXRevocationChecker.setOcspResponses) that was validly signed but not bound to the certificate being checked. When no SingleResponse in the response matched the certificate's CertID, the checker fell through and returned success, treating the certificate as not revoked. An attacker holding a revoked certificate could therefore staple an unrelated "good" response from the same issuer (for example one covering a different serial number) and pass revocation checking. ProvOcspRevocationChecker now fails over when no SingleResponse matches the certificate's CertID, so CRL fallback runs instead of the response being silently accepted, matching the binding the network-fetch path already enforces via OcspCache.
- The MLS wire decoder (MLSInputStream) allocated the buffer for an opaque field directly from the attacker-declared Varint length - up to 0x3FFFFFFF (~1 GiB) - before checking that the input held that many bytes. Because opaque fields appear in the first bytes of unauthenticated structures (PublicMessage, KeyPackage, Welcome, PrivateMessage), a few-byte message could force a ~1 GiB heap allocation prior to any signature or MAC verification, and a handful of concurrent messages could exhaust the heap. The declared length is now validated against the bytes actually remaining in the input before the buffer is allocated (matching the existing check in slice()), so an over-long length is rejected with an IOException rather than driving a large allocation.
- LMS/HSS (RFC 8554 / NIST SP 800-208) signature parsing leaked a NullPointerException out of its declared IOException contract when the attacker-supplied signature carried an LM-OTS or LMS parameter-set type code outside the registered table. LMOtsSignature.getInstance and LMSSignature.getInstance looked the type code up (a Map.get that returns null for an unknown code) and immediately dereferenced the result to size the C / y / path buffers. Because LMSPublicKeyParameters.generateLMSContext and HSSPublicKeyParameters.generateLMSContext - the public verify-prep reached from the JCA Signature.verify path and the lightweight LMS/HSS verify - catch only IOException, the NullPointerException propagated out of verify, a remote denial-of-service reachable when verifying a malformed LMS/HSS signature (for example one carried in a certificate). Both signature parse sites now reject an unknown type code with an IOException ("unknown LM-OTS type code" / "unknown LMS type code"), matching the public-key parse (LMSPublicKeyParameters.getInstance), which already did so; the XMSS / XMSS^MT public-key OID lookups in PublicKeyFactory were likewise already guarded.
- Several lightweight PQC signature verifiers threw an unchecked exception instead of returning false when handed a malformed or truncated signature. FalconSigner.verifySignature read the signature header byte and computed the nonce/signature split with no length check (an empty signature threw ArrayIndexOutOfBoundsException, a sub-nonce-length one a NegativeArraySizeException); MayoSigner, SnovaSigner and QRUOVSigner indexed the fixed-size signature - and, for QR-UOV, copied it into a parameter-set-sized buffer - before validating its length, throwing ArrayIndexOutOfBoundsException on a short input; and the stateful XMSSSigner, XMSSMTSigner, LMSSigner and HSSSigner let the signature-decode exception (ArrayIndexOutOfBoundsException / IllegalArgumentException / IllegalStateException) escape verifySignature. All now reject a malformed signature by returning false - matching MLDSASigner, HawkSigner, FaestSigner and the SLH-DSA / UOV / HAETAE / MQOM verifiers, which already guarded - closing a denial-of-service reachable wherever an attacker-supplied PQC signature is verified (for example a signature carried on a certificate). The fixed-size schemes reject before any indexing; the stateful verifiers catch the decode failure.
- PQC public-key and private-key parameter classes that decode a key from a raw byte[] did not validate the encoding length against the parameter set, so a too-short or wrong-length encoding was accepted and the offset computed from the parameter set then overran it, raising an ArrayIndexOutOfBoundsException out of a later crypto operation instead of a clean rejection at decode. For the signature schemes this crashed signature verification, reachable whenever verification uses an attacker-supplied public key - most directly a malformed ML-DSA or Falcon issuer certificate exercised during certification-path validation (a denial of service). MLDSAPublicKeyParameters (both the org.bouncycastle.crypto.params class and the deprecated org.bouncycastle.pqc.crypto.mldsa copy reached by the certificate / KeyFactory decode path) accepted any encoding longer than 32 bytes, splitting off a 1-byte t1 that Packing.unpackPublicKey then indexed past; FalconPublicKeyParameters stored H with no length check at all. Both now reject a malformed length at construction with an IllegalArgumentException, matching MLKEMPublicKeyParameters / SLHDSAPublicKeyParameters which already validated. The same decode-time length check has been added to the remaining PQC public-key parameter classes that lacked it - the signature schemes MAYO, SNOVA, QR-UOV, HAWK, HAETAE, SQIsign and the legacy SPHINCS-256, and the KEMs FrodoKEM, HQC, NTRU, NTRU+, SNTRUPrime, NTRU-LPRime, SABER and X-Wing, plus the matching single-fixed-length private-key constructors - so a malformed-length PQC key is rejected on decode rather than crashing a later encapsulation, decapsulation or verification. FalconSigner.verifySignature additionally rejects an over-short signature instead of throwing. Classic McEliece needed the check in two independent places: the now-deprecated legacy pqc.crypto.cmce classes, and the separate ISO/IEC 18033-2:2006/Amd 2:2026-standardised crypto.params / crypto.kems.cmce implementation, which carried no validation at all. NewHope's public-key class is a dual-role carrier for the two RLWE exchange messages, so its length bound is instead enforced where each role is known (NewHope.sharedA / sharedB) rather than in the constructor.
- The CMS container parse path was hardened so that a structurally malformed or absent inner content surfaces as the declared CMSException rather than a raw RuntimeException. The byte[] / InputStream entry points route the outer ContentInfo through CMSUtils.readContentInfo, but the inner body was re-interpreted unguarded: CMSAuthEnvelopedData and CMSAuthenticatedData re-parsed it with AuthEnvelopedData.getInstance / AuthenticatedData.getInstance (leaking IllegalArgumentException on a non-SEQUENCE or otherwise invalid inner element), and CMSCompressedData (getContent, getContentStream) and CMSDigestedData (getDigestedContent, verify) reached the encapsulated content through a cast to ASN1OctetString (leaking ClassCastException, or — in CMSDigestedData.getDigestedContent — reporting the misleading "exception reading digested stream."). These are reachable when parsing untrusted RFC 5083 AuthEnveloped, RFC 5652 sec. 9 Authenticated (MACed), or compressed / digested CMS, so a caller that catches only the documented CMSException took an uncaught exception. The ASN1OctetString casts are now ASN1OctetString.getInstance calls, and every guarded inner getInstance across CMSSignedData, CMSEnvelopedData, CMSCompressedData, CMSDigestedData, CMSAuthEnvelopedData and CMSAuthenticatedData now reports a malformed inner element as CMSException("Malformed content.") and an absent one as CMSException("Missing content."), each carrying the original exception as the cause. CMSCompressedData.getContentStream is now declared to throw CMSException, matching its sibling content accessors. CMSEncryptedData(ContentInfo) is not declared to throw CMSException and is documented as the one container that still surfaces a raw IllegalArgumentException on malformed content (its only untrusted-bytes reach, PKCS12SafeBagFactory, already declares it). Well-formed messages are unaffected.
- The OpenPGP signature subpackets Features, TrustSignature, SignatureTarget, RevocationKey and RevocationReason read a fixed offset of their body from their accessors (for example Features.getFeatures() reads the first octet, TrustSignature.getTrustAmount() the second) but did not validate the body length when parsed. SignatureSubpacketInputStream accepts a subpacket whose length field is 1 (just the type octet, leaving an empty body), so a malicious key or signature carrying a truncated such subpacket decoded cleanly and then threw an ArrayIndexOutOfBoundsException later when an application read the subpacket (for example checking the Features of a received key's self-signature). These five subpackets now validate their body length in the wire-parse constructor, rejecting a truncated subpacket with an IllegalArgumentException at decode time (surfaced by the parser as a MalformedPacketException) rather than the deferred ArrayIndexOutOfBoundsException, matching the existing IssuerFingerprint and IntendedRecipientFingerprint behaviour. Legitimate subpackets, which always carry correctly-sized bodies, are unaffected, and the value-based constructors are unchanged.
- ElGamalEngine performed no validation of the two ciphertext components on decryption: the first component gamma was raised to the (static, reused) private-key-derived exponent (p-1-x) with no check that it lies in the valid range, so a peer could submit a small-order or out-of-range element (gamma = 1, p-1, p, ...) and, given a chosen-ciphertext decryption oracle against a reused decryption key, mount a small-subgroup confinement / key-recovery attack -- weaker even than DHBasicAgreement, which already range-checks its peer value. processBlock now rejects gamma or phi outside [2, p-2] with an IllegalArgumentException ("ElGamal ciphertext element is weak") before the modular exponentiation, mirroring the peer-value validation added to DHAgreement and the existing DHBasicAgreement check. Legitimate ciphertexts are unaffected (a well-formed gamma = g^k mod p always lies in (1, p-1)); the encryption path is unchanged.
- EthereumIESEngine, a standalone copy of IESEngine carrying the Ethereum RLPx tweaks (it is not a subclass, so it did not inherit the IESEngine fix above), had the same stream-mode key-derivation flaw: in the static-key path (the four-argument init, with no ephemeral component) it placed the keystream K1 first and the MAC key K2 at a message-length-dependent offset behind it, so a single known-plaintext recovery of K1 exposed the MAC key of any shorter message and let an attacker forge a ciphertext+tag the recipient accepts from one observation. It now uses the same fixed K2-first layout regardless of whether an ephemeral component is present, closing the forgery; the keystream is hashed into the MAC key with SHA-256 as before. The ephemeral-component wire format is unchanged; only the static-static stream-mode encoding changes (ciphertext produced by earlier versions in that specific mode will no longer decrypt). As with IESEngine, static-key stream mode remains a deterministic many-time pad unsuitable for more than one message under a given key pair, as now noted in the EthereumIESEngine javadoc.
- PKIXCertPathReviewer.getPolicyTree() always returned null, even after successfully validating a certificate path whose certificates carry the certificatePolicies extension. The RFC 3280 sec. 6.1 policy processing in checkPolicy() built the valid policy tree in a local variable and discarded it at the end without ever assigning it to the policyTree field the getter returns (the field was left at the null set in init()), contradicting the method's documented contract and diverging from the JDK CertPathValidator, whose PKIXCertPathValidatorResult.getPolicyTree() exposes the tree for such a path. Both reviewer copies (org.bouncycastle.pkix.jcajce and org.bouncycastle.x509) now store the computed tree to the policyTree field, so getPolicyTree() returns the populated valid-policy-tree on a successful validation (and null only when no valid policy tree exists, as documented).
- The keybox (GnuPG .kbx) X509 certificate-blob parser (CertificateBlob.parseContent) read the u32 sizeOfReservedSpace length field and handed it straight to KeyBoxByteBuffer.bN, omitting the explicit "sizeOfReservedSpace exceeds content remaining in buffer" bounds check that its near-identical sibling PublicKeyRingBlob.parseContent already applies -- the guard had been added to one copy of the duplicated parse routine but not the other. A crafted keybox declaring an oversized reserved-space length therefore failed deep inside bN with a generic message rather than the descriptive IllegalStateException the OpenPGP blob raises. KeyBoxByteBuffer.bN's own size<0 / size>remaining guards already prevented an oversized allocation, so this completes the bounds check across the CertificateBlob / PublicKeyRingBlob pair for parser-robustness parity.
- KeyBoxByteBuffer.u32(), the keybox (GnuPG .kbx) parser's unsigned-32 reader, assembled the four bytes in int arithmetic and then widened the int to long, so a 32-bit field with bit 31 set was sign-extended to a negative long (0xFFFFFFFF was read as -1 rather than 4294967295). This gave the length / offset / size fields incorrect values above 2^31, silently defeated the "> remaining()" length guards in CertificateBlob.parseContent and PublicKeyRingBlob.parseContent for the upper half of the u32 range (an oversized length slipped past the guard down to KeyBoxByteBuffer.bN, which still rejected it, so no over-allocation occurred), and made the blob timestamp accessors (getRecheckAfter / getNewestTimestamp / getBlobCreatedAt and FirstBlob.getFileCreatedAt / getLastMaintenanceRun) return negative for dates beyond 2038. u32() now masks the assembled value to its unsigned 32-bit range, so the length guards cover the whole range and the timestamps stay positive. Values below 2^31 (every keybox seen in practice) are unchanged.
- The keybox (GnuPG .kbx) key-blob parsers (CertificateBlob.parseContent and PublicKeyRingBlob.parseContent) read a u16 user-ID count and, for each entry, copied a slice of attacker-controlled length out of the blob via KeyBoxByteBuffer.rangeOf. Each slice was bounded by the buffer size individually but not collectively, so a crafted blob declaring up to 65535 user-ID entries that each point at (almost) the whole blob could force retention of roughly bufferSize^2 bytes -- a ~150 KiB keybox driving multi-gigabyte allocation, a memory-exhaustion denial of service reachable on untrusted keybox input (the blob integrity digest is an unkeyed checksum an attacker can recompute). The cumulative user-ID data is now bounded by the blob's declared length -- which a well-formed keybox, whose user IDs are stored once within the blob, always satisfies -- and the parse aborts with an IllegalStateException ("userID data exceeds blob length") once the total exceeds it. Applied to both key-blob parsers.
- MessageDigestUtils.getDigestName (org.bouncycastle.jcajce.util) mapped the RIPEMD-256 digest OID (TeleTrusTObjectIdentifiers.ripemd256, 1.3.36.3.2.3) to the name "RIPEMD-128" instead of "RIPEMD-256", a copy/paste error in the static OID table dating to 2015. Because getDigestName feeds digest creation in the operator layer (OperatorHelper.createMessageDigest), a certificate, CMS SignerInfo or OCSP response whose digest algorithm was RIPEMD-256 was either hashed with the 16-byte RIPEMD-128 digest (wrong digest, so signature verification false-rejects) or refused outright with NoSuchAlgorithmException, depending on whether the calling path stripped the hyphen from the returned name. The OID now maps to "RIPEMD-256"; the sibling JcaJceUtils.getDigestAlgName table was already correct. Every consequence was fail-closed (no false-accept).
- The OpenSSL key readers (org.bouncycastle.openssl) leaked unchecked exceptions out of parse methods that declare only IOException, the same parser-robustness class as the X509CertificateHolder / X509CRLHolder and PKCS#12 keystore hardening above. (1) PEMParser's PublicKeyParser passed a malformed "PUBLIC KEY" body straight to SubjectPublicKeyInfo.getInstance with no try/catch, so a body decoding to the wrong ASN.1 type leaked an IllegalStateException ("unexpected object") or IllegalArgumentException ("failed to construct sequence") out of readObject() -- every other per-type parser in the file already wraps its decode in a PEMException, the structurally identical RSAPublicKeyParser most directly. (2) PEMParser's KeyPairParser ("RSA/DSA/EC PRIVATE KEY") decoded a legacy Proc-Type/DEK-Info IV with Hex.decode, which throws a DecoderException -- a RuntimeException that is not an IllegalArgumentException -- on a non-hex IV; the surrounding catch handled only IOException and IllegalArgumentException, so a well-formed-but-non-hex IV escaped readObject() (the earlier release note covers the separate missing-IV and malformed-base64-body cases; the "PRIVATE KEY" PrivateKeyParser path already caught this). (3) JcaPrivateKeyReader.readDER guarded the outer DER shape but then called PrivateKeyInfo.getInstance / RSAPrivateKey.getInstance / new PKCS8EncryptedPrivateKeyInfo unwrapped, so malformed inner content leaked an IllegalArgumentException ("illegal object in getInstance") or NoSuchElementException out of the public readKey(...) methods. All three sites now wrap the decode and re-throw a PEMException; the structurally-unwrapped X509AttributeCertificateParser (already safe, converting malformed input to a CertIOException) was wrapped for consistency. Well-formed PEM/DER keys are unaffected. The same per-type PEM parser table and key reader in bc-csharp should be corrected too.
- PKCS12KeyStoreSpi.engineLoad and PKCS12PBMAC1KeyStoreSpi.engineLoad (the BC provider's "PKCS12" / "PKCS12-PBMAC1" KeyStore.load implementations) leaked a RuntimeException out of their declared IOException contract when handed a malformed keystore. The top-level safe-contents parse loop was already guarded, but the MAC-data block sitting outside it was not: a corrupted MAC iteration count surfaced as IllegalStateException ("negative iteration count found" / "iteration count ... greater than ...") from PKCS12Util.validateIterationCount, and a MAC whose authenticated-safe content was not an OCTET STRING surfaced as IllegalArgumentException ("illegal object in getInstance: ...") from PKCS12Util.getContentOctets. Both are reachable when loading an untrusted .p12. The MAC-parameter parse is now performed under the same guard as the MAC computation, so a malformed keystore fails with an IOException (original cause attached) rather than an uncaught exception; the intentional NullPointerException for a missing password where one is required is unchanged. Found by mutational fuzzing of KeyStore.load.
- CMSSignedData's parsing constructors (the byte[], InputStream and ContentInfo forms, and the shared CMSUtils.readContentInfo used by the other CMS container types) leaked a RuntimeException out of their declared CMSException contract on malformed input: an inner tag of the wrong class surfaced as IllegalStateException ("Expected CONTEXT tag but found APPLICATION", "unexpected implicit primitive encoding") from the ASN.1 layer, which the readContentInfo and CMSSignedData.getSignedData catch blocks (catching only IOException, ClassCastException and IllegalArgumentException) let through. Both catch sites now catch RuntimeException and re-throw it as CMSException ("Malformed content.", original cause attached), matching the declared contract and the CMSAuthEnvelopedData hardening of github #2133. Found by mutational fuzzing of the CMSSignedData(byte[]) constructor.
- The X509CRLHolder(byte[]) and X509CRLHolder(InputStream) constructors (org.bouncycastle.cert), which declare throws IOException, could instead leak an unchecked IllegalArgumentException on a malformed CRL. To decide whether a CRL is indirect, construction eagerly parses the issuingDistributionPoint extension value (via Extension.getParsedValue), and a structurally valid CertificateList carrying a non-DER issuingDistributionPoint extnValue made that decode throw an IllegalArgumentException ("can't convert extension: ...") that escaped the declared IOException contract, so a caller catching only IOException crashed on a hostile CRL. The eager issuingDistributionPoint parse is now guarded and a malformed extension is reported as a CertIOException (a subclass of IOException); the X509CRLHolder(CertificateList) constructor, which is handed an already-parsed structure, continues to surface the malformed extension as the unchecked IllegalArgumentException it always has. Well-formed CRLs, including indirect CRLs carrying a valid issuingDistributionPoint, are unaffected. (X509CertificateHolder did not share this leak, as it does not eagerly parse an extension value during construction.)
- The PKCS#12 password-based key derivation in the pkix operator and OpenSSL PKCS#8 layer ran with an unbounded, wire-supplied iteration count, where the keystore path (KeyStore.getInstance("PKCS12")) and the sibling PBES2 / scrypt / PBMAC1 paths already capped it. The count is carried in the PKCS12PBEParams of an attacker-supplied AlgorithmIdentifier and was fed straight into the KDF by five code paths: PKCS12PBEUtils.createCipherParameters and createMacCalculator (org.bouncycastle.pkcs.bc), the pkcs-12PbeIds branch of JcePKCSPBEInputDecryptorProviderBuilder and the legacy PKCS#12 branch of JcePKCS12MacCalculatorBuilderProvider (org.bouncycastle.pkcs.jcajce), and the isPKCS12 branch of JceOpenSSLPKCS8DecryptorProviderBuilder (org.bouncycastle.openssl.jcajce). Decrypting an attacker-supplied pbeWithSHAAnd*-encrypted PKCS#8 key or PKCS#12 bag (PKCS8EncryptedPrivateKeyInfo.decryptPrivateKeyInfo / a PKCS12PfxPdu safe bag), or verifying an attacker-supplied PKCS#12 integrity MAC (the MAC key is derived before the MAC can be checked, so the cost is incurred pre-authentication), therefore ran the derivation for as long as the count demanded - roughly 30 minutes of CPU per call at the 2^31-1 ceiling - a CPU denial of service. The lightweight cipher / MAC and the JCE MAC paths now bound the count through PKCS12Util.validateIterationCount (the org.bouncycastle.pkcs12.max_it_count security property, default 5,000,000, as the keystore path already did), and the JCE and OpenSSL decryptor builders bound it with the same org.bouncycastle.pbe.max_iteration_count check (default 10,000,000) their PBES2 / PBKDF2 branch already used; a count over the cap, negative, or 2^31 or larger is now rejected cleanly rather than run (the lightweight path previously truncated such a count with intValue(), silently producing a weak zero-round derivation). Normally-written PKCS#12 / PKCS#8 files, whose iteration counts are a few thousand, are unaffected.
- TimeStampResp and TimeStampReq (org.bouncycastle.asn1.tsp), the RFC 3161 timestamp response/request ASN.1 types, leaked an unchecked RuntimeException on a malformed top-level SEQUENCE instead of the IllegalArgumentException their getInstance(...) contract implies. TimeStampResp's private constructor read its mandatory status field via Enumeration.nextElement() with no hasMoreElements() guard (the optional timeStampToken field was already guarded this way), so an empty SEQUENCE threw NoSuchElementException; TimeStampReq's private constructor read its two mandatory leading fields (version, messageImprint) via seq.getObjectAt(0) / getObjectAt(1) with no check that the sequence held at least two elements (the optional trailing fields were already bounds-checked against the captured element count), so a zero- or one-element SEQUENCE threw ArrayIndexOutOfBoundsException. Both classes are reached from pkix's public entry points TimeStampResponse(byte[] / InputStream) and TimeStampRequest(byte[] / InputStream) -- the standard way a client parses a TSA reply or a TSA server ingests a client's request -- whose catch blocks are narrowed to IllegalArgumentException / ClassCastException, so the escaping RuntimeException violated the constructors' declared throws IOException, TSPException / throws IOException contracts. Both private constructors now reject a too-short SEQUENCE up front with a diagnosable IllegalArgumentException; well-formed timestamp requests and responses are unaffected.
- During attribute-certificate path validation (PKIXAttrCertPathValidatorSpi, the "RFC3281" CertPathValidator), the attribute certificate's own signature was never cryptographically verified - RFC3281CertPathUtilities checked validity period, issuer, extensions and the issuer's certificate path, but not the signature over the AC itself, so a validation could succeed for an attribute certificate whose content had been tampered with or that was never signed by the named AC issuer. RFC3281CertPathUtilities now verifies the attribute certificate's signature against the AC issuer's public key (via the new CertPathValidatorUtilities.verifyX509AttributeCertificate, honouring the configured signature provider) and fails validation with a CertPathValidatorException when it does not verify.
- The NTRU+ KEM could fail decapsulation intermittently: a multiply-add step in the polynomial arithmetic used an unreduced value where R mod q was required, so for some (valid) key/ciphertext pairs the recovered shared secret disagreed with the encapsulated one. The reduction has been corrected and decapsulation now round-trips for all generated keys.
- org.bouncycastle.crypto.agreement.DHAgreement.calculateAgreement did not validate the peer's ephemeral public value ("message") before raising it to the local private key, allowing a peer to submit a small-order or out-of-range element (a small-subgroup confinement attack, which with a reused private key can leak it via CRT). The ephemeral value is now subjected to the same DH public-value range and subgroup checks as the peer's static key, and null arguments are rejected up front.
- Provider exception throws of UnrecoverableKeyException, IllegalBlockSizeException and BadPaddingException - JCA/JCE exception classes with no (String, Throwable) constructor - discarded the underlying cause, leaving only its message text folded into the new exception's string. Throw sites across the keystore SPIs and the KEM/cipher SPIs now attach the original exception as the cause (via the new org.bouncycastle.jcajce.provider.util.SecurityExceptions factories, which use initCause), so callers can walk getCause() for diagnosis; exception types and message texts are unchanged (issue #2309).
- A batch of fixed-arity ASN.1 SEQUENCE types leaked ArrayIndexOutOfBoundsException from getInstance(...) when handed a SEQUENCE with fewer elements than the type's mandatory minimum, instead of the IllegalArgumentException the getInstance contract implies. Lower-bound size checks with diagnosable "bad sequence size" messages were added to the decode constructors of the OCSP types RevokedInfo, SingleResponse, Signature, ResponseBytes and CertID (org.bouncycastle.asn1.ocsp), the CMS types Attribute, CompressedData, DigestedData, KeyTransRecipientInfo, OtherRevocationInfoFormat, RecipientEncryptedKey, OtherRecipientInfo, IssuerAndSerialNumber and OriginatorPublicKey (org.bouncycastle.asn1.cms), the CMP/CRMF types CertStatus, PBMParameter, CAKeyUpdAnnContent, PKMACValue, CertId, ProtectedPart, AttributeTypeAndValue and POPOSigningKeyInput (org.bouncycastle.asn1.cmp / .crmf), and PbkdMacIntegrityCheck (org.bouncycastle.asn1.bc). This complements the OtherName/SafeBag/SignerInfo hardening elsewhere in this release; well-formed structures are unaffected.
- The DSTU4145 Signature implementation threw a NullPointerException from initSign when handed a private key it did not recognise; it now fails with an InvalidKeyException identifying the problem, matching the initVerify path.
- Parsing an OpenPGP secret-key packet whose string-to-key usage octet named an unknown inner S2K type surfaced an unchecked UnsupportedPacketVersionException from SecretKeyPacket; it is now reported as a MalformedPacketException (an IOException subclass), so stream-parsing callers catching IOException see a malformed packet rather than an unchecked crash.
- The CRMF OptionalValidity type (org.bouncycastle.asn1.crmf) accepted an empty SEQUENCE on decode even though RFC 4211 requires at least one of notBefore/notAfter to be present - a rule its programmatic constructor already enforced. getInstance of an empty OptionalValidity now throws an IllegalArgumentException.
- A TLS server or client certificate carrying a malformed tls-features (RFC 7633) extension - one whose extension value is not a SEQUENCE - caused a ClassCastException during the BC TLS handshake. The malformed extension is now rejected with a fatal bad_certificate alert per the TLS protocol.
- DeltaCertificateRequestAttributeValue.getInstance (org.bouncycastle.asn1.x509) returned null for every input, making the delta-certificate-request attribute unreadable through the standard factory; it now decodes the attribute value properly, and an empty DeltaCertificateRequest SEQUENCE is rejected with a diagnosable IllegalArgumentException rather than an ArrayIndexOutOfBoundsException.
- DANEEntry.isValidCertificate (org.bouncycastle.cert.dane) contained an always-true logical-OR test, so entries with any certificate-usage octet were accepted; the check now enforces the RFC 6698/8162 certificate-usage range 0..3.
- TimeStampToken (org.bouncycastle.tsp) leaked ArrayIndexOutOfBoundsException for a token whose ESS signing-certificate attribute carried an empty certs SEQUENCE or an empty attribute-value SET, and ERSEvidenceRecord (org.bouncycastle.tsp.ers) did the same for an empty ArchiveTimeStampSequence or an empty chain; all four cases now fail with a diagnosable TSPException / ERSException, matching the classes' declared contracts.
- SSHBuffer (org.bouncycastle.crypto.util), used by the OpenSSH key parsers, treated a length prefix with bit 31 set as a large positive value, producing confusing failures downstream; block and big-num reads now reject a negative uint32 length prefix up front with a diagnosable exception.
- Parsing a malformed HTTP authentication challenge in an EST response (org.bouncycastle.est) could throw a StringIndexOutOfBoundsException from the challenge splitter; the parser now handles truncated and delimiter-less challenges and reports them cleanly.
- On the CMS AuthEnvelopedData generate side the content-encryption AlgorithmParameters were instantiated from the AES base-cipher name rather than the content-encryption OID, so AES-GCM content emitted a bare IV OCTET STRING where RFC 5084 requires GCMParameters (the CCM and ChaCha20-Poly1305 paths were similarly name-driven). The org.bouncycastle.cms.jcajce layer now resolves the parameters by OID, producing the RFC 5084 GCMParameters / CCMParameters encodings; the decode side already accepted both forms, so interop with BC's own earlier output is preserved.

### 2.1.3 Additional Features and Functionality

- KCCMBlockCipher (DSTU 7624 CCM mode) now accepts associated data whose length is not a multiple of the underlying block size and a nonce shorter than the block size, instead of throwing "padding not supported" or mis-constructing the MAC. init() zero-extends a short nonce to the block size, and processAssociatedText zero-pads the trailing partial associated-data block into the CBC-MAC. Multi-block associated data whose length is a multiple of the block size (the only variable-length case the previous code accepted) authenticates exactly as before (github PR #2350).
- As announced in the 1.84 release notes, the JCE wrappers for the pre-standardisation round-3 algorithms Dilithium, SPHINCS+ and Kyber have been removed: the BC provider no longer registers the "Dilithium" and "SPHINCSPlus" algorithm families or the SubjectPublicKeyInfo/PrivateKeyInfo key-info converters for their OIDs, and the BCPQC provider no longer registers "Dilithium", "SPHINCSPlus" or "Kyber" (which was just ML-KEM). The algorithm implementations themselves have not been deleted and remain accessible via the low-level org.bouncycastle.pqc.crypto APIs; they will be deleted in a later release. Applications should move to the standardised forms - ML-DSA, SLH-DSA and ML-KEM.
- The constants class org.bouncycastle.iana.AEADAlgorithm has been removed. It was added for draft-zauner-tls-aes-ocb (which expired without adoption) and has never been referenced by any BC code; the IANA AEAD algorithm-number registry it mirrored is unrelated to the org.bouncycastle.asn1.iana OID classes, which are unaffected.
- The IANA OID class org.bouncycastle.asn1.iana.IANAObjectIdentifiers has moved from the bcutil module to bcprov: it now lives in the core source tree (published in the bcprov jar and exported by the org.bouncycastle.provider module), and the previously separate internal org.bouncycastle.internal.asn1.iana copy used by core/prov has been removed so there is a single definition. The public class name is unchanged, so class-path users are unaffected. A JPMS (module-path) consumer that read org.bouncycastle.asn1.iana solely through "requires org.bouncycastle.util" must now add "requires org.bouncycastle.provider" (bcutil already requires bcprov, so the module is present on the path); OSGi consumers see the package exported by the bcprov bundle rather than bcutil (issue #2176).
- The SP 800-208 XMSS / XMSS^MT parameter sets (SHA-256/192, SHAKE256/256, SHAKE256/192) are now usable through the JCA/JCE. New tree-digest selector constants (XMSSParameterSpec / XMSSMTParameterSpec .SHA256_192, .SHAKE256_256, .SHAKE256_192) and the corresponding named parameter-set constants (e.g. XMSSParameterSpec.SHA2_10_192 / .SHAKE256_10_256 / .SHAKE256_10_192 and the XMSSMT_* equivalents) let a KeyPairGenerator obtained from the BCPQC provider generate these sets, which previously could only be built through the lightweight API. The generated keys encode in the RFC 9802 form (id-alg-xmss-hashsig / id-alg-xmssmt-hashsig) and round-trip through the BCPQC KeyFactory; getTreeDigest() reports the specific variant (it now accounts for the security parameter n, so SHA-256/192 is distinguished from SHA-256/256 and SHAKE256/192 from SHAKE256/256, which share a tree-digest OID). The lightweight org.bouncycastle.pqc.crypto.xmss.XMSSParameters / XMSSMTParameters constructors taking an explicit n are now public so callers can build these sets directly. Requesting an unknown tree digest from the XMSS / XMSS^MT KeyPairGenerator now fails with InvalidAlgorithmParameterException rather than a later NullPointerException (issue #2176).
- The tree-digest-named XMSS / XMSS^MT Signature algorithms (XMSS-SHA256, XMSS-SHAKE256, XMSSMT-SHA256, ... obtained from the BCPQC provider, and their proprietary OID aliases) now reject a key whose tree hash function does not match the named family, throwing InvalidKeyException from initSign / initVerify rather than silently signing or verifying with the key's own tree digest. The SP 800-208 SHAKE256/256 and SHAKE256/192 sets are treated as part of the SHAKE256 family (they share the id-shake256-len tree-digest OID) and SHA-256/192 as part of the SHA-256 family, so those keys are accepted by the SHAKE256 / SHA256 named signers. The generic "XMSS" / "XMSSMT" signers (the RFC 9802 id-alg-xmss-hashsig / id-alg-xmssmt-hashsig aliases) remain key-driven and accept any key, and the "<digest>withXMSS-..." pre-hash signers are unaffected because their leading digest names the message pre-hash, which is independent of the key's tree digest (issue #2176).
- ARIA-GCM/CCM and SM4-GCM/CCM can now be used as CMS content-encryption algorithms for AuthEnvelopedData. Previously only AES-GCM/CCM (and ChaCha20-Poly1305) were recognised as AEAD on the generate side, ARIA had no OID-addressable AEAD AlgorithmParameters, and SM4 had no GCM/CCM Cipher at all; an attempt to round-trip CMS AuthEnvelopedData under any of these failed. The BC provider now registers OID-addressable SM4-GCM/SM4-CCM Ciphers, AlgorithmParameters and AlgorithmParameterGenerators (GMObjectIdentifiers.sms4_gcm 1.2.156.10197.1.104.8 / sms4_ccm .104.9) and ARIA-GCM/CCM AlgorithmParameters/AlgorithmParameterGenerators (NSRIObjectIdentifiers.id_aria128/192/256_gcm and _ccm), the CMS encrypt path recognises all eight OIDs as AEAD and generates the correct RFC 5084 nonce/parameters for them, and the lightweight org.bouncycastle.crypto.util.CipherFactory / CipherKeyGeneratorFactory / AlgorithmIdentifierFactory recognise them too, so both the JCA/JCE (JceCMSContentEncryptorBuilder) and lightweight (BcCMSContentEncryptorBuilder) content-encryptor builders can now produce and recover CMS AuthEnvelopedData under ARIA-GCM/CCM and SM4-GCM/CCM. Decode-side recognition was added in the same release.
- CMS recipients can now be restricted to a set of acceptable content-encryption algorithms. The new fluent setter setAllowedContentAlgorithms(Set<ASN1ObjectIdentifier>) is available on all JCA/JCE recipients (JceKeyTransRecipient, JceKeyAgreeRecipient, JceKEMRecipient, JcePasswordRecipient, JceKEKRecipient) and all lightweight recipients (BcKeyTransRecipient, BcKEKRecipient, BcPasswordRecipient); when set, an attempt to recover content protected under any other content-encryption (or, for AuthenticatedData, content-MAC) algorithm is refused before any key unwrap or content processing, throwing the new org.bouncycastle.cms.CMSAlgorithmNotAllowedException (a subclass of CMSException, so existing catch blocks are unaffected). This lets a caller reject an attacker downgrading the content-encryption algorithm carried in the recipient info to a weaker one. The shared state and check live on a new common base class org.bouncycastle.cms.AbstractRecipient; with no allowed set configured (the default) behaviour is unchanged and every algorithm is accepted.
- CMS recipients can now require a minimum AEAD authentication tag size when recovering AuthEnvelopedData. The new fluent setter setMinimumTagSize(int tagSizeInBits) is available on the JCA/JCE recipients (JceKeyTransRecipient, JceKeyAgreeRecipient, JceKEMRecipient, JcePasswordRecipient, JceKEKRecipient); when set, recovering content whose AES-GCM/CCM content-encryption algorithm carries a shorter ICV tag is refused before any decryption, throwing the new org.bouncycastle.cms.CMSTagLengthException (a subclass of CMSException). This is a caller-chosen floor layered on top of the existing global org.bouncycastle.gcm.allow_short_tags policy, letting a recipient reject an attacker downgrading the tag length (e.g. to 32 or 64 bits). The check (on org.bouncycastle.cms.AbstractRecipient) is a no-op for non-AEAD content and when no minimum is set, so default behaviour is unchanged.
- CMSSignedData.replaceSigners() and addDigestAlgorithm() recompute the SignedData version from the content per RFC 5652 (a non-id-data eContentType, for example, computes to version 3). A producer that needs to pin a specific version can now call the new CMSSignedData.asVersion(int), which returns a copy of the message with the SignedData version field forced to the given value and everything else unchanged. This covers interop with profiles that require a fixed version irrespective of content - notably Microsoft Authenticode, whose signatures must carry version 1 even though their SPC_INDIRECT_DATA eContentType would otherwise compute to version 3. The org.bouncycastle.asn1.cms.SignedData structure gains a constructor taking an explicit ASN1Integer version to support this (issue #2344).
- The Argon2 password-based KDF (RFC 9106) is now available through the BC JCE provider as SecretKeyFactory "ARGON2", complementing the existing lightweight org.bouncycastle.crypto.generators.Argon2BytesGenerator. Parameters are supplied via the new org.bouncycastle.jcajce.spec.Argon2KeySpec (variant Argon2d/Argon2i/Argon2id, version 1.0/1.3, salt, iterations, memory cost in KiB, parallelism and output key length in bits, plus optional secret and additional data), following the style of the existing SCRYPT SecretKeyFactory and ScryptKeySpec. The attacker-cost guards on the lightweight generator still apply: the memory exponent is capped by org.bouncycastle.argon2.max_memory_exp (default 24, i.e. 16 GiB).
- The BCJSSE hostname verifier no longer falls back to matching the subject CN of a server certificate when the certificate carries no SubjectAltName dNSName entry; by default only a matching SAN dNSName (or, for an IP literal, an iPAddress SAN) satisfies HTTPS endpoint identification. RFC 9525 sec. 6.3 deprecates CN as a TLS server identifier and CAB Forum Baseline Requirements 7.1.4.2 require SAN dNSName entries for publicly-trusted server certs; the CN fallback was also a Name-Constraints bypass surface, as RFC 5280 name constraints only constrain SubjectAltName entries of the constrained type, so a dNSName-constrained sub-CA could issue a SAN-less leaf carrying an unrelated hostname in CN. The legacy SunJSSE-compatible CN matching remains available, as an opt-in for certificates that only identify the server via CN, by setting the org.bouncycastle.jsse.hostname_check_cn_fallback system/security property (Properties.JSSE_HOSTNAME_CHECK_CN_FALLBACK) to "true".
- PKIXNameConstraintValidator gains an opt-in relaxed directoryName matching mode for GSMA SGP.22 v2.5 (Remote SIM Provisioning) certificate chains, gated behind the new org.bouncycastle.x509.sgp22_name_constraints system property (default off). When enabled, a permitted-subtree RDN is satisfied by any matching subject RDN regardless of position, additional subject attributes beyond those named in the subtree are tolerated (SGP.22 sec. 4.5.2.1.0.2), and a serialNumber RDN is matched with a startsWith comparison wherever it appears (SGP.22 sec. 4.5.2.1.0.3). This is deliberately looser than the contiguous-prefix DN matching mandated by RFC 5280 sec. 7.1. A pre-existing, ungated SGP.22 serialNumber startsWith concession in the strict matching path has been moved behind the same property, so default validation is now fully RFC 5280 strict (a single serialNumber name constraint is compared by equality, not prefix, unless the property is set) (issue #2327).
- Classic McEliece as standardised in ISO/IEC 18033-2:2006/Amd 2:2026 (Clause 13) is now implemented under org.bouncycastle.crypto and registered in the BouncyCastle (BC) provider, in the same style as ML-KEM and FrodoKEM. The standard selects sixteen parameter sets - the four code sizes mceliece460896, mceliece6688128, mceliece6960119 and mceliece8192128, each in a base form, a semi-systematic ("f") key-generation variant, a plaintext-confirmation ("pc") variant, and a combined "pcf" variant - and assigns them object identifiers under id-kem-cm (1.0.18033.2.2.6.1 through 1.0.18033.2.2.6.16, in ISOIECObjectIdentifiers). In a pc parameter set the encapsulation appends a 32-byte confirmation C1 = Hash(2, e) to the ciphertext and derives the session key over the full C0 || C1 (ISO 13.12.3 / 13.13.3), with the decapsulator recomputing and constant-time comparing C1 before the implicit-rejection step; the non-pc and "f" sets are the existing NIST round-3 construction. All sixteen sets use GF(2^13) and produce a 256-bit (32-byte) session key. (The smaller NIST round-3 size mceliece348864 is not standardised and is not provided in the new location.) BC provides the sixteen sets as org.bouncycastle.crypto.params.CMCEParameters constants, driven by the lightweight CMCEKeyPairGenerator (org.bouncycastle.crypto.generators) and CMCEKEMGenerator / CMCEKEMExtractor (org.bouncycastle.crypto.kems), and through the BC provider as KeyPairGenerator / KeyFactory / KeyGenerator / Cipher "CMCE" (the parameter set selected via org.bouncycastle.jcajce.spec.CMCEParameterSpec) under the new OIDs. All sixteen sets are verified byte-for-byte against the Classic McEliece reference KAT vectors - the non-pc and "f" sets against the NIST round-3/round-4 vectors, and the pc/pcf sets against vectors generated from the official libmceliece reference (lib.mceliece.org) driven by the NIST CTR-DRBG, the generator itself validated by regenerating the non-pc/"f" vectors byte-identically. The earlier Classic McEliece implementation under org.bouncycastle.pqc.crypto.cmce and the BCPQC provider (the NIST round-3, non-pc construction, including the non-standardised mceliece348864 size) is retained for backwards compatibility but deprecated; new code should use the org.bouncycastle.crypto / BC provider classes.
- FrodoKEM as standardised in ISO/IEC 18033-2:2006/Amd 2:2026 (Clause 14) is now implemented under org.bouncycastle.crypto and registered in the BouncyCastle (BC) provider, in the same style as ML-KEM. The standard specifies eight parameter sets at the 976 and 1344 security levels - the salted "FrodoKEM" (applying the Salted Fujisaki-Okamoto transform: the seed seedSE is enlarged to twice the security parameter and a salt of twice the security parameter is folded into the G_2 hash and the derived shared secret and carried in the ciphertext) and the ephemeral "eFrodoKEM" (no salt; to be used only where fewer than 2^8 ciphertexts are produced per public key), each with AES or SHAKE generation of the matrix A, and assigns object identifiers to all eight variants. BC provides all eight parameter sets: org.bouncycastle.crypto.params.FrodoKEMParameters.frodokem976shake / frodokem1344shake / frodokem976aes / frodokem1344aes (salted) and efrodokem976shake / efrodokem1344shake / efrodokem976aes / efrodokem1344aes (ephemeral), driven by the lightweight FrodoKEMKeyPairGenerator (org.bouncycastle.crypto.generators) and FrodoKEMGenerator / FrodoKEMExtractor (org.bouncycastle.crypto.kems), and through the BC provider as KeyPairGenerator / KeyFactory / KeyGenerator / Cipher "FRODOKEM" (the parameter set selected via org.bouncycastle.jcajce.spec.FrodoKEMParameterSpec) under the new OIDs id-kem-frodokem976-shake through id-kem-efrodokem1344-aes (1.0.18033.2.2.7.1 .. 1.0.18033.2.2.7.8, in ISOIECObjectIdentifiers). The implementation is verified byte-for-byte against the FrodoKEM team's reference KAT vectors for all eight parameter sets (both SHAKE and AES generation of the matrix A), and the matrix multiply (FrodoKEMEngine.matrix_mul) uses an ikj-ordered, JIT auto-vectorisable form that is bit-for-bit identical to the schoolbook product. The earlier FrodoKEM implementation under org.bouncycastle.pqc.crypto.frodo and the BCPQC provider (the unsalted NIST round 3 construction, equivalently eFrodoKEM, including the non-standardised 640 parameter sets) is retained for backwards compatibility but deprecated; new code should use the org.bouncycastle.crypto / BC provider classes.
- The (BC)JSSE provider now honours TlsPeer.getHandshakeTimeoutMillis() for blocking SSLSockets, configured through the new org.bouncycastle.jsse.handshakeTimeoutMillis system property (default 0, meaning no timeout). Previously the handshake timeout was respected only by the DTLS protocols; the blocking stream-TLS path relied on the socket's per-read SO_TIMEOUT, which aborts a fully stalled peer but cannot bound the total handshake time (a peer dripping bytes slower than the handshake completes, but faster than SO_TIMEOUT, could hold the handshake open indefinitely). When the property is set, the BCJSSE socket now enforces a total wall-clock deadline across the complete handshake, throwing a TlsTimeoutException when it expires. The default behaviour is unchanged, and the deadline is not applied to the transport-agnostic blocking TlsClientProtocol / TlsServerProtocol stream API, which has no timed-read primitive (callers there should drive the non-blocking API and enforce their own deadline) (issue #1666).
- The BC JCE provider now registers the Java 9+ standard signature algorithm names for ECDSA producing IEEE P1363 format (fixed-width r || s) output: NONEwithECDSAinP1363Format and SHA1/SHA224/SHA256/SHA384/SHA512withECDSAinP1363Format, plus the SHA3-224/256/384/512 equivalents. These map to the same engine as the existing PLAIN-ECDSA / CVC-ECDSA names and are registered with the EC key attributes, so Signature.getInstance(...) resolves them on the auto-provider-selection path - which is how the JDK's built-in XML signature support (org.jcp.xml.dsig.internal.dom.DOMSignatureMethod) obtains an ECDSA Signature, previously forcing callers onto a custom bridge provider (issue #751).
- PGPCompressedData.getDataStream(long limit) is a new opt-in overload that caps the number of decompressed bytes a caller may read from an OpenPGP compressed data packet, throwing a StreamOverflowException (an IOException) once the limit is exceeded. Because the compressed data packet carries no decompressed-length field, the existing no-arg getDataStream() returns an unbounded stream, so a small ZIP/ZLIB/BZIP2 packet can expand into an arbitrarily large amount of data ("decompression bomb") where a caller chooses to buffer the full output on read; the new overload lets callers processing untrusted input bound that expansion ahead of reading, mirroring the existing org.bouncycastle.cms.jcajce.ZlibExpanderProvider(long) limit. The no-arg getDataStream() behaviour is unchanged. Note the limit bounds decompressed output only; for BZIP2 the underlying decompressor still allocates its fixed working buffers (sized by the packet's block-size header) at stream construction.
- The SHA_Interleave function from RFC 2945 sec. 3.1 (used by SRP-SHA1 to produce a 320 bit session key) is now available, as org.bouncycastle.crypto.digests.SHA1InterleaveDigest in the lightweight API and as MessageDigest "SHA1-INTERLEAVE" (alias "SHA-1-INTERLEAVE") in the BC JCE provider. The complete input is buffered until doFinal: leading zero bytes are removed, a further leading byte is removed if the remaining length is odd, the even-numbered and odd-numbered bytes are hashed separately with SHA-1, and the two hashes are interleaved to form the 40 byte result (issue #473).
- CMSEnvelopedDataStreamGenerator and CMSAuthEnvelopedDataStreamGenerator can now produce definite-length (DL) and DER encoded output for content of any size: setEncoding("DER"/"DL") plus the new open(out, inputLength, encryptor) overloads pre-compute every enclosing header from the content length, so nothing is buffered and the content may exceed the size of a Java array. The exact ciphertext length is taken from the new org.bouncycastle.operator.KnownLengthOutputEncryptor interface when the encryptor implements it, falling back to an algorithm-identifier-based computation for the common CBC (padded), AES-GCM and AES-CCM content encryption algorithms; both the declared content length and the predicted ciphertext length are enforced, with a mismatch failing rather than emitting corrupt lengths. For AuthEnvelopedData the AEAD tag lives in the separate mac field (predicted from the GCM/CCM parameters) and any authenticated attributes are generated and fed to the encryptor's AAD stream at open() time, ahead of the content, as AEAD modes require. CMSSignedDataStreamGenerator gains the same for encapsulated content via the new single-pass open(out, contentLength) overloads: every enclosing header, including the trailing signerInfos SET's, is pre-computed from the content length and per-signer SignerInfo length predictions (SignerInfoGenerator.getPredictedEncodedLength), which require the underlying signer to implement the new org.bouncycastle.operator.FixedLengthContentSigner interface - JcaContentSignerBuilder supplies it automatically for RSA (PKCS#1 v1.5 and PSS, the modulus size), Ed25519/Ed448 and ML-DSA; DER-encoded ECDSA/DSA signatures vary in length and are rejected up front with a pointer at the two-pass alternative. That alternative, generate(out, CMSTypedData), supports every signature algorithm with no length known in advance: the first pass streams the content through the digest calculators and computes the signatures, so all lengths are exact, and the second pass writes the structure while re-digesting the re-read content - a source that changed between passes fails rather than producing a structure whose signatures don't verify. Declared content lengths and each SignerInfo length are enforced at write/close time. Underpinning this are new streaming definite-length ASN.1 generators - org.bouncycastle.asn1.DLSequenceGenerator and DLOctetStringGenerator (with DLGenerator length arithmetic helpers) - which write a definite-length header up front from a long body length, the counterpart of the indefinite-length BER generator family. The read side keeps pace: the ASN.1 streaming parser (ASN1StreamParser / DefiniteLengthInputStream) now traverses and drains definite lengths beyond 31 bits, so CMSSignedDataParser / CMSEnvelopedDataParser / CMSAuthEnvelopedDataParser round-trip such structures in full - materialization into in-memory objects remains bounded by what a Java array can hold and is rejected cleanly past that, and the in-memory ASN1InputStream path is unchanged. Exercised end to end past the byte[] limit by the gated DefiniteLengthLargeDataTest (-Dbc.test.largedata=true) (issue #1482).
- PKIXCertPathReviewer now reports a notification when a non-CA certificate in the path carries the name constraints extension. RFC 5280 sec. 4.2.1.10 requires the extension to be used only in CA certificates, and the sec. 6.1 path validation algorithm never processes it on the final certificate, so its presence on an end-entity certificate is an issuance defect; behaviour elsewhere in the ecosystem is split (the JDK and OpenSSL accept such paths, GnuTLS/botan/wolfSSL reject them). BC's CertPathValidator is unchanged - it continues to accept the path, matching the JDK and OpenSSL - but both reviewer copies (org.bouncycastle.pkix.jcajce and org.bouncycastle.x509) surface the defect against the offending certificate (issue #2320).
- The JCA-backed TLS crypto (JcaTlsCrypto) now supports raw public key certificates (RFC 7250), reaching parity with the lightweight BcTlsCrypto; previously JcaTlsCrypto.createCertificate threw an unsupported_certificate alert for CertificateType.RawPublicKey. The new org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsRawKeyCertificate wraps a SubjectPublicKeyInfo (reconstructing the java.security.PublicKey via the configured JcaJceHelper) and is now the base class for JcaTlsCertificate, mirroring the BcTlsCertificate extends BcTlsRawKeyCertificate structure so the signature/verifier handling is shared between the X.509 and raw public key cases. Raw public key handshakes (negotiated via the client_certificate_type / server_certificate_type extensions) now work end-to-end on either crypto backend.
- The NTRU KEM polynomial multiply (org.bouncycastle.pqc.math.ntru.Polynomial.rqMul, the cyclic convolution in Z[x]/(xn-1) underlying key generation, encapsulation and decapsulation for every HPS / HRSS parameter set) has been reimplemented from a naive O(n2) schoolbook convolution to recursive Karatsuba (O(n1.585)). Because the ring uses a power-of-two coefficient modulus and the multiply defers reduction to its caller, the kernel is closed under +/-/* and the Karatsuba result is bit-for-bit identical to the schoolbook result modulo 216; the change is verified byte-identical against all KAT vectors and preserves the constant-time (data-independent) access pattern. End-to-end keygen+encapsulate+decapsulate is roughly 1.7x-2.6x faster across the ntruhps2048509 / ntruhps2048677 / ntruhps4096821 / ntruhps40961229 / ntruhrss701 / ntruhrss1373 parameter sets.
- GOST3412_2015Engine (Kuznyechik, GOST 34.12-2015 / RFC 7801) has been substantially sped up. The linear transform L (previously the LFSR R applied 16 times, ~256 GF(2^8) table lookups plus 16 register shifts per call) is now a set of precomputed lookup tables - L(data) = XOR_i LT[i][data[i]] - with the S-box folded into them (LS / inverse-LS tables) so each round is a key XOR plus one table pass, and the inverse round uses the equivalent-decryption restructure. The block-processing loop and the inverse step no longer allocate per-round work buffers, and the 64 KB GF(2^8) multiply table is no longer rebuilt per engine instance. Output is byte-identical to the previous implementation and the change is constant-time-neutral (the tables are indexed by the same block bytes the S-box already indexes); measured ~9x faster on a CPU-bound encrypt+decrypt loop.
- TlsServer.getExternalPSK(Vector) now declares throws IOException, so a TLS 1.3 server can abort external-PSK selection with a specific alert by throwing a TlsFatalAlert from it - e.g. unknown_psk_identity when none of the offered identities is recognised, or decrypt_error when an identity is recognised but invalid or expired (RFC 8446 6.2). Previously the method could not signal an alert. The change is source- and binary-compatible for existing implementations (an override need not declare the exception); the default AbstractTlsServer implementation still simply returns null (issue #1673).
- AES-GMAC is now supported as the macAlgorithm in CMS AuthenticatedData per RFC 9044. The BC JCE provider registers Mac, KeyGenerator, AlgorithmParameters and AlgorithmParameterGenerator services for id-aes128-GMAC (2.16.840.1.101.3.4.1.9), id-aes192-GMAC (.29) and id-aes256-GMAC (.49), so JceCMSMacCalculatorBuilder(CMSAlgorithm.AES128_GMAC) (and the 192/256 variants) produces and verifies an AuthenticatedData whose macAlgorithm carries the RFC 9044 GMACParameters (a 12-octet nonce and, by default, a 16-octet tag). GMACParameters shares the RFC 5084 GCMParameters wire format, so the parameter handling is aliased to the existing GCM AlgorithmParameters; org.bouncycastle.crypto.macs.GMac.init now also accepts AEADParameters so the RFC 9044 tag length (12 to 16 octets) flows through to the computed MAC.
- The system/security property "org.bouncycastle.gcm.allow_short_tags" (also exposed as Properties.GCM_ALLOW_SHORT_TAGS) lets callers opt in to short AES-GCM authentication tags. RFC 5084 constrains the AES-GCM ICV (tag) length carried in GCMParameters to 12 to 16 octets (96 to 128 bits), which BC enforces by default on both the read and write sides of CMS AuthEnvelopedData. When this property is set to "true", GCMParameters additionally accepts tags down to the NIST SP 800-38D minimum of 4 octets (32 bits; SP 800-38D sec. 5.2.1.2 permits a 32-bit tag for limited applications), so a CMS AuthEnvelopedData carrying such a tag can be produced and consumed. Short tags weaken integrity protection, so this defaults to off and must be enabled explicitly; anything below 4 octets or above 16 octets is still rejected, and with the property unset a structure carrying a sub-12-octet tag continues to be refused with "Invalid ICV length".
- KeccakDigest (and thus every SHA-3, SHAKE, cSHAKE, KMAC, ParallelHash and TupleHash instance, plus all SHAKE-based PQC schemes) now packs only the squeeze lanes a caller actually consumes. Previously each squeeze block eagerly converted the full rate (e.g. all 17 lanes / 136 bytes for SHAKE256) from the state into the internal byte queue, even when the caller read fewer bytes; the packing is now deferred and materialised lazily per consumed lane. The change is byte-for-byte output-preserving (verified against the SHA-3 / SHAKE / cSHAKE / KMAC CAVP vectors and the ML-KEM / ML-DSA / SLH-DSA KATs, including the SavableDigest encode-mid-squeeze round-trip) and noticeably speeds up consumers that squeeze less than a full rate block: roughly 1.11x for SLH-DSA-SHAKE signing and 1.12x for SHA3-256 of short inputs. Full-block consumers (the ML-KEM / ML-DSA matrix expansion, SHAKE used as a long XOF) are unaffected.
- KCCMBlockCipher (DSTU 7624 CCM mode) now accepts input whose length is not a multiple of the underlying block size, where previously a partial block threw "partial blocks not supported". Partial blocks are handled following the generic CCM construction (NIST SP 800-38C / RFC 3610): the CBC-MAC zero-pads the trailing partial block and the counter keystream is truncated for it. DSTU 7624:2014 publishes no partial-block CCM test vector, so the behaviour is verified by round-trip self-consistency only and has not been confirmed against an independent conformant implementation; callers needing guaranteed DSTU 7624 interoperability should keep input block-aligned. DSTU7624Mac (a CBC-MAC variant that binds no message length) deliberately continues to reject non-block-aligned input rather than zero-pad it, since padding an unkeyed-length CBC-MAC would introduce tag collisions and DSTU 7624 specifies no padding for it; its javadoc now explains the rationale (issue #287).
- The four exception classes in org.bouncycastle.operator (OperatorException, OperatorCreationException, OperatorStreamException, RuntimeOperatorException) now carry class-level and per-constructor javadoc explaining what each exception represents and what its typical underlying causes are. The three classes that previously kept the cause in a private field and overrode getCause() (OperatorException, OperatorStreamException, RuntimeOperatorException) now route the cause through the standard Throwable(msg, cause) constructor so printStackTrace() prints "Caused by: ..." for the original failure (issue #1504).
- Initial CAdES (CMS Advanced Electronic Signatures) high-level builders, in the new org.bouncycastle.cades package, covering all four CAdES baseline levels (ETSI EN 319 122-1 / RFC 5126): B-B (CAdESSignerInfoGeneratorBuilder + CAdESSignedDataGenerator: mandatory ESS signing-certificate-v2 reference plus optional commitment-type / signature-policy / signer-location / content-hints), B-T (CAdESSignatureTimestampUtil: id-aa-signatureTimeStampToken over the SignerInfo signature value, with caller-fetched RFC 3161 token, plus a getSignatureTimestamps read-back and a validateSignatureTimestamps self-consistency check that re-derives the SignerInfo.signature imprint under each embedded token's hash algorithm), B-LT (CAdESLongTermValuesUtil: id-aa-ets-certificateRefs / certValues / revocationRefs / revocationValues, supporting both CRLs and OCSP responses, with getCertificateValues / getCertificateRevocationLists / getOcspResponses read-back and a validateLongTermValues self-consistency check that confirms every reference hash matches its corresponding value) and B-LTA (CAdESArchiveTimestampUtil: id-aa-ets-archiveTimestampV2 over the ETSI TS 101 733 v1.7.4 Annex A.2 canonicalisation, with archive-timestamps stripped so chains are renewable, plus a getArchiveTimestamps read-back covering both the v2 and legacy id-aa-ets-archiveTimestamp OIDs and a validateArchiveTimestamps self-consistency check that re-derives the canonical-stripped imprint under each token's hash algorithm). CAdESLevelDetector inspects a SignerInformation and reports the attained level. The newer ETSI EN 319 122-1 v3 archive-timestamp form (id-aa-ets-archiveTimestampV3) is not yet supported. The low-level ASN.1 types under org.bouncycastle.asn1.esf and org.bouncycastle.asn1.ess remain available for callers needing finer-grained control (issue #275).
- The system/security property "org.bouncycastle.pkcs1.strict_digestinfo" (also exposed as Properties.PKCS1_STRICT_DIGESTINFO) lets callers opt in to strict RFC 8017 Appendix A.2.4 enforcement when verifying RSA PKCS#1 v1.5 signatures: when set to "true", DigestInfo encodings whose AlgorithmIdentifier omits the required NULL parameters octets are rejected. Default (unset / "false") preserves the legacy lenient fallback that accepts the two-byte-shorter encoding for compatibility with implementations that have historically produced it. Affects both the BC JCE provider's DigestSignatureSpi (e.g. Signature.getInstance("SHA256withRSA", "BC")) and the lightweight crypto RSADigestSigner (issue #2273).
- The system/security property "org.bouncycastle.asn1.allow_non_der_time" (also exposed as Properties.ASN1_ALLOW_NON_DER_TIME) controls whether an ASN.1 UTCTime / GeneralizedTime carrying non-DER contents may be serialized through a DEROutputStream. Reading is always lenient: a wire value that is valid ASN.1 but not valid DER — for example a UTCTime without the seconds element ("YYMMDDHHMMZ"), a time terminated with a "+hhmm"/"-hhmm" offset rather than "Z", or a GeneralizedTime fraction carrying trailing zeros — parses without complaint into a usable ASN1UTCTime / ASN1GeneralizedTime. Default (unset / "true") preserves BC's historical pass-through, allowing such a primitive to be re-emitted as DER unchanged. Setting it to "false" enforces the DER restrictions of X.690 sec. 11.7 / 11.8 (and hence the RFC 5280 sec. 4.1.2.5 profile, which requires seconds and Zulu) on the DER write side: the primitive's toDERObject() throws an IllegalStateException if it would emit non-conformant content, so any attempt to write it to a DEROutputStream fails. BER serialization is unaffected. Programmatically constructing a time from a java.util.Date always produces DER content (issue #1973 / #1986).
- KeyPurposeId constants for the four Extended Key Usage KeyPurposeIds defined in RFC 9809 sec. 3: id_kp_configSigning (id-kp 41, signing general-purpose configuration files), id_kp_trustAnchorConfigSigning (id-kp 42, signing trust anchor configuration files), id_kp_updatePackageSigning (id-kp 43, signing software / firmware update packages) and id_kp_safetyCommunication (id-kp 44, authenticating peers for safety-critical communication). The matching human-readable names are also registered in X509CertificateFormatter so the new EKUs print symbolically.
- KeyPurposeId constant for the Extended Key Usage KeyPurposeId defined in RFC 9734 sec. 3: id_kp_imUri (id-kp 40, 1.3.6.1.5.5.7.3.40), included in certificates that prove the identity of an Instant Messaging (IM) client whose IM URI (RFC 3860) or XMPP URI (RFC 6121) appears in the subjectAltName. The matching human-readable name is also registered in X509CertificateFormatter so the EKU prints symbolically.
- RFC 9763 ("Related Certificates for Use in Multiple Authentications within a Protocol") support, the non-composite path for hybrid post-quantum migration. Two new ASN.1 types: org.bouncycastle.asn1.x509.RelatedCertificate (the certificate extension carried on the new-algorithm end-entity certificate, identified by Extension.relatedCertificate / X509ObjectIdentifiers.id_pe_relatedCert = 1.3.6.1.5.5.7.1.36 — a SEQUENCE of DigestAlgorithmIdentifier and OCTET STRING hash of the entire related Certificate DER) and org.bouncycastle.asn1.cms.RequesterCertificate (the CSR attribute value carried under PKCSObjectIdentifiers.id_aa_relatedCertRequest = 1.2.840.113549.1.9.16.2.60 — a SEQUENCE of IssuerAndSerialNumber certID, BinaryTime requestTime, SEQUENCE OF IA5String locationInfo URIs and BIT STRING signature). A new org.bouncycastle.asn1.cms.BinaryTime type implements the RFC 6019 INTEGER (0..MAX) seconds-since-epoch time used by requestTime; the companion id-aa-binarySigningTime OID continues to live at PKCSObjectIdentifiers.pkcs_9_at_binarySigningTime. Operator-style helpers in the new org.bouncycastle.cert.RelatedCertificateTool (sibling of DeltaCertificateTool) cover the wire-format operations: createRelatedCertificate / isRelatedCertificate (build and verify the extension via a DigestCalculator / DigestCalculatorProvider), createRequesterCertificate / verifyRequesterCertificate (sign and verify the CSR attribute via a ContentSigner / ContentVerifier), and toAttribute / fromAttribute (wrap and unwrap the value as a PKCS#9 Attribute under the id-aa-relatedCertRequest OID). writeSignatureInput streams the RFC 9763 sec. 4.1 signed bytes — the bare concatenation of DER(certID) and DER(requestTime), NOT a SEQUENCE wrapper — directly into a supplied OutputStream with no intermediate byte[].
- KeyPurposeId constant id_kp_documentSigning (id-kp 36) for the Extended Key Usage KeyPurposeId defined in RFC 9336 sec. 3.1, identifying public keys whose certified usage is to verify signatures over documents intended for human consumption (PDF, XML, JSON, etc.) — distinct from id_kp_codeSigning (executable code) and id_kp_emailProtection (S/MIME). The matching human-readable name is also registered in X509CertificateFormatter so the new EKU prints symbolically.
- FalconPrivateKeyParameters.getPublicKeyParameters() returns the matching FalconPublicKeyParameters for a private key, mirroring MLDSAPrivateKeyParameters.getPublicKeyParameters(). When the private key no longer carries its encoded public key (e.g. it was reconstructed from only the private encoding f ‖ g ‖ F, with no public key bytes or key-generation seed retained), the public key h is recomputed from the private polynomials as h = g * f^-1 mod (q, x^n+1). Lets wallet / HSM code recover the public key from a stored private key without re-running keygen (issue #2297).
- The system/security property "org.bouncycastle.x509.crl_cache_ttl" (also exposed as Properties.X509_CRL_CACHE_TTL) sets a TTL, in seconds, for entries in the internal CRL cache used by CertPathValidator and X509RevocationChecker. When set to a positive value, cached entries are evicted whichever expires sooner: the configured TTL or the CRL's own nextUpdate. Unset (or 0) preserves the legacy behaviour of trusting the CRL's nextUpdate alone (issue #1833).
- The BC PKCS#12 KeyStore (Provider "BC", types "PKCS12", "PKCS12-DEF" and the variants, plus "PKCS12-PBMAC1") now accepts SecretKey entries via the standard JCE KeyStore.SecretKeyEntry API. Entries are written using the standards-compliant RFC 7292 sec. 4.2.5 secretBag form: the SafeBag's bagId is id-secretBag, the inner SecretBag carries the algorithm OID as secretTypeId and the SecretKey.getEncoded() bytes as a DER OCTET STRING secretValue, and the bag is placed inside the keystore's encrypted SafeContents block (so the raw key bytes are protected by the keystore PBE). Phase 1 supports algorithms with a registered OID: AES (128 / 192 / 256, by key length), DESede / TripleDES, and HmacSHA1 / SHA-224 / SHA-256 / SHA-384 / SHA-512 / SHA3-{224,256,384,512}. Algorithms without a registered OID are rejected at setKeyEntry-time with a pointer at BCFKS. As an opt-in interop path, setting the system/security property "org.bouncycastle.pkcs12.allow_sun_secret_keys" (Properties.PKCS12_ALLOW_SUN_SECRET_KEYS) lets BC additionally decode SunJCE-style secretBag entries on load — those use the same id-secretBag SafeBag, but the inner SecretBag's secretTypeId is pkcs8ShroudedKeyBag and its secretValue wraps an EncryptedPrivateKeyInfo containing the secret-key bytes. BC always writes the standards-compliant form regardless (issue #1807).
- The system/security properties "org.bouncycastle.argon2.max_memory_exp", "org.bouncycastle.argon2.max_passes" and "org.bouncycastle.argon2.max_parallelism" bound the Argon2 cost parameters accepted from untrusted input (notably an OpenPGP Argon2 S2K specifier, whose passes/parallelism/memory fields are honoured before the message can be authenticated). max_memory_exp caps the memory exponent (memory ≤ 2^exp KiB); its default has been lowered to 24 (16 GiB) from the previous 30 (2^30 KiB = 1 TiB) so that a single decrypt attempt cannot exhaust the heap, and it may still be raised to a ceiling of 30. max_passes (default 10) and max_parallelism (default 16) bound the iteration and lane counts, which OpenPGP key derivation previously accepted unbounded (one byte each, up to 255); a passphrase-encrypted message exceeding any active limit is now rejected with a PGPException rather than processed.
- Argon2BytesGenerator now accepts a caller-supplied BlockPool via Argon2Parameters.Builder.withBlockPool(...), allowing reuse of working memory across successive generateBytes calls (issue #1646 / PR #1647). A bounded FixedBlockPool implementation is included.
- Argon2BytesGenerator's BLAKE2 compression (the dominant cost in fillMemoryBlocks) has been restructured so each of the eight G mixing functions per round loads its four working words into locals, mixes them entirely in registers, and writes them back once, instead of re-reading and re-writing the backing long[] on every quarter-round. The change is byte-identical (RFC 9106 / draft-irtf-cfrg-argon2 vectors unchanged) and touches only the data-independent compression, so the data-dependent (Argon2d/id) addressing and its constant-time posture are unaffected. Measured ~6-10% faster end-to-end across HotSpot (JDK 8-25) and GraalVM.
- BCFKS keystore now supports storing and retrieving javax.crypto.interfaces.PBEKey entries, so passwords and other PBE-based secrets no longer need to be stored as HMAC keys (issue #2164).
- X509v3CertificateBuilder now exposes setters for the constructor arguments (setIssuer, setSerialNumber, setNotBefore, setNotAfter, setSubject, setSubjectPublicKeyInfo) to support equivalence-comparison use cases (issue #1545).
- org.bouncycastle.asn1.x509.qualified.QcType — typed wrapper for the ETSI EN 319 412-5 sec. 4.2.3 QcType statementInfo (SEQUENCE OF OBJECT IDENTIFIER) carried inside a QCStatement whose statementId is id_etsi_qcs_QcType. Constructors take either a single OID or an array; hasType(ASN1ObjectIdentifier) returns whether a given QcType OID (id_etsi_qct_esign / id_etsi_qct_eseal / id_etsi_qct_web) is declared. QCStatementUnitTest has been extended to round-trip every ETSI QC statement type — QcCompliance, QcSSCD, QcType, QcCClegislation, RetentionPeriod and LimitValue — through encode/parse via QCStatement (issue #1467).
- CMSSignedDataParser now exposes getCertificateSet() and getCRLSet() returning the raw ASN1Set fields as parsed from the wire, preserving every certificate / CRL choice (X.509, attribute certificate, other-format) in original encoding order. The existing getCertificates() / getCRLs() Stores filter to X.509 only, which is sufficient for typical verification but loses non-X.509 choices and is unsuitable when the wire-encoding order matters (archive-timestamp imprint canonicalisation, audit, etc.). Building on the new accessors, CAdESArchiveTimestampUtil.computeArchiveTimestampImprint now also accepts a CMSSignedDataParser, computing the ETSI TS 101 733 Annex A.2 archive-timestamp v2 imprint directly from the parser without materialising the whole SignedData — useful when validating archive-timestamps on signatures whose certificate / CRL / SignerInfo sections would not comfortably fit in memory (issue #1983).
- The CMS stream parsers now also expose the original wire coding of the remaining SignedData fields: CMSContentInfoParser.isBEREncoded() reports whether the outer ContentInfo used the indefinite-length (BER) method, CMSSignedDataParser.getDigestAlgorithmsSet() returns the digestAlgorithms field as a BERSet/DLSet reflecting the wire form with original element order, and CMSSignedDataParser.isContentBEREncoded() reports whether the eContent OCTET STRING was constructed (BER) or primitive definite-length — removing the need for a second raw pass over the stream when the original coding must be reproduced. For augmentation, CMSSignedDataParser.replaceSignersPreservingEncoding() rewrites the signerInfos of a SignedData stream while copying the version, digestAlgorithms, encapContentInfo, certificates and crls elements through verbatim (the content is piped, not buffered) and writing the new signerInfos unsorted in store order, so everything an ETSI TS 101 733 archive-timestamp v2 imprint covers is preserved byte for byte when attaching the timestamp as an unsigned attribute (issue #1983).
- S/MIME boundary scan failures (a multipart missing its closing boundary line) now throw SMIMEBoundaryNotFoundException, a MessagingException subclass carrying typed diagnostics: the boundary, the body part's Content-Type/Content-Disposition, the expected and found boundary-line counts, and the bytes consumed from the raw stream - all of which also appear in the exception message. The last non-empty line read before the failure is available via getLastLineRead() only and is deliberately excluded from the message, so stack traces remain free of potentially confidential message content by default (issue #2318).
- The CMS generators now support encoding selection uniformly: setEncoding("BER"/"DL"/"DER") has been promoted to the CMSSignedGenerator and CMSEnvelopedGenerator base classes, so it is available on the signed, enveloped, auth-enveloped and authenticated data generators (in-memory and streaming alike) and is honoured all the way through getEncoded() - in the definite-length modes the encrypted/encapsulated content is carried as a primitive OCTET STRING and the EnvelopedData/AuthEnvelopedData/AuthenticatedData/EncryptedContentInfo ASN.1 classes now follow their components (as SignedData already did), emitting definite-length sequences when nothing in them is BER, with "DER" producing a canonical encoding (re-encoding as DER is the identity). The streaming generators need the content length supplied up front via their length-taking open() methods - CMSAuthenticatedDataStreamGenerator has gained matching open(out, inputLength, macCalculator) methods (the MAC algorithm must have a spec-fixed output length, i.e. the HMAC family, so the mac field can be sized before the content streams; authenticated attribute sets are sized with a placeholder digest). The default remains BER and BER output is unchanged; note that a parse of a fully definite-length message now also re-encodes definite-length rather than being forced back to BER (issue #1296).
- CMS EnvelopedData now supports RFC 8418 ECDH key agreement using X25519 or X448 with HKDF (SHA-256/384/512). Three CMSAlgorithm constants (ECDH_HKDF_SHA256, ECDH_HKDF_SHA384, ECDH_HKDF_SHA512) and the corresponding KeyAgreement registrations (XDHwithSHA256HKDF / XDHwithSHA384HKDF / XDHwithSHA512HKDF) have been added (issue #1845).
- The SM2 JCE Cipher now accepts a ciphertext-format mode in the transformation string. Cipher.getInstance("SM2/C1C3C2/NoPadding", "BC") and Cipher.getInstance("SM2/C1C2C3/NoPadding", "BC") select between the two SM2Engine modes; the previous "SM2"/"SM2/NONE/NoPadding" forms continue to default to C1C2C3 (issue #1302).
- SimplePKIResponse now also accepts the unsigned Full PKI Response variant used for EST server-generated errors (RFC 7030 4.2.3 / 4.4.2): a CMS SignedData carrying an id-cct-PKIResponse PKIResponse SEQUENCE. New accessors getPKIResponse(), getControlAttributes(), getCmsContents() and getStatusInfoV2() return the embedded content as structured TaggedAttribute / TaggedContentInfo / CMCStatusInfoV2 objects. A new PKIResponseBuilder assembles SimplePKIResponse instances for both shapes — the Full PKI Response error case (addControlAttribute / addStatusInfoV2 / addCmsContent / addOtherMsg) and the cert-delivery success case used by EST /simpleenroll (addCertificate). CMSSignedData has a new getSignedContentType() returning the encapsulated content type as an ASN1ObjectIdentifier (issue #1452).
- org.bouncycastle.gpg.KeyGripCalculator computes the GnuPG-style 20-byte SHA-1 keygrip for a BCPGKey. The calculator is constructed with a caller-supplied SHA-1 PGPDigestCalculator. RSA public keys are supported initially (matching libgcrypt's _gcry_rsa_compute_keygrip: SHA-1 of the canonical unsigned big-endian modulus); other key types throw on calculateKeygrip() until support is added (issue #676).
- CMS key transport now supports the SM2 cipher: JceKeyTransRecipientInfoGenerator wraps the CEK and JceKeyTransRecipient unwraps it when the keyEncryptionAlgorithm is GMObjectIdentifiers.sm2encrypt_with_sm3. The ciphertext format defaults to C1C3C2 (GB/T 35276 envelope encoding) and the SM4-CBC content encryption is exposed as the new CMSAlgorithm.SM4_CBC constant.
- org.bouncycastle.asn1.pkcs.SecretBag — RFC 7292 ASN.1 holder for the PKCS#12 secretBag bag type, complementing the existing CertBag / CRLBag classes. PKCS12SecretBag and PKCS12SecretBagBuilder in org.bouncycastle.pkcs sit alongside the SafeBag / SafeBagBuilder pair: PKCS12SafeBagBuilder takes a PKCS12SecretBag in a new constructor, and PKCS12SafeBag.getBagValue() returns a PKCS12SecretBag for safe bags of type secretBag.
- JCE provider plumbing for the LEA (Lightweight Encryption Algorithm) block cipher built on the existing core LEAEngine. Cipher.LEA (ECB) plus the standard transformation forms (LEA/CBC/PKCS5Padding etc.), Cipher.LEA-GCM, Cipher.LEA-CCM, Mac.LEA-CMAC / LEA-GMAC / LEA-Poly1305, KeyGenerator.LEA and SecretKeyFactory.LEA are registered, with 128/192/256-bit keys supported.
- org.bouncycastle.pkcs.util.PKCS12Util replaces org.bouncycastle.jce.PKCS12Util as the canonical helper for re-encoding PKCS#12 files to definite length. The new class additionally understands RFC 9579 PBMAC1-protected PFX files (the deprecated org.bouncycastle.jce.PKCS12Util threw UnsupportedOperationException for those). Existing org.bouncycastle.jce.PKCS12Util callers continue to work for the legacy SHA-based PBE MAC; the class is now annotated @Deprecated.
- HashMLDSASigner now exposes generateSignature(hash) and verifySignature(hash, signature) overloads alongside the streaming Signer API, letting callers feed an externally computed digest into HashML-DSA without having to stream the message through update(...). The DER-encoded digest OID is taken from the parameter set the signer was initialised with. The same external-hash mode is exposed through the BC JCE provider via Signature.getInstance("ML-DSA-{44,65,87}-WITH-SHA512-EXTERNAL-HASH", "BC") (plus the parameter-set-agnostic "HASH-ML-DSA-EXTERNAL-HASH"); Signature.update(...) accepts the pre-computed SHA-512 digest in place of the message, and a wrong-length input is reported as a SignatureException (issue #2198).
- BLS signatures over the BLS12-381 curve, per draft-irtf-cfrg-bls-signature, in the new org.bouncycastle.crypto.bls package. Public keys are 48-byte compressed G1 points and signatures 96-byte compressed G2 points in the Zcash encoding used by Eth2 consensus clients, Filecoin and Zcash. All three variants are provided as static-API classes — BLS12_381BasicScheme (suite NUL_), BLS12_381MessageAugmentation (AUG_) and BLS12_381ProofOfPossession (POP_, with PopProve / PopVerify and a fastAggregateVerify path) — each offering KeyGen, SkToPk, KeyValidate, Sign, Verify, Aggregate and AggregateVerify, with a BC-conventional BLSSigner / BLSKeyPairGenerator / BLSParameters surface alongside. Aggregate-verify enforces the draft §2.9 per-message aggregated-key identity-rejection check on every path (including ProofOfPossession), blocking the rogue-key cancellation forgery in which an attacker holding pk and -pk submits an aggregate whose contributions cancel in the pairing equation. Built on RFC 9380 hash-to-curve, the optimal ate pairing (with a multi-pairing that shares one final exponentiation across N verifications), endomorphism-based subgroup checks, and constant-time scalar multiplication on all secret-scalar paths. KAT-tested against the RFC 9380 Appendix J vectors and cross-checked byte-for-byte against the Eth2 bls12-381-tests vectors (Lighthouse / Prysm / Teku / Nimbus / Lodestar).
- XChaCha20 stream cipher and XChaCha20-Poly1305 AEAD per draft-irtf-cfrg-xchacha-03. New lightweight types org.bouncycastle.crypto.engines.XChaCha20Engine (extends ChaCha7539Engine) and org.bouncycastle.crypto.modes.XChaCha20Poly1305 (extends ChaCha20Poly1305) take a 256 bit key and a 192 bit nonce: the first 128 bits of nonce + key feed HChaCha20 to derive a 256 bit subkey, which is then used with the remaining 64 bits of nonce (prefixed with four zero bytes to form a 96 bit IETF nonce) to drive a standard ChaCha20-IETF stream. The 192 bit nonce removes the per-key counter / deterministic-nonce constraint of the standard ChaCha20-Poly1305 by making collisions negligibly likely up to ~2^80 random nonces per key. Registered in the BC JCE provider as Cipher.XChaCha20 / Cipher.XChaCha20-Poly1305 with matching KeyGenerator.XChaCha20 and AlgorithmParameters entries; ChaCha20Poly1305's underlying engine and nonce size are now extension points so XChaCha20-Poly1305 reuses the existing AEAD construction unchanged (issue #631).
- BcPasswordRecipientInfoGenerator / JcePasswordRecipientInfoGenerator now reject AES_GCM, AES_WRAP and AES_WRAP_PAD as kekAlgorithm with a message that points the caller at RFC 3211 sec. 2.3 (PWRI-KEK requires a CBC-mode block cipher inner KEK, distinct from the AEAD or wrap algorithm used for the content encryption). The previous error "cannot find key size for algorithm: ..." was opaque. As a related broadening of legitimate PWRI-KEK support, the kek size lookup table and the BcCMS createRFC3211Wrapper factory now also recognise CAMELLIA{128,192,256}_CBC, complementing the JCE-side CamelliaRFC3211Wrap registration (issue #491).
- SignerInformation now offers a three-argument addCounterSigners(SignerInformation outer, SignerId targetCounterSigner, SignerInformationStore counterSigners) overload that nests the supplied counter-signers underneath the counter-signer in `outer`'s subtree whose SID matches `targetCounterSigner`, rebuilding the containing SignerInfos on the way back up. The existing two-argument form remains unchanged and still attaches its counter-signers as peers of any existing counter-signers (an additional counterSignature attribute in `outer`'s unsignedAttributes, per RFC 5652 sec. 11.4) — callers who wanted to build a counter-counter-signature tree previously had no way to do so. Counter-signatures live in unsignedAttributes, which is not covered by the enclosing signer's signature, so the rewrite preserves all existing signatures (issue #769).
- RFC 9802 ("Use of the HSS and XMSS Hash-Based Signature Algorithms in Internet X.509 Public Key Infrastructure") support. The HSS/LMS leg (id-alg-hss-lms-hashsig, raw public key in the subjectPublicKey BIT STRING) was already in place; XMSS and XMSS^MT now follow suit: the new IANAObjectIdentifiers constants id_alg_xmss_hashsig (1.3.6.1.5.5.7.6.34) and id_alg_xmssmt_hashsig (1.3.6.1.5.5.7.6.35) are used as the public key and signature AlgorithmIdentifier (parameters absent), with the raw RFC 8391 public key (u32str(oid) || root || SEED) carried directly in the BIT STRING with no OCTET STRING wrapping, and the raw signature carried directly in the signatureValue. SubjectPublicKeyInfoFactory, the BCPQC XMSS/XMSSMT KeyFactory/Signature registrations, the BC-provider key-info converters and DefaultSignatureAlgorithmIdentifierFinder/DefaultSignatureNameFinder all produce and recognise the RFC form; the two legacy forms — the draft-vangeest-x509-hash-sigs encoding (OIDs 0.4.0.127.0.15.1.1.13.0 / 14.0 with the key DER-wrapped in an OCTET STRING) and the original BC-proprietary parameterised form — continue to be read, as do mixed wrapped/unwrapped variants of either OID set. As a related hardening, decoding an XMSS / XMSS^MT SubjectPublicKeyInfo whose RFC 8391 parameter-set identifier is unrecognised now fails with an IOException naming the identifier rather than a NullPointerException. Note keys generated for non-standard tree heights (no RFC 8391 identifier exists for them) still encode in the BC-proprietary form. The three self-signed example certificates from RFC 9802 Appendices A-C (HSS, XMSS, XMSS^MT) are carried as interop vectors in the certificate test battery — each is decoded through the standard BC CertificateFactory and its self-signature verified (issue #2002).
- Support for the legacy (pre-RFC 3161) Microsoft Authenticode time stamping protocol, the PKCS#9-countersignature-based protocol behind "signtool /t". The new ASN.1 class org.bouncycastle.asn1.microsoft.TimeStampRequest models the wire-format request — countersignatureType OBJECT IDENTIFIER, optional Attributes, and a ContentInfo of type data carrying the signature (encryptedDigest) to be countersigned — and MicrosoftObjectIdentifiers gains the SPC_TIME_STAMP_REQUEST_OBJID countersignature type OID (microsoftTimeStampRequest, 1.3.6.1.4.1.311.3.2.1). The response is a plain PKCS#7 SignedData incorporated as a PKCS#9 countersignature, which the existing CMS API already covers; a self-contained end-to-end example (request construction, in-process time stamp service, countersignature attachment, certificate merge and verification of both signatures) ships as misc/src/main/java/org/bouncycastle/cms/examples/AuthenticodeTimeStampExample.java (issue #2005).
- The Gradle build now exposes a top-level `copyJars` task (in the `distribution` group) that gathers the produced jars (main, sources and javadoc) for `bccore`, `bcutil`, `bcprov`, `bcpkix`, `bcpg`, `bctls`, `bcmls`, `bcmail` and `bcjmail` into a single `dist/` directory at the project root, providing a "dist"-style aggregate output for consumers who don't want to scrape each module's `build/libs` directory. The directory is cleared at the start of each invocation so stale version artifacts don't accumulate. A sibling `copyMavenJars` task produces the same set minus `bccore`, matching the artifacts published to Maven Central (`bccore`'s classes are already bundled into `bcprov`) (issue #2301).
- PEMUtilities.crypt (used by JcePEMEncryptorBuilder / JcePEMDecryptorProviderBuilder for the OpenSSL legacy PEM private-key encryption form — "Proc-Type: 4,ENCRYPTED" / "DEK-Info: <alg>,<iv-hex>") now recognises the SM4- algorithm-name prefix alongside AES-/DES-/DES-EDE-/BF-/RC2-, so an EC or RSA private key written with DEK-Info: SM4-CBC,<iv> can be parsed and decrypted via the normal PEMParser path instead of throwing "unknown encryption with private key". JcePEMEncryptorBuilder additionally now chooses a 16-byte IV for SM4- algorithms (matching AES- and SM4's 128-bit block size); previously SM4- would have used the 8-byte default applied to the 64-bit-block legacy ciphers. SM4 has a fixed 128-bit key; key derivation follows the same OpenSSL EVP_BytesToKey path the AES- branch uses (PBKDF-OpenSSL SecretKeyFactory, first 8 bytes of IV as salt). Issue #1066. Note: this is the legacy OpenSSL PEM encryption format, distinct from the PKCS#5 PBES2 EncryptedPrivateKeyInfo SM4-CBC support added under issue #1454.
- JceOpenSSLPKCS8EncryptorBuilder and JceOpenSSLPKCS8DecryptorProviderBuilder (and the underlying PEMUtilities cipher / PRF tables) now support SM4-CBC as a PBES2 content-encryption algorithm and HMAC-SM3 as a PBKDF2 PRF, alongside the existing AES-CBC / 3DES-CBC ciphers and HMAC-SHA-{1,224,256,384,512} / SHA-3 / GOST3411 PRFs. PKCS8Generator and JceOpenSSLPKCS8EncryptorBuilder expose the new SM4_CBC constant (GMObjectIdentifiers.sms4_cbc, 1.2.156.10197.1.104.2) and PKCS8Generator exposes PRF_HMACSM3 (GMObjectIdentifiers.hmac_sm3) so callers can produce a GM/T-aligned encrypted PKCS#8 in a single line, e.g. new JceOpenSSLPKCS8EncryptorBuilder(PKCS8Generator.SM4_CBC).setProvider("BC").setPRF(PKCS8Generator.PRF_HMACSM3).setPassword(...).build(). The BC JCE provider's SM4 registration gained AlgorithmParameters / AlgorithmParameterGenerator OID aliases for sms4_cbc so the standard PKCS#8 / PBES2 lookup pipeline resolves correctly (issue #1454).
- A new convenience class org.bouncycastle.openssl.jcajce.JcaPrivateKeyReader reads a private key from a file, stream, byte[] or Reader and returns a java.security.PrivateKey, auto-detecting the encoding: PKCS#1 (traditional "RSA PRIVATE KEY") and PKCS#8 keys, in PEM or DER, including the password-protected variants (DEK-Info traditional PEM and EncryptedPrivateKeyInfo / "ENCRYPTED PRIVATE KEY") which are decrypted with a supplied password. PEM forms are dispatched by the type PEMParser returns and DER forms by the structure of the outermost SEQUENCE (no element-count heuristics); a bare PKCS#1 RSAPrivateKey is wrapped as a PKCS#8 PrivateKeyInfo with the rsaEncryption algorithm identifier before conversion. The writers (JcaPKCS8Generator / JcePEMEncryptorBuilder / JceOpenSSLPKCS8EncryptorBuilder) are unchanged and remain the way to emit keys. org.bouncycastle.openssl.jcajce.JcaPKIXIdentityBuilder now delegates its key parsing to the new reader and gains a setPassword(char[]) method, so it loads encrypted private keys (previously it failed with "unrecognised private key file"). Based on initial work contributed in github #597.
- RFC 7894 "Alternative Challenge Password Attributes for Enrollment over Secure Transport (EST)" support. Three new PKCS#9 OIDs in the id-aa branch — id_aa_otpChallenge (id-aa 56), id_aa_revocationChallenge (id-aa 57) and id_aa_estIdentityLinking (id-aa 58) — and matching typed value classes OtpChallenge, RevocationChallenge and EstIdentityLinking under org.bouncycastle.asn1.est. Each wraps a DirectoryString (SIZE 1..255), picks the PrintableString encoding when the input is in the printable subset and falls back to UTF8String otherwise (per RFC 7894 §3 SHOULD), and exposes toAttribute() / fromAttribute(Attribute) helpers for round-tripping through a PKCS#9 Attribute inside a CertificationRequest or CSR-Attributes response. The existing CSRAttributesResponse indexer recognises the new OIDs automatically. ESTService.enrollPop / simpleEnrollPoP / simpleEnrollPopWithServersideCreation gain new overloads accepting a CSRAttributesResponse, and a new public org.bouncycastle.est.TlsUniqueAttributeUtil helper centralises the RFC 7894 §4 attribute-selection rule: when the server's CSR-Attributes response advertises id-aa-estIdentityLinking, the tls-unique value is conveyed in that attribute (preferred); otherwise the legacy pkcs_9_at_challengePassword attribute is used (RFC 7030 §3.5). Existing enrollment overloads remain byte-for-byte unchanged on the wire for callers that don't pass a CSR-Attributes response (issue #338).
- JceCMSContentEncryptorBuilder and BcCMSContentEncryptorBuilder now accept a caller-supplied content-encryption key via new build overloads: JceCMSContentEncryptorBuilder.build(SecretKey) and build(byte[]), and BcCMSContentEncryptorBuilder.build(byte[]) and build(KeyParameter). The original build() variant continues to draw a fresh key internally (correct for CMS EnvelopedData, where the CEK is freshly drawn per message and wrapped per recipient). The new overloads support the CMS EncryptedData use case (no recipients, long-lived locally-stored key) and the case where the CEK is supplied by an external KMS such as AWS Nitro Enclaves (issues #1509 / #2115). The BcCMSContentEncryptorBuilder.build(KeyParameter) form is the lightweight peer of JceCMSContentEncryptorBuilder.build(SecretKey) and lets callers who already hold a BC KeyParameter (e.g. from an HKDF or a lightweight key agreement) feed it in without an intermediate byte[] round trip.
- FAEST post-quantum digital signature scheme per the FAEST v2.0 algorithm specification (NIST PQC additional digital signatures process). Lightweight implementation in org.bouncycastle.pqc.crypto.faest covering all twelve parameter sets — base FAEST (AES one-way function): faest_128s/f, faest_192s/f, faest_256s/f; and FAEST-EM (Even-Mansour one-way function): faest_em_128s/f, faest_em_192s/f, faest_em_256s/f — via FaestKeyPairGenerator, FaestSigner and the matching FaestPublicKeyParameters / FaestPrivateKeyParameters. JCE provider plumbing is registered through BCPQC: KeyPairGenerator.Faest, Signature.Faest, KeyFactory.Faest, FaestParameterSpec (twelve constants + fromName lookup), FaestKey interface and BCFaestPublicKey / BCFaestPrivateKey. Twelve BC-arc OIDs in BCObjectIdentifiers (faest.{1..12}) cover the SubjectPublicKeyInfo / PrivateKeyInfo wire form via the PublicKeyFactory / PrivateKeyFactory / SubjectPublicKeyInfoFactory / PrivateKeyInfoFactory converter plumbing, and BouncyCastleProvider.loadPQCKeys() registers a FaestKeyFactorySpi against each OID so the standard BC provider can decode FAEST-bearing certificates and PKCS#8 keys without BCPQC in the lookup chain.
- HAETAE post-quantum digital signature scheme (KpqC, Korean Post-Quantum Cryptography competition). Lightweight implementation in org.bouncycastle.pqc.crypto.haetae covering all three parameter sets — HAETAE-2, HAETAE-3 and HAETAE-5 (NIST security levels 2, 3 and 5) — via HAETAEKeyPairGenerator, HAETAESigner and the matching HAETAEPublicKeyParameters / HAETAEPrivateKeyParameters. JCE provider plumbing is registered through BCPQC: KeyPairGenerator.Haetae, Signature.Haetae, KeyFactory.Haetae, HaetaeParameterSpec (three constants + fromName lookup), HaetaeKey interface and BCHaetaePublicKey / BCHaetaePrivateKey, along with per-parameter-set aliases (HAETAE-2 / HAETAE-3 / HAETAE-5). Three BC-arc OIDs in BCObjectIdentifiers (haetae.{1..3} under bc-sig.18) cover the SubjectPublicKeyInfo / PrivateKeyInfo wire form via the PublicKeyFactory / PrivateKeyFactory / SubjectPublicKeyInfoFactory / PrivateKeyInfoFactory converter plumbing, and BouncyCastleProvider.loadPQCKeys() registers a HaetaeKeyFactorySpi against each OID so the standard BC provider can decode HAETAE-bearing certificates and PKCS#8 keys without BCPQC in the lookup chain.
- Hawk post-quantum digital signature scheme (NIST PQC additional digital signatures process). Lightweight implementation in org.bouncycastle.pqc.crypto.hawk covering the three parameter sets hawk-256, hawk-512 and hawk-1024 via HawkKeyPairGenerator, HawkSigner and the matching HawkPublicKeyParameters / HawkPrivateKeyParameters; HawkSigner.generateSignature returns the signature bytes only, per the MessageSigner contract. JCE provider plumbing is registered through BCPQC: KeyPairGenerator.Hawk, Signature.Hawk, KeyFactory.Hawk, HawkParameterSpec (three constants + fromName lookup), HawkKey interface and BCHawkPublicKey / BCHawkPrivateKey. Three BC-arc OIDs in BCObjectIdentifiers (hawk.{1..3} under bc-sig.15) cover the SubjectPublicKeyInfo / PrivateKeyInfo wire form via the PublicKeyFactory / PrivateKeyFactory / SubjectPublicKeyInfoFactory / PrivateKeyInfoFactory converter plumbing, and BouncyCastleProvider.loadPQCKeys() registers a HawkKeyFactorySpi against each OID so the standard BC provider can decode Hawk-bearing certificates and PKCS#8 keys without BCPQC in the lookup chain.
- QR-UOV (Quotient-Ring Unbalanced Oil and Vinegar) post-quantum digital signature scheme per the QR-UOV Round 2 NIST submission. Lightweight implementation in org.bouncycastle.pqc.crypto.qruov covering all twelve parameter sets across NIST security categories 1/3/5 — (q=127,L=3,v=156,m=54), (q=31,L=3,v=165,m=60), (q=31,L=10,v=600,m=70), (q=7,L=10,v=740,m=100), and the cat-3 / cat-5 dimensions — via QRUOVKeyPairGenerator, QRUOVSigner and the matching QRUOVPublicKeyParameters / QRUOVPrivateKeyParameters. Each parameter set is offered in both PRG flavours from the QR-UOV reference (AES-CTR and SHAKE), accessible via the qruov_*_aes and qruov_*_shake constants on QRUOVParameters and exercised against both kat_aes/ and kat_shake/ NIST KAT trees in core/src/test. JCE provider plumbing is registered through BCPQC: KeyPairGenerator.QRUOV, Signature.QRUOV, KeyFactory.QRUOV, QRUOVParameterSpec (twelve constants + fromName lookup), QRUOVKey interface and BCQRUOVPublicKey / BCQRUOVPrivateKey. The JCE surface exposes the canonical SHAKE-PRG variant; twelve BC-arc OIDs in BCObjectIdentifiers (qruov.{1..12} under bc-sig.17) cover the SubjectPublicKeyInfo / PrivateKeyInfo wire form via the PublicKeyFactory / PrivateKeyFactory / SubjectPublicKeyInfoFactory / PrivateKeyInfoFactory converter plumbing, and BouncyCastleProvider.loadPQCKeys() registers a QRUOVKeyFactorySpi against each OID so the standard BC provider can decode QR-UOV-bearing certificates and PKCS#8 keys without BCPQC in the lookup chain.
- PGPPublicKey.copyMinimal(KeyFingerPrintCalculator) and PGPPublicKeyRing.copyMinimal(KeyFingerPrintCalculator) return a copy of a public key (or public-key ring) carrying only the underlying public-key packets — user IDs, user-attribute packets, trust packets, key certifications and subkey-binding signatures are all dropped. The master/subkey distinction is preserved through the packet types (PublicKeyPacket vs PublicSubkeyPacket). Useful for producing a minimal key for OpenPGP v6 revocation-certificate distribution, stripping irrelevant user IDs / attribute packets from a key downloaded from a key server, or wire-size reduction (issue #1400).
- TestResourceFinder (the six per-module copies under <module>/src/test/java/org/bouncycastle/test/) now picks the bc-test-data root via, in order, the bc.test.data.home system property, the BC_TEST_DATA_HOME environment variable, and finally the existing walk-up-from-working-directory search. When the property or environment variable is set its value is used directly, and a mistyped path now fails fast with a FileNotFoundException naming the source (-Dbc.test.data.home or $BC_TEST_DATA_HOME) and the bad path rather than silently falling through. The walk-up fallback preserves the default sibling-checkout convention (bc-test-data alongside bc-java) so existing setups keep working without configuration. The Gradle build no longer sets the property itself; supply -Dbc.test.data.home=... or export BC_TEST_DATA_HOME=... only when the layout differs from the sibling convention.
- Initial support for Merkle Tree Certificates, tracking the published draft-ietf-plants-merkle-tree-certs-05 (uint48 start/end widths in MTCProof, the CosignedMessage signature format with the 12-byte "subtree/v1\n\0" label, the id-pe-mtcCertificationAuthority CA-cert extension, and the MerkleTreeCertEntryExtension list carried at the front of both MerkleTreeCertEntry and MTCProof). New OID arc in org.bouncycastle.asn1.plants (MTCObjectIdentifiers — placeholder constants under Cloudflare's IANA PEN to be deleted when IANA assigns the production OIDs). High-level types in org.bouncycastle.cert.plants (JCA-free and lightweight-crypto-free operator abstractions): MTCSignature carries the TLS-encoded cosigner_id / signature pair; MerkleTreeCertEntryExtension carries a single (extension_type, extension_data) pair; MTCProof wraps the signatureValue carried inside a Merkle Tree certificate (ordered extensions list, uint48 start / end pair, inclusion proof, ordered list of MTCSignatures) with strict length and ordering enforcement; MTCCosignedMessage encodes the draft sec. 5.3.1 CosignedMessage wire form; MerkleTreeHash is the hash-function operator and MerkleTreePrimitives implements the RFC 6962-style subtree inclusion / consistency / covering algorithms over it; InvalidProofException reports proof-validation failures; MTCSignatureVerifier and MTCCosignerVerifier / MTCCosignerVerifierProvider are the operator interfaces the validator and the trusted-subtree manager call to verify cosigner signatures; MerkleTreeCertificateValidator reconstructs the per-leaf inclusion proof (writing the MTCProof's extensions wire bytes into the hash per sec. 7.2 step 8.2) and dispatches cosigner verification through the operator, with relying-party policy expressed as log-scoped trusted subtrees (sec. 7.4) and revoked serial-number ranges (sec. 7.5) in ValidationParams; LandmarkSequence parses the published landmark wire form; LandmarkCertificateManager / MTCCertificationAuthorityCertificate / TrustAnchorIDs cover the issuance-side and trust-anchor binary identifier handling. Lightweight bindings live in org.bouncycastle.cert.plants.bc: BcSha256MerkleTreeHash implements MerkleTreeHash using SHA-256, BcMTCSignatureVerifier dispatches to the appropriate lightweight Signer for the cosigner's algorithm identifier, and BcMTCCosignerVerifierProvider routes through them. Parallel JCA bindings live in org.bouncycastle.cert.plants.jcajce — JcaSha256MerkleTreeHash, JcaMTCSignatureVerifier and JcaMTCCosignerVerifierProvider — taking a JcaJceHelper / Provider so callers can pin to a specific JCE provider; the draft algorithm identifiers map to JCA Signature names internally (ECDSA-P256-SHA256 / ECDSA-P384-SHA384 use SHA{256,384}WITHPLAIN-ECDSA so the wire-format r||s signature bytes round-trip). Two supporting X.509 ASN.1 types — org.bouncycastle.asn1.x509.MTCCertificationAuthority and TBSCertificateLogEntry — and a new X509Extension entry round out the certificate-side plumbing.
- MQOM v2.1 ("MQ on my Mind") post-quantum digital signature scheme (NIST PQC additional digital signatures process, round 2). Lightweight implementation in org.bouncycastle.pqc.crypto.mqom covering all thirty-six parameter sets — categories cat1/cat3/cat5 across base fields gf2/gf16/gf256, fast/short trade-offs and r3/r5 variants — via MQOMKeyPairGenerator, MQOMSigner and the matching MQOMPublicKeyParameters / MQOMPrivateKeyParameters. JCE provider plumbing is registered through BCPQC: KeyPairGenerator.MQOM, Signature.MQOM, KeyFactory.MQOM, MQOMParameterSpec (thirty-six constants + fromName lookup), MQOMKey interface and BCMQOMPublicKey / BCMQOMPrivateKey. Thirty-six BC-arc OIDs in BCObjectIdentifiers (mqom.{1..36}) cover the SubjectPublicKeyInfo / PrivateKeyInfo wire form via the PublicKeyFactory / PrivateKeyFactory / SubjectPublicKeyInfoFactory / PrivateKeyInfoFactory converter plumbing, and BouncyCastleProvider.loadPQCKeys() registers an MQOMKeyFactorySpi against each OID so the standard BC provider can decode MQOM-bearing certificates and PKCS#8 keys without BCPQC in the lookup chain.
- UOV (Unbalanced Oil and Vinegar) post-quantum digital signature scheme (NIST PQC additional digital signatures process, round 2; pqov reference). Lightweight implementation in org.bouncycastle.pqc.crypto.uov covering all twelve parameter sets — security levels Is, Ip, III and V across encoding variants classic (uncompressed), pkc (compressed public key) and pkc_skc (compressed public key and seed-only secret key) — via UOVKeyPairGenerator, UOVSigner and the matching UOVPublicKeyParameters / UOVPrivateKeyParameters. JCE provider plumbing is registered through BCPQC: KeyPairGenerator.UOV, Signature.UOV, KeyFactory.UOV, UOVParameterSpec (twelve constants + fromName lookup), UOVKey interface and BCUOVPublicKey / BCUOVPrivateKey. Twelve BC-arc OIDs in BCObjectIdentifiers (uov.{1..12}) cover the SubjectPublicKeyInfo / PrivateKeyInfo wire form via the PublicKeyFactory / PrivateKeyFactory / SubjectPublicKeyInfoFactory / PrivateKeyInfoFactory converter plumbing, and BouncyCastleProvider.loadPQCKeys() registers a UOVKeyFactorySpi against each OID so the standard BC provider can decode UOV-bearing certificates and PKCS#8 keys without BCPQC in the lookup chain.
- SQIsign (Short Quaternion and Isogeny Signature) post-quantum digital signature scheme (NIST PQC additional digital signatures process, round 2; reference C implementation). Lightweight implementation in org.bouncycastle.pqc.crypto.sqisign covering all three NIST-API parameter sets — sqisign_lvl1, sqisign_lvl3 and sqisign_lvl5 (NIST security categories I, III and V) — via SQIsignKeyPairGenerator, SQIsignSigner and the matching SQIsignPublicKeyParameters / SQIsignPrivateKeyParameters. The engine implements the full SQIsign pipeline — quaternion-order and ideal arithmetic, the ideal-to-isogeny correspondence (Clapotis), theta-coordinate 2-dimensional (dim-2) isogenies and per-security-level GF(p²) field arithmetic — and reproduces the reference C implementation's known-answer-test vectors (public key, secret key and signature) byte-for-byte. JCE provider plumbing is registered through BCPQC: KeyPairGenerator.SQIsign, Signature.SQIsign, KeyFactory.SQIsign with per-parameter-set aliases; SQIsignParameterSpec (three constants + case-insensitive fromName lookup), SQIsignKey interface and BCSQIsignPublicKey / BCSQIsignPrivateKey. Three BC-arc OIDs in BCObjectIdentifiers (sqisign.{1..3}) cover the SubjectPublicKeyInfo / PrivateKeyInfo wire form via the PublicKeyFactory / PrivateKeyFactory / SubjectPublicKeyInfoFactory / PrivateKeyInfoFactory converter plumbing, and BouncyCastleProvider.loadPQCKeys() registers an SQIsignKeyFactorySpi against each OID so the standard BC provider can decode SQIsign-bearing certificates and PKCS#8 keys without BCPQC in the lookup chain. Note: SQIsign signing and key generation are not constant-time — the arithmetic is BigInteger-based throughout (base field, elliptic-curve and the secret-dependent quaternion / ideal / lattice layers) and includes secret-dependent rejection and lattice-reduction loops, matching the reference implementation.
- SDitH (Syndrome-Decoding-in-the-Head) post-quantum digital signature scheme (NIST PQC additional digital signatures process, round 2). Lightweight implementation in org.bouncycastle.pqc.crypto.sdith covering all twelve parameter sets — both MPC structures (Hypercube and Threshold) across NIST categories cat1/cat3/cat5 and base fields gf256/p251 — via SDitHKeyPairGenerator, SDitHSigner and the matching SDitHPublicKeyParameters / SDitHPrivateKeyParameters. SDitHSigner dispatches between SDitHEngine (hypercube; seed-tree + per-iteration MPC simulation) and SDitHThresholdEngine (threshold; Shamir-style linear secret sharing + per-execution Merkle tree of party-share commitments) via SDitHParameters.getVariant(). JCE provider plumbing is registered through BCPQC: KeyPairGenerator.SDitH, Signature.SDitH, KeyFactory.SDitH, SDitHParameterSpec (twelve constants + fromName lookup), SDitHKey interface and BCSDitHPublicKey / BCSDitHPrivateKey, plus parameter-locked SPIs for each of SDITH-{HYPERCUBE,THRESHOLD}-CAT{1,3,5}-{GF256,P251}. Twelve BC-arc OIDs in BCObjectIdentifiers (sdith.{1..12}) cover the SubjectPublicKeyInfo / PrivateKeyInfo wire form via the PublicKeyFactory / PrivateKeyFactory / SubjectPublicKeyInfoFactory / PrivateKeyInfoFactory converter plumbing, and BouncyCastleProvider.loadPQCKeys() registers an SDitHKeyFactorySpi against each OID so the standard BC provider can decode SDitH-bearing certificates and PKCS#8 keys without BCPQC in the lookup chain. The generic KeyFactory.SDitH accepts X509EncodedKeySpec / PKCS8EncodedKeySpec for all twelve parameter sets, including the threshold variants (issue #2312).
- SDitH performance: the GF(256) scalar-times-vector multiply-accumulate at the heart of the matmul and the threshold engine's share arithmetic is now word-parallel and bitsliced — eight field elements per long via the constant-time mask-select / SWAR-xtime kernel in the new public org.bouncycastle.util.GF256 (companion to util.GF16; the same primitive UOV's vecMadd256 uses), giving roughly 2x faster gf256 signing with byte-identical output, and the GF(251^4) extension-field multiplication is flattened from a nested 16-multiplication tower to the optimized reference's 9-multiplication deferred-reduction form. Both changes are oracle-verified against the naive kernels and KAT-identical across all twelve parameter sets (issue #2312).
- Initial decode-only support for Certificate Transparency, covering both RFC 6962 (CT v1) and RFC 9162 (CT v2). New OID constants on X509ObjectIdentifiers for the Google 11129 arc (id_ce_ct_embeddedSCTList = 1.3.6.1.4.1.11129.2.4.2, id_ce_ct_precertPoison, id_kp_ct_precertSigning, id_ocsp_ct_sctList) plus the v2 1.3.101 arc (id_ce_ct_transparencyInformation = 1.3.101.75 server-cert extension, id_ct_precertificate = 1.3.101.78 CMS eContentType). New org.bouncycastle.cert.ct package carries the TLS-encoded wire types: SignedCertificateTimestamp / SignedCertificateTimestampList (v1) and TransItem / TransItemList / SignedCertificateTimestampDataV2 / SctExtension (v2). Each list type exposes a fromExtensions(Extensions) helper that walks the corresponding extension OID; each wire type round-trips through getEncoded(). A misc/.../cert/examples/CTSCTListExample.java prints the embedded SCTs from a DER or PEM certificate supplied on the command line. Verifying an SCT against a log's STH (fetching the inclusion proof and checking the log's public-key signature) is intentionally not in scope for this round — those layer onto the wire types added here. github #228.
- Initial support for draft-ietf-lamps-certdiscovery (Certificate Discovery in PKIX). Two new ASN.1 types under org.bouncycastle.asn1.x509 — CertDiscoveryMethod (CHOICE over byUri [0] IMPLICIT IA5String / byInclusion Certificate / byLocalPolicy NULL) and RelatedCertificateDescriptor (SEQUENCE { method, intent OID OPTIONAL, signatureAlgorithm [0] IMPLICIT AlgorithmIdentifier OPTIONAL, publicKeyAlgorithm [1] IMPLICIT AlgorithmIdentifier OPTIONAL }) — plus a pkix-side org.bouncycastle.cert.RelatedCertificateDescriptorBuilder that emits an AccessDescription suitable for adding to the SubjectInfoAccess extension (accessLocation is an otherName GeneralName wrapping the descriptor). RelatedCertificateDescriptor.fromExtensions(Extensions) walks SIA on the read side and returns every certificate-discovery descriptor it carries. The draft OIDs (id-ad-certDiscovery, id-on-relatedCertificateDescriptor, id-rcd plus the five intent OIDs id-rcd-agility / -redundancy / -dual / -priv-key-stmt / -self) are TBD in the document, so BC ships them as placeholders under the BC private arc (BCObjectIdentifiers.id_ad_certDiscovery and friends at 1.3.6.1.4.1.22554.4.3 .. .5.5); the constant names match what IANA is expected to assign, so production callers will need to swap the values once the draft progresses to RFC.
- SMIMESignedGenerator's class Javadoc now explicitly documents that the MimeMultipart it returns sources the signature body part through a JavaMail DataHandler callback, so JavaMail re-runs the CMS signing pipeline on every MimeMessage.writeTo. The cryptographic signature still verifies on every call, but the wire bytes are not stable across calls for non-deterministic signature schemes (ECDSA / DSA / RSA-PSS) or whenever a fresh signing-time signed attribute is captured per call. Callers needing byte-for-byte stable serialisation should serialise the message once and reuse the bytes, or use SMIMESignedWriter from the pkix module which captures the signature once into a buffer and emits the inline body part directly (issue #1460).
- BCrypt.generate(byte[], byte[], int) is now @Deprecated and a new BCrypt.generate(byte[], byte[], int, boolean addTerminator) overload makes the bcrypt password-terminator decision explicit at the call site. addTerminator=true appends the spec-required 0x00 terminator byte (equivalent to feeding the input through BCrypt.passwordToByteArray(char[])) before the EksBlowfishSetup password schedule; addTerminator=false passes the supplied bytes through unchanged. addTerminator is ignored when pwInput.length is exactly 72 — there is no room for the terminator without exceeding the bcrypt 72-byte input limit, and two 72-byte inputs sharing a common prefix may collide in the same way an unterminated shorter input does. The deprecated 3-arg form delegates to the new overload with addTerminator=false and is byte-for-byte unchanged; it remains available for test-vector validation and interop with implementations that produce the 24-byte raw hash directly. For general password hashing use OpenBSDBCrypt — it handles termination, salt formatting and the modular crypt output line — and is the path most callers want (issue #1741).
- QCSyntaxExample in misc/src/main/java/org/bouncycastle/asn1/examples/ — decode-only worked example for the RFC 3739 qCStatements extension (1.3.6.1.5.5.7.1.3): reads an X.509 certificate (DER or PEM), walks the SEQUENCE OF QCStatement, and prints any id-qcs-pkixQCSyntax-v1 (RFC 3039) and id-qcs-pkixQCSyntax-v2 (RFC 3739) entries — for v2 decoding the statementInfo as SemanticsInformation (semanticsIdentifier + nameRegistrationAuthorities). Statements with any other statementId (for example the ETSI EN 319 412-5 statements) are printed as a raw ASN.1 dump so the example doubles as a starting point for inspecting unfamiliar qualified-certificate profiles (issue #1416).
- RFC 8702 "Use of the SHAKE One-Way Hash Functions in the Cryptographic Message Syntax (CMS)" KMAC support, completing the SHAKE-based CMS profile (the digest and RSASSA-PSS / ECDSA signature halves were already in place). New CMSAlgorithm.KMACwithSHAKE128 / KMACwithSHAKE256 constants and a JceCMSMacCalculatorBuilder path that emits an absent-parameters AlgorithmIdentifier when the defaults (256-bit / 512-bit output, empty customizationString) are in effect and a KMACwithSHAKEnnn-params SEQUENCE when they aren't. New jcajce.spec.KMACParameterSpec carries (macSizeInBits, customizationString) for non-default callers; the JCE Mac.KMAC128 / Mac.KMAC256 SPIs now accept this spec on engineInit and re-instantiate the underlying lightweight KMAC engine with the supplied customization, tracking the configured output length through engineGetMacLength / engineDoFinal. AlgorithmParameters.OID.id_KmacWithSHAKE{128,256} (and the SP 800-185 id_Kmac{128,256} OIDs) decodes the KMACwithSHAKEnnn-params SEQUENCE into a KMACParameterSpec via the new KMACwithSHAKE128_params / KMACwithSHAKE256_params ASN.1 holders, and Alg.Alias.Mac.<oid> aliases are added for all four OIDs so JCE lookups by OID resolve. EnvelopedDataHelper's MAC_ALG_NAMES picks up the two RFC 8702 OIDs, so CMS AuthenticatedData round-trips KMAC-with-SHAKE end-to-end (verified in NewAuthenticatedDataTest with default and non-default parameter sets for both KMAC128 and KMAC256).
- BIP-340 Schnorr signatures over secp256k1, the on-chain signature scheme used by Bitcoin Taproot. The lightweight class org.bouncycastle.crypto.signers.BIP340Signer implements org.bouncycastle.crypto.Signer for ECPrivateKeyParameters / ECPublicKeyParameters constrained to secp256k1, with the BIP-340 §3 tagged-SHA-256 challenge / aux / nonce hashes, even-Y normalisation on both the private and the ephemeral side, x-only 32-byte public keys and fixed 64-byte r||s signatures (none of which match BC's ECDSA defaults). The signer is randomized by default, following the usual BC low-level signer convention: a fresh 32-byte aux_rand is drawn per generateSignature() call (BIP-340 §3.2, recommended for side-channel hardening) from the SecureRandom supplied via ParametersWithRandom, or from the default CryptoServicesRegistrar source when none is supplied. Deterministic Schnorr (aux_rand = 0^32) is BIP-340 compliant but must be requested explicitly via new BIP340Signer(true) — the absence of a supplied SecureRandom does not silently select it. BIP340Signer.decodePublicKey(byte[32]) is exposed as the verifier-side helper, returning null for x-coordinates outside [0,p) or with no curve point — matching the cases BIP-340 §3.1 defines as verification failures. The BIP-340bis variable-length-message extension is supported. A lightweight example sits at misc/src/main/java/org/bouncycastle/crypto/examples/BIP340SignerExample.java; the official bitcoin/bips test vectors are exercised via core/src/test/java/org/bouncycastle/crypto/test/BIP340SignerTest.java (issue #1114).
- DeltaCertificateRequestAttributeValueBuilder (the draft-bonnell-lamps-chameleon-certs sec. 5 delta certificate request attribute builder) now exposes setExtensions(Extensions) so the [1] EXPLICIT extensions field can be populated; previously the builder could set only subject and signatureAlgorithm even though the parser already read the extensions field back. A new DeltaCertAttributeUtils.trimDeltaCertificateRequest(delta, baseRequest) helper encodes only the fields that differ from a base CSR (sec. 5.1), mirroring the cert-side DeltaCertificateTool.trimDeltaCertificateDescriptor: subject and signatureAlgorithm are dropped when they equal the base, and the extensions field drops any extension whose criticality and DER-encoded value match the base, whose type is absent from the base, or which is the delta-certificate-request OID itself. As part of the same change the builder now tags the extensions field [1] EXPLICIT to match the parser and the draft ASN.1 (issue #2234 / PR #2259).
- The GOST 34.10-2018 signature names are now registered as JCE aliases. GOST 34.10-2018 is the interstate (CIS/EAEU) re-adoption of GOST R 34.10-2012 and is algorithmically identical to it, using the same TC26 OIDs (1.2.643.7.1.1.1 / .1.1.2), so "ECGOST3410-2018", "ECGOST3410-2018-256", "ECGOST3410-2018-512" (and the dotted "GOST-3410-2018-*" spellings) now resolve onto the existing ECGOST3410-2012 KeyFactory, KeyPairGenerator, Signature and KeyAgreement implementations. No new engine is introduced; the aliases exist so callers naming the 2018 standard can obtain the algorithm directly (issue #1028).
- The BC JCE EdDSA Signature engines (Signature.getInstance("Ed25519"/"Ed448"/"EdDSA", "BC")) now honour an AlgorithmParameterSpec via setParameter, selecting the RFC 8032 instance: the prehash variants Ed25519ph / Ed448ph, and a context (Ed25519ctx, or the context permitted by Ed448 and the prehash variants). On JDK 15+ the standard java.security.spec.EdDSAParameterSpec is accepted, so BC can stand in for SunEC for prehash / context EdDSA signing and verification (verified by cross-provider interop, including byte-identical signatures since EdDSA is deterministic). On any JDK the BC org.bouncycastle.jcajce.spec.EdDSAParameterSpec carries the same selectors through its new (curveName, prehash) and (curveName, prehash, context) constructors and isPrehash() / getContext() accessors; a context longer than 255 bytes is rejected, and parameters must be set before initSign / initVerify. Previously setParameter threw UnsupportedOperationException and only the pure variants were reachable. The engines also now report the selected instance through Signature.getParameters() (null when no parameters were set, matching SunEC), and AlgorithmParameters.getInstance("Ed25519"/"Ed448", "BC") round-trips the selectors via the BC EdDSAParameterSpec (and, on JDK 15+, java.security.spec.EdDSAParameterSpec); these parameters have no encoded form, since RFC 8410 specifies the EdDSA AlgorithmIdentifier with absent parameters, so getEncoded() throws (issue #2313).
- ARIAEngine (RFC 5794) block processing has been rewritten for speed while remaining byte-identical. The state is held in two longs (eliminating the per-block byte[16] and its arraycopies) and the round transform A(SL(.)) is computed by a SWAR multiply-broadcast: because the ARIA diffusion A is a GF(2) involution, A applied to one substituted byte is that byte replicated at the seven output positions of its column, which is exactly the byte times a precomputed 0x01-packed mask, so a round becomes the XOR over the 16 input bytes of S-box(byte) * mask. This keeps only the existing 1KB S-boxes and 32 long constants resident (a full T-table form was tried and rejected — its larger tables lost to cache pressure against ARIA's already-cheap XOR diffusion). Measured ~1.3-1.4x ARIA encrypt/decrypt throughput on HotSpot across JDK 8-25 (neutral on GraalVM, which already compiled the byte path to the same speed), benefiting every mode that wraps the engine (ARIA-GCM/CBC/CFB/CTR, etc.). The key schedule is unchanged.
- Classic McEliece (org.bouncycastle.pqc.crypto.cmce) key generation and decapsulation are faster, byte-for-byte identically to before and with the scheme's constant-time properties preserved. CMCEEngine.pk_gen now runs the systematic-form Gaussian elimination over 64-bit words (long[][]) instead of single bytes, matching the uint64_t representation of the reference implementation; the row XOR clears 64 columns per step rather than 8, indexed only by public loop counters (mov_columns and the public-key extraction continue to operate on the byte form, which is synced once per key generation). CMCEEngine.decrypt now precomputes 1/g(L_i)² for the support once and shares it between its two syndrome passes (for the received word and for the recovered error vector) rather than re-evaluating the Goppa polynomial at every support element twice. The speedups are JIT-dependent: on HotSpot C2 keygen is up to ~1.2× (flat for mceliece8192128, whose 1024-byte rows C2 already auto-vectorises) and decapsulation ~1.15-1.22×; on GraalVM CE, whose vectoriser does not auto-widen the byte XOR, keygen is ~3-5× faster. All ten parameter sets remain byte-identical against the known-answer-test vectors.
- Initial Owl augmented PAKE in the new org.bouncycastle.crypto.agreement.owl package — an academic protocol (Hao, Bag, Chen, Lopez 2024) that extends J-PAKE with explicit user-registration and key-confirmation phases. Lightweight implementation supports the four-pass authentication exchange (OwlClient / OwlServer with OwlAuthenticationInitiate / OwlAuthenticationServerResponse / OwlAuthenticationFinish payloads), the initial user-registration exchange (OwlClientRegistration / OwlServerRegistration with OwlInitialRegistration / OwlFinishRegistration payloads), and optional explicit key-confirmation (OwlKeyConfirmation, both directions). Schnorr zero-knowledge proofs follow RFC 8235 over the OwlCurve elliptic-curve groups (OwlCurves.NIST_P256 supplied; OwlCurve constructor accepts any short-Weierstrass curve), and the shared primitives — Schnorr ZKP creation / validation, public-key validation, MAC-tag computation, transcript hashing — live in OwlUtil. Owl is not (yet) an IETF standard; users wanting a standardised PAKE should prefer the existing J-PAKE (org.bouncycastle.crypto.agreement.jpake / .ecjpake) or stronger asymmetric PAKEs. See misc/.../crypto/examples/OwlExample.java for a worked client+server exchange (PR #2168).
- RFC 9690 "Use of the RSA-KEM Algorithm in the Cryptographic Message Syntax (CMS)" support (obsoletes RFC 5990). RSA-KEM key transport now flows through the RFC 9629 KEMRecipientInfo pipeline already in place for ML-KEM / NTRU: the CMS layer was wired for the ISO 18033-2 id-kem-rsa AlgorithmIdentifier (1.0.18033.2.2.4) on the wrap and unwrap sides via JceKEMRecipientInfoGenerator / JceCMSKEMKeyWrapper / JceCMSKEMKeyUnwrapper, but the JCE Cipher service it looked up by name (RSA-KTS-KEM-KWS) was not registered. A new org.bouncycastle.jcajce.provider.asymmetric.rsa.RSAKEMCipherSpi (registered as Cipher.RSA-KTS-KEM-KWS, with Alg.Alias entries against ISOIECObjectIdentifiers.id_kem_rsa) closes the gap: WRAP_MODE performs the ISO 18033-2 RSA encapsulation, applies the KTSParameterSpec-supplied KDF (KDF2 / KDF3 / HKDF, per RFC 9690 §3.2 and §4) to the shared secret with the CMSORIforKEMOtherInfo bytes as the otherInfo / info input, and AES-Wraps the CEK under the derived KEK; UNWRAP_MODE is the symmetric inverse. The RFC 9690 mandatory-to-implement combination (KDF3-SHA-256 + AES-128-WRAP) plus the KDF2-SHA-256, KDF3-SHA-512 and HKDF-SHA-256 variants and AES-128/192/256-WRAP are exercised by new round-trip tests in pkix NewEnvelopedDataTest.
- RFC 9709 "Encryption Key Derivation in the Cryptographic Message Syntax (CMS) Using HKDF with SHA-256" interoperates with the new RFC 9690 KEM recipients: the existing id-alg-cek-hkdf-sha256 (1.2.840.113549.1.9.16.3.31) outer-wrap (opt-in on JceCMSContentEncryptorBuilder via setEnableSha256HKdf(true)) drives CMS_CEK_HKDF_SHA256(IKM, info = DER(inner contentEncryptionAlgorithm)) with the fixed salt "The Cryptographic Message Syntax" to derive the effective CEK from the recipient-delivered IKM, defending against the algorithm-substitution downgrade described in RFC 9709 §1. The recipient-side HKDF derivation (in EnvelopedDataHelper.getJceKey(AlgorithmIdentifier, GenericKey)) now triggers for KEM recipients as well as KeyTrans, KEK and KeyAgree recipients — a new NewEnvelopedDataTest case exercises RSA-KEM (RFC 9690, KDF3-SHA-256 + AES-128-WRAP) layered with the id-alg-cek-hkdf-sha256 content wrap end-to-end.
- Experimental support for Composite ML-KEM (draft-ietf-lamps-pq-composite-kem), which pairs ML-KEM with a traditional KEM (RSA-OAEP / ECDH / X25519 / X448) so the derived secret stays secure while either component does, with the KEM combiner ss = SHA3-256(mlkemSS || tradSS || tradCT || tradPK || Label) of section 3.4. The BC provider registers each of the twelve composite parameter sets — under both its algorithm name (e.g. MLKEM768-ECDH-P256-SHA3-256) and OID — as a KeyPairGenerator (producing org.bouncycastle.jcajce.CompositePublicKey / CompositePrivateKey pairs whose components are the ML-KEM key followed by the traditional key), a KeyGenerator that encapsulates and decapsulates via KEMGenerateSpec / KEMExtractSpec, and a KeyFactory for X.509 / PKCS#8 keys. Verified against the draft Appendix F test vectors.
- RFC 9474 RSA Blind Signatures (RSABSSA) — a blind signature protocol producing standard RSASSA-PSS signatures. Lightweight implementation in org.bouncycastle.crypto.signers covering the four named variants from RFC 9474 sec. 5 — RSABSSA-SHA384-{PSS,PSSZERO}-{Randomized,Deterministic} — via the RSABlindSignatureParameters variant class plus RSABlindSignatureClient (a single blind call covering RFC 9474 Prepare and Blind, then finalize) and RSABlindSignatureServer (server-side BlindSign with the RFC 9474 sec. 4.3 step 3 RSAVP1 self-check that catches CRT faults before the value leaves the server). The randomised variants prepend a 32-byte prefix to msg, the PSSZERO variants use an empty EMSA-PSS salt, and Finalize verifies the unblinded signature via standard RSASSA-PSS before returning so a fault that survived BlindSign is caught client-side too. Known-answer tested against all four RFC 9474 Appendix A test vectors via core/src/test/java/org/bouncycastle/crypto/test/RSABlindSignatureTest.java. See misc/src/main/java/org/bouncycastle/crypto/examples/RSABlindSignatureExample.java for a worked client/server exchange.
- DSTU7564Digest (Kupyna, DSTU 7564:2014) round function has been optimised by fusing its shiftRows, subBytes and mixColumns layers into eight precomputed 256-entry T-tables (the same construction Whirlpool uses for C0..C7): each output column is now the XOR of eight table lookups, replacing the per-column S-box reassembly and the SWAR mixColumn arithmetic, with shiftRows folded into the source-column selection. Output is byte-for-byte unchanged for both the 256/384-bit (512-bit state) and 512-bit (1024-bit state) variants, and DSTU7564Mac benefits transparently; measured throughput improves by roughly 1.2x-1.3x across JDK 8 through 25 (and GraalVM).
- OpenSSHPrivateKeyUtil.parsePrivateKeyBlob can now decrypt passphrase-protected openssh-key-v1 private keys. A new parsePrivateKeyBlob(byte[], byte[] passphrase) overload derives the cipher key and IV with the OpenSSH bcrypt_pbkdf KDF (the only KDF the format defines, kdfname "bcrypt") and decrypts the private section; the supported ciphers are aes128/192/256-ctr, aes128/192/256-cbc, 3des-cbc and the AEAD aes128/256-gcm@openssh.com and chacha20-poly1305@openssh.com (the AEAD tag is verified before the key is returned, and a wrong passphrase is rejected via the tag or the checkint guard rather than silently mis-decrypted). The bcrypt_pbkdf KDF is exposed for reuse as the public static BCrypt.pbkdfGenerate(password, salt, rounds, outputLength), cross-checked against the OpenBSD reference implementation. The existing single-argument parsePrivateKeyBlob(byte[]) continues to handle unencrypted keys and now throws a clear "passphrase required" message for an encrypted one. The same support is wired through the JCA layer: OpenSSHPrivateKeySpec gains an OpenSSHPrivateKeySpec(byte[], char[] password) constructor, and the RSA / DSA / EC / EdDSA KeyFactory implementations thread the passphrase through, so KeyFactory.getInstance(alg, "BC").generatePrivate(new OpenSSHPrivateKeySpec(blob, password)) decrypts an encrypted key (the EC KeyFactory now also accepts the openssh-key-v1 format, which it previously handled only in the ASN.1 / SEC1 form) (issue #1733).
- AIMer post-quantum digital signature scheme (KpqC Round 2 submission, MPC-in-the-head signature based on the AIM one-way function). Lightweight implementation in org.bouncycastle.pqc.crypto.aimer covering all six parameter sets — aimer-128f/s, aimer-192f/s, aimer-256f/s (NIST security categories 1/3/5 in fast and short trade-off flavours) — via AIMerKeyPairGenerator, AIMerSigner and the matching AIMerPublicKeyParameters / AIMerPrivateKeyParameters. JCE provider plumbing is registered through BCPQC: KeyPairGenerator.AIMer, Signature.AIMer, KeyFactory.AIMer, AIMerParameterSpec (six constants + fromName lookup), AIMerKey interface and BCAIMerPublicKey / BCAIMerPrivateKey. Six BC-arc OIDs in BCObjectIdentifiers (aimer.{1..6} under bc-sig.20) cover the SubjectPublicKeyInfo / PrivateKeyInfo wire form via the PublicKeyFactory / PrivateKeyFactory / SubjectPublicKeyInfoFactory / PrivateKeyInfoFactory converter plumbing, and BouncyCastleProvider.loadPQCKeys() registers an AIMerKeyFactorySpi against each OID so the standard BC provider can decode AIMer-bearing certificates and PKCS#8 keys without BCPQC in the lookup chain.
- The Gradle build can now generate CycloneDX 1.6 bill-of-materials documents for the release artifacts (gradle/cbom.gradle and gradle/sbom.gradle, tasks generateCbom and generateSbom). generateCbom produces a CBOM (Cryptographic Bill of Materials) for the provider jar — bcprov-<vmrange>-<version>-cyclonedx.json — by introspecting the JCA service tables of BouncyCastleProvider and BouncyCastlePQCProvider in the freshly built jar: one cryptographic-asset component per algorithm, with the CycloneDX primitive classification (block-cipher / stream-cipher / ae / pke / kem / signature / hash / xof / mac / kdf / key-agree / drbg / combiner), the crypto functions each algorithm exposes, and the algorithm OIDs recovered from the provider's Alg.Alias registrations. generateSbom produces an SBOM mirroring the published bc-<vmrange>-bom Maven BOM — bc-<vmrange>-bom-<version>-cyclonedx.json — with one component per published module jar (the set is read from the :bom project's platform constraints, and Maven coordinates from each module's publication, so it cannot drift from what is published), MD5/SHA-1/SHA-256 hashes matching the Maven repository checksum files, the declared external dependencies, and the inter-module dependency graph; the matching .pom and .module (Gradle Module Metadata) files are produced alongside by the same maven-publish generators a real publish runs, giving the complete publishable set for the BOM coordinates. Both documents validate against the CycloneDX 1.6 schema and are byte-for-byte reproducible for a given version: the serial number is a name-based UUID over the artifact purl, and the timestamp is the git commit time, carried as a Source-Date-Epoch manifest attribute in the bccore sources jar (overridable via the SOURCE_DATE_EPOCH environment variable, per the reproducible-builds.org convention).
- A new certificate-diagnostics API, org.bouncycastle.cert.X509CertificateReviewer, reports every structural problem in a certificate rather than just the first. The strict parse path is unchanged - org.bouncycastle.asn1.x509.Certificate / TBSCertificate / Extensions still fail fast on the first defect and never return a partially-parsed object - but reviewStructure(byte[]) / reviewStructure(ASN1Sequence) run the same single-sourced checks in collecting mode and return a Review: a list of Findings (each pairing a location with the exception the strict path would have thrown, in parse order) plus the recovered X509CertificateHolder when, and only when, the strict path would also accept it. It is the parse-side analogue of PKIXCertPathReviewer (issues #1508, #1511).
- The PKCS12 keystore's default PBE iteration count has been raised from 51200 to 600000, in line with current OWASP guidance for PBKDF1-style iterated SHA-256 derivations; keystores written with the old default (and any count up to the org.bouncycastle.pkcs12.max_it_count cap) continue to load. The maximum-iteration-count property name is now exposed as the Properties.PKCS12_MAX_IT_COUNT constant.
- The Mayo signature algorithm's object identifiers have moved from the interim BC arc to the OQS interop-registered values (1.3.9999.8.n.3 for MAYO-1/2/3/5), Mayo can now be used for CMS signing and X.509 certificate work (the DefaultSignatureAlgorithmIdentifierFinder / DefaultSignatureNameFinder tables and the BC-provider key-info converters cover the new OIDs), and the hyphenated MAYO-1/MAYO-2/MAYO-3/MAYO-5 algorithm names are registered alongside the existing forms.
- The low-level Ed25519 implementation (org.bouncycastle.math.ec.rfc8032.Ed25519) gains an ExpandedKey representation: expandPrivateKey / generatePrivateKey produce the pre-hashed expanded form, and generatePublicKey / sign overloads consume it directly. This lets a caller expand the 32-byte seed once and sign many messages without re-running the SHA-512 key expansion per signature, and supports deployments that hold only the expanded key.
- A new org.bouncycastle.crypto.agreement.ECDHRawAgreement implements the RawAgreement interface for plain ECDH, writing the fixed-length X9.63 field-element encoding of the shared secret directly into a caller-supplied buffer (getAgreementSize() bytes) - the natural fit for HPKE/TLS-style KDF pipelines that consume the raw shared secret, avoiding the BigInteger round trip of ECDHBasicAgreement.
- The ML-DSA lightweight implementation has been given a performance refactor (including merging the PolyVecK/PolyVecL vector types) that is byte-identical on the wire, together with a constant-time audit of the secret-dependent paths.
- Safe-prime parameter generation for DH and ElGamal (DHParametersGenerator / ElGamalParametersGenerator) is substantially faster: candidate search now sieves both p and (p-1)/2 together, and g = 2 is chosen when it is a quadratic residue, avoiding a full generator search.
- DefaultAlgorithmNameFinder (org.bouncycastle.operator) now maps the NIST AES-GCM and AES-CCM content-encryption OIDs to the conventional "AES-128/GCM" ... "AES-256/CCM" names instead of falling back to the dotted OID string (issue #1763).
- The ASN.1 stream-safety limits are now publicly addressable: the maximum nested-construction depth and the maximum declared object length are controlled by the org.bouncycastle.asn1.max_cons_depth and org.bouncycastle.asn1.max_limit system properties, exposed as the Properties.ASN1_MAX_CONS_DEPTH and Properties.ASN1_MAX_LIMIT constants (values and defaults unchanged).
- The EST client's TLS channel authorizer (org.bouncycastle.est.jcajce) has been hardened in line with RFC 9525 (which obsoletes RFC 6125): a wildcard is accepted only when the single '*' is the complete content of the left-most label and it must match exactly one non-empty label, so partial wildcards ("f*o.example"), wildcards in inner labels, and wildcards spanning label boundaries or a known public suffix are rejected (issue #1495).

### 2.1.4 Security Fixes

- CVE-2026-8763 - Name Constraints bypass via trailing dot in rfc822Name and URI.
- CVE-2026-12185 - BKS/UBER keystore allocates from untrusted lengths before integrity check.
- CVE-2026-12802 - CMS AuthEnvelopedData fails to enforce tag-length on decryption.
- CVE-2026-12803 - KCCMBlockCipher MAC does not bind nonce when AAD is absent (cross-nonce AEAD forgery).
- CVE-2026-12816 - IESEngine stream-mode MAC forgery via length-dependent KDF split.
- CVE-2026-12817 - OpenPGP AEAD decryption skips final tag on chunk-aligned data.
- CVE-2026-12852 - MLS wire decoder allocates attacker-declared opaque length before bounds check.
- CVE-2026-12860 - RSA PKCS#1 verification skips last two hash bytes in NULL-omitted path.
- CVE-2026-13506 - Lazy ASN.1 sequence forcing resets nesting-depth guard.
- CVE-2026-13586 - PKCS#12 MAC and bag-decryption KDF iteration-count bound (DoS).
- CVE-2026-14682 - Possible OOM from unbounded up-front allocation on a definite-length read.
- CVE-2026-15505 - PKCS#8 / PBES2 decryptors honour unbounded KDF cost from input.
- CVE-2026-58059 - Quadratic-time escaping when stringifying X.500 distinguished names.
- CVE-2026-58060 - HSS public-key level count unbounded, enabling huge allocation on verify.
- CVE-2026-58061 - CCM-family modes write plaintext to caller buffer before tag check.
- CVE-2026-58062 - Stapled OCSP response accepted without binding to the checked certificate.
- CVE-2026-58063 - BCFKS keystore load honours unbounded KDF cost from untrusted file.
- CVE-2026-59638 - JSSE hostname verifier CN-fallback enabled by default despite documented opt-in.
- CVE-2026-59639 - CMS verifySignatures returns true for SignedData with zero signers.
- CVE-2026-59640 - OpenPGP CFB quick-check oracle active on symmetric/session-key paths.
- CVE-2026-59641 - S/MIME validator trusts signer-asserted signingTime for path validation.
- CVE-2026-59642 - CMS AuthenticatedData content not bound to MAC when authAttrs present.
- CVE-2026-59643 - OpenPGP inline-signature policy failures silently ignored.
- CVE-2026-59644 - MLS hash-ratchet honours arbitrary 32-bit generation counter from sender.
- CVE-2026-59645 - OER parser recurses without depth limit on self-referential IEEE 1609.2 schema.
- CVE-2026-59646 - DTLS handshake reassembler allocates buffer from unchecked 24-bit length.
- CVE-2026-59647 - CRMF/CMP password-MAC honours unbounded iteration count.
- CVE-2026-59648 - OpenPGP Argon2 S2K honours attacker-chosen memory and passes.
- CVE-2026-59649 - OpenPGP user-attribute subpacket length bounded only by JVM max memory.
- CVE-2026-59650 - MTI/A0 DH agreement exponentiates unvalidated peer value.
- CVE-2026-59651 - BKS keystore accepts legacy version with 16-bit integrity MAC key.
- CVE-2026-59652 - LDAP filter injection in legacy jdk1.4 LDAPStoreHelper.

### 2.1.5 Additional Notes

- The standardised PQC algorithms ML-KEM, ML-DSA, SLH-DSA, FrodoKEM, and CMCE have been repackaged under org.bouncycastle.crypto and the versions under org.bouncycastle.crypto.pqc have been deprecated. These deprecated versions will be removed in BC 1.86.

### 2.2.1 Version

Release: 1.84
Date: 2026, April 14th

### 2.2.2 Defects Fixed

- Random numbers being generated for DSTU4145 signature calculations were 1 bit shorter than they could be. The code has been corrected to allow the generated numbers to occupy the full numeric range available.
- HKDF implementation has been corrected to use multiple IKMs if available.
- CompositePublic/PrivateKey builders had an issue identifying brainpool and EdDSA curves from the algorithm names due to an error in the OID mapping table. This has been fixed.
- S/MIME: Fix AuthEnveloped support for AES192/GCM and AES256/GCM.
- CMS: Use implicit tag for AuthEnvelopedData.authEncryptedContentInfo.encryptedContent.
- Fixed Strings.split to handle delimiters at position 0.
- Fixed FrodoKEM error sampling to be constant-time.
- Fixed PKIXNameConstraintValidator to treat a DNS name as intersecting itself.
- Fixed PKCS12 key stores not calling getInstance with the original provider (which was forcing provider registration).
- A resource leak due to the SMIMESigned constructor leaving background threads hanging on MessagingException has been fixed.
- OpenPGP: Fixed an issue where a custom signature creation time was ignored when generating message signatures.
- OpenPGP: Fixed SKESK encoding for direct-S2K-encrypted messages.

### 2.2.3 Additional Features and Functionality

- In line with JVM changes, KEM support has been backported to Java 17.
- BCJSSE: Configurable (client) early key_share groups via BCSSLParameters.earlyKeyShares or "org.bouncycastle.jsse.client.earlyKeyShares" system property.
- BCJSSE: Support for curveSM2MLKEM768 hybrid NamedGroup in TLS 1.3 per draft-yang-tls-hybrid-sm2-mlkem-03.
- BCJSSE: Log when default cipher suites are disabled.
- BCJSSE: Experimental support for ShangMi crypto in TLS 1.3 per RFC 8998 (not enabled by default).
- CMS: Added CMSAuthEnvelopedDataStreamGenerator.open taking an explicit content type.
- HKDF: Provider support for HKDFParameterSpec.Expand.
- Added initial support for RFC 9380 (Hashing to Elliptic Curves); see org.bouncycastle.crypto.hash2curve .
- PKCS12: Added default max iteration count of 5,000,000 (configurable via "org.bouncycastle.pkcs12.max_it_count" property).
- TLS: Use javax.crypto.KEM API (when available) to access ML-KEM implementation (incl. hybrids).
- A new KeyStore, PKCS12-PBMAC1, has been added which defaults to using PBMAC1 and supports RFC 9879.
- A new property "org.bouncycastle.asn1.max_cons_depth" has been added to allow setting of the maximum nesting for SETs/SEQUENCESs in ASN.1. Default is 32.
- A new property "org.bouncycastle.asn1.max_limit" has been added to allow setting of the stream size of ASN.1 encodings. The value can be either in bytes, or appended with k (1 kilobyte blocks), m (1 megabyte blocks), or g (1 gigabyte blocks).
- Added NTRU+ support to the lightweight PQC API and the BCPQC provider.
- Added SM4 key wrap/unwrap mode, SM2 key exchange, and logging to SM2Signer.
- OpenPGP: Added encryption‑key filtering by purpose, a new OpenPGPKey constructor, KeyPassphraseProvider‑based passphrase change, wildcard (anonymous) recipient handling, and Web‑of‑Trust methods for third‑party signature chains and delegations.
- CMSSignedDataStreamGenerator can now support the generation of DER/DL encoded SignedData objects (note memory restrictions still apply).
- It is now possible to add extra digest alorithm IDs to CMSSignedDataStreamGenerator when required.

### 2.2.4 Security Fixes

- CVE-2025-14813 - GOSTCTR implementation unable to process more than 255 blocks correctly.
- CVE-2026-0636 - LDAP Injection Vulnerability in LDAPStoreHelper.java.
- CVE-2026-3505 - Unbounded PGP AEAD chunk size leads to pre-auth resource exhaustion.
- CVE-2026-5588 - PKIX draft CompositeVerifier accepts empty signature sequence as valid.
- CVE-2026-5598 - Non-constant time comparisons risk private key leakage in FrodoKEM.

### 2.2.5 Additional Notes

- DSA was recently deprecated by NIST and several users have requested that we move to an RSA signing certificate for provider signing instead of our current DSA one. We are grateful to report that Oracle have been very supportive of this and issued us a second RSA certificate based on a new RSA key for signing providers. Providers signed with the previous DSA key will continue to work as before.
- This will be the last release which will recognise Dilithium and SphincsPlus in the BC provider, the Kyber wrapper (which is just ML-KEM) will also be removed. The algorithms won't be deleted in 1.85, but will only be accessible via the low-level APIs and deleted in a later release.

### 2.3.1 Version

Release: 1.83
Date: 2025, November 27th.

### 2.3.2 Defects Fixed

- Attempting to check a password on a stripped PGP key would throw an exception. Checking the password on such a key will now always return false.
- Fixed an issue in KangarooTwelve where premature absorption caused erroneous 168-byte padding; absorption is now delayed so correct final-byte padding is applied.
- BCJSSE: Fix supported_versions creation for renegotiation handshake.
- (D)TLS: Reneg info now only offered with pre-1.3.

### 2.3.3 Additional Features and Functionality

- A generic "COMPOSITE" algorithm name has been added as a JCA Signature algorithm. The algorithm will identify the composite signature to use from the composite key passed in.
- The composite signatures implementation has been updated to the final draft and now follows the submitted standard.
- Support for the generation and use as trust anchors has been added for certificate signatures with id-alg-unsigned as the signature type.
- Support for CMP direct POP for encryption keys using challenge/response has been added to the CMP/CRMF APIs.
- Support for SupportedCurves attribute added to the BC provider
- BCJSSE: Added support for SLH-DSA signature schemes in TLS 1.3 per draft-reddy-tls-slhdsa-01.
- Support has been added for the Java 25 KDF API (current algorithms, PBKDF2, SCRYPT, and HKDF).
- Support for composite signatures is now included in CMS and timestamping.
- It is now possible to disable the Lenstra check in RSA where the public key is not available via the system/security property "org.bouncycastle.rsa.no_lenstra_check".

### 2.4.1 Version

Release: 1.82
Date: 2025, 17th September.

### 2.4.2 Defects Fixed

- SNOVA and MAYO are now correctly added to the JCA provider module-info file.
- TLS: Avoid nonce reuse error in JCE AEAD workaround for pre-Java7.
- BCJSSE: Session binding map is now shared across all stages of the session lifecycle (SunJSSE compatibility).
- The CMCEPrivateKeyParameters#reconstructPublicKey method was returning an empty byte array. It now returns an encoding of the public key.
- CBZip2InputStream no longer auto-closes at end-of-contents.
- The BC CertPath implementation was eliminating certificates on the bases of the Key-ID. This is not in accordance with RFC 4158 and has been fixed.
- Support for the previous set of libOQS Falcon OIDs has been restored.
- The BC CipherInputStream could throw an exception if asked to handle an AEAD stream consisting of the MAC only. This has been fixed.
- Some KeyAgreement classes were missing in the Java 11 class hierarchy. This has been fixed.
- A typo in a constant name in the HPKE class has been fixed and the old constant deprecated.
- Fuzzing analysis has been done on the OpenPGP API and additional code has been added to prevent escaping exceptions.

### 2.4.3 Additional Features and Functionality

- SHA3Digest, CSHAKE, TupleHash, KMAC now provide support for Memoable and EncodableService.
- BCJSSE: Added support for integrity-only cipher suites in TLS 1.3 per RFC 9150.
- BCJSSE: Added support for system properties "jdk.tls.client.maxInboundCertificateChainLength" and "jdk.tls.server.maxInboundCertificateChainLength".
- BCJSSE: Added support for ML-DSA signature schemes in TLS 1.3 per draft-ietf-tls-mldsa-00.
- The Composite post-quantum signatures implementation has been updated to the latest draft (07) draft-ietf-lamps-pq-composite-sigs.
- "<name>_PREHASH" implementations are now provided for all composite signatures to allow the hash of the data to be used instead of the actual data in signature calculation.
- The gradle build can now be used to generate an Bill of Materials (BOM) file.
- It is now possible to configure the SignerInfoVerifierBuilder used by the SignedMailValidator class.
- The Ascon family of algorithms has been updated with the latest published changes.
- Composite signature keys can now be constructed from the individual keys of the algorithms composing the composite.
- PGPSecretKey, PGPSignatureGenerator now support version 6.
- Further optimisation work has been done on ML-KEM public key validation.
- Zeroization of passwords in the JCA PKCS12 key store has been improved.
- The "org.bouncycastle.drbg.effective_256bits_entropy" property has been added for platforms where the entropy source is not producing 1 full bit of entropy per bit and additional bits are required (default value 282).
- Support has been added to the CMS content encryptors to allow a generated key to be passed in, rather than always having them generate their own.
- OpenPGPKeyGenerator now allows for the use of empty UserIDs (version 4 compatibility).
- The HQC KEM has been updated with the latest draft updates.

### 2.4.4 Additional Notes

- The legacy post-quantum package has now been removed.

### 2.5.1 Version

Release: 1.81
Date: 2025, 4th June.

### 2.5.2 Defects Fixed

- A potention NullPointerException in the KEM KDF KemUtil class has been removed.
- Overlapping input/output buffers in doFinal could result in data corruption. This has been fixed.
- Fixed Grain-128AEAD decryption incorrectly handle MAC verification.
- Add configurable header validation to prevent malicious header injection in PGP cleartext signed messages; Fix signature packet encoding issues in PGPSignature.join() and embedded signatures while phasing out legacy format.
- Fixed ParallelHash initialization stall when using block size B=0.
- The PRF from the PBKDF2 function was been lost when PBMAC1 was initialized from protectionAlgorithm. This has been fixed.
- The lowlevel DigestFactory was cloning MD5 when being asked to clone SHA1. This has been fixed.

### 2.5.3 Additional Features and Functionality

- XWing implementation updated to draft-connolly-cfrg-xwing-kem/07/
- Further support has been added for generation and use of PGP V6 keys
- Additional validation has been added for armored headers in Cleartext Signed Messages.
- The PQC signature algorithm proposal Mayo has been added to the low-level API and the BCPQC provider.
- The PQC signature algorithm proposal Snova has been added to the low-level API and the BCPQC provider.
- Support for ChaCha20-Poly1305 has been added to the CMS/SMIME APIs.
- The Falcon implementation has been updated to the latest draft.
- Support has been added for generating keys which encode as seed-only and expanded-key-only for ML-KEM and ML-DSA private keys.
- Private key encoding of ML-DSA and ML-KEM private keys now follows the latest IETF draft.
- The Ascon family of algorithms has been updated to the initial draft of SP 800-232. Some additional optimisation work has been done.
- Support for ML-DSA's external-mu calculation and signing has been added to the BC provider.
- CMS now supports ML-DSA for SignedData generation.
- Introduce high-level OpenPGP API for message creation/consumption and certificate evaluation.
- Added JDK21 KEM API implementation for HQC algorithm.
- BCJSSE: Strip trailing dot from hostname for SNI, endpointID checks.
- BCJSSE: Draft support for ML-KEM updated (draft-connolly-tls-mlkem-key-agreement-05).
- BCJSSE: Draft support for hybrid ECDHE-MLKEM (draft-ietf-tls-ecdhe-mlkem-00).
- BCJSSE: Optionally prefer TLS 1.3 server's supported_groups order (BCSSLParameters.useNamedGroupsOrder).

### 2.6.1 Version

Release: 1.80
Date: 2025, 14th January.

### 2.6.2 Defects Fixed

- A splitting issue for ML-KEM lead to an incorrect size for kemct in KEMRecipientInfos. This has been fixed.
- The PKCS12 KeyStore has been adjusted to prevent accidental doubling of the Oracle trusted certificate attribute (results in an IOException when used with the JVM PKCS12 implementation).
- The SignerInfoGenerator copy constructor was ignoring the certHolder field. This has been fixed.
- The getAlgorithm() method return value for a CompositePrivateKey was not consistent with the corresponding getAlgorithm() return value for the CompositePrivateKey. This has been fixed.
- The international property files were missing from the bcjmail distribution. This has been fixed.
- Issues with ElephantEngine failing on processing large/multi-block messages have been addressed.
- GCFB mode now fully resets on a reset.
- The lightweight algorithm contestants: Elephant, ISAP, PhotonBeetle, Xoodyak now support the use of the AEADParameters class and provide accurate update/doFinal output lengths.
- An unnecessary downcast in CertPathValidatorUtilities was resulting in the ignoring of URLs for FTP based CRLs. This has been fixed.
- A regression in the OpenPGP API could cause NoSuchAlgorithmException to be thrown when attempting to use SHA-256 in some contexts. This has been fixed.
- EtsiTs1029411TypesAuthorization was missing an extension field. This has been added.
- Interoperability issues with single depth LMS keys have been addressed.

### 2.6.3 Additional Features and Functionality

- CompositeSignatures now updated to draft-ietf-lamps-pq-composite-sigs-03.
- ML-KEM, ML-DSA, SLH-DSA, and Composite private keys now use raw encodings as per the latest drafts from IETF 121: draft-ietf-lamps-kyber-certificates-06, draft-ietf-lamps-dilithium-certificates-05, and draft-ietf-lamps-x509-slhdsa.
- Initial support has been added for RFC 9579 PBMAC1 in the PKCS API.
- Support has been added for EC-JPAKE to the lightweight API.
- Support has been added for the direct construction of S/MIME AuthEnvelopedData objects, via the SMIMEAuthEnvelopedData class.
- An override "org.bouncycastle.asn1.allow_wrong_oid_enc" property has been added to disable new OID encoding checks (use with caution).
- Support has been added for the PBEParemeterSpec.getParameterSpec() method where supported by the JVM.
- ML-DSA/SLH-DSA now return null for Signature.getParameters() if no context is provided. This allows the algorithms to be used with the existing Java key tool.
- HQC has been updated to reflect the reference implementation released on 2024-10-30.
- Support has been added to the low-level APIs for the OASIS Shamir Secret Splitting algorithms.
- BCJSSE: System property "org.bouncycastle.jsse.fips.allowGCMCiphersIn12" no longer used. FIPS TLS 1.2 GCM suites can now be enabled according to JcaTlsCrypto#getFipsGCMNonceGeneratorFactory (see JavaDoc for details) if done in alignment with FIPS requirements.
- Support has been added for OpenPGP V6 PKESK and message encryption.
- PGPSecretKey.copyWithNewPassword() now includes AEAD support.
- The ASCON family of algorithms have been updated in accordance with the published FIPS SP 800-232 draft.

### 2.7.1 Version

Release: 1.79
Date: 2024, 30th October.

### 2.7.2 Defects Fixed

- Leading zeroes were sometimes dropped from Ed25519 signatures leading to verification errors in the PGP API. This has been fixed.
- Default version string for Armored Output is now set correctly in 18on build.
- The Elephant cipher would fail on large messages. This has been fixed.
- CMSSignedData.replaceSigners() would re-encode the digest algorithms block, occassionally dropping ones where NULL had been previously added as an algorithm parameter. The method now attempts to only use the original digest algorithm identifiers.
- ERSInputStreamData would fail to generate the correct hash if called a second time with a different hash algorithm. This has been fixed.
- A downcast in the CrlCache which would cause FTP based CRLs to fail to load has been removed.
- ECUtil.getNamedCurveOid() now trims curve names of excess space before look up.
- The PhotonBeetle and Xoodyak digests did not reset properly after a doFinal() call. This has been fixed.
- Malformed AlgorithmIdentifiers in CertIDs could cause caching issues in the OCSP cache. This has been fixed.
- With Java 21 a provider service class will now be returned with a null class name where previously a null would have been returned for a service. This can cause a NullPointerException to be thrown by the BC provider if a non-existant service is requested. This issue has now been worked around.
- CMS: OtherKeyAttribute.keyAttr now treated as optional.
- CMS: EnvelopedData and AuthEnvelopedData could calculate the wrong versions. This has been fixed.
- The default version header for PGP armored output did not carry the correct version string. This has been fixed.
- In some situations the algorithm lookup for creating PGPDigestCalculators would fail due to truncation of the algorithm name. This has been fixed.

### 2.7.3 Additional Features and Functionality

- Object Identifiers have been added for ML-KEM, ML-DSA, and SLH-DSA.
- The PQC algorithms, ML-KEM, ML-DSA (including pre-hash), and SLH-DSA (including pre-hash) have been added to the BC provider and the lightweight API.
- A new spec, ContextParameterSpec, has been added to support signature contexts for ML-DSA and SLH-DSA.
- BCJSSE: Added support for security property "jdk.tls.server.defaultDHEParameters" (disabled in FIPS mode).
- BCJSSE: Added support for signature_algorithms_cert configuration via "org.bouncycastle.jsse.client.SignatureSchemesCert" and "org.bouncycastle.jsse.server.SignatureSchemesCert" system properties or BCSSLParameters property "SignatureSchemesCert".
- BCJSSE: Added support for boolean system property "org.bouncycastle.jsse.fips.allowGCMCiphersIn12" (false by default).
- (D)TLS: Remove redundant verification of self-generated RSA signatures.
- CompositePrivateKeys now support the latest revision of the composite signature draft.
- Delta Certificates now support the latest revision of the delta certificate extension draft.
- A general KeyIdentifier class, encapsulating both PGP KeyID and the PGP key fingerprint has been added to the PGP API.
- Support for the LibrePGP PreferredEncryptionModes signature subpacket has been added to the PGP API.
- Support for Version 6 signatures, including salts, has been added to the PGP API.
- Support for the PreferredKeyServer signature supacket has been added to the PGP API.
- Support for RFC 9269, "Using KEMs in Cryptographic Message Syntax (CMS)", has been added to the CMS API.
- Support for the Argon2 S2K has been added to the PGP API.
- The system property "org.bouncycastle.pemreader.lax" has been introduced for situations where the BC PEM parsing is now too strict.
- The system property "org.bouncycastle.ec.disable_f2m" has been introduced to allow F2m EC support to be disabled.
- ETSIQCObjectIdentifiers now defines id_etsi_qcs_QcCClegislation (0.4.0.1862.1.7), the ETSI EN 319 412-5 qualified-certificate statement identifying the country legislation under which the qualified certificate was issued (issue #1467).

### 2.8.1 Version

Release: 1.78.1
Date: 2024, 18th April.

### 2.8.2 Defects Fixed

- The new dependency of the the PGP API on the bcutil jar was missing from the module jar, the OSGi manifest, and the Maven POM. This has been fixed.
- Missing exports and duplicate imports have been added/removed from the OSGi manifests.
- The OSGi manifests now have the same bundle IDs as 1.77 and lock down dependencies to the equivalent variations.
- A check in the X.509 Extensions class preventing the parsing of empty extensions has been removed.

### 2.9.1 Version

Release: 1.78
Date: 2024, 7th April.

### 2.9.2 Defects Fixed

- Issues with a dangling weak reference causing intermittent NullPointerExceptions in the OcspCache have been fixed.
- Issues with non-constant time RSA operations in TLS handshakes have been fixed.
- Issue with Ed25519, Ed448 signature verification causing intermittent infinite loop have been fixed.
- Issues with non-constant time ML-KEM implementation ("Kyber Slash") have been fixed.
- Align ML-KEM input validation with FIPS 203 IPD requirements.
- Make PEM parsing more forgiving of whitespace to align with RFC 7468 - Textual Encodings of PKIX, PKCS, and CMS Structures.
- Fix CCM length checks with large nonce sizes (n=12, n=13).
- EAC: Fixed the CertificateBody ASN.1 type to support an optional Certification Authority Reference in a Certificate Request.
- ASN.1: ObjectIdentifier (also Relative OID) parsing has been optimized and the contents octets for both types are now limited to 4096 bytes.
- BCJSSE: Fixed a missing null check on the result of PrivateKey.getEncoded(), which could cause issues for HSM RSA keys.
- BCJSSE: When endpoint identification is enabled and an SSL socket is not created with an explicit hostname (as happens with HttpsURLConnection), hostname verification could be performed against a DNS-resolved IP address. This has been fixed.
- The missing module import of java.logging to the provider module has been added.
- GOST ASN.1 public key alg parameters are now compliant with RFC 9215.
- An off-by-one error in the encoding for EccP256CurvePoint for ITS has been fixed.
- PEM Parser now enforces PEM headers to start at the beginning of the line to be meaningful.

### 2.9.3 Additional Features and Functionality

- An implementation of MLS (RFC 9420 - The Messaging Layer Security Protocol) has been added as a new module.
- NTRU now supports NTRU-HPS4096-1229 and NTRU-HRSS-1373.
- Improvements to PGP support, including Camellia key wrapping and Curve25519, Curve448 key types (including XDH with HKDF).
- Added initial support for ML-KEM in TLS.
- Added XWing hybrid KEM construction (X25519 + ML-KEM-768).
- Introduced initial KEMSpi support (NTRU, SNTRU Prime) for JDK 21+.
- Introduced initial composite signature support for X509 Certificates.
- PKCS#12 now supports PKCS12-AES256-AES128, PKCS12-AES256-AES128-GCM, PKCS12-DEF-AES256-AES128, and PKCS12-DEF-AES256-AES128-GCM.
- The default type for the KeyStore.getInstance("PKCS12", "BC") can now be set using the org.bouncycastle.pkcs12.default system/security property.
- The PGP SExpParser will now handle Ed25519 and Ed448 keys.
- Dilithium and Kyber key encoding updated to latest Draft RFCs (draft-ietf-lamps-dilithium-certificates and draft-ietf-lamps-kyber-certificates)
- Support has been added for encryption key derivation using HKDF in CMS - see draft-housley-lamps-cms-cek-hkdf-sha256.
- X500Name now recognises jurisdiction{C,ST,L} DNs.
- CertPathValidationContext and CertificatePoliciesValidation now include implementations of Memoable.
- The Composite post-quantum signatures implementation has been updated to the latest draft draft-ounsworth-pq-composite-sigs.
- X509v2CRLBuilder now exposes setThisUpdate(Date), setThisUpdate(Date, Locale) and setThisUpdate(Time) overloads, mirroring the existing setNextUpdate methods so the thisUpdate field can be reset after the builder has been constructed (issue #1545).

### 2.9.4 Notes.

- Both versions of NTRUPrime have been updated to produce 256 bit secrets in line with Kyber. This should also bring them into line with other implementations such as those used in OpenSSH now.
- BCJSSE: The boolean system property 'org.bouncycastle.jsse.fips.allowRSAKeyExchange" now defaults to false. All RSA key exchange cipher suites will therefore be disabled when the BCJSSE provider is used in FIPS mode, unless this system property is explicitly set to true.
- OSGi compatibility should now be much improved.
- SignedMailValidator now includes a more general rollback method for locating the signature's trust anchor for use when the first approach fails.
- The PKCS12 store using GCM does not include the PKCS#12 MAC so no longer includes use of the PKCS#12 PBE scheme and only uses PBKDF2.
- In keeping with the current set of experimental OIDs for PQC algorithms, OIDs may have changed to reflect updated versions of the algorithms.

### 2.9.5 Security Advisories.

Release 1.78 deals with the following CVEs:

- CVE-2024-29857 - Importing an EC certificate with specially crafted F2m parameters can cause high CPU usage during parameter evaluation.
- CVE-2024-30171 - Possible timing based leakage in RSA based handshakes due to exception processing eliminated.
- CVE-2024-30172 - Crafted signature and public key can be used to trigger an infinite loop in the Ed25519 verification code.
- CVE-2024-34447 - When endpoint identification is enabled in the BCJSSE and an SSL socket is not created with an explicit hostname (as happens with HttpsURLConnection), hostname verification could be performed against a DNS-resolved IP address. This has been fixed.

### 2.10.1 Version

Release: 1.77
Date: 2023, November 13th

### 2.10.2 Defects Fixed

- Using an unescaped '=' in an X.500 RDN would result in the RDN being truncated silently. The issue is now detected and an exception is thrown.
- asn1.eac.CertificateBody was returning certificateEffectiveDate from getCertificateExpirationDate(). This has been fixed to return certificateExpirationDate.
- DTLS: Fixed retransmission in response to re-receipt of an aggregated ChangeCipherSpec.
- (D)TLS: Fixed compliance for supported_groups extension. Server will no longer negotiate an EC cipher suite using a default curve when the ClientHello includes the supported_groups extension but it contains no curves in common with the server. Similarly, a DH cipher suite will not be negotiated when the ClientHello includes supported_groups, containing at least one FFDHE group, but none in common with the server.
- IllegalStateException was being thrown by the Ed25519/Ed448 SignatureSpi. This has been fixed.
- TLS: class annotation issues that could occur between the BC provider and the TLS API for the GCMParameterSpec class when the jars were loaded on the boot class path have been addressed.
- Attempt to create an ASN.1 OID from a zero length byte array is now caught at construction time.
- Attempt to create an X.509 extension block which is empty will now be blocked cause an exception.
- IES implementation will now accept a null ParameterSpec if no nonce is needed.
- An internal method in Arrays was failing to construct its failure message correctly on an error. This has been fixed.
- HSSKeyPublicParameters.generateLMSContext() would fail for a unit depth key. This has been fixed.

### 2.10.3 Additional Features and Functionality

- BCJSSE: Added org.bouncycastle.jsse.client.omitSigAlgsCertExtension and org.bouncycastle.jsse.server.omitSigAlgsCertExtension boolean system properties to control (for client and server resp.) whether the signature_algorithms_cert extension should be omitted if it would be identical to signature_algorithms. Defaults to true, the historical behaviour.
- The low-level HPKE API now allows the sender to specify an ephemeral key pair.
- Support has been added for the delta-certificate requests in line with the current Chameleon Cert draft from the IETF.
- Some accommodation has been added for historical systems to accommodate variations in the SHA-1 digest OID for CMS SignedData.
- TLS: the TLS API will now try "RSAwithDigestAndMFG1" as well as the newer RSAPSS algorithm names when used with the JCA.
- TLS: RSA key exchange cipher suites are now disabled by default.
- Support has been added for PKCS#10 requests to allow certificates using the altSignature/altPublicKey extensions.

### 2.10.4 Notes.

- Kyber and Dilithium have been updated according to the latest draft of the standard. Dilithium-AES and Kyber-AES have now been removed. Kyber now produces 256 bit secrets for all parameter sets (in line with the draft standard).
- NTRU has been updated to produce 256 bit secrets in line with Kyber.
- SPHINCS+ can now be used to generate certificates in line with those used by (Open Quantum Safe) OQS.
- Falcon object identifiers are now in line with OQS as well.
- PQC CMS SignedData now defaults to SHA-256 for signed attributes rather than SHAKE-256. This is also a compatibility change, but may change further again as the IETF standard for CMS is updated.

### 2.11.1 Version

Release: 1.76
Date: 2023, July 29th

### 2.11.2 Defects Fixed

- Service allocation in the provider could fail due to the lack of a permission block. This has been fixed.
- JceKeyFingerPrintCalculator has been generalised for different providers by using "SHA-256" for the algorithm string.
- BCJSSE: Fixed a regression in 1.74 (NullPointerException) that prevents a BCJSSE server from negotiating TLSv1.1 or earlier.
- DTLS: Fixed server support for client_certificate_type extension.
- Cipher.unwrap() for HQC could fail due to a miscalculation of the length of the KEM packet. This has been fixed.
- There was exposure to a Java 7 method in the Java 5 to Java 8 BCTLS jar which could cause issues with some TLS 1.2 cipher suites running on older JVMs. This is now fixed.

### 2.11.3 Additional Features and Functionality

- BCJSSE: Following OpenJDK, finalizers have been removed from SSLSocket subclasses. Applications should close sockets and not rely on garbage collection.
- BCJSSE: Added support for boolean system property "jdk.tls.client.useCompatibilityMode" (default "true").
- DTLS: Added server support for session resumption.
- JcaPKCS10CertificationRequest will now work with EC on the OpenJDK provider.
- TimeStamp generation now supports the SHA3 algorithm set.
- The SPHINCS+ simple parameters are now fully supported in the BCPQC provider.
- Kyber, Classic McEliece, HQC, and Bike now supported by the CRMF/CMS/CMP APIs.
- Builder classes have been add for PGP ASCII Armored streams allowing CRCs and versions to now be optional.
- An UnknownPacket type has been added to the PGP APIs to allow for forwards compatibility with upcoming revisions to the standard.

### 2.12.1 Version

Release: 1.75
Date: 2023, June 21st

### 2.12.2 Defects Fixed

- Several Java 8 method calls were accidentally introduced in the Java 5 to Java 8 build. The affected classes have been refactored to remove this.
- (D)TLS: renegotiation after resumption now fixed to avoid breaking connection.

### 2.12.3 Notes.

- The ASN.1 core package has had some dead and retired methods cleaned up and removed.

### 2.13.1 Version

Release: 1.74
Date: 2023, June 12th

### 2.13.2 Defects Fixed

- AsconEngine: Fixed a buffering bug when decrypting across multiple processBytes calls (ascon128a unaffected).
- Context based sanity checking on PGP signatures has been added.
- The ParallelHash clone constructor was not copying all fields. This is now fixed.
- The maximimum number of blocks for CTR/SIC modes was 1 block less than it should have been. This is now fixed.

### 2.13.3 Additional Features and Functionality

- The PGP API now supports wildcard key IDs for public key based data encryption.
- LMS now supports SHA256/192, SHAKE256/192, and SHAKE256/256 (the additional SP 8000-208 parameter sets).
- The PGP API now supports V5 and V6 AEAD encryption for encrypted data packets.
- The PGP examples have been updated to reflect key size and algorithm changes that have occurred since they were first written (10+ years...).
- (D)TLS: A new callback 'TlsPeer.notifyConnectionClosed' will be called when the connection is closed (including by failure).
- BCJSSE: Improved logging of connection events and include unique IDs in connection-specific log messages.
- BCJSSE: Server now logs the offered cipher suites when it fails to select one.
- BCJSSE: Added support for SSLParameters namedGroups and signatureSchemes properties (can also be used via BCJSSE extension API in earlier Java versions).
- DTLS: The initial handshake re-send time is now configurable by overriding 'TlsPeer.getHandshakeResendTimeMillis'.
- DTLS: Added support for connection IDs per RFC 9146.
- DTLS: Performance of DTLSVerifier has been improved so that it can reasonably be used for all incoming packets.
- Initial support has been added for A Mechanism for Encoding Differences in Paired Certificates.
- The PGP API now supports parsing, encoding, and fingerprinting of V6 EC/EdEC keys.
- A thread safe verifier API has been added to the PGP API to support multi-threaded verification of certifications on keys and user IDs.
- The number of keys/sub-keys in a PGPKeyRing can now be found by calling PGPKeyRing.size().
- The PQC algorithms LMS/HSS, SPHINCS+, Dilithium, Falcon, and NTRU are now supported directly by the BC provider.

### 2.13.4 Notes.

- The now defunct PQC SIKE algorithm has been removed, this has also meant the removal of its resource files so the provider is now quite a bit smaller.
- As a precaution, HC128 now enforces a 128 bit IV, previous behaviour for shorter IVs can be supported where required by padding the IV to the 128 bits with zero.
- PGP encrypted data generation now uses integrity protection by default. Previous behaviour for encrypted data can be supported where required by calling PGPDataEncryptorBuilder.setWithIntegrityPacket(false) when data encryption is set up.
- There are now additional sanity checks in place to prevent accidental mis-use of PGPSignature objects. If this change causes any issues, you might want to check what your code is up to as there is probably a bug.

### 2.13.5 Security Advisories.

- CVE-2023-33201 - this release fixes an issue with the X509LDAPCertStoreSpi where a specially crafted certificate subject could be used to try and extract extra information out of an LDAP server with wild-card matching enabled.

### 2.14.1 Version

Release: 1.73
Date: 2023, April 8th

### 2.14.2 Defects Fixed

- BCJSSE: Instantiating a JSSE provider in some contexts could cause an AccessControl exception. This has been fixed.
- The EC key pair generator can generate out of range private keys when used with SM2. A specific SM2KeyPairGenerator has been added to the low-level API and is used by KeyPairGenerator.getInstance("SM2", "BC"). The SM2 signer has been updated to check for out of range keys as well..
- The attached signature type byte was still present in Falcon signatures as well as the detached signature byte. This has been fixed.
- There was an off-by-one error in engineGetOutputSize() for ECIES. This has been fixed.
- The method for invoking read() internally in BCPGInputStream could result in inconsistent behaviour if the class was extended. This has been fixed.
- Fixed a rounding issue with FF1 Format Preserving Encryption algorithm for certain radices.
- Fixed RFC3394WrapEngine handling of 64 bit keys.
- Internal buffer for blake2sp was too small and could result in an ArrayIndexOutOfBoundsException. This has been fixed.
- JCA PSS Signatures using SHAKE128 and SHAKE256 now support encoding of algorithm parameters.
- PKCS10CertificationRequest now checks for empty extension parameters.
- Parsing errors in the processing of PGP Armored Data now throw an explicit exception ArmoredInputException.
- PGP AEAD streams could occassionally be truncated. This has been fixed.
- The ESTService class now supports processing of chunked HTTP data.
- A constructed ASN.1 OCTET STRING with a single member would sometimes be re-encoded as a definite-length OCTET STRING. The encoding has been adjusted to preserve the BER status of the object.
- PKIXCertPathReviewer could fail if the trust anchor was also included in the certificate store being used for path analysis. This has been fixed.
- UTF-8 parsing of an array range ignored the provided length. This has been fixed.
- IPAddress has been written to provide stricter checking and avoid the use of Integer.parseInt().
- A Java 7 class snuck into the Java 5 to Java 8 build. This has been addressed.

### 2.14.3 Additional Features and Functionality

- The Rainbow NIST Post Quantum Round-3 Candidate has been added to the low-level API and the BCPQC provider (level 3 and level 5 parameter sets only).
- The GeMSS NIST Post Quantum Round-3 Candidate has been added to the low-level API.
- The org.bouncycastle.rsa.max_mr_tests property check has been added to allow capping of MR tests done on RSA moduli.
- Significant performance improvements in PQC algorithms, especially BIKE, CMCE, Frodo, HQC, Picnic.
- EdDSA verification now conforms to the recommendations of Taming the many EdDSAs, in particular cofactored verification. As a side benefit, Pornin's basis reduction is now used for EdDSA verification, giving a significant performance boost.
- Major performance improvements for Anomalous Binary (Koblitz) Curves.
- The lightweight Cryptography finalists Ascon, ISAP, Elephant, PhotonBeetle, Sparkle, and Xoodyak have been added to the light-weight cryptography API.
- BLAKE2bp and BLAKE2sp have been added to the light-weight cryptography API.
- Support has been added for X.509, Section 9.8, hybrid certificates and CRLs using alternate public keys and alternate signatures.
- The property "org.bouncycastle.emulate.oracle" has been added to signal the provider should return algorithm names on some algorithms in the same manner as the Oracle JCE provider.
- An extra replaceSigners method has been added to CMSSignedData which allows for specifying the digest algorithm IDs to be used in the new CMSSignedData object.
- Parsing and re-encoding of ASN.1 PEM data has been further optimized to prevent unecessary conversions between basic encoding, definite length, and DER.
- Support has been added for KEM ciphers in CMS in accordance with draft-ietf-lamps-cms-kemri
- Support has been added for certEncr in CRMF to allow issuing of certificates for KEM public keys.
- Further speedups have been made to CRC24.
- GCMParameterSpec constructor caching has been added to improve performance for JVMs that have the class available.
- The PGPEncrytedDataGenerator now supports injecting the session key to be used for PGP PBE encrypted data.
- The CRMF CertificateRequestMessageBuilder now supports optional attributes.
- Improvements to the s calculation in JPAKE.
- A general purpose PQCOtherInfoGenerator has been added which supports all Kyber and NTRU.
- An implementation of HPKE (RFC 9180 - Hybrid Public Key Encryption) has been added to the light-weight cryptography API.

### 2.14.4 Security Advisories.

- The PQC implementations have now been subject to formal review for secret leakage and side channels, there were issues in BIKE, Falcon, Frodo, HQC which have now been fixed. Some weak positives also showed up in Rainbow, Picnic, SIKE, and GeMSS - for now this last set has been ignored as the algorithms will either be updated if they reappear in the Signature Round, or deleted, as is already the case for SIKE (it is now in the legacy package). Details on the group responsible for the testing can be found in the CONTRIBUTORS file.
- For at least some ECIES variants (e.g. when using CBC) there is an issue with potential malleability of a nonce (implying silent malleability of the plaintext) that must be sent alongside the ciphertext but is outside the IES integrity check. For this reason the automatic generation of nonces with IED is now disabled and they have to be passed in using an IESParameterSpec. The current advice is to agree on a nonce between parties and then rely on the use of the ephemeral key component to allow the nonce (rather the so called nonce) usage to be extended.

### 2.14.5 Notes.

- Most test data files have now been migrated to a separate project bc-test-data which is also available on github. If you clone bc-test-data at the same level as the bc-java project the tests will find the test data they require.
- There has been further work to make entropy collection more friendly in container environments. See DRBG.java for details. We would welcome any further feedback on this as we clearly cannot try all situations first hand.

### 2.15.1 Version

Release: 1.72.2, 1.72.3
Date: 2022, November 20th

### 2.15.2 Defects Fixed

- PGP patch release - fix for OSGI and version header in 1.72.1 jar file.

### 2.16.1 Version

Release: 1.72.1
Date: 2022, October 25th

### 2.16.2 Defects Fixed

- PGP patch release - fix for regression in OpenPGP PGPEncryptedData.java which could result in checksum failures on correct files.

### 2.17.1 Version

Release: 1.72
Date: 2022, September 25th

### 2.17.2 Defects Fixed

- There were parameter errors in XMSS^MT OIDs for XMSSMT_SHA2_40/4_256 and XMSSMT_SHA2_60/3_256. These have been fixed.
- There was an error in Merkle tree construction for the Evidence Records (ERS) implementation which could result in invalid roots been timestamped. ERS now produces an ArchiveTimeStamp for each data object/group with an associated reduced hash tree. The reduced hash tree is now calculated as a simple path to the root of the tree for each record.
- OpenPGP will now ignore signatures marked as non-exportable on encoding.
- A tagging calculation error in GCMSIV which could result in incorrect tags has been fixed.
- Issues around Java 17 which could result in failing tests have been addressed.

### 2.17.3 Additional Features and Functionality

- BCJSSE: TLS 1.3 is now enabled by default where no explicit protocols are supplied (e.g. "TLS" or "Default" SSLContext algorithms, or SSLContext.getDefault() method).
- BCJSSE: Rewrite SSLEngine implementation to improve compatibility with SunJSSE.
- BCJSSE: Support export of keying material via extension API.
- (D)TLS: Add support for 'tls-exporter' channel binding per RFC 9266.
- (D)TLS (low-level API): By default, only (D)TLS 1.2 and TLS 1.3 are offered now. Earlier versions are still supported if explicitly enabled. Users may need to check they are offering suitable cipher suites for TLS 1.3.
- (D)TLS (low-level API): Add support for raw public keys per RFC 7250.
- CryptoServicesRegistrar now has a setServicesConstraints() method on it which can be used to selectively turn off algorithms.
- The NIST PQC Alternate Candidate, Picnic, has been added to the low level API and the BCPQC provider.
- SPHINCS+ has been upgraded to the latest submission, SPHINCS+ 3.1 and support for Haraka has been added.
- Evidence records now support timestamp renewal and hash renewal.
- The SIKE Alternative Candidate NIST Post Quantum Algorithm has been added to the low-level API and the BCPQC provider.
- The NTRU Round 3 Finalist Candidate NIST Post Quantum Algorithm has been added to the low-level API and the BCPQC provider.
- The Falcon Finalist NIST Post Quantum Algorithm has been added to the low-level API and the BCPQC provider.
- The CRYSTALS-Kyber Finalist NIST Post Quantum Algorithm has been added to the low-level API and the BCPQC provider.
- Argon2 Support has been added to the OpenPGP API.
- XDH IES has now been added to the BC provider.
- The OpenPGP API now supports AEAD encryption and decryption.
- The NTRU Prime Alternative Candidate NIST Post Quantum Algorithms have been added to the low-level API and the BCPQC provider.
- The CRYSTALS-Dilithium Finalist NIST Post Quantum Algorithm has been added to the low-level API and the BCPQC provider.
- The BIKE NIST Post Quantum Alternative/Round-4 Candidate has been added to the low-level API and the BCPQC provider.
- The HQC NIST Post Quantum Alternative/Round-4 Candidate has been added to the low-level API and the BCPQC provider.
- Grain128AEAD has been added to the lightweight API.
- A fast version of CRC24 has been added for use with the PGP API.
- Some additional methods and fields have been exposed in the PGPOnePassSignature class to (hopefully) make it easier to deal with nested signatures.
- CMP support classes have been updated to reflect the latest editions to the the draft RFC "Lightweight Certificate Management Protocol (CMP) Profile".
- Support has been added to the PKCS#12 implementation for the Oracle trusted certificate attribute.
- Performance of our BZIP2 classes has been improved.

### 2.17.4 Notes

Keep in mind the PQC algorithms are still under development and we are still at least a year and a half away from published standards. This means the algorithms may still change so by all means experiment, but do not use the PQC algoritms for anything long term.

The legacy "Rainbow" and "McEliece" implementations have been removed from the BCPQC provider. The underlying classes are still present if required. Other legacy algorithm implementations can be found under the org.bouncycastle.pqc.legacy package.

### 2.17.5 Security Notes

The PQC SIKE algorithm is provided for research purposes only. It should now be regarded as broken. The SIKE implementation will be withdrawn in BC 1.73.

### 2.18.1 Version

Release: 1.71
Date: 2022, March 31st.

### 2.18.2 Defects Fixed

- In line with GPG the PGP API now attempts to preserve comments containing non-ascii UTF-8 characters.
- An accidental partial dependency on Java 1.7 has been removed from the TLS API.
- JcaPKIXIdentityBuilder would fail to process File objects correctly. This is now fixed.
- Some byte[] parameters to the CMP API were not being defensively cloned to prevent accidental changes. Extra defensive cloning has been added.
- CMS primitives would sometimes convert ASN.1 definite-length encodings into indefinite-length encodings. The primitives will now try and preserve the original encoding where possible.
- CMSSignedData.getAttributeCertificates() now properly restricts the tag values checked to just 1 (the obsolete v1 tag) and 2 (for the more current v2 certificates).
- BCJSSE now tries to validate a custom KeyManager selection in order to catch errors around a key manager ignoring key type early.
- Compressed streams in PGP ending with zero length partial packets could cause failure on parsing the OpenPGP API. This has been fixed.
- The fallback mode for JceAsymmetricKeyWrapper/Unwrapper would lose track of any algorithm parameters generated in the initial attempt. The algorithm parameters are now propagated.
- An accidental regression introduced by a fix for another issue in PKIXCertPathReviewer around use of the AuthorityKeyIdentifier extension and it failing to match a certificate uniquely when the serial number field is missing has been fixed.
- An error was found in the creation of TLS 1.3 Export Keying Material which could cause compatibility issues. This has been fixed.

### 2.18.3 Additional Features and Functionality

- Support has been added for OpenPGP regular expression signature packets.
- Support has been added for OpenPGP PolicyURI signature packets.
- A utility method has been added to PGPSecretKeyRing to allow for inserting or replacing a PGPPublicKey.
- A utility method has been added to PGPSecretKeyRing to allow for inserting or replacing a PGPPublicKey.
- The NIST PQC Finalist, Classic McEliece has been added to the low level API and the BCPQC provider.
- The NIST PQC Alternate Candidate, SPHINCS+ has been added to the BCPQC provider.
- The NIST PQC Alternate Candidate, FrodoKEM has been added to the low level API and the BCPQC provider.
- The NIST PQC Finalist, SABER has been added to the low level API and the BCPQC provider.
- KMAC128, KMAC256 has been added to the BC provider (empty customization string).
- TupleHash128, TupleHash256 has been added to the BC provider (empty customization string).
- ParallelHash128, ParallelHash256 has been added to the BC provider (empty customization string, block size 1024 bits).
- Two new properties: "org.bouncycastle.rsa.max_size" (default 15360) and "org.bouncycastle.ec.fp_max_size" (default 1042) have been added to cap the maximum size of RSA and EC keys.
- RSA modulus are now checked to be provably composite using the enhanced MR probable prime test.
- Imported EC Fp basis values are now validated against the MR prime number test before use. The certainty level of the prime test can be determined by "org.bouncycastle.ec.fp_certainty" (default 100).
- The BC entropy thread now has a specific name: "BC-ENTROPY-GATHERER".
- Utility methods have been added for joining/merging PGP public keys and signatures.
- Blake3-256 has been added to the BC provider.
- DTLS: optimisation to delayed handshake hash.
- Further additions to the ETSI 102 941 support in the ETSI/ITS package: certification request, signed message generation and verification now supported.
- CMSSignedDataGenerator now supports the direct generation of definite-length data.
- The NetscapeCertType class now has a hasUsages() method on it for querying usage settings on its bit string.
- Support for additional input has been added for deterministic (EC)DSA.
- The OpenPGP API provides better support for subkey generation.
- BCJSSE: Added boolean system properties "org.bouncycastle.jsse.client.dh.disableDefaultSuites" and "org.bouncycastle.jsse.server.dh.disableDefaultSuites". Default "false". Set to "true" to disable inclusion of DH cipher suites in the default cipher suites for client/server respectively.
- ASN.1 object support has been added for the Lightweight Certificate Management Protocol (CMP), currently in draft.
- A HybridValueParamterSpec class has been added for use with KeyAgreement to support SP 800-56C hybrid (so classical/post-quantum) key agreement.

### 2.18.4 Notes

- The deprecated QTESLA implementation has been removed from the BCPQC provider.
- The submission update to SPHINCS+ has been added. This changes the generation of signatures - particularly deterministic ones.

### 2.19.1 Version

Release: 1.70
Date: 2021, November 29th.

### 2.19.2 Defects Fixed

- Blake 3 output limit is enforced.
- The PKCS12 KeyStore was relying on default precedence for its key Cipher implementation so was sometimes failing if used from the keytool. The KeyStore class now makes sure it uses the correct Cipher implementation.
- Fixed bzip2 compression for empty contents (GH #993).
- ASN.1: More robust handling of high tag numbers and definite-length forms.
- BCJSSE: Fix a concurrent modification issue in session contexts (GH#968).
- BCJSSE: Don't log sensitive system property values (GH#976).
- BCJSSE: Fixed a priority issue amongst imperfect-match credentials in KeyManager classes.
- The IES AlgorithmParameters object has been re-written to properly support all the variations of IESParameterSpec.
- getOutputSize() for ECIES has been corrected to avoid occassional underestimates.
- The lack of close() in the ASN.1 Dump command line utility was triggering false positives in some code analysis tools. A close() call has been added.
- PGPPublicKey.getBitStrength() now properly recognises EdDSA keys.

### 2.19.3 Additional Features and Functionality

- Missing PGP CRC checksums can now be optionally ignored using setDetectMissingCRC() (default false) on ArmoredInputStream.
- PGPSecretKey.copyWithNewPassword() now has a variant which uses USAGE_SHA1 for key protection if a PGPDigestCalculator is passed in.
- PGP ASCII armored data now skips "\t", "\v", and "\f".
- PKCS12 files with duplicate localKeyId attributes on certificates will now have the incorrect attributes filtered out, rather than the duplicate causing an exception.
- PGPObjectFactory will now ignore packets representing unrecognised signature versions in the input stream.
- The X.509 extension generator will now accumulate some duplicate X.509 extensions into a single extension where it is possible to do so.
- Removed support for maxXofLen in Kangaroo digest.
- Ignore marker packets in PGP Public and Secret key ring collection.
- An implementation of LEA has been added to the low-level API.
- Access, recovery, and direct use for PGP session keys has been added to the OpenPGP API for processing encrypted data.
- A PGPCanonicalizedDataGenerator has been added which converts input into canonicalized literal data for text and UTF-8 mode.
- A getUserKeyingMaterial() method has been added to the KeyAgreeRecipientInformation class.
- ASN.1: Tagged objects (and parsers) now support all tag classes. Special code for ApplicationSpecific has been deprecated and re-implemented in terms of TaggedObject.
- ASN.1: Improved support for nested tagging.
- ASN.1: Added support for GraphicString, ObjectDescriptor, RelativeOID.
- ASN.1: Added support for constructed BitString encodings, including efficient parsing for large values.
- TLS: Added support for external PSK handshakes.
- TLS: Check policy restrictions on key size when determining cipher suite support.
- A performance issue in KeccakDigest due to left over debug code has been identified and dealt with.
- BKS key stores can now be used for collecting protected keys (note: any attempt to store such a store will cause an exception).
- A method for recovering user keying material has been added to KeyAgreeRecipientInformation.
- Support has been added to the CMS API for SHA-3 based PLAIN-ECDSA.
- The low level BcDefaultDigestProvider now supports the SHAKE family of algorithms and the SM3 alogirthm.
- PGPKeyRingGenerator now supports creation of key-rings with direct-key identified keys.
- The PQC NIST candidate, signature algorithm SPHINCS+ has been added to the low-level API.
- ArmoredInputStream now explicitly checks for a '\n' if in crLF mode.
- Direct support for NotationDataOccurances, Exportable, Revocable, IntendedRecipientFingerPrints, and AEAD algorithm preferences has been added to PGPSignatureSubpacketVector.
- Further support has been added for keys described using S-Expressions in GPG 2.2.X.
- Support for OpenPGP Session Keys from the (draft) Stateless OpenPGP CLI has been added.
- Additional checks have been added for PGP marker packets in the parsing of PGP objects.
- A CMSSignedData.addDigestAlgorithm() has been added to allow for adding additional digest algorithm identifiers to CMS SignedData structures when required.
- Support has been added to CMS for the LMS/HSS signature algorithm.
- The system property "org.bouncycastle.jsse.client.assumeOriginalHostName" (default false) has been added for dealing with SNI problems related to the host name not being propagate by the JVM.
- The JcePKCSPBEOutputEncryptorBuilder now supports SCRYPT with ciphers that do not have algorithm parameters (e.g. AESKWP).
- Support is now added for certificates using ETSI TS 103 097, "Intelligent Transport Systems (ITS)" in the bcpkix package.

### 2.19.4 Notes.

- While this release should maintain source code compatibility, developers making use of some parts of the ASN.1 library will find that some classes need recompiling. Apologies for the inconvenience.

### 2.20.1 Version

Release: 1.69
Date: 2021, June 7th.

### 2.20.2 Defects Fixed

- Lightweight and JCA conversion of Ed25519 keys in the PGP API could drop the leading byte as it was zero. This has been fixed.
- Marker packets appearing at the start of PGP public key rings could cause parsing failure. This has been fixed.
- ESTService could fail for some valid Content-Type headers. This has been fixed.
- Originator key algorithm parameters were being passed as NULL in key agreement recipients. The parameters now reflect the value of the parameters in the key's SubjectPublicKeyInfo.
- ContentType on encapsulated data was not been passed through correctly for authenticated and enveloped data. This has been fixed.
- NTRUEncryptionParameters and NTRUEncryptionKeyGenerationParameters were not correctly cloning the contained message digest. This has been fixed.
- CertificateFactory.generateCertificates()/generateCRLs() would throw an exception if extra data was found at the end of a PEM file even if valid objects had been found. Extra data is now ignored providing at least one object found.
- Internal class PKIXCRLUtil could throw a NullPointerException for CRLs with an absent nextUpdate field. This has been fixed.
- PGP ArmoredInputStream now fails earlier on malformed headers.
- The McElieceKobaraImaiCipher was randomly throwing "Bad Padding: invalid ciphertext" exception while decrypting due to leading zeroes been missed during processing of the cipher text. This has been fixed.
- Ed25519 keys being passed in via OpenSSH key spec are now validated in the KeyFactory.
- Blowfish keys are now range checked on cipher construction.
- In some cases PGPSecretKeyRing was failing to search its extraPubKeys list when searching for public keys.
- The BasicConstraintsValidation class in the BC cert path validation tools has improved conformance to RFC 5280.
- AlgorithmIdentifiers involving message digests now attempt to follow the latest conventions for the parameters field (basically DER NULL appears less).
- Fix various conversions and interoperability for XDH and EdDSA between BC and SunEC providers.
- TLS: Prevent attempts to use KeyUpdate mechanism in versions before TLS 1.3.

### 2.20.3 Additional Features and Functionality

- GCM-SIV has been added to the lightweight API and the provider.
- Blake3 has been added to the lightweight API.
- The OpenSSL PEMParser can now be extended to add specialised parsers.
- Base32 encoding has now been added, the default alphabet is from RFC 4648.
- The KangarooTwelve message digest has been added to the lightweight API.
- An implementation of the two FPE algorithms, FF1 and FF3-1 in SP 800-38G has been added to the lightweight API and the JCE provider.
- An implementation of ParallelHash has been added to the lightweight API.
- An implementation of TupleHash has been added to the lightweight API.
- RSA-PSS now supports the use of SHAKE128 and SHAKE256 as the mask generation function and digest.
- ECDSA now supports the use of SHAKE128 and SHAKE256.
- PGPPBEEncryptedData will now reset the stream if the initial checksum fails so another password can be tried.
- Iterators on public and secret key ring collections in PGP now reflect the original order of the public/secret key rings they contain.
- KeyAgreeRecipientInformation now has a getOriginator() method for retrieving the underlying orginator information.
- PGPSignature now has a getDigestPrefix() method for people wanting exposure to the signature finger print details.
- The old BKS-V1 format keystore is now disabled by default. If you need to use BKS-V1 for legacy reasons, it can be re-enabled by adding:

      org.bouncycastle.bks.enable_v1=true

  to the java.security file. We would be interested in hearing from anyone that needs to do this.
- PLAIN-ECDSA now supports the SHA3 digests.
- Some highlevel support for RFC 4998 ERS has been added for ArchiveTimeStamp and EvidenceRecord. The new classes are in the org.bouncycastle.tsp.ers package.
- ECIES has now also support SHA256, SHA384, and SHA512.
- digestAlgorithms filed in CMS SignedData now includes counter signature digest algorithms where possible.
- A new property "org.bouncycastle.jsse.config" has been added which can be used to configure the BCJSSE provider when it is created using the no-args constructor.
- In line with changes in OpenSSL 1.1.0, OpenSSLPBEParametersGenerator can now be configured with a digest.
- PGPKeyRingGenerator now includes a method for adding a subkey with a primary key binding signature.
- Support for ASN.1 PRIVATE tags has been added.
- Performance enhancements to Nokeon, AES, GCM, and SICBlockCipher.
- Support for ecoding/decoding McElieceCCA2 keys has been added to the PQC API
- BCJSSE: Added support for jdk.tls.maxCertificateChainLength system property (default is 10).
- BCJSSE: Added support for jdk.tls.maxHandshakeMessageSize system property (default is 32768).
- BCJSSE: Added support for jdk.tls.client.enableCAExtension (default is 'false').
- BCJSSE: Added support for jdk.tls.client.cipherSuites system property.
- BCJSSE: Added support for jdk.tls.server.cipherSuites system property.
- BCJSSE: Extended ALPN support via standard JSSE API to JDK 8 versions after u251/u252.
- BCJSSE: Key managers now support EC credentials for use with TLS 1.3 ECDSA signature schemes (including brainpool).
- TLS: Add TLS 1.3 support for brainpool curves per RFC 8734.

### 2.20.4 Notes

- There is a small API change in the PKIX package to the DigestAlgorithmIdentifierFinder interface as a find() method that takes an ASN1ObjectIdentifier has been added to it. For people wishing to extend their own implementations, see DefaultDigestAlgorithmIdentifierFinder for a sample implementation.
- A version of the bcmail API supporting Jakarta Mail has now been added (see bcjmail jar).
- Some work has been done on moving out code that does not need to be in the provider jar. This has reduced the size of the provider jar and should also make it easier for developers to patch the classes involved as they no longer need to be signed. bcpkix and bctls are both dependent on the new bcutil jar.

### 2.21.1 Version

Release: 1.68
Date: 2020, December 21st.

### 2.21.2 Defects Fixed

- Some BigIntegers utility methods would fail for BigInteger.ZERO. This has been fixed.
- PGPUtil.isKeyRing() was not detecting secret sub-keys in its input. This has been fixed.
- The ASN.1 class, ArchiveTimeStamp was insisting on a value for the optional reducedHashTree field. This has been fixed.
- BCJSSE: Lock against multiple writers - a possible synchronization issue has been removed.

### 2.21.3 Additional Features and Functionality

- BCJSSE: Added support for system property com.sun.net.ssl.requireCloseNotify. Note that we are using a default value of 'true'.
- BCJSSE: 'TLSv1.3' is now a supported protocol for both client and server. For this release it is only enabled by default for the 'TLSv1.3' SSLContext, but can be explicitly enabled using 'setEnabledProtocols' on an SSLSocket or SSLEngine, or via SSLParameters.
- BCJSSE: Session resumption is now also supported for servers in TLS 1.2 and earlier. For this release it is disabled by default, and can be enabled by setting the boolean system property org.bouncycastle.jsse.server.enableSessionResumption to 'true'.
- The provider RSA-PSS signature names that follow the JCA naming convention.
- FIPS mode for the BCJSSE now enforces namedCurves for any presented certificates.
- PGPSignatureSubpacketGenerator now supports editing of a pre-existing sub-packet list.

### 2.22.1 Version

Release: 1.67
Date: 2020, November 1st.

### 2.22.2 Defects Fixed

- BCJSSE: SunJSSE compatibility fix - override of getChannel() removed and 'urgent data' behaviour should now conform to what the SunJSSE expects.
- Nested BER data could sometimes cause issues in octet strings. This has been fixed.
- Certificates/CRLs with short signatures could cause an exception in toString() in the BC X509 Certificate implmentation. This has been fixed.
- In line with latest changes in the JVM, SignatureSpis which don't require parameters now return null on engineGetParameters().
- The RSA KeyFactory now always preferentially produces RSAPrivateCrtKey where it can on requests for a KeySpec based on an RSAPrivateKey.
- CMSTypedStream$FullReaderStream now handles zero length reads correctly.
- Unecessary padding was added on KMAC when the key length was block aligned. This has been fixed.
- Zero length data would cause an unexpected exception from RFC5649WrapEngine. This has been fixed.
- OpenBSDBcrypt was failing to handle some valid prefixes. This has been fixed.

### 2.22.3 Additional Features and Functionality

- Performance of Argon2 has been improved.
- Performance of Noekeon has been improved.
- A setSessionKeyObfuscation() method has been added to PublicKeyKeyEncryptionMethodGenerator to allow turning off of session key obfuscation (default is on, method primarily to get around early version GPG issues with AES-128 keys).
- Implemented 'safegcd' constant-time modular inversion (as well as a variable-time variant). It has replaced Fermat inversion in all our EC code, and BigInteger.modInverse in several other places, particularly signers. This improves side-channel protection, and also gives a significant performance boost.
- Performance of custom binary ECC curves and Edwards Curves has been improved.
- BCJSSE: New boolean system property 'org.bouncycastle.jsse.keyManager.checkEKU' allows to disable ExtendedKeyUsage restrictions when selecting credentials (although the peer may still complain).
- Initial support has been added for "Composite Keys and Signatures For Use In Internet PKI" using the test OID. Please note there will be further refinements to this as the draft is standardised.
- The BC EdDSA signature API now supports keys implementing all methods on the EdECKey and XECKey interfaces directly.
- Work has begun on classes to support the ETSI TS 103 097, Intelligent Transport Systems (ITS) in the bcpkix package.
- Further optimization work has been done on GCM.
- A NewHope based processor, similar to the one for Key Agreement has been added for trying to "quantum hard" KEM algorithms.
- PGP clear signed signatures now support SHA-224.
- Treating absent vs NULL as equivalent can now be configured by a system property. By default this is not enabled.
- Mode name checks in Cipher strings should now make sure an improper mode name always results in a NoSuchAlgorithmException.
- In line with changes in OpenSSL, the OpenSSLPBKDF now uses UTF-8 encoding.

### 2.22.4 Security Advisory

- As described in CVE-2020-28052, the OpenBSDBCrypt.checkPassword() method had a flaw in it due to a change for BC 1.65. BC 1.66 is also affected. The issue is fixed in BC 1.67. If you are using OpenBSDBCrypt.checkPassword() and you are using BC 1.65 or BC 1.66 we strongly advise moving to BC 1.67 or later.

### 2.23.1 Version

Release: 1.66
Date: 2020, July 4th.

### 2.23.2 Defects Fixed

- EdDSA verifiers now reset correctly after rejecting overly long signatures.
- BCJSSE: SSLSession.getPeerCertificateChain could throw NullPointerException. This has been fixed.
- qTESLA-I verifier would reject some valid signatures. This has been fixed.
- qTESLA verifiers now reject overly long signatures.
- PGP regression caused failure to preserve existing version header when headers were reset. This has now been fixed.
- PKIXNameConstraintValidator had a bad cast preventing use of multiple OtherName constraints. This has been fixed.
- Serialisation of the non-CRT RSA Private Key could cause a NullPointerException. This has been fixed.
- An extra 4 bytes was included in the start of HSS public key encodings. This has been fixed.
- CMS with Ed448 using a direct signature was using id-shake256-len rather than id-shake256. This has been fixed.
- Use of GCMParameterSpec could cause an AccessControlException under some circumstances. This has been fixed.
- DTLS: Fixed high-latency HelloVerifyRequest handshakes.
- An encoding bug for rightEncoded() in KMAC has been fixed.
- For a few values the cSHAKE implementation would add unnecessary pad bytes where the N and S strings produced encoded data that was block aligned. This has been fixed.
- There were a few circumstances where Argon2BytesGenerator might hit an unexpected null. These have been removed.

### 2.23.3 Additional Features and Functionality

- The qTESLA signature algorithm has been updated to v2.8 (20191108).
- BCJSSE: Client-side OCSP stapling now supports status_request_v2 extension.
- Support has been added for PKIXRevocationChecker for users of Java 8 and later.
- Support has been added for "ocsp.enable", "ocsp.responderURL" for users of Java 8 and later.
- Support has been added for "org.bouncycastle.x509.enableCRLDP" to the PKIX validator.
- BCJSSE: Now supports system property 'jsse.enableFFDHE'
- BCJSSE: Now supports system properties 'jdk.tls.client.SignatureSchemes' and 'jdk.tls.server.SignatureSchemes'.
- Multi-release support has been added for Java 11 XECKeys.
- Multi-release support has been added for Java 15 EdECKeys.
- The MiscPEMGenerator will now output general PrivateKeyInfo structures.
- A new property "org.bouncycastle.pkcs8.v1_info_only" has been added to make the provider only produce version 1 PKCS8 PrivateKeyInfo structures.
- The PKIX CertPathBuilder will now take the target certificate from the target constraints if a specific certificate is given to the selector.
- BCJSSE: A range of ARIA and CAMELLIA cipher suites added to supported list.
- BCJSSE: Now supports the PSS signature schemes from RFC 8446 (TLS 1.2 onwards).
- Performance of the Base64 encoder has been improved.
- The PGPPublicKey class will now include direct key sigantures when checking for key expiry times.

### 2.23.4 Notes

The qTESLA update breaks compatibility with previous versions. Private keys now include a hash of the public key at the end, and signatures are no longer interoperable with previous versions.

### 2.24.1 Version

Release: 1.65
Date: 2020, March 31st.

### 2.24.2 Defects Fixed

- DLExternal would encode using DER encoding for tagged SETs. This has been fixed.
- ChaCha20Poly1305 could fail for large (>~2GB) files. This has been fixed.
- ChaCha20Poly1305 could fail for small updates when used via the provider. This has been fixed.
- Properties.getPropertyValue could ignore system property when other local overrides set. This has been fixed.
- The entropy gathering thread was not running in daemon mode, meaning there could be a delay in an application shutting down due to it. This has been fixed.
- A recent change in Java 11 could cause an exception with the BC Provider's implementation of PSS. This has been fixed.
- BCJSSE: TrustManager now tolerates having no trusted certificates.
- BCJSSE: Choice of credentials and signing algorithm now respect the peer's signature_algorithms extension properly.
- BCJSSE: KeyManager for KeyStoreBuilderParameters no longer leaks memory.

### 2.24.3 Additional Features and Functionality

- LMS and HSS (RFC 8554) support has been added to the low level library and the PQC provider.
- SipHash128 support has been added to the low level library and the JCE provider.
- BCJSSE: BC API now supports explicitly specifying the session to resume.
- BCJSSE: Ed25519, Ed448 are now supported when TLS 1.2 or higher is negotiated (except in FIPS mode).
- BCJSSE: Added support for extended_master_secret system properties: jdk.tls.allowLegacyMasterSecret, jdk.tls.allowLegacyResumption, jdk.tls.useExtendedMasterSecret .
- BCJSSE: KeyManager and TrustManager now check algorithm constraints for keys and certificate chains.
- BCJSSE: KeyManager selection of server credentials now prefers matching SNI hostname (if any).
- BCJSSE: KeyManager may now fallback to imperfect credentials (expired, SNI mismatch).
- BCJSSE: Client-side OCSP stapling support (beta version: via status_request extension only, provides jdk.tls.client.enableStatusRequestExtension, and requires CertPathBuilder support).
- TLS: DSA in JcaTlsCrypto now falls back to stream signing to work around NoneWithDSA limitations in default provider.

### 2.25.1 Version

Release: 1.64
Date: 2019, October 7th.

### 2.25.2 Defects Fixed

- OpenSSH: Fixed padding in generated Ed25519 private keys.
- Validation of headers in PemReader now looks for tailing dashes in header.
- PKIXNameConstraintValidator was throwing a NullPointerException on OtherName. This has been fixed.
- Some compatibility issues around the signature encryption algorithm field in CMS SignedData and the GOST algorithms have been addressed.
- GOST3410-2012-512 now uses the GOST3411-2012-256 as its KDF digest.

### 2.25.3 Additional Features and Functionality

- PKCS12: key stores containing only certificates can now be created without the need to provide passwords.
- BCJSSE: Initial support for AlgorithmConstraints; protocol versions and cipher suites.
- BCJSSE: Initial support for 'jdk.tls.disabledAlgorithms'; protocol versions and cipher suites.
- BCJSSE: Add SecurityManager check to access session context.
- BCJSSE: Improved SunJSSE compatibility of the NULL_SESSION.
- BCJSSE: SSLContext algorithms updated for SunJSSE compatibility (default enabled protocols).
- The digest functions Haraka-256 and Haraka-512 have been added to the provider and the light-weight API
- XMSS/XMSS^MT key management now allows for allocating subsets of the private key space using the extraKeyShard() method. Use of StateAwareSignature is now deprecated.
- Support for Java 11's NamedParameterSpec class has been added (using reflection) to the EC and EdEC KeyPairGenerator implementations.

### 2.25.4 Removed Features and Functionality

- Deprecated ECPoint 'withCompression' tracking has been removed.

### 2.25.5 Security Advisory

- A change to the ASN.1 parser in 1.63 introduced a regression that can cause an OutOfMemoryError to occur on parsing ASN.1 data. We recommend upgrading to 1.64, particularly where an application might be parsing untrusted ASN.1 data from third parties.

### 2.26.1 Version

Release: 1.63
Date: 2019, September 10th.

### 2.26.2 Defects Fixed

- The ASN.1 parser would throw a large object exception for some objects which could be safely parsed. This has been fixed.
- GOST3412-2015 CTR mode was unusable at the JCE level. This has been fixed.
- The DSTU MACs were failing to reset fully on doFinal(). This has been fixed.
- The DSTU MACs would throw an exception if the key was a multiple of the size as the MAC's underlying buffer size. This has been fixed.
- EdEC and QTESLA were not previously usable with the post Java 9 module structure. This is now fixed.
- ECNR was not correctly bounds checking the input and could produce invalid signatures. This is now fixed.
- ASN.1: Enforce no leading zeroes in OID branches (longer than 1 character).
- TLS: Fix X448 support in JcaTlsCrypto.
- Fixed field reduction for secp128r1 custom curve.
- Fixed unsigned multiplications in X448 field squaring.
- Some issues over subset Name Constraint validation in the CertPath analyser have now been fixed.
- TimeStampResponse.getEncoded() could throw an exception if the TimeStampToken was null. This has been fixed.
- Unnecessary memory usage in the ARGON2 implementation has been removed.
- Param-Z in the GOST-28147 algorithm was not resolving correctly. This has been fixed.
- It is now possible to specify different S-Box parameters for the GOST 28147-89 MAC.

### 2.26.3 Additional Features and Functionality

- QTESLA is now updated with the round 2 changes. Note: the security catergories, and in some cases key generation and signatures, have changed. For people interested in comparison, the round 1 version is now moved to org.bouncycastle.pqc.crypto.qteslarnd1 - this package will be deleted in 1.64. Please keep in mind that QTESLA may continue to evolve.
- Support has been added for generating Ed25519/Ed448 signed certificates.
- A method for recovering the message/digest value from an ECNR signature has been added.
- Support for the ZUC-128 and ZUC-256 ciphers and MACs has been added to the provider and the lightweight API.
- Support has been added for ChaCha20-Poly1305 AEAD mode from RFC 7539.
- Improved performance for multiple ECDSA verifications using same public key.
- Support for PBKDF2withHmacSM3 has been added to the BC provider.
- The S/MIME API has been fixed to avoid unnecessary delays due to DNS resolution of a hosts name in internal MimeMessage preparation.
- The valid path for EST services has been updated to cope with the characters used in the Aruba clearpass EST implementation.

### 2.27.1 Version

Release: 1.62
Date: 2019, June 3rd.

### 2.27.2 Defects Fixed

- DTLS: Fixed infinite loop on IO exceptions.
- DTLS: Retransmission timers now properly apply to flights monolithically.
- BCJSSE: setEnabledCipherSuites ignores unsupported cipher suites.
- BCJSSE: SSLSocket implementations store passed-in 'host' before connecting.
- BCJSSE: Handle SSLEngine closure prior to handshake.
- BCJSSE: Provider now configurable using security config under Java 11 and later.
- EdDSA verifiers now reject overly long signatures.
- XMSS/XMSS^MT OIDs now using the values defined in RFC 8391.
- XMSS/XMSS^MT keys now encoded with OID at start.
- An error causing valid paths to be rejected due to DN based name constraints has been fixed in the CertPath API.
- Name constraint resolution now includes special handling of serial numbers.
- Cipher implementations now handle ByteBuffer usage where the ByteBuffer has no backing array.
- CertificateFactory now enforces presence of PEM headers when required.
- A performance issue with RSA key pair generation that was introduced in 1.61 has been mostly eliminated.

### 2.27.3 Additional Features and Functionality

- Builders for X509 certificates and CRLs now support replace and remove extension methods.
- DTLS: Added server-side support for HelloVerifyRequest.
- DTLS: Added support for an overall handshake timeout.
- DTLS: Added support for the heartbeat extension (RFC 6520).
- DTLS: Improve record seq. behaviour in HelloVerifyRequest scenarios.
- TLS: BasicTlsPSKIdentity now reusable (returns cloned array from getPSK).
- BCJSSE: Improved ALPN support, including selectors from Java 9.
- Lightweight RSADigestSigner now support use of NullDigest.
- SM2Engine now supports C1C3C2 mode.
- SHA256withSM2 now added to provider.
- BCJSSE: Added support for ALPN selectors (including in BC extension API for earlier JDKs).
- BCJSSE: Support 'SSL' algorithm for SSLContext (alias for 'TLS').
- The BLAKE2xs XOF has been added to the lightweight API.
- Utility classes added to support journaling of SecureRandom and algorithms to allow persistance and later resumption.
- PGP SexprParser now handles some unprotected key types.
- NONEwithRSA support added to lightweight RSADigestSigner.
- Support for the Ethereum flavor of IES has been added to the lightweight API.

### 2.28.1 Version

Release: 1.61
Date: 2019, February 4th.

### 2.28.2 Defects Fixed

- Use of EC named curves could be lost if keys were constructed via a key factory and algorithm parameters. This has been fixed.
- RFC3211WrapEngine would not properly handle messages longer than 127 bytes. This has been fixed.
- The JCE implementations for RFC3211 would not return null AlgorithmParameters. This has been fixed.
- TLS: Don't check CCS status for hello_request.
- TLS: Tolerate unrecognized hash algorithms.
- TLS: Tolerate unrecognized SNI types.
- An incompatibility issue in ECIES-KEM encryption in cofactor mode has been fixed.
- An issue with XMSS/XMSSMT private key loading which could result in invalid signatures has been fixed.
- StateAwareSignature.isSigningCapable() now returns false when the key has reached it's maximum number of signatures.
- The McEliece KeyPairGenerator was failing to initialize the underlying class if a SecureRandom was explicitly passed.
- The McEliece cipher would sometimes report the wrong value on a call to Cipher.getOutputSize(int). This has been fixed.
- CSHAKEDigest.leftEncode() was using the wrong endianness for multi byte values. This has been fixed.
- Some ciphers, such as CAST6, were missing AlgorithmParameters implementations. This has been fixed.
- An issue with the default "m" parameter for 1024 bit Diffie-Hellman keys which could result in an exception on key pair generation has been fixed.
- The SPHINCS256 implementation is now more tolerant of parameters wrapped with a SecureRandom and will not throw an exception if it receives one.
- A regression in PGPUtil.writeFileToLiteralData() which could cause corrupted literal data has been fixed.
- Several parsing issues related to the processing of CMP PKIPublicationInfo have been fixed.
- The ECGOST curves for id-tc26-gost-3410-12-256-paramSetA and id-tc26-gost-3410-12-512-paramSetC had incorrect co-factors. These have been fixed.

### 2.28.3 Additional Features and Functionality

- The qTESLA signature algorithm has been added to PQC light-weight API and the PQC provider.
- The password hashing function, Argon2 has been added to the lightweight API.
- BCJSSE: Added support for endpoint ID validation (HTTPS, LDAP, LDAPS).
- BCJSSE: Added support for 'useCipherSuitesOrder' parameter.
- BCJSSE: Added support for ALPN.
- BCJSSE: Various changes for improved compatibility with SunJSSE.
- BCJSSE: Provide default extended key/trust managers.
- TLS: Added support for TLS 1.2 features from RFC 8446.
- TLS: Removed support for EC point compression.
- TLS: Removed support for record compression.
- TLS: Updated to RFC 7627 from draft-ietf-tls-session-hash-04.
- TLS: Improved certificate sig. alg. checks.
- TLS: Finalised support for RFC 8442 cipher suites.
- Support has been added to the main Provider for the Ed25519 and Ed448 signature algorithms.
- Support has been added to the main Provider for the X25519 and X448 key agreement algorithms.
- Utility classes have been added for handling OpenSSH keys.
- Support for processing messages built using GPG and Curve25519 has been added to the OpenPGP API.
- The provider now recognises the standard SM3 OID.
- A new API for directly parsing and creating S/MIME documents has been added to the PKIX API.
- SM2 in public key cipher mode has been added to the provider API.
- The BCFKSLoadStoreParameter has been extended to allow the use of certificates and digital signatures for verifying the integrity of BCFKS key stores.

### 2.28.4 Removed Features and Functionality

- Deprecated methods for EC point construction independent of curves have been removed.

### 2.29.1 Version

Release: 1.60
Date: 2018, June 30

### 2.29.2 Defects Fixed

- Base64/UrlBase64 would throw an exception on a zero length string. This has been fixed.
- Base64/UrlBase64 would throw an exception if there was whitespace in the last 4 characters. This has been fixed.
- The SM2 Signature JCE class now properly resets of Signature.sign() is called.
- XMSS applies further validation to deserialisation of the BDS tree so that failure occurs as soon as tampering is detected (see CVE below).
- An off by one error in the JsseDefaultHostnameAuthorizer isValidNameMatch method has been fixed.
- BCJSSE: Return empty byte array instead of null, for the null session ID.
- If a checksum calculator was passed to a PGPSecretKey constructor, but the encryptor was set to null, the wrong checksum would be calculated for the S2K usage. This has been fixed.
- The CRMF EncryptedValue, when containing a private key, held an encoding of an EncryptedPrivateKeyInfo, rather than just the encrypted bytes. This has been fixed.
- EC point precomputations could fail due to race conditions in concurrent settings. Point precomputation was reworked to fix this.
- PGP key rings containing EdDSA signatures would cause an exception on parsing. This has been fixed.
- BCJSSE: a mixed case error for brainpool curves in the supported groups set has been fixed.
- getVersion() on the CRMF CertTemplate class could cause a null pointer exception if the optional version field was left out. This has been fixed.
- Use of a short buffer with RSA via the JCE could result in an escaping ArrayIndexOutOfBoundsException. This has been fixed so that a ShortBufferException is now thrown.
- SM2Engine.decrypt() ignored the offset parameter and assumed zero. This has been fixed.
- A PEM encoded TRUSTED CERTIFICATE missing a trust block would result in a NullPointerException. This has been fixed.
- If the Sun provider was removed entirely the BC SecureRandom was unable to seed and caused an InstantiationException. A back up seeding strategy has been added to prevent this.
- In some situations the use of sm2p256v1 would result in "unknown curve name". This has been fixed.
- CMP PollReqContent now supports multiple certificate request IDs.

### 2.29.3 Additional Features and Functionality

- TLS: Extended CBC padding is now optional (and disabled by default).
- TLS: Now supports channel binding 'tls-server-end-point'.
- TLS: InterruptedIOException (e.g. socket timeout) during app-data reads no longer fails connection; handshake is optionally resumable after IIOE using 'TlsProtocol.setResumableHandshake()'.
- TLS: Added utility methods and constants for ALPN (RFC 7301).
- BCJSSE: Now supports system property 'jdk.tls.client.protocols'
- BCJSSE: Now supports SSLParameters.setSNIMatchers.
- BCJSSE: SNI can now be used in earlier JDKs via BC extensions.
- BCJSSE: Session context now holds sessions via soft references.
- An implementation of CryptoServicesRegistrar has been added to allow configuring of DSA/DH parameters and global setting of the SecureRandom used in the APIs.
- Support has been added for the Unified Model of key agreement for both regular Diffie-Hellman and ECCDH.
- Standard key-wrapping ciphers can now be used for wrapping other data where the cipher supports it.
- BCFKS can now support the use of generalised wrapping algorithms.
- A parser has now been added for the GNU keybox file format.
- The GPG SExpr parser now covers a wider range of key types and validates associated checksums as well.
- PGP EC operations now support more than just NIST curves.
- Restrictions on the output sizes of the Blake2b/s digests in the lightweight API have been removed.
- The Whirlpool digest OID has been added to its corresponding mappings for the JCA.
- Support has been added for SHA-3 based signatures to the CMS API.
- Support has been added to the CMS API for the generation of ECGOST key transport messages.
- The ECElGamalEncryptor now supports the use of ECGOST curves.
- The number of signature subpackets in OpenPGP signatures that are converted into explicit types automatically has been increased.
- RFC 8032: Added low-level implementations of Ed25519 and Ed448.
- The provider jars now include a services entry for the 2 providers they hold.
- Support has been added for the German BSI KAEG Elliptic Curve key agreement algorithm with X9.63 as the KDF to the JCE.
- Support has been added for the German BSI KAEG Elliptic Curve session key KDF to the lightweight API.

### 2.29.4 Security Related Changes and CVE's Addressed by this Release

- CVE-2018-1000180: issue around primality tests for RSA key pair generation if done using only the low-level API.
- CVE-2018-1000613: lack of class checking in deserialization of XMSS/XMSS^MT private keys with BDS state information.

### 2.30.1 Version

Release: 1.59
Date: 2017, December 28

### 2.30.2 Defects Fixed

- Issues with using PQC based keys with the provided BC KeyStores have now been fixed.
- ECGOST-2012 public keys were being encoded with the wrong OID for the digest parameter in the algorithm parameter set. This has been fixed.
- SM3 has now been added as an acceptable algorithm for TSP timestamps.
- SM2 signatures were using the wrong default identity value. This has now been fixed.
- An edge condition in Blake2b for hashes on data with a length in the range of 2**64 - 127 to 2**64 has been identifed and fixed.
- The ISO Trailer for SHA512/256 used in X9.31 and ISO9796-2 signatures was incorrect. This has been fixed.
- The BCJSSE SSLEngine implementation now correctly wraps/unwraps application data only in whole records.
- The curve parameters for tc26_gost_3410_12_256_paramSetA were incorrect. These have been fixed.
- Further work has been done to try and prevent escaping exceptions on opening random files as BCFKS files or PKCS#12 files.
- An off-by-one error for the max N check for SCRYPT has been fixed. SCRYPT should now be compliant with RFC 7914.
- ASN1GeneralizedTime will now accept a broader range of input strings.

### 2.30.3 Additional Features and Functionality

- GOST3410-94 private keys encoded using ASN.1 INTEGER are now accepted in private key info objects.
- SCRYPT is now supported as a SecretKeyFactory in the provider and in the PKCS8 APIs
- The BCJSSE provider now supports session resumption in clients.
- The BCJSSE provider now supports Server Name Indication.
- The BCJSSE provider now supports the jdk.tls.namedGroups system property.
- The BCJSSE provider now supports the org.bouncycastle.jsse.ec.disableChar2 system property, which optionally disables the use of characteristic-2 elliptic curves.
- EC key generation and signing now use cache-timing resistant table lookups.
- Performance of the DSTU algorithms has been greatly improved.
- Support has been added for generating certificates and signatures in the PKIX API using SHA-3 based digests.
- Further work has been done on improving SHA-3 performance.
- The organizationIdentifier (2.5.4.97) attribute has been added to BCStyle.
- GOST3412-2015 has been added to the JCE provider and the lightweight API.
- The Blake2s message digest has been added to the provider and the lightweight API.
- Unified Cofactor Diffie-Hellman (ECCDHU) is now supported for EC in the JCE and the lightweight API.
- A DEROtherInfo generator for key agreement using NewHope as the source of the shared private info has been added that can be used in conjunction with regular key agreement algorithms.
- RFC 7748: Added low-level implementations of X25519 and X448.

### 2.30.4 Security Related Changes and CVE's Addressed by this Release

- CVE-2017-13098 ("ROBOT"), a Bleichenbacher oracle in TLS when RSA key exchange is negotiated. This potentially affected BCJSSE servers and any other TLS servers configured to use JCE for the underlying crypto - note the two TLS implementations using the BC lightweight APIs are not affected by this.

### 2.31.1 Version

Release: 1.58
Date: 2017, August 18

### 2.31.2 Defects Fixed

- NewHope and SPHINCS keys are now correctly created off certificates by the BC provider.
- Use of the seeded constructor with SecureRandom() and the BC provider in first position could cause a stack overflow error. This has been fixed.
- The boolean flag on ECDSAPublicKey in CVCertficate was hard coded. This has been fixed.
- An edge condition in IV processing for GOFB mode has been found and fixed.
- ANSSI named EC curves were not being recognised in PKCS#10 and certificate parsing. This has been fixed.
- BaseStreamCipher.engineSetMode() could sometimes throw an IllegalArgumentException rather than a NoSuchAlgorithmException. This has been fixed.
- Some class resolving used by the provider would fail if the BC jar was loaded on the boot class path. This has been fixed.
- An off-by-one range check in SM2Signer has been fixed.
- Retrieving an SM2 key from a certificate could result in a NullPointerException due to a problem with the curve lookup. This has been fixed.
- A race condition that could occur inside the HybridSecureRandom on reseed and result in an exception has been fixed.
- DTLS now supports records containing multiple handshake messages.

### 2.31.3 Additional Features and Functionality

- An implementation of GOST3410-2012 has been added to light weight API and the JCA provider.
- Support for ECDH GOST3410-2012 and GOST3410-2001 have been added. The CMS API can also handle reading ECDH GOST3410 key transport messages.
- Additional mappings have been added for a range of CVC-ECDSA algorithms.
- XMMS and XMSSMT are now available via the BCPQC provider. Support has been added for using these keys in certificates as well.
- Support has been added for DSTU-7564 message digest and the DSTU-7624 ciphers, together with their associated modes.
- A new system property org.bouncycastle.asn1.allow_unsafe_integer has been added to allow parsing of malformed ASN.1 integers in a similar fashion to what BC 1.56 did. The default behavior remains as reject malformed integers.
- SignedMailValidator would only pick up the first email address in a DN, even when there was more than one. This has been fixed.
- PEMParser will now support a broader range of PBKDFs in encrypted private key files.
- Work has been done on speeding up the SHA-3 family. The functions are now 3 to 4 times faster.
- Some EC aliases in the provider had no corresponding implementations. These have been cleaned up.
- TimeStampResponses now support definite-length encoding to allow the preservation of order in certificates sets for legacy responses.
- The TSP API now supports SM2withSM3.
- The BCJSSE provider now has a FIPS mode.
- The BCJSSE provider now supports layered sockets.
- The new TLS API now has protocol/API support for the status_request extension (OCSP stapling).
- The new TLS API now supports RFC 7633 - X.509v3 TLS Feature Extension (e.g. "must staple"), enabled in default clients.
- TLS exceptions have been made more directly informative.

### 2.31.4 Removed Features and Functionality

- Per RFC 7465, removed support for RC4 in the new TLS API.
- Per RFC 7568, removed support for SSLv3 in the new TLS API.

### 2.32.1 Version

Release: 1.57
Date: 2017, May 11

### 2.32.2 Defects Fixed

- A class cast exception for master certification removal in PGPPublicKey.removeCertification() by certification has been fixed.
- GOST GOFB 28147-89 mode had an edge condition concerning the incorrect calculation of N4 (see section 6.1 of RFC 5830) affecting about 1% of IVs. This has been fixed.
- The X.509 PolicyConstraints class was using implicit rather than explicit tagging for the SkipCerts field. This has been fixed.
- Key expiration in the OpenPGP is now calculated for ambiguous self signatures using the most recently created self-signature, in line with GPG and the recommendation in RFC 4880.
- Multiple validity periods in PGP keys were resolved in an adhoc fashion, in line with GPG's approach the PGP has been changed to return the most recent validity period signed.
- An occasional class cast exception that could occur with nested multi-parts in the S/MIME API has been fixed.
- A couple of bogus aliases associated AlgorithmParameters that did not resolve in the provider have been removed.
- The CMS API will now correctly verify PSS signatures with odd length salts.
- Choosing an invalid mode on a stream cipher in the JCE could result in an IllegalArgumentException. This has now been corrected to throw a NoSuchAlgorithmException.
- Optional parameters for ECDSA public keys in CVCertificates were hard coded to non-optional. This has been fixed.
- Passing a PKCS12 key to a Mac in the BC JCE always resulted in SHA-1 being used to process the password regardless of the underlying MAC algorithm. This has been fixed. An unrecognised HMAC will also now result in an exception.
- The Base64 encoder now explicitly validates 2 character padding as being "==".
- EC FixedPointCombMultiplier avoids 'infinity' point in lookup tables, reducing timing side-channels.
- Reuse of a Blake2b digest with a call to reset() rather than doFinal() could result in incorrect padding being introduced and the wrong digest result produced. This has been fixed.

### 2.32.3 Additional Features and Functionality

- ARIA (RFC 5794) is now supported by the provider and the lightweight API.
- ARIA Key Wrapping (RFC 5649 style) is now supported by the provider and the lightweight API.
- SM2 signatures, key exchange, and public key encryption has been added to the lightweight API.
- XMSS has been added to the lightweight PQ API. Note: this should be treated as beta code.
- API support for client side EST (RFC 7030), as well as some CMC (RFC 5273) has been added to the PKIX API. A full set of ASN.1 classes for both protocols has been added as well.
- A test client for EST which will interop with the 7030 test server at http://testrfc7030.com/ has been added to the general test module in the current source tree.
- The BCJSSE provider now supports SSLContext.getDefault(), with very similar behaviour to the SunJSSE provider, including checks of the relevant javax.net.ssl.* system properties and auto-loading of jssecacerts or cacerts as the default trust store.

### 2.32.4 Security Related Changes

- The default parameter sizes for DH and DSA are now 2048. If you have been relying on key pair generation without passing in parameters generated keys will now be larger.
- Further work has been done on preventing accidental re-use of a GCM cipher without first changing its key or iv.

### 2.33.1 Version

Release: 1.56
Date: 2016, December 23

### 2.33.2 Defects Fixed

- See section 2.15.4 for Security Defects.
- Using unknown status with the ASN.1 CertStatus primitive could result in an IllegalArgumentException on construction. This has been fixed.
- A potentional NullPointerException in a precomputation in WNafUtil has been removed.
- PGPUtil.getDecoderStream() would throw something other than an IOException for empty and very small data. This has been fixed.

### 2.33.3 Additional Features and Functionality

- Support for the explicit setting of AlgorithmParameters has been added to the JceCMSContentEncryptorBuilder and the JceCMSMacCaculatorBuilder classes to allow configuration of the session cipher/MAC used.
- EC, ECGOST3410, and DSTU4145 Public keys are now validated on construction in the JCA/JCE and the light weight API.
- DSA Public keys are now validated on construction in the JCA/JCE and the light weight API.
- Diffie-Hellman public keys are now validated where parameters allow it.
- Some validations are now applied to RSA moduli and public exponents.
- The ASN.1 Object Identifier cache now uses a Concurrent HashMap for additional speed.
- AES-CCM MAC support has been added to the provider.
- Support for ChaCha7539 (ChaCha20 as defined in RFC 7539) and Poly1305 have been added to the provider.
- Support has been added for defining your own curves and making them available to the key generators and factories.
- Methods have been added for specifying that a PGPPublicKey/PGPPublicKeyRing is being encoded for export and trust packets are not required.
- Plain-ECDSA and SHA-3 support has been added to DefaultDigestAlgorithmIdentifierFinder.
- SHA-3 support has been added to BcDefaultDigestProvider.
- A higher level TLS API and JSSE provider have been added to the project.

### 2.33.4 Security Related Changes and CVE's Addressed by this Release

- It is now possible to configure the provider to only import keys for specific named curves.
- Work has been done to improve the "constant time" behaviour of the RSA padding mechanisms.
- The GCM ciphers in the JCE and lightweight API will now fail if an attempt is made to use them for encryption after a doFinal or without changing the IV.
- The constructor for IESParameterSpec that allows the use of cipher without a nonce has been deleted. See also details for CVE-2016-1000344, CVE-2016-1000352.
- Strict encoding enforcement has been introduced for ASN1Integer.
- CVE-2016-1000338: DSA does not fully validate ASN.1 encoding of signature on verification. It is possible to inject extra elements in the sequence making up the signature and still have it validate, which in some cases may allow the introduction of "invisible" data into a signed structure.
- CVE-2016-1000339: AESFastEngine has a side channel leak if table accesses can be observed. The use of lookup large static lookup tables in AESFastEngine means that where data accesses by the CPU can be observed, it is possible to gain information about the key used to initialize the cipher. We now recommend not using AESFastEngine where this might be a concern. The BC provider is now using AESEngine by default.
- CVE-2016-1000340: Static ECDH vulnerable to carry propagation bug. Carry propagation bugs in the implementation of squaring for several raw math classes have been fixed (org.bouncycastle.math.raw.Nat???). These classes are used by our custom elliptic curve implementations (org.bouncycastle.math.ec.custom.**), so there was the possibility of rare (in general usage) spurious calculations for elliptic curve scalar multiplications. Such errors would have been detected with high probability by the output validation for our scalar multipliers.
- CVE-2016-1000341: DSA signature generation vulnerable to timing attack. Where timings can be closely observed for the generation of signatures, the lack of blinding in 1.55 or earlier, may allow an attacker to gain information about the signatures k value and ultimately the private value as well.
- CVE-2016-1000342: ECDSA does not fully validate ASN.1 encoding of signature on verification. It is possible to inject extra elements in the sequence making up the signature and still have it validate, which in some cases may allow the introduction of "invisible" data into a signed structure.
- CVE-2016-1000343: DSA key pair generator generates a weak private key if used with default values. If the JCA key pair generator is not explicitly initialised with DSA parameters, 1.55 and earlier generates a private value assuming a 1024 bit key size. In earlier releases this can be dealt with by explicitly passing parameters to the key pair generator.
- CVE-2016-1000344: DHIES allows the use of unsafe ECB mode. This algorithm is now removed from the provider.
- CVE-2016-1000345: DHIES/ECIES CBC mode vulnerable to padding oracle attack. For BC 1.55 and older, in an environment where timings can be easily observed, it is possible with enough observations to identify when the decryption is failing due to padding.
- CVE-2016-1000346: Other party DH public key not fully validated. This can cause issues as invalid keys can be used to reveal details about the other party's private key where static Diffie-Hellman is in use. As of this release the key parameters are checked on agreement calculation.
- CVE-2016-1000352: ECIES allows the use of unsafe ECB mode. This algorithm is now removed from the provider.

### 2.33.5 Security Advisory

- We consider the carry propagation bugs fixed in this release to have been exploitable in previous releases (1.51-1.55), for static ECDH, to reveal the long-term key, per "Practical realisation and elimination of an ECC-related software bug attack", Brumley et.al.. The most common case of this would be the non-ephemeral ECDH ciphersuites in TLS. These are not enabled by default in our TLS implementations, but they can be enabled explicitly by users. We recommend that users DO NOT enable static ECDH ciphersuites for TLS.

### 2.34.1 Version

Release: 1.55
Date: 2016, August 18

### 2.34.2 Defects Fixed

- Issues with cloning of blake digests with salts and personalisation strings have been fixed.
- The JceAsymmetricValueDecryptor in the CRMF package now attempts to recognise a wider range of parameters for the key wrapping algorithm, rather than relying on a default.
- GCM now fails if an attempt is made to go past 2^32-1 blocks.
- (r, k) ordering for Poly1305 has been modified to be brought into line with RFC 7539.
- An occasional error in Poly1305 due to sign-extension has been fixed.
- TimeStampRequest was always failing to validate if extensions were present. This has been fixed.
- ECIES/IES algorithm parameters encoding failed on default parameters. This has been fixed.
- PGPObjectFactory.iterator() could fail when called on data with multiple stream packets. This has been fixed.
- The McEliece implementation in the BCPQC provider has been revised and now has working key factories associated with it.
- The X.509 UserNotice class can now cope with empty sequences.
- Creation of multiple providers concurrently could cause issues with a non-synchronized Map in the provider. Code is now synchronized.
- If the lightweight OAEP encoder is fed oversized input it will now throw something more informative than an ArrayOutOfBoundsException or simply truncate.
- Attempting to use the PasswordRecipientInfoGenerator without explicitly setting the salt would cause a NullPointerException. This has been fixed.
- The BasicConstraintsValidation in the CertPath API would throw a NullPointerException on an unconstrained path length. This has been fixed.
- A shift error for > 24 bit numbers in TlsUtils has been fixed.
- OAEP encryption for a zero length message would create invalid cipher text. This has been fixed.
- Trying to use of non-default parameters for OAEP in CRMF would resort to the default parameter set. This has been fixed.
- If the BC provider was not registered, creating a CertificateFactory would cause a new provider object to be created. This has been fixed.

### 2.34.3 Additional Features and Functionality

- The DANE API has been updated to reflect the latest standard changes.
- The signature algorithm SPHINCS-256 has been added to the post-quantum provider (BCPQC). Support is in place for SHA-512 and SHA3-512 (using trees based around SHA512_256 and SHA3_256 respectively).
- The key exchange algorithm NewHope has been added to the post-quantum provider (BCPQC). Support is in place for the regular configuration using SHA3-256 as the flattening algorithm for the agreed value.
- The CMS password recipient generator now allows the PRF to be changed to something other than SHA-1
- Direct support for the SignatureTarget packet has been added to the OpenPGP API.
- TLS: support for ClientHello Padding Extension (RFC 7685).
- TLS: support for ECDH_anon key exchange.
- Support has been added for HMAC SHA-3. Aliases have been added for NIST OIDs for SHA-3 HMAC as well.
- Support has been added for SHA-3 in DSA, ECDSA, DDSA, and ECDDSA. Aliases have been added for NIST OIDs for DSA and ECDSA as well.
- Support has been added for SHA-3 with RSA PKCS 1.5, PSS, and OAEP.
- Support has been added for GOST R 34.11-2012 to the provider and the lightweight API.
- PGP armored output can now be generated without a version string.
- The TimeStampTokenGenerator will now generate timestamps down to a millisecond resolution.
- Additional search methods have been added to PGP public and secret key rings.

### 2.35.1 Version

Release: 1.54
Date: 2015, December 29

### 2.35.2 Defects Fixed

- Blake2b-160, Blake2b-256, Blake2b-384, and Blake2b-512 are now actually in the provider and an issue with cloning Blake2b digests has been fixed.
- PKCS#5 Scheme 2 using DESede CBC is now supported by the PKCS#12 implementation.
- The IES engine would sometimes throw a "too short" exception on small messages which were the right length. This has been fixed.
- Cipher.getOutputSize() for IES ciphers would throw a ClassCastException. This has been fixed.
- It turns out, after advice one way and another that the NESSIE test vectors for Serpent are now what should be followed and that the vectors in the AES submission are regarded as an algorithm called Tnepres. The Serpent version now follows the NESSIE vectors, and the Tnepres cipher has been added to the provider and the lightweight API for compatibility.
- Problems with DTLS record-layer version handling were resolved, making version negotiation work properly.

### 2.35.3 Additional Features and Functionality

- Camellia and SEED key wrapping are now supported for CMS key agreement
- The BC TLS/DTLS code now includes a non-blocking API.
- CTR/SIC mode now support an internal counter. The internal counter can be turned on by passing an IV smaller than the block size of the cipher's algorithm.
- The lightweight CMS API operators now support CAST5 and RC2 CBC encryption.
- The CMS API now supports Diffie-Hellman as specified in RFC 3370.
- Support has been added to the CMS API for PKCS#7 ANY type encapsulated content where the encapsulated content is not an OCTET STRING.
- PSSSigner in the lightweight API now supports fixed salts.

### 2.35.4 Security Advisory

- (D)TLS 1.2: Motivated by CVE-2015-7575, we have added validation that the signature algorithm received in DigitallySigned structures is actually one of those offered (in signature_algorithms extension or CertificateRequest). With our default TLS configuration, we do not believe there is an exploitable vulnerability in any earlier releases. Users that are customizing the signature_algorithms extension, or running a server supporting client authentication, are advised to double-check that they are not offering any signature algorithms involving MD5.

### 2.35.5 Notes

If you have been using Serpent, you will need to either change to Tnepres, or take into account the fact that Serpent is now byte-swapped compared to what it was before.

### 2.36.1 Version

Release: 1.53
Date: 2015, October 10

### 2.36.2 Defects Fixed

- The BC JCE cipher implementations could sometimes fail when used in conjunction with the JSSE and NIO. This has been fixed.
- PGPPublicKey.getBitStrength() always returned 0 for EC keys. This has been fixed.
- A PKCS12 key store containing a looping certificate chain could cause an OutOfMemoryException. This has been fixed.
- A change in JDK 1.8 meant that X509Certificate.verify(PublicKey, Provider) would cause a stack overflow. This has been fixed.
- Nested multiparts with irregular post-amble could cause verification issues for the SMIMESigned classes. This has been fixed.
- CMSSignedData now supports verification of signed attributes where the calculated digest uses a different algorithm from the digest used in the signature.
- TRUSTED CERTIFICATE parsing in PEM files was ignoring the attribute block. A new class X509TrustedCertificateBlock is now returned containing both the certificate and the trust information.
- Adding a password to a PGP key which did not previously have one would result in an improperly formatted key. This has been fixed.
- ECIES/IES was only using a 4 byte label length for the MAC tag when it should have been an 8 byte one. This has now been fixed and OldECIES/OldIES has been added for backwards compatibility.
- The JceCRMFEncryptorBuilder was not recognising key size specific object identifiers properly. This has been fixed.
- The OpenPGP ClearSignedFileProcessor would not handle verification of single line files properly. This has been fixed.
- The BC X509Certificate class was no longer in agreement with the standard class for hashCode(). The BC X509Certificate class will now track the changes made in the standard Java distribution.
- PGP signature hashed sub-packets with long length encodings would fail to validate on signature checking. This has been fixed.
- The S/MIME API would occasionally leak InputStreams which could cause issues with custom DataSource implementations. This has been fixed.
- The PKCS#12 KeyStore implementation would sometimes leave orphaned chain certificates in the key store after private key deletion. This has been fixed.
- A bug in the DirectKeySignature OpenPGP example which could lead to extra data appearing in the signature has been fixed.
- Explicit configuration of a BcAsymmetricKeyWrapper with a SecureRandom was not properly propagated internally. This has been fixed.
- A CRL with a null certificate issuer would sometimes result in a NullPointerException during CertPathProcessing. This has been fixed.
- The CertPath processor would occasionally fail to match a DistributionPoint name correctly. This has been fixed.
- In order to avoid confusion about thread safety, BCrypt now uses a new instance for hash calculation every time it is invoked.
- Some decidedly odd argument casting in the PKIXCertPathValidator has been fixed to throw an InvalidAlgorithmParameterException.
- Presenting an empty array of certificates to the PKIXCertPathValidator would cause an IndexOutOfRangeException instead of a CertPathValidatorException. This has been fixed.

### 2.36.3 Additional Features and Functionality

- It is now possible to specify that an unwrapped key must be usable by a software provider in the asymmetric unwrappers for CMS.
- A Blake2b implementation has been added to the provider and lightweight API.
- SHA3 has now been added to the provider and the lightweight API. SHAKE128 and SHAKE256 have also been added to the lightweight API. The original implementation of the draft standard has been renamed to Keccak.
- The CMS API now supports RFC 6211 for both SignedData and AuthenticatedData.
- The ASN.1 parser for ECGOST private keys will now parse keys encoded with a private value represented as an ASN.1 INTEGER.
- EAX mode and CMAC is now supported for ciphers such as SHACAL-2 and Threefish.
- The SM4 block cipher has been added to the provider and the lightweight API.
- X9.31, ISO9796/2, and PSS signature support has been added for SHA512/224, SHA512/256.
- SubjectPublicKeyInfoFactory now supports DSA parameters.
- A range of new algorithms are now support for EC key agreement.
- EC ContentSigners and EC ContentVerifiers have been added to the lightweight operator package in the PKIX APIs.
- The PKCS#12 key store will now garbage collect orphaned certificates on saving.
- Caching for ASN.1 ObjectIdentifiers has been rewritten to make use of an intern method. The "usual suspects" are now interned automatically, and the cache is used by the parser. Other OIDs can be added to the cache by calling ASN1ObjectIdentifier.intern().

### 2.36.4 Notes

It turns out there was a similar, but different, issue in Crypto++ to the BC issue with ECIES. Crypto++ 6.0 now offers a corrected version of ECIES which is compatible with that which is now in BC.

### 2.37.1 Version

Release: 1.52
Date: 2015, March 2

### 2.37.2 Defects Fixed

- GenericSigner in the lightweight API would fail if the digest started with a zero byte, occasionally causing a TLS negotiation to fail. This has been fixed.
- Some BC internal classes expected the BC provider to be accessible within the provider. This has been fixed.
- Email based policy constraints in CertPath validation did not include '@'domain.name as a possible match. This has been fixed.
- The Shacal2Engine would throw an ArrayIndexOutOfBoundsException if presented with input longer than a block size. This has been fixed.
- Using PKCS5/PKCS7 with pad values greater than 127 would result in an exception on decryption. This has been fixed.
- EC private key values could encode to an OCTET STRING which was shorter than that described in RFC 5915/SEC 1. This has been fixed.
- Providing multiple trust anchors to the CertPath validator could cause a StackOverflowError on an invalid CertPath. This has been fixed.
- TLS: bad-padding handling when encrypt-then-MAC enabled is now fixed.
- ECDH KeyAgreement.init() was not properly honoring the JCE API in respect to non-null parameters. This has been fixed.
- PKCS symmetric padding now takes into account pad lengths of more than 127 bytes.
- Corrupted input to RFC5649WrapEngine could cause an out of memory error. This has been fixed.
- OSGI import issues for bcmail have been fixed.
- A badly formed issuer in a X.509 certificate could cause a null pointer exception in X509CertificateHolder.toString(). This has been fixed.
- CMSSignedData.verifySignatures() could fail on a correct counter signature due to a mismatch of the SID. This has been fixed.

### 2.37.3 Additional Features and Functionality

- The CMP support class CMPCertificate restricted the types of certificates that could be added. A more flexible method has been introduced to allow for other certificate types.
- Support classes have be added for DNS-based Authentication of Named Entities (DANE) to the PKIX distribution.
- Work has been done to reduce computation requirements for long skips associated with implementations of the SkippingCipher interface.
- AES GCM mode is now supported by CMS EnvelopedData.
- Iteration count is now settable in BcPKCS12MacCalculatorBuilder.
- Support for BCrypt and it's OpenBSD variant has been added to the lightweight API.
- It's now possible to specify the direction of the underlying cipher used for key wrapping with NIST/RFC3394 wrappers.
- TLS: server-side support for DHE key exchange.
- TLS: server-side support for PSK and SRP ciphersuites.
- TLS: (EC)DSA now supports signatures with non-SHA1 digests.
- TLS: support for ECDHE_ECDSA/AES/CCM ciphersuites from RFC 7251.
- Cipher.getIV() now returns nonces for AEAD modes.
- OIDs for dhPublicNumber and dhKeyAgreement are now supported by the provider.
- OIDs for several signature types using the RIPEMD family of digests have been added to the provider.
- JcaJceUtils.getDigestAlgName() has been added to assist in converting OIDs representing message digests into JCA algorithm names.
- BasicOCSPResp.getSignatureAlgorithmID() has been added to allow algorithm indentifier details to be returned from a basic OCSP response.
- Additional OIDs have been added for OCSP.
- X509CRLObject.getSignAlgName() now attempts to return an actual name, rather than an OID for, for the signature algorithm.
- SignedMailValidator now pays attention to the date in the PKIXParameters object if it is set.
- A missing signing time in a signature no longer causes SignedMailValidator to fail a signature, but provide a warning instead.
- An AlgorithmNameFinder implementation has been added to the PKIX API to provide "human friendly" translations of algorithm OIDs.
- Support has been added for X9.31-1998 DRBG and X9.31-1998 RSA signatures to the lightweight API and the provider.
- CertPath validator will now make use of the issuer key identifier and the issuer name if a key identifier is available for the issuer.
- Support for some JDK1.5+ language features has finally made its way into the repository.
- A load store parameter, PKCS12StoreParameter, has been added to support DER only encoding of PKCS12 key stores.

### 2.37.4 Security Advisory

- The CTR DRBGs would not populate some bytes in the requested block of random bytes if the size of the block requested was not an exact multiple of the block size of the underlying cipher being used in the DRBG. If you are using the CTR DRBGs with "odd" keysizes, we strongly advise upgrading to this release, or contacting us for a work around.

### 2.38.1 Version

Release: 1.51
Date: 2014, July 28

### 2.38.2 Defects Fixed

- The AEAD GCM AlgorithmParameters object was unable to return a GCMParameterSpec object. This has been fixed.
- Cipher.getIV() was returning null for AEAD mode ciphers. This has been fixed.
- CipherInputStream would fail for some AEAD mode ciphers if the message was over 4k in length. This has been fixed.
- The JCE provider will now produce simple RSAPrivateKey objects where CRT coefficients are not provided.
- PGP key signature certifications did not support DIRECT KEY signatures. This has been fixed.
- User Attribute subpackets in PGP with long length encodings could result in certification verification failing. This has been fixed.
- Calls to CommandMap.setDefaultCommandMap() in the SMIME API are now wrapped in doPrivileged() blocks to allow them to work with a security manager.
- The encoding of the certificate_authorities field of a TLS CertificateRequest has been fixed.
- EC point formats are now strictly enforced in the TLS API.
- The provider implementation was failing to throw an exception if algorithm parameters were passed in when none were required for EC key agreement. This has been fixed.
- PKCS#12 files containing keys/certificates with empty attribute sets attached to them no longer cause an ArrayIndexOutOfBoundsException to be thrown.
- Issues with certificate verification and server side DTLS/TLS 1.2 have now been fixed.

### 2.38.3 Additional Features and Functionality

- The range of key algorithm names that will be interpreted by KeyAgreement.generateSecret() has been expanded for ECDH derived algorithms in the provider. A KeyAgreement of ECDHwithSHA1KDF can now be explicitly created.
- ECIES now supports the use of IVs with the underlying block cipher and CBC mode in both the lightweight and the JCE APIs.
- Support has been add for RFC5649 key wrapping using AES.
- The PGP API now allows access and handling of User IDs as raw byte arrays, to deal with keyrings not using UTF-8.
- The PGP API now provides automatic conversion of embedded signatures in signature sub-packet vectors.
- The PGP API now fully supports ECDH as outlined in RFC 6637.
- GCM and GMAC now support tag lengths down to 32 bits.
- Custom implementations for many of the SEC Fp curves have been added, resulting in drastically improved performance. The current list includes all secp***k1 and secp***r1 curves from 192 to 521 bits. They can be accessed via the org.bouncycastle.crypto.ec.CustomNamedCurves class and are generally selected by other internal APIs in place of the generic implementations.
- Automatic EC point validation added, both for decoded inputs and multiplier outputs.
- A SkippingCipher interface has been added for ciphers that can be moved into a specific state for a given byte address. The lightweight class StreamBlockCipher has been generalised to support any BlockCipher object that can support a streaming mode.
- ASN.1 date/time objects now support the passing in of a Locale to allow for constructing the object using a Date interpreted from a different locale to the default for the JVM.
- The range of Diffie-Hellman OIDs recognised by the provider has been extended.
- Some utility methods for interpreting OIDs have been exposed in the JcaJceUtils class.
- A method has been added to CMSSignedData for replacing the OCSP responses associated with a signed message.
- Use of RC2/RC4 in the CMS is now provider independent.
- TlsInputStream now provides a means of supporting InputStream.available().
- Dependencies on the JCA have been removed from PGPObjectFactory.
- Further work has been done on improving key quality with EC and DSA algorithms.
- KDFCounterBytesGenerator now supports suffix and prefix fixed input data, as outlined in NIST SP 800-108.
- Support has been added to allow retrieval and resetting the internal state of the SHA/SHA-2 digests in the lightweight API using an encoded format.
- BSI plain ECDSA is now supported by the provider.
- The provider now advertises RSA PSS signature implementations directly using the standard naming.
- Full support is now provided for client-side auth in the D/TLS server code.
- Compatibility issues with some OSGI containers have been addressed.

### 2.38.4 Notes

- Support for NTRUSigner has been deprecated as the algorithm has been withdrawn.
- Some changes have affected the return values of some methods. If you are migrating from an earlier release, it is recommended to recompile before using this release.
- There has been further clean out of deprecated methods in this release. If your code has previously been flagged as using a deprecated method you may need to change it. The OpenPGP API is the most heavily affected.

### 2.39.1 Version

Release: 1.50
Date: 2013, December 3

### 2.39.2 Defects Fixed

- The DualECSP800DRBG sometimes truncated the last block in the generated stream incorrectly. This has been fixed.
- Keys produced from RSA certificates with specialised parameters would lose the parameter settings. This has been fixed.
- OAEP parameters were being ignored on CMS key trans recipient processing. This has been fixed.
- OpenPGP NotationData was restricting the name and value lengths to 255 characters and truncating silently. This has been fixed.
- CTS mode is now in alignment with the errata for RFC 2040, as detailed in RFC 3962.
- Occasionally the provider implementation of DH KeyAgreement would drop a leading zero byte off the start of the shared secret (see RFC 2631 2.1.2). This has been fixed.
- RFC3394WrapEngine was ignoring the offset parameter inOff and using zero instead. This has been fixed.
- GOST keys would not encode using the CryptoPro parameter set, even if it was available. This has been fixed.
- The TimeStampRequest stream constructor was not setting the extensions field correctly. This has been fixed.
- Default RC2 parameters for 40 bit RC2 keys in CMSEnvelopedData were encoding incorrectly. This has been fixed.
- In case of a long hash the DSTU4145 implementation would sometimes remove one bit too much during truncation. This has been fixed.

### 2.39.3 Additional Features and Functionality

- Additional work has been done on CMS recipient generation to simplify the generation of OAEP encrypted messages and allow for non-default parameters.
- OCB implementation updated to account for changes in draft-irtf-cfrg-ocb-03.
- RFC 6637 ECDSA and ECDH support has been added to the OpenPGP API.
- Implementations of Threefish and Skein have been added to the provider and the lightweight API.
- Implementations of the SM3 digest have been added to the provider and the lightweight API.
- The 3 MAC based KDF generators in NIST SP 800-108 have been added to the lightweight API.
- Support has been added for the GOST PKCS#5 PBKDF2 PBE function and handling of GOST PKCS#12 files.
- Support has been added for the CryptoPro GOST CFB mode key meshing.
- Implementations of XSalsa20 and ChaCha have been added. Support for reduced round Salas20 has been added.
- Support has been added for RFC 6979 Determinstic DSA/ECDSA to the provider and the lightweight API.
- Support for RC2 and RC4 in the CMS API has been generalised to work for other JCE providers.
- Support for the Poly1305 MAC has been added to the lightweight API and the JCE Provider.
- OpenSSL JcaPEMKeyConverter now supports OIDs for RSA and DSA as well as ECDSA.
- A simplified certificate path API has been added to the PKIX package. It is not fully NIST compliant yet, however it does provide a range of basic validations without having to use the JCA.
- Package version information is now included in the jar MANIFEST.MF.
- The JDK 1.5+ provider will now recognise and use GCMParameterSpec if it is run in a 1.7 JVM.
- Client side support and some server side support has been added for TLS/DTLS 1.2.

### 2.39.4 Notes

- org.bouncycastle.crypto.DerivationFunction is now a base interface, the getDigest() method appears on DigestDerivationFunction.
- Recent developments at NIST indicate the SHA-3 may be changed before final standardisation. Please bare this in mind if you are using it.
- Other recent developments have raised concerns about the DualECDRBG. We have left the class in place for now, but it is now possible to provide your own parameter values, rather than using the NIST defined ones, if you choose to do so.
- Most deprecated methods have been removed from the PKIX API.
- As the IDEA patent has finally expired, IDEA is now supported by the standard provider.
- ECDH support for OpenPGP should still be regarded as experimental. It is still possible there will be compliance issues with other implementations.

### 2.40.1 Version

Release: 1.49
Date: 2013, May 31

### 2.40.2 Defects Fixed

- Occasional ArrayOutOfBounds exception in DSTU-4145 signature generation has been fixed.
- The handling of escaped characters in X500 names is much improved.
- The BC CertificateFactory no longer returns null for CertificateFactory.getCertPathEncodings().
- PKCS10CertificationRequestBuilder now encodes no attributes as empty by default. Encoding as absent is still available via a boolean flag.
- DERT61String has been reverted back to its previous implementation. A new class DERT61UTF8String has been introduced which defaults to UTF-8 encoding.
- OAEPEncoding could throw an array output bounds exception for small keys with large mask function digests. This has been fixed.
- PEMParser would throw a NullPointerException if it ran into explicit EC curve parameters, it would also throw an Exception if the named curve was not already defined. The parser now returns X9ECParmameters for explicit parameters and returns an ASN1ObjectIdentifier for a named curve.
- The V2TBSCertListGenerator was adding the wrong date type for CRL invalidity date extensions. This has been fixed.

### 2.40.3 Additional Features and Functionality

- A SecretKeyFactory has been added that enables use of PBKDF2WithHmacSHA.
- Support has been added to PKCS12 KeyStores and PfxPdu to handle PKCS#5 encrypted private keys.
- Support has been added for SHA-512/224, SHA-512/256, as well as a general SHA-512/t in the lightweight API.
- The JcaPGPPrivateKey class has been added to provide better support in the PGP API for HSM private keys.
- A new KeyStore type, BKS-V1, has been added for people needing to create key stores compatible with earlier versions of Bouncy Castle. Please note this keystore type offers a reduced integrity check of 16 bits and the rgular BKS should be used where possible.
- Some extra generation methods have been added to TimeStampResponseGenerator to allow more control in the generation of TimeStampResponses.
- It is now possible to override the SignerInfo attributes during TimeStampTokenGeneration.
- The TSP API now supports generation of certIDs based on digests other than SHA-1.
- OCSP responses can now be included in CMS SignedData objects.
- The SipHash MAC algorithm has been added to the lightweight API and the provider.
- ISO9796-2 PSS signatures can now be initialised with a signature to allow the signer to deal with odd recovered message lengths on verification.
- The 4 DRBGs described in NIST SP 800-90A have been added to the prng package together with SecureRandom builders.
- Support has been added for OCB mode in the lightweight API.
- DSA version 2 parameter and key generation is now supported in the provider and lightweight API.
- A new interface Memoable has been added for objects that can copy in and out their state. The digest classes now support this. A special class NonMemoableDigest has been added which hides the Memoable interface where it should not be available.
- TDEA is now recognised as an alias for DESede.
- A new package org.bouncycastle.crypto.ec has been introduced to the light wieght API with a range of EC based cryptographic operators.
- The OpenPGP API now supports password changing on V3 keys if the appropriate PBEKeyEncryptor is used.
- The OpenPGP API now supports password changing on secret key rings where only the private keys for the subkeys have been exported.
- Support has been added to the lightweight API for RSA-KEM and ECIES-KEM.
- Support has been added for NIST SP 800-38D - GMAC to AES and other 128 bit block size algorithms.
- The org.bouncycastle.crypto.tls package has been extended to support client and server side TLS 1.1.
- The org.bouncycastle.crypto.tls package has been extended to support client and server side DTLS 1.0.
- A basic commitment package has been introduced into the lightweight API containing a digest based commitment scheme.
- It is now possible to set the NotAfter and NotBefore date in the CRMF CertificateRequestMessageBuilder class.

### 2.40.4 Notes

- The NTRU implementation has been moved into the org.bouncycastle.pqc package hierarchy.
- The change to PEMParser to support explicit EC curves is not backward compatible. If you run into a named curve you need to use org.bouncycastle.asn1.x9.ECNamedCurveTable.getByOID() to look the curve up if required.

### 2.41.1 Version

Release: 1.48
Date: 2013, February 10

### 2.41.2 Defects Fixed

- Occasional key compatibility issues in IES due to variable length keys have been fixed.
- PEMWriter now recognises the new PKCS10CertificationRequest object.
- The provider implementation for RSA now resets when the init method is called.
- SignerInformation has been rewritten to better support signers without any associated signed attributes.
- An issue with an incorrect version number of SignedData associated with the use of SubjectKeyIdentifiers has now been fixed.
- An issue with the equals() check in BCStrictStyle has been fixed.
- The BC SSL implementation has been modified to deal with the "Lucky Thirteen" attack.
- A regression in 1.47 which prevented key wrapping with regular symmetric PBE algorihtms has been fixed.

### 2.41.3 Additional Features and Functionality

- IES now supports auto generation of ephemeral keys in both the JCE and the lightweight APIs.
- A new class PEMParser has been added to return the new CertificateHolder and Request objects introduced recently.
- An implementation of Password Authenticated Key Exchange by Juggling (J-PAKE) has now been added to the lightweight API.
- Support has now been added for the DSTU-4145-2002 to the lightweight API and the provider.
- The BC X509Certificate implementation now provides support for the JCA methods X509Certificate.getSubjectAlternativeNames() and X509Certificate.getIssuerAlternativeNames().
- PEMReader can now be configured to support different providers for encyrption and public key decoding.
- Some extra DSA OIDs have been added to the supported list for the provider.
- The BC provider will now automatically try to interpret other provider software EC private keys. It is no longer necessary to use a KeyFactory for conversion.
- A new provider, the BCPQC (for BC Post Quantum) provider has been added with support for the Rainbow signature algorithm and the McEliece family of encryption algorithms.
- Support has been added for the SHA3 family of digests to both the provider and the lightweight API.
- T61String now uses UTF-8 encoding by default rather than a simple 8 bit transform.

### 2.42.1 Version

Release: 1.47
Date: 2012, March 30

### 2.42.2 Defects Fixed

- OpenPGP ID based certifications now support UTF-8. Note: this may mean that some old certifications no longer validate - if this happens a retry can be added using by converting the ID using Strings.fromByteArray(Strings.toByteArray(id)) - this will strip out the top byte in each character.
- IPv4/IPv6 parsing in CIDR no longer assumes octet boundaries on a mask.
- The CRL PKIX routines will now only rebuild the CRL as a last resort when looking for the certificate issuer.
- The DEK-Info header in PEM generation was lower case. It is now upper case in accordance with RFC 1421.
- An occasional issue causing an OutOfMemoryException for PGP compressed data generation has now been fixed.
- An illegal argument exception that could occur with multi-valued RDNs in the X509v3CertificateBuilder has been fixed.
- Shared secret calculation in IES could occasionally add a leading zero byte. This has been fixed.
- PEMReader would choke on a private key with an empty password. This has been fixed.
- The default MAC for a BKS key store was 2 bytes, this has been upgraded to 20 bytes. This fix is now also referred to in CVE-2018-5382.
- BKS key store loading no longer freezes on negative iteration counts.
- A regression in 1.46 which prevented parsing of PEM files with extra text at the start has been fixed.
- CMS secret key generation now attempts to stop use of invalid lengths with OIDs that predefine a key length.
- Check of DH parameter L could reject some valid keys. This is now fixed.

### 2.42.3 Additional Features and Functionality

- Support is now provided via the RepeatedKey class to enable IV only re-initialisation in the JCE layer. The same effect can be acheived in the light weight API by using null as the key parameter when creating a ParametersWithIV object.
- CRMF now supports empty poposkInput.
- The OpenPGP API now supports operator based interfaces for most operations and lightweight implementations have been added for JCE related functionality.
- JcaSignerId and JceRecipientId will now match on serial number, issuer, and the subject key identifier if it's available.
- CMS Enveloped and AuthenticatedData now support OriginatorInfo.
- NTRU encryption and signing is now provided in the lightweight source and the ext version of the provider.
- There is now API support for Extended Access Control (EAC).
- The performance of CertPath building and validation has been improved.
- The TLS Java Client API has been updated to make support for GSI GSSAPI possible.
- Support for ECDSA_fixed_ECDH authentication has been added to the TLS client.
- Support for the Features signature sub-packet has been added to the PGP API.
- The number of lightweight operators for PGP and CMS/SMIME has been increased.
- Classes involved in CRL manipulation have been rewritten to reduce memory requirements for handling and parsing extremely large CRLs.
- RFC 5751 changed the definition of the micalg parameters defined in RFC 3851. The SMIMESignedGenerator is now up to date with the latest micalg parameter set and a constructor has been added to allow the old micalg parameter set to be used.
- An operator based framework has been added for processing PKCS#8 and PKCS#12 files.
- The J2ME lcrypto release now includes higher level classes for handling PKCS, CMS, CRMF, CMP, EAC, OpenPGP, and certificate generation.

### 2.42.4 Other notes

Okay, so we have had to do another release. The issue we have run into is that we probably didn't go far enough in 1.46, but we are now confident that moving from this release to 2.0 should be largely just getting rid of deprecated methods. While this release does change a lot it is relatively straight forward to do a port and we have a porting guide which explains the important ones. The area there has been the most change in is the ASN.1 library which was in bad need of a rewrite after 10 years of patching. On the bright side the rewrite did allow us to eliminate a few problems and bugs in the ASN.1 library, so we have some hope anyone porting to it will also have similar benefits. As with 1.46 the other point of emphasis has been making sure interface support is available for operations across the major APIs, so the lightweight API or some local role your own methods can be used instead for doing encryption and signing.

### 2.43.1 Version

Release: 1.46
Date: 2011, February 23

### 2.43.2 Defects Fixed

- An edge condition in ECDSA which could result in an invalid signature has been fixed.
- Exhaustive testing has been performed on the ASN.1 parser, eliminating another potential OutOfMemoryException and several escaping run time exceptions.
- BC generated certificates generated different hashCodes from other equivalent implementations. This has been fixed.
- Parsing an ESSCertIDv2 would fail if the object did not include an IssuerSerialNumber. This has been fixed.
- DERGeneralizedTime.getDate() would produce incorrect results for fractional seconds. This has been fixed.
- PSSSigner would produce incorrect results if the MGF digest and content digest were not the same. This has been fixed.

### 2.43.3 Additional Features and Functionality

- A null genTime can be passed to TimeStampResponseGenerator.generate() to generate timeNotAvailable error responses.
- Support has been added for reading and writing of openssl PKCS#8 encrypted keys.
- New streams have been added for supporting general creation of PEM data, and allowing for estimation of output size on generation. Generators have been added for some of the standard OpenSSL objects.
- CRL searching for CertPath validation now supports the optional algorithm given in Section 6.3.3 of RFC 5280, allowing the latest CRL to be used for a set time providing the certificate is unexpired.
- AES-CMAC and DESede-CMAC have been added to the JCE provider.
- Support for CRMF (RFC 4211) and CMP (RFC 4210) has been added.
- BufferedBlockCipher will now always reset after a doFinal().
- Support for CMS TimeStampedData (RFC 5544) has been added.
- JCE EC keypairs are now serialisable.
- TLS now supports client-side authentication.
- TLS now supports compression.
- TLS now supports ECC cipher suites (RFC 4492).
- PGP public subkeys can now be separately decoded and encoded.
- An IV can now be passed to an ISO9797Alg3Mac.

### 2.43.4 Other notes

Baring security patches we expect 1.46 will be the last of the 1.* releases. The next release of BC will be version 2.0. For this reason a lot of things in 1.46 that relate to CMS have been deprecated and new methods have been added to the CMS and certificate handling APIs which provide greater flexibility in how digest and signature algorithms get used. It is now possible to use the lightweight API or a simple custom API with CMS and for certificate generation. In addition a lot of methods and some classes that were deprecated for reasons of been confusing, or in some cases just plan wrong, have been removed.

So there are four things useful to know about this release:

- It's not a simple drop in like previous releases, if you wish migrate to it you will need to recompile your application.
- If you avoid deprecated methods it should be relatively painless to move to version 2.0
- The X509Name class will utlimately be replacde with the X500Name class, the getInstance() methods on both these classes allow conversion from one type to another.
- The org.bouncycastle.cms.RecipientId class now has a collection of subclasses to allow for more specific recipient matching. If you are creating your own recipient ids you should use the constructors for the subclasses rather than relying on the set methods inherited from X509CertSelector. The dependencies on X509CertSelector and CertStore will be removed from the version 2 CMS API.

### 2.44.1 Version

Release: 1.45
Date: 2010, January 12

### 2.44.2 Defects Fixed

- OpenPGP now supports UTF-8 in file names for literal data.
- The ASN.1 library was losing track of the stream limit in a couple of places, leading to the potential of an OutOfMemoryError on a badly corrupted stream. This has been fixed.
- The provider now uses a privileged block for initialisation.
- JCE/JCA EC keys are now serialisable.

### 2.44.3 Additional Features and Functionality

- Support for EC MQV has been added to the light weight API, provider, and the CMS/SMIME library.

### 2.44.4 Security Advisory

- This version of the provider has been specifically reviewed to eliminate possible timing attacks on algorithms such as GCM and CCM mode.

### 2.45.1 Version

Release: 1.44
Date: 2009, October 9

### 2.45.2 Defects Fixed

- The reset() method in BufferedAsymmetricBlockCipher is now fully clearing the buffer.
- Use of ImplicitlyCA with KeyFactory and Sun keyspec no longer causes NullPointerException.
- X509DefaultEntryConverter was not recognising telephone number as a PrintableString field. This has been fixed.
- The SecureRandom in the J2ME was not using a common seed source, which made cross seeeding of SecureRandom's impossible. This has been fixed.
- Occasional uses of "private final" on methods were causing issues with some J2ME platforms. The use of "private final" on methods has been removed.
- NONEwithDSA was not resetting correctly on verify() or sign(). This has been fixed.
- Fractional seconds in a GeneralisedTime were resulting in incorrect date conversions if more than 3 decimal places were included due to the Java date parser. Fractional seconds are now truncated to 3 decimal places on conversion.
- The micAlg in S/MIME signed messages was not always including the hash algorithm for previous signers. This has been fixed.
- SignedMailValidator was only including the From header and ignoring the Sender header in validating the email address. This has been fixed.
- The PKCS#12 keystore would throw a NullPointerException if a null password was passed in. This has been fixed.
- CertRepMessage.getResponse() was attempting to return the wrong underlying field in the structure. This has been fixed.
- PKIXCertPathReviewer.getTrustAnchor() could occasionally cause a null pointer exception or an exception due to conflicting trust anchors. This has been fixed.
- Handling of explicit CommandMap objects with the generation of S/MIME messages has been improved.

### 2.45.3 Additional Features and Functionality

- PEMReader/PEMWriter now support encrypted EC keys.
- BC generated EC private keys now include optional fields required by OpenSSL.
- Support for PSS signatures has been added to CMS and S/MIME.
- CMS processing will attempt to recover if there is no AlgorithmParameters object for a provider and use an IvParameterSpec where possible.
- CertificateID always required a provider to be explicitly set. A null provider is now interpreted as a request to use the default provider.
- SubjectKeyIdentifier now supports both methods specified in RFC 3280, section 4.2.1.2 for generating the identifier.
- Performance of GCM mode has been greatly improved (on average 10x).
- The BC provider has been updated to support the JSSE in providing ECDH.
- Support for mac lengths of 96, 104, 112, and 120 bits has been added to existing support for 128 bits in GCMBlockCipher.
- General work has been done on trying to propagate exception causes more effectively.
- Support for loading GOST 34.10-2001 keys has been improved in the provider.
- Support for raw signatures has been extended to RSA and RSA-PSS in the provider. RSA support can be used in CMSSignedDataStreamGenerator to support signatures without signed attributes.

### 2.46.1 Version

Release: 1.43
Date: 2009, April 13

### 2.46.2 Defects Fixed

- Multiple countersignature attributes are now correctly collected.
- Two bugs in HC-128 and HC-256 related to sign extension and byte swapping have been fixed. The implementations now pass the latest ecrypt vector tests.
- X509Name.hashCode() is now consistent with equals.

### 2.46.3 Security Advisory

- The effect of the sign extension bug was to decrease the key space the HC-128 and HC-256 ciphers were operating in and the byte swapping inverted every 32 bits of the generated stream. If you are using either HC-128 or HC-256 you must upgrade to this release.

### 2.47.1 Version

Release: 1.42
Date: 2009, March 16

### 2.47.2 Defects Fixed

- A NullPointer exception which could be result from generating a diffie-hellman key has been fixed.
- CertPath validation could occasionally mistakenly identify a delta CRL. This has been fixed.
- '=' inside a X509Name/X509Principal was not being properly escaped. This has been fixed.
- ApplicationSpecific ASN.1 tags are now recognised in BER data. The getObject() method now handles processing of arbitrary tags.
- X509CertStoreSelector.getInstance() was not propagating the subjectAlternativeNames attribute. This has been fixed.
- Use of the BC PKCS#12 implementation required the BC provider to be registered explicitly with the JCE. This has been fixed.
- OpenPGP now fully supports use of the Provider object.
- CMS now fully supports use of the Provider object.
- Multiplication by negative powers of two is fixed in BigInteger.
- OptionalValidity now encodes correctly.

### 2.47.3 Additional Features and Functionality

- Support for NONEwithECDSA has been added.
- Support for Grainv1 and Grain128 has been added.
- Support for EAC algorithms has been added to CMS/SMIME.
- Support for basic CMS AuthenticatedData to the CMS package.
- Jars are now packaged using pack200 for JDK1.5 and JDK 1.6.
- ASN1Dump now supports a verbose mode for displaying the contents of octet and bit strings.
- Support for the SRP-6a protocol has been added to the lightweight API.

### 2.48.1 Version

Release: 1.41
Date: 2008, October 1

### 2.48.2 Defects Fixed

- The GeneralName String constructor now supports IPv4 and IPv6 address parsing.
- An issue with nested-multiparts with postamble for S/MIME that was causing signatures to fail verification has been fixed.
- ESSCertIDv2 encoding now complies with RFC 5035.
- ECDSA now computes correct signatures for oversized hashes when the order of the base point is not a multiple of 8 in compliance with X9.62-2005.
- J2ME SecureRandom now provides additional protection against predictive and backtracking attacks when high volumes of random data are generated.
- Fix to regression from 1.38: PKIXCertPathCheckers were not being called on intermediate certificates.
- Standard name "DiffieHellman" is now supported in the provider.
- Better support for equality tests for '#' encoded entries has been added to X509Name.

### 2.48.3 Additional Features and Functionality

- Camellia is now 12.5% faster than previously.
- A smaller version (around 8k compiled) of Camellia, CamelliaLightEngine has also been added.
- CMSSignedData generation now supports SubjectKeyIdentifier as well as use of issuer/serial.
- A CMSPBE key holder for UTF-8 keys has been added to the CMS API.
- Salt and iteration count can now be recovered from PasswordRecipientInformation.
- Methods in the OpenPGP, CMS, and S/MIME APIs which previously could only take provider names can now take providers objects as well (JDK1.4 and greater).
- Support for reading and extracting personalised certificates in PGP Secret Key rings has been added.

### 2.49.1 Version

Release: 1.40
Date: 2008, July 12

### 2.49.2 Defects Fixed

- EAX mode ciphers were not resetting correctly after a doFinal/reset. This has been fixed.
- The SMIME API was failing to verify doubly nested multipart objects in signatures correctly. This has been fixed.
- Some boolean parameters to IssuingDistributionPoint were being reversed. This has been fixed.
- A zero length RDN would cause an exception in an X509Name. This has been fixed.
- Passing a null to ExtendedPKIXParameters.setTrustedACIssuers() would cause a NullPointerException. This has been fixed.
- CertTemplate was incorrectly encoding issuer and subject fields when set.
- hashCode() for X509CertificateObject was very poor. This has been fixed.
- Specifying a greater than 32bit length for a stream and relying on the default BCPGOutputStream resulted in corrupted data. This has been fixed.
- PKCS7Padding validation would not fail if pad length was 0. This has been fixed.
- javax.crypto classes no longer appear in the JDK 1.3 provider jar.
- Signature creation time was not being properly initialised in new V4 PGP signature objects although the encoding was correct. This has been fixed.
- The '+' character can now be escaped or quoted in the constructor for X509Name, X509Prinicipal.
- Fix to regression from 1.38: PKIXCertPathValidatorResult.getPublicKey was returning the wrong public key when the BC certificate path validator was used.

### 2.49.3 Additional Features and Functionality

- Galois/Counter Mode (GCM) has been added to the lightweight API and the JCE provider.
- SignedPublicKeyAndChallenge and PKCS10CertificationRequest can now take null providers if you need to fall back to the default provider mechanism.
- The TSP package now supports validation of responses with V2 signing certificate entries.
- Unnecessary local ID attributes on certificates in PKCS12 files are now automatically removed.
- The PKCS12 store types PKCS12-3DES-3DES and PKCS12-DEF-3DES-3DES have been added to support generation of PKCS12 files with both certificates and keys protected by 3DES.

### 2.49.4 Additional Notes

- Due to problems for some users caused by the presence of the IDEA algorithm, an implementation is no longer included in the default signed jars. Only the providers of the form bcprov-ext-*-*.jar now include IDEA.

### 2.50.1 Version

Release: 1.39
Date: 2008, March 29

### 2.50.2 Defects Fixed

- A bug causing the odd NullPointerException has been removed from the LocalizedMessage class.
- IV handling in CMS for the SEED and Camellia was incorrect. This has been fixed.
- ASN.1 stream parser now throws exceptions for unterminated sequences.
- EAX mode was not handling non-zero offsetted data correctly and failing. This has been fixed.
- The BC X509CertificateFactory now handles multiple certificates and CRLs in streams that don't support marking.
- The BC CRL implementation could lead to a NullPointer exception being thrown if critical extensions were missing. This has been fixed.
- Some ASN.1 structures would cause a class cast exception in AuthorityKeyIdentifier. This has been fixed.
- The CertID class used by the TSP library was incomplete. This has been fixed.
- A system property check in PKCS1Encoding to cause a AccessControlException under some circumstances. This has been fixed.
- A decoding issue with a mis-identified tagged object in CertRepMessage has been fixed.
- \# is now properly recognised in the X509Name class.

### 2.50.3 Additional Features and Functionality

- Certifications associated with user attributes can now be created, verified and removed in OpenPGP.
- API support now exists for CMS countersignature reading and production.
- The TSP package now supports parsing of responses with V2 signing certificate entries.
- Lazy evaluation of DER sequences has been introduced to ASN1InputStream to allow support for larger sequences.
- KeyPurposeId class has been updated for RFC 4945.
- CertPath processing has been further extended to encompass the NIST CertPath evaluation suite.
- Initial support has been added for HP_CERTIFICATE_REQUEST in the TLS API.
- Providers for JDK 1.4 and up now use SignatureSpi directly rather than extending Signature. This is more in track with the way dynamic provider selection now works.
- PGP example programs now handle blank names in literal data objects.
- The ProofOfPossession class now better supports the underlying ASN.1 structure.
- Support has been added to the provider for the VMPC MAC.

### 2.51.1 Version

Release: 1.38
Date: 2007, November 7

### 2.51.2 Defects Fixed

- SMIME signatures containing non-standard quote-printable data could be altered by SMIME encryption. This has been fixed.
- CMS signatures that do not use signed attributes were vulnerable to one of Bleichenbacher's RSA signature forgery attacks. This has been fixed.
- The SMIMESignedParser(Part) constructor was not producing a content body part that cleared itself after writeTo() as indicated in the JavaDoc. This has been fixed.
- BCPGInputStream now handles data blocks in the 2**31->2**32-1 range.
- A bug causing second and later encrypted objects to be ignored in KeyBasedFileProcessor example has been fixed.
- Value of the TstInfo.Tsa field is now directly accessible from TimeStampTokenInfo.
- Generating an ECGOST-3410 key using an ECGenParameterSpec could cause a ClassCastException in the key generator. This has been fixed.
- Use of the parameters J and L in connection with Diffie-Hellman parameters in the light weight API was ambiguous and confusing. This has been dealt with.
- Some entities were not fully removed from a PKCS#12 file when deleted due to case issues. This has been fixed.
- Overwriting entities in a PKCS#12 file was not fully compliant with the JavaDoc for KeyStore. This has been fixed.
- TlsInputStream.read() could appear to return end of file when end of file had not been reached. This has been fixed.

### 2.51.3 Additional Features and Functionality

- Buffering in the streaming CMS has been reworked. Throughput is now usually higher and the behaviour is more predictable.
- It's now possible to pass a table of hashes to a CMS detached signature rather than having to always pass the data.
- Classes supporting signature policy and signer attributes have been added to the ASN.1 ESS/ESF packages.
- Further work has been done on optimising memory usage in ASN1InputStream. In some cases memory usage has been reduced to 25% of previous.
- Pre-existing signers can now be added to the SMIMESignedGenerator.
- Support has been added to the provider for the VMPC stream cipher.
- CertPathReviewer has better handling for problem trust anchors.
- Base64 encoder now does initial size calculations to try to improve resource usage.

### 2.52.1 Version

Release: 1.37
Date: 2007, June 15

### 2.52.2 Defects Fixed

- The ClearSignedFileProcessor example for OpenPGP did not take into account trailing white space in the file to be signed. This has been fixed.
- A possible infinite loop in the CertPathBuilder and SignedMailValidator have been removed.
- Requesting DES, DESede, or Blowfish keys using regular Diffie-Hellman now returns the same length keys as the regular JCE provider.
- Some uncompressed EC certificates were being interpreted as compressed and causing an exception. This has been fixed.
- Adding a CRL with no revocations on it to the CRL generator could cause an exception to be thrown. This has been fixed.
- Using the default JDK provider with the CMS library would cause exceptions in some circumstances. This has been fixed.
- BC provider DSAKeys are now serializable.
- Using only a non-sha digest in S/MIME signed data would produce a corrupt MIME header. This has been fixed.
- The default private key length in the lightweght API for generated DiffieHellman parameters was absurdly small, this has been fixed.
- Cipher.getParameters() for PBEwithSHAAndTwofish-CBC was returning null after intialisation. This has been fixed.

### 2.52.3 Additional Features and Functionality

- The block cipher mode CCM has been added to the provider and light weight API.
- The block cipher mode EAX has been added to the provider and light weight API.
- The stream cipher HC-128 and HC-256 has been added to the provider and lightwieght API.
- The stream cipher ISAAC has been added to the lightweight API.
- Support for producing and parsing notation data signature subpackets has been added to OpenPGP.
- Support for implicit tagging has been added to DERApplicationSpecific.
- CMS better supports basic Sun provider.
- A full set of SEC-2 EC curves is now provided in the SEC lookup table.
- Specifying a null provider in CMS now always uses the default provider, rather than causing an exception.
- Support has been added to the OpenPGP API for parsing experimental signatures
- CertPath validator now handles inherited DSA parameters and a wider range of name constraints.
- Further work has been done on improving the performance of ECDSA - it is now about two to six times faster depending on the curve.
- The Noekeon block cipher has been added to the provider and the lightweight API.
- Certificate generation now supports generation of certificates with an empty Subject if the subjectAlternativeName extension is present.
- The JCE provider now supports RIPEMD160withECDSA.

### 2.53.1 Version

Release: 1.36
Date: 2007, March 16

### 2.53.2 Defects Fixed

- DSA key generator now checks range and keysize.
- Class loader issues with i18n classes should now be fixed.
- X.500 name serial number value now output as unambiguous long form SERIALNUMBER
- The fix for multipart messages with mixed content-transfer-encoding in 1.35 caused a regression for processing some messages with embedded multiparts that contained blank lines of preamble text - this should now be fixed.
- Another regression which sometimes affected the SMIMESignedParser has also been fixed.
- SharedFileInputStream compatibility issues with JavaMail 1.4 have been addressed.
- JDK 1.5 and later KeyFactory now accepts ECPublicKey/ECPrivateKey to translateKey.
- JDK 1.5 and later KeyFactory now produces ECPublicKeySpec/ECPrivateKeySpec on getKeySpec.
- Some surrogate pairs were not assembled correctly by the UTF-8 decoder. This has been fixed.
- Alias resolution in PKCS#12 is now case insensitive.

### 2.53.3 Additional Features and Functionality

- CMS/SMIME now supports basic EC KeyAgreement with X9.63.
- CMS/SMIME now supports RFC 3211 password based encryption.
- Support has been added for certificate, CRL, and certification request generation for the regular SHA algorithms with RSA-PSS.
- Further work has been done in speeding up prime number generation in the lightweight BigInteger class.
- Support for the SEED algorithm has been added to the provider and the lightweight API.
- Support for the Salsa20 algorithm has been added to the provider and the lightweight API.
- CMS/SMIME now support SEED and Camellia
- A table of TeleTrusT curves has been added.
- CMSSignedData creation and Collection CertStore now preserves the order of certificates/CRls if the backing collection is ordered.
- CMS Signed objects now use BER encoding for sets containing certificates and CRLs, allowing specific ordering to be specified for the objects contained.
- CMS enveloped now works around providers which throw UnsupportedOperationException if key wrap is attempted.
- DSASigner now handles long messages. SHA2 family digest support for DSA has been added to the provider.

### 2.54.1 Version

Release: 1.35
Date: 2006, December 16

### 2.54.2 Defects Fixed

- Test data files are no longer in the provider jars.
- SMIMESignedParser now handles indefinite length data in SignerInfos.
- Under some circumstances the SMIME library was failing to canonicalize mixed-multipart data correctly. This has been fixed.
- The l parameter was being ignored for the DH and ElGamal key generation. This has been fixed.
- The ASN1Sequence constructor for OtherRecipientInfo was broken. It has been fixed
- Regression - DN fields SerialNumber and Country were changed to encode as UTF8String in 1.34 in the X509DefaultEntryConverter, these now encode as PrintableString.
- CMSSignedData.replaceSigners() was not replacing the digest set as well as the signers. This has been fixed.
- DERGeneralizedTime produced a time string without a GMT offset if they represented local time. This has been fixed.
- Some temp files were still being left on Windows by the SMIME library. All of the known problems have been fixed.
- Comparing ASN.1 object for equality would fail in some circumstances. This has been fixed.
- The IESEngine could incorrectly encrypt data when used in block cipher mode. This has been fixed.
- An error in the encoding of the KEKRecipientInfo has been fixed. Compatability warning: this may mean that versions of BC mail prior to 1.35 will have trouble processing KEK messages produced by 1.35 or later.

### 2.54.3 Additional Features and Functionality

- Further optimisations to elliptic curve math libraries.
- API now incorporates a CertStore which should be suitable for use with LDAP.
- The streaming ASN.1 API is now integrated into the base one, the sasn1 package has been deprecated.
- The OpenPGP implementation now supports SHA-224 and BZIP2.
- The OpenPGP implementation now supports SHA-1 checksumming on secret keys.
- The JCE provider now does RSA blinding by default.
- CMSSignedDataParser now provides methods for replacing signers and replacing certificates and CRLs.
- A generic store API has been added to support CRLs, Certificates and Attribute certificates.
- The CMS/SMIME API now supports inclusion and retrieval of version 2 attribute certificates.
- Support for generating CertificationRequests and Certificates has been added for GOST-3410-2001 (ECGOST)
- CMS/SMIME now support ECGOST
- Basic BER Octet Strings now encode in a canonical fashion by default.
- DERUTCTime can now return Date objects
- Validating constructors have been added to DERPrintableString, DERIA5String, and DERNumericString.
- A lightweight API for supporting TLS has been added.
- Implementations of the TEA and XTEA ciphers have been added to the light weight API and the provider.
- PEMReader now supports OpenSSL ECDSA key pairs.
- PGP packet streams can now be closed off using close() on the returned stream as well as closing the generator.

### 2.55.1 Version

Release: 1.34
Date: 2006, October 2

### 2.55.2 Defects Fixed

- Endianess of integer conversion in KDF2BytesGenerator was incorrect. This has been fixed.
- Generating critical signature subpackets in OpenPGP would result in a zero packet tag. This has been fixed.
- Some flags in PKIFailure info were incorrect, and the range of values was incomplete. The range of values has been increased and the flags corrected.
- The helper class for AuthorityKeyExtension generation was including the subject rather than the issuer DN of the CA certificate. This has been fixed.
- SMIMESignedParser now avoids JavaMail quoted-printable recoding issue.
- Verification of RSA signatures done with keys with public exponents of 3 was vunerable to Bleichenbacher's RSA signature forgery attack. This has been fixed.
- PGP Identity strings were only being interpreted as ASCII rather than UTF-8. This has been fixed.
- CertificateFactory.generateCRLs now returns a Collection rather than null.

### 2.55.3 Additional Features and Functionality

- An ISO18033KDFParameters class had been added to support ISO18033 KDF generators.
- An implemention of the KDF1 bytes generator algorithm has been added.
- An implementation of NaccacheStern encryption has been added to the lightweight API.
- X509V2CRLGenerator can now be loaded from an existing CRL.
- The CMS enveloped data generators will now attempt to use the default provider for encryption if the passed in provider can only handle key exchange.
- OpenPGP file processing has been substantially speeded up.
- The PKCS1Encoder would accept PKCS1 packets which were one byte oversize. By default this will now cause an error. However, as there are still implementations which still produce such packets the older behaviour can be turned on by setting the VM system property org.bouncycastle.pkcs1.strict to false before creating an RSA cipher using PKCS1 encoding.
- A target has been added to the bc-build.xml to zip up the source code rather than leaving it in a directory tree. The build scripts now run this target by default.
- Use of toUpperCase and toLowerCase has been replaced with a locale independent converter where appropriate.
- Support for retrieving the issuers of indirect CRLs has been added.
- Classes for doing incremental path validation of PKIX cert paths have been added to the X.509 package and S/MIME.
- Locale issues with String.toUpperCase() have now been worked around.
- Optional limiting has been added to ASN1InputStream to avoid possible OutOfMemoryErrors on corrupted streams.
- Support has been added for SHA224withECDSA, SHA256withECDSA, SHA384withECDSA, and SHA512withECDSA for the generation of signatures, certificates, CRLs, and certification requests.
- Performance of the prime number generation in the BigInteger library has been further improved.
- In line with RFC 3280 section 4.1.2.4 DN's are now encoded using UTF8String by default rather than PrintableString.

### 2.55.4 Security Advisory

- If you are using public exponents with the value three you *must* upgrade to this release, otherwise it will be possible for attackers to exploit some of Bleichenbacher's RSA signature forgery attacks on your applications.

### 2.56.1 Version

Release: 1.33
Date: 2006, May 3

### 2.56.2 Defects Fixed

- OCSPResponseData was including the default version in its encoding. This has been fixed.
- BasicOCSPResp.getVersion() would throw a NullPointer exception if called on a default version response. This has been fixed.
- Addition of an EC point under Fp could result in an ArithmeticException. This has been fixed.
- The n value for prime192v2 was incorrect. This has been fixed.
- ArmoredInputStream was not closing the underlying stream on close. This has been fixed.
- Small base64 encoded strings with embedded white space could decode incorrectly using the Base64 class. This has been fixed.

### 2.56.3 Additional Features and Functionality

- The X509V2CRLGenerator now supports adding general extensions to CRL entries.
- A RoleSyntax implementation has been added to the x509 ASN.1 package, and the AttributeCertificateHolder class now support the IssuerSerial option.
- The CMS API now correctly recognises the OIW OID for DSA with SHA-1.
- DERUTF8String now supports surrogate pairs.

### 2.57.1 Version

Release: 1.32
Date: 2006, March 27

### 2.57.2 Defects Fixed

- Further work has been done on RFC 3280 compliance.
- The ASN1Sequence constructor for SemanticsInformation would sometimes throw a ClassCastException on reconstruction an object from a byte stream. This has been fixed.
- The SharedInputStream.read(buf, 0, len) method would return 0 at EOF, rather than -1. This has been fixed.
- X9FieldElement could fail to encode a Fp field element correctly. This has been fixed.
- The streaming S/MIME API was occasionally leaving temporary files around. The SIMEUtil class responsible for creating the files now returns a FileBackedMimeBodyPart object which has a dispose method on it which should allow removal of the file backing the body part.
- An encoding defect in EnvelopedData generation in the CMS streaming, S/MIME API has been fixed.
- DER constructed octet strings could cause exceptions in the streaming ASN.1 library. This has been fixed.
- Several compatibility issues connected with EnvelopedData decoding between the streaming CMS library and other libraries have been fixed.
- JDK 1.4 and earlier would sometimes encode named curve parameters explicitly. This has been fixed.
- An incorrect header for SHA-256 OpenPGP clear text signatures has been fixed.
- An occasional bug that could result in invalid clear text signatures has been fixed.
- OpenPGP clear text signatures containing '\r' as line separators were not being correctly canonicalized. This has been fixed.

### 2.57.3 Additional Features and Functionality

- The ASN.1 library now includes classes for the ICAO Electronic Passport.
- Support has been added to CMS and S/MIME for ECDSA.
- Support has been added for the SEC/NIST elliptic curves.
- Support has been added for elliptic curves over F2m.
- Support has been added for repeated attributes in CMS and S/MIME messages.
- A wider range of RSA-PSS signature types is now supported for CRL and Certificate verification.

### 2.57.4 Possible compatibility issue

- Previously elliptic curve keys and points were generated with point compression enabled by default. Owing to patent issues in some jurisdictions, they are now generated with point compression disabled by default.

### 2.58.1 Version

Release: 1.31
Date: 2005, December 29

### 2.58.2 Defects Fixed

- getCriticalExtensionOIDs on an X.509 attribute certificate was returning the non-critical set. This has been fixed.
- Encoding uncompressed ECDSA keys could occasionally introduce an extra leading zero byte. This has been fixed.
- Expiry times for OpenPGP master keys are now recognised across the range of possible certifications.
- PGP 2 keys can now be decrypted by the the OpenPGP library.
- PGP 2 signature packets threw an exception on trailer processing. This has been been fixed.
- Attempting to retrieve signature subpackets from an OpenPGP version 3 signature would throw a null pointer exception. This has been fixed.
- Another occasional defect in EC point encoding has been fixed.
- In some cases AttributeCertificateHolder.getIssuer() would return an empty array for attribute certificates using the BaseCertificateID. This has been fixed.
- OIDs with extremely large components would sometimes reencode with unnecessary bytes in their encoding. The optimal DER encoding will now be produced instead.

### 2.58.3 Additional Features and Functionality

- The SMIME package now supports the large file streaming model as well.
- Additional ASN.1 message support has been added for RFC 3739 in the org.bouncycastle.x509.qualified package.
- Support has been added for Mac algorithm 3 from ISO 9797 to both the lightweight APIs and the provider.
- The provider now supports the DESEDE64 MAC algorithm.
- CertPathValidator has been updated to better support path validation as defined in RFC 3280.

### 2.59.1 Version

Release: 1.30
Date: 2005, September 18

### 2.59.2 Defects Fixed

- Whirlpool was calculating the wrong digest for 31 byte data and could throw an exception for some other data lengths. This has been fixed.
- AlgorithmParameters for IVs were returning a default of RAW encoding of the parameters when they should have been returning an ASN.1 encoding. This has been fixed.
- Base64 encoded streams without armoring could cause an exception in PGPUtil.getDecoderStream(). This has been fixed.
- PGPSecretKey.copyWithNewPassword() would incorrectly tag sub keys. This has been fixed.
- PGPSecretKey.copyWithNewPassword() would not handle the NULL algorithm. This has been fixed.
- Directly accessing the dates on an X.509 Attribute Certificate constructed from an InputStream would return null, not the date objects. This has been fixed.
- KEKIdentifier would not handle OtherKeyAttribute objects correctly. This has been fixed.
- GetCertificateChain on a PKCS12 keystore would return a single certificate chain rather than null if the alias passed in represented a certificate not a key. This has been fixed.

### 2.59.3 Additional Features and Functionality

- RSAEngine no longer assumes keys are byte aligned when checking for out of range input.
- PGPSecretKeyRing.removeSecretKey and PGPSecretKeyRing.insertSecretKey have been added.
- There is now a getter for the serial number on TimeStampTokenInfo.
- Classes for dealing with CMS objects in a streaming fashion have been added to the CMS package.
- PGPCompressedDataGenerator now supports partial packets on output.
- OpenPGP Signature generation and verification now supports SHA-256, SHA-384, and SHA-512.
- Both the lightweight API and the provider now support the Camellia encryption algorithm.

### 2.60.1 Version

Release: 1.29
Date: 2005, June 27

### 2.60.2 Defects Fixed

- HMac-SHA384 and HMac-SHA512 were not IETF compliant. This has been fixed.
- The equals() method on ElGamalKeyParameters and DHKeyParameters in the lightweight API would sometimes return false when it should return true. This has been fixed.
- Parse error for OpenSSL style PEM encoded certificate requests in the PEMReader has been fixed.
- PGPPublicKey.getValidDays() now checks for the relevant signature for version 4 and later keys as well as using the version 3 key valid days field.
- ISO9796 signatures for full recovered messsages could incorrectly verify for similar messages in some circumstances. This has been fixed.
- The occasional problem with decrypting PGP messages containing compressed streams now appears to be fixed.

### 2.60.3 Additional Features and Functionality

- Support has been added for the OIDs and key generation required for HMac-SHA224, HMac-SHA256, HMac-SHA384, and HMac-SHA512.
- SignerInformation will used default implementation of message digest if signature provider doesn't support it.
- The provider and the lightweight API now support the GOST-28147-94 MAC algorithm.
- Headers are now settable for PGP armored output streams.

### 2.60.4 Notes

- The old versions of HMac-SHA384 and HMac-SHA512 can be invoked as OldHMacSHA384 and OldHMacSHA512, or by using the OldHMac class in the lightweight API.

### 2.61.1 Version

Release: 1.28
Date: 2005, April 20

### 2.61.2 Defects Fixed

- Signatures on binary encoded S/MIME messages could fail to validate when correct. This has been fixed.
- getExtensionValue() on CRL Entries were returning the encoding of the inner object, rather than the octet string. This has been fixed.
- CertPath implementation now returns an immutable list for a certificate path.
- Generic sorting now takes place in the CertificateFactory.generateCertPath() rather than CertPathValidator.
- DERGeneralizedTime can now handle time strings with milli-seconds.
- Stateful CertPathCheckers were not being initialised in all cases, by the CertPathValidator. This has been fixed.
- PGPUtil file processing methods were failing to close files after processing. This has been fixed.
- A disordered set in a CMS signature could cause a CMS signature to fail to validate when it should. This has been fixed.
- PKCS12 files where both the local key id and friendly name were set on a certificate would not parse correctly. This has been fixed.
- Filetype for S/MIME compressed messages was incorrect. This has been fixed.
- BigInteger class can now create negative numbers from byte arrays.

### 2.61.3 Additional Features and Functionality

- S/MIME now does canonicalization on non-binary input for signatures.
- Micalgs for the new SHA schemes are now supported.
- Provided and lightweight API now support ISO 7816-4 padding.
- The S/MIME API now directly supports the creation of certificate management messages.
- The provider and the light weight API now support the cipher GOST-28147, the signature algorithms GOST-3410 (GOST-3410 94) and EC GOST-3410 (GOST-3410 2001), the message digest GOST-3411 and the GOST OFB mode (use GOFB).
- CMSSignedDataGenerator will used default implementation of message digest if signature provider doesn't support it.
- Support has been added for the creation of ECDSA certificate requests.
- The provider and the light weight API now support the WHIRLPOOL message digest.

### 2.61.4 Notes

- Patches for S/MIME binary signatures and canonicalization were actually applied in 1.27, but a couple of days after the release - if the class CMSProcessableBodyPartOutbound is present in the package org.bouncycastle.mail.smime you have the patched 1.27. We would recommend upgrading to 1.28 in any case as some S/MIME 3.1 recommendations have also been introduced for header creation.
- GOST private keys are probably not encoding correctly and can be expected to change.

### 2.62.1 Version

Release: 1.27
Date: 2005, February 20

### 2.62.2 Defects Fixed

- Typos in the provider which pointed Signature algorithms SHA256WithRSA, SHA256WithRSAEncryption, SHA384WithRSA, SHA384WithRSAEncryption, SHA512WithRSA, and SHA512WithRSAEncryption at the PSS versions of the algorithms have been fixed. The correct names for the PSS algorithms are SHA256withRSAandMGF1, SHA384withRSAandMGF1, and SHA512withRSAandMGF1.
- X509CertificateFactory failed under some circumstances to reset properly if the input stream being passed to generateCertificate(s)() changed, This has been fixed.
- OpenPGP BitStrength for DSA keys was being calculated from the key's generator rather than prime. This has been fixed.
- Possible infinite loop in ASN.1 SET sorting has been removed.
- SHA512withRSAandMGF1 with a zero length salt would cause an exception if used with a 1024 bit RSA key. This has been fixed.
- Adding an Exporter to a PGPSubpacketVector added a Revocable instead. This has been fixed.
- AttributeCertificateIssuer.getPrincipal() could throw an ArrayStoreException. This has been fixed.
- CertPathValidator now guarantees to call any CertPathCheckers passed in for each certificate.
- TSP TimeStampToken was failing to validate time stamp tokens with the issuerSerial field set in the ESSCertID structure. This has been fixed.
- Path validation in environments with frequently updated CRLs could occasionally reject a valid path. This has been fixed.

### 2.62.3 Additional Features and Functionality

- Full support has been added for the OAEPParameterSpec class to the JDK 1.5 povider.
- Full support has been added for the PSSParameterSpec class to the JDK 1.4 and JDK 1.5 providers.
- Support for PKCS1 signatures for SHA-256, SHA-384, and SHA-512 has been added to CMS.
- PGPKeyRingCollection classes now support partial matching of user ID strings.
- This release disables the quick check on the IV for a PGP public key encrypted message in order to help prevent applications being vunerable to oracle attacks.
- The CertPath support classes now support PKCS #7 encoding.
- Point compression can now be turned off when encoding elliptic curve keys.

### 2.62.4 Changes that may affect compatibility

- org.bouncycastle.jce.interfaces.ElGamalKey.getParams() has been changed to getParameters() to avoid clashes with a JCE interface with the same method signature.
- org.bouncycastle.jce.interfaces.ECKey.getParams() has been changed in JDK 1.5 to getParameters() to avoid clashes with a JCE interface with the same method signature. The getParams() method in pre-1.5 has been deprecated.
- SHA256WithRSAEncryption, SHA384WithRSAEncryption, SHA512WithRSAEncryption now refer to their PKCS #1 V1.5 implementations. If you were using these previously you should use SHA256WithRSAAndMGF1, SHA384WithRSAAndMGF1, or SHA512WithRSAAndMGF1.

### 2.63.1 Version

Release: 1.26
Date: 2005, January 15

### 2.63.2 Defects Fixed

- The X.509 class UserNotice assumed some of the optional fields were not optional. This has been fixed.
- BCPGInputStream would break on input packets of 8274 bytes in length. This has been fixed.
- Public key fingerprints for PGP version 3 keys are now correctly calculated.
- ISO9796-2 PSS would sometimes throw an exception on a correct signature. This has been fixed.
- ASN1Sets now properly sort their contents when created from scratch.
- A bug introduced in the CertPath validation in the last release which meant some certificate paths would validate if they were invalid has been fixed.

### 2.63.3 Additional Features and Functionality

- Support for JDK 1.5 naming conventions for OAEP encryption and PSS signing has been added.
- Support for Time Stamp Protocol (RFC 3161) has been added.
- Support for Mozilla's PublicKeyAndChallenge key certification message has been added.
- OpenPGP now supports key rings containing GNU_DUMMY_S2K.
- Support for the new versions (JDK 1.4 and later) of PBEKeySpec has been added to the providers.
- PBEWithMD5AndRC2, PBEWithSHA1AndRC2 now generate keys rather than exceptions.
- The BigInteger implementation has been further optimised to take more advantage of the Montgomery number capabilities.

### 2.63.4 JDK 1.5 Changes

- The JDK 1.5 version of the provider now supports the new Elliptic Curve classes found in the java.security packages. Note: while we have tried to preserve some backwards compatibility people using Elliptic curve are likely to find some minor code changes are required when moving code from JDK 1.4 to JDK 1.5 as the java.security APIs have changed.

### 2.64.1 Version

Release: 1.25
Date: 2004, October 1

### 2.64.2 Defects Fixed

- In some situations OpenPGP would overread when a stream had been broken up into partial blocks. This has been fixed.
- Explicitly setting a key size for RC4 in the CMS library would cause an exception. This has been fixed.
- getSignatures() on PGPPublicKey would throw a ClassCastException in some cases. This has been fixed.
- Encapsulated signed data was been generated with the wrong mime headers, this has been fixed.
- The isSignature method on PGPSecretKey now correctly identifies signing keys.
- An interoperability issue with DH key exchange between the Sun JCE provider and the BC provider, concerning sign bit expansion, has been fixed.
- The X509CertificateFactory would fail to reset correctly after reading an ASN.1 certificate chain. This has been fixed.
- CertPathValidator now handles unsorted lists of certs.
- The PGPSignatureGenerator would sometimes throw an exception when adding hashed subpackets. This has been fixed.
- Ordered equality in X509Name was not terminating as early as possible. This has been fixed.
- getBitStrength for PGPPublicKeys was returning the wrong value for ElGamal keys. This has been fixed.
- getKeyExpirationTime/getSignatureExpirationTime was returning a Date rather than a delta. This isn't meaningful as a Date and has been changed to a long.
- the crlIssuer field in DistributionPoint name was encoding/decoding incorrectly. This has been fixed.
- X509Name now recognises international characters in the input string and stores them as BMP strings.
- Parsing a message with a zero length body with SMIMESigned would cause an exception. This has been fixed.
- Some versions of PGP use zeros in the data stream rather than a replication of the last two bytes of the iv as specified in the RFC to determine if the correct decryption key has been found. The decryption classes will now cope with both.

### 2.64.3 Additional Features and Functionality

- Support for extracting signatures based on PGP user attributes has been added to PGPPublicKey.
- BCPGArmoredInputStream should cope with plain text files better.
- The OpenPGP library can now create indefinite length streams and handle packets greater than (2^32 - 1) in length.
- Direct support for adding SignerUserID and PrimaryUserID has been added to the PGPSignatureSubpacketGenerator.
- Support for ISO-9796-2/PSS has been added to the lightweight API.
- API support for extracting recovered messages from signatures that support message recovery has been added to the lightweight API.
- String value conversion in a DN being processed by X509Name is now fully configurable.
- It is now possible to create new versions of CMSSignedData objects without having to convert the original object down to its base ASN.1 equivalents.
- Support for adding PGP revocations and other key signatures has been added.
- Support for SHA-224 and SHA224withRSA has been added.
- Trailing bit complement (TBC) padding has been added.
- OID components of up to 2^63 bits are now supported.

### 2.65.1 Version

Release: 1.24
Date: 2004, June 12

### 2.65.2 Defects Fixed

- OpenPGP Secret key rings now parse key rings with user attribute packets in them correctly.
- OpenPGP Secret key rings now parse key rings with GPG comment packets in them.
- X509Name and X509Principal now correctly handle BitStrings.
- OpenPGP now correctly recognises RSA signature only keys.
- When re-encoding PGP public keys taken off secret keys getEncoded would sometimes throw a NullPointerException. This has been fixed.
- A basic PKCS12 file with a single key and certificate, but no attributes, would cause a null pointer exception. This has been fixed.
- Signature verification now handles signatures where the parameters block is missing rather than NULL.
- Lightweight CBCBlockCipherMac was failing to add padding if padding was being explicitly provided and data length was a multiple of the block size. This has been fixed.
- ZIP compression in PGP was failing to compress data in many cases. This has been fixed.
- Signatures were occasionally produced with incorrect padding in their associated bit strings, this has been fixed.
- An encoding error introduced in 1.23 which affected generation of the KeyUsage extension has been fixed.

### 2.65.3 Additional Features and Functionality

- PKCS12 keystore now handles single key/certificate files without any attributes present.
- Support for creation of PGPKeyRings incorporating sub keys has been added.
- ZeroPadding for encrypting ASCII data has been added.

### 2.66.1 Version

Release: 1.23
Date: 2004, April 10

### 2.66.2 Defects Fixed

- Reading a PGP Secret key file would sometimes cause a class cast exception. This has been fixed.
- PGP will now read SecretKeys which are encrypted with the null algorithm.
- PGP ObjectFactory will recognise Marker packets.
- BasicConstraints class now handles default empty sequences correctly.
- S2K Secret Key generation now supported in OpenPGP for keys greater than 160 bits, a bug causing it to occasionally generate the wrong key has been fixed.
- OpenPGP implementation can now read PGP 8 keys.
- Decoding issues with Secret Sub Keys should now be fixed.
- PGP would occasionally unpack ElGamal encrypted data incorrectly, this has been fixed.
- OCSP TBSRequest now uses abbreviated encoding if the default version is used.
- X509Name class will now print names with nested pairs in component sets correctly.
- RC4 now resets correctly on doFinal.

### 2.66.3 Additional Features and Functionality

- PGP V3 keys and V3 signature generation is now supported.
- Collection classes have been added for representing files of PGP public and secret keys.
- PEMReader now supports "RSA PUBLIC KEY".
- RipeMD256 and RipeMD320 have been added.
- Heuristic decoder stream has been added to OpenPGP which "guesses" how the input is constructed.
- ArmoredInputStream now recognises clear text signed files.
- ArmoredOutputStream now provides support for generating clear text signed files.
- Support has been added to CMS for RipeMD128, RipeMD160, and RipeMD256.
- Support for generating certification directly and editing PGP public key certifications has been added.
- Support has been added for modification detection codes to the PGP library.
- Examples have been rewritten to take advantage of the above.
- SMIMESigned can now covert data straight into a mime message.
- DERGeneralizedTime getTime() method now handles a broader range of input strings.

### 2.67.1 Version

Release: 1.22
Date: 2004, February 7

### 2.67.2 Defects Fixed

- Generating DSA signatures with PGP would cause a class cast exception, this has been fixed.
- PGP Data in the 192 to 8383 byte length would sometimes be written with the wrong length header. This has been fixed.
- The certificate factory would only parse the first certificate in a PKCS7 object. This has been fixed.
- getRevocationReason() in RevokedStatus in OCSP would throw an exception for a non-null reason, rather than a null one. This has been fixed.
- PSS signature verification would fail approximately 0.5 % of the time on correct signatures. This has been fixed.
- Encoding of CRL Distribution Points now always works.

### 2.67.3 Additional Features and Functionality

- Additional methods for getting public key information have been added to the PGP package.
- Some support for user attributes and the image attribute tag has been added.
- Support for the AuthorityInformationAccess extension has been added.
- Support for ElGamal encryption/decryption has been added to the PGP package.

### 2.68.1 Version

Release: 1.21
Date: 2003, December 6

### 2.68.2 Defects Fixed

- The CertPath validator would fail for some valid CRLs. This has been fixed.
- AES OIDS for S/MIME were still incorrect, this has been fixed.
- The CertPathBuilder would sometimes throw a NullPointerException looking for an issuer. This has been fixed.
- The J2ME BigInteger class would sometimes go into an infinite loop generating prime numbers. This has been fixed.
- DERBMPString.equals() would throw a class cast exception. This has been fixed.

### 2.68.3 Additional Features and Functionality

- PEMReader now handles public keys.
- OpenPGP/BCPG should now handle partial input streams. Additional methods for reading subpackets off signatures.
- The ASN.1 library now supports policy qualifiers and policy info objects.

### 2.69.1 Version

Release: 1.20
Date: 2003, October 8

### 2.69.2 Defects Fixed

- BigInteger toString() in J2ME/JDK1.0 now produces same output as the Sun one.
- RSA would throw a NullPointer exception with doFinal without arguments. This has been fixed.
- OCSP CertificateID would calculate wrong issuer hash if issuer cert was not self signed. This has been fixed.
- Most of response generation in OCSP was broken. This has been fixed.
- The CertPath builder would sometimes go into an infinite loop on some chains if the trust anchor was missing. This has been fixed.
- AES OIDS were incorrect, this has been fixed.
- In some cases BC generated private keys would not work with the JSSE. This has been fixed.

### 2.69.3 Additional Features and Functionality

- Support for reading/writing OpenPGP public/private keys and OpenPGP signatures has been added.
- Support for generating OpenPGP PBE messages and public key encrypted messages has been added.
- Support for decrypting OpenPGP messages has been added.
- Addition of a Null block cipher to the light weight API.

### 2.70.1 Version

Release: 1.19
Date: 2003, June 7

### 2.70.2 Defects Fixed

- The PKCS12 store would throw an exception reading PFX files that had attributes with no values. This has been fixed.
- RSA Private Keys would not serialise if they had PKCS12 bag attributes attached to them, this has been fixed.
- GeneralName was encoding OtherName as explicitly tagged, rather than implicitly tagged. This has been fixed.
- ASN1 parser would sometimes mistake an implicit null for an implicit empty sequence. This has been fixed.

### 2.70.3 Additional Features and Functionality

- S/MIME and CMS now support the draft standard for AES encryption.
- S/MIME and CMS now support setable key sizes for the standard algorithms.
- S/MIME and CMS now handle ARC4/RC4 encrypted messages.
- The CertPath validator now passes the NIST test suite.
- A basic OCSP implementation has been added which includes request generation and the processing of responses. Response generation is also provided, but should be treated as alpha quality code.
- CMS now attempts to use JCA naming conventions in addition to the OID name in order to find algorithms.

### 2.71.1 Version

Release: 1.18
Date: 2003, February 8

### 2.71.2 Defects Fixed

- DESKeySpec.isParityAdjusted in the clean room JCE could go into an infinite loop. This has been fixed.
- The SMIME API would end up throwing a class cast exception if a MimeBodyPart was passed in containing a MimeMultipart. This is now fixed.
- ASN1InputStream could go into an infinite loop reading a truncated input stream. This has been fixed.
- Seeding with longs in the SecureRandom for the J2ME and JDK 1.0, only used 4 bytes of the seed value. This has been fixed.

### 2.71.3 Additional Features and Functionality

- The X.509 OID for RSA is now recognised by the provider as is the OID for RSA/OAEP.
- Default iv's for DES are now handled correctly in CMS.
- The ASN.1 classes have been updated to use the generic ASN1* classes where possible.
- A constructor has been added to SMIMESigned to simplify the processing of "application/pkcs7-mime; smime-type=signed-data;" signatures.
- Diffie-Hellman key generation is now faster in environments using the Sun BigInteger library.

### 2.72.1 Version

Release: 1.17
Date: 2003, January 8

### 2.72.2 Defects Fixed

- Reuse of an CMSSignedObject could occasionally result in a class cast exception. This has been fixed.
- The X.509 DistributionPointName occasionally encoded incorrectly. This has been fixed.
- BasicConstraints construction would break if an ASN.1 sequence was used with only the required parameter. This has been fixed.
- The DERObject constructor in OriginatorIdentifierOrKey was leaving the id field as null. This has been fixed.

### 2.72.3 Additional Functionality and Features

- RC2 now supports the full range of parameter versions and effective key sizes.
- CompressedData handling has been added to CMS/SMIME.
- The 1.4 version now allows X500Principles to be generated directly from CRLs.
- SMIME objects now support binary encoding. The number of signature types recognised has been increased.
- CMS can create signed objects with encapsulated data. Note: while this was been done we realised we could simplify things, we did and for the most part people won't notice, other than the occasional reference to CMSSignable will need to be replaced with CMSProcessable.
- X509Name and X509Principal now support forward and reverse X509Name to string conversion, with changeable lookup tables for converting OIDs into strings. Both classes also now allow the direction of encoding to be set when a string is converted as well as changeable lookup tables for string to OID conversion.

### 2.73.1 Version

Release: 1.16
Date: 2002, November 30

### 2.73.2 Defects Fixed

- CRLS were only working for UTC time constructed Time objects, this has been fixed.
- KeyUsage and ReasonFlags sometimes encoded longer than necessary. This has been fixed.
- BER encoded sets are now recognised and dealt with.
- Encoding issues in CMS which were causing problems with backwards compatibility with older CMS/SMIME clients have been fixed.
- KeyFactory now allows for creation of RSAKey*Spec classes.
- The X509CertSelector in the clean room CertPath API is now less likely to throw a NullPointerException at the wrong time.
- Macs now clone correctly in the clean room JCE.

### 2.73.3 Additional Functionality and Features

- PGPCFB support has been added to the provider and the lightweight API.
- There are now three versions of the AESEngine, all faster than before, with the largest footprint one being the fastest. The JCE AES now refers to the fastest.
- The 1.4 version of the library now allows for X500Principals to be generated directly from certificates.
- X509Name has been extended to parse numeric oids, "oid." oids, and to recognise the LDAP UID.
- Immutable sequences and sets have been introduced to the ASN.1 package.
- The SMIME/CMS ASN.1 base classes have been rewritten to reduce the size of the package for use with the lightweight API.
- The SMIME/CMS api's have been rewritten to allow them to take advantage of the Cert Path API, remove code suited to inclusion in the provider, and to support multiple recipients/signers.

### 2.74.1 Version

Release: 1.15
Date: 2002, September 6

### 2.74.2 Defects Fixed

- The base string for the oids in asn1.x509.KeyPurposeId was incorrect. This has been fixed.
- MimeBodyParts in the SMIME Generator did not have their Content-Type properly set up after decryption. This has been fixed.
- If a X.509 certificate did not have all the keyUsage extension bits set, the provider wasn't padding the return value of the key usage extension to 8 booleans in length. This has been fixed.
- In some cases the simple BC keystore allowed overwriting of an alias with one of the same name. This has been fixed.
- The key schedule for RC5-64 was not always being calculated correctly. This has been fixed.
- On reset buffered blockcipher was only partially erasing the previous buffer. This has been fixed.
- All lightweight mac classes now do a reset on doFinal.
- ASN.1 object identifiers wouldn't encode the first byte correctly if the OID started with 2 and the second number was greater than 47. This has been fixed.
- If a key had PKCS9 attributes associated with it on storage they took precedence over the local alias used to add the key to the PKCS12 key store. The local name now takes precedence.
- ReasonFlags now correctly encodes.

### 2.74.3 Additional Functionality and Features

- The PKCS12 key store now handles key bags in encryptedData bags.
- The X509NameTokenizer now handles for '\' and '"' characters.
- SMIME v2 compliance has been added. Use setVersion(2) in the generator classes.
- The ASN.1 library now supports ENUMERATED, UniversalString and the X.509 library support for CRLs now includes CRLReason, and some elements of CertificatePolicies.
- Both the provider and the lightweight library now support a basic SIC mode for block ciphers.

### 2.75.1 Version

Release: 1.14
Date: 2002, June 17

### 2.75.2 Defects Fixed

- there was a bug in the BigInteger right shifting for > 31 bit shifts. This has been fixed.
- x509 name had it's equality test based on the order of the directory elements, this has been fixed.
- the mode used with the RSA cipher in KeyTransRecipientInfoParser in the smime implementation was not compatible with the Sun JCE. This has been fixed.
- PKCS7 SignedData now supports single length signing chains.
- When a root certificate had a different issuer id from the subject id, or had it's own AuthorityKeyExtension the PKCS12 key store would drop the root certificate from the certificate chain. This has been fixed.
- The PKCS10 CertificationRequestInfo class always expected at least one attribute. This has been fixed.
- UTF-8 strings are now correctly recognised.
- The Tiger implementation was producing results in reverse byte order for each of the 3 words making up the digest. This has been fixed.
- asn1.x509.ExtendedKeyUsage used to throw a null pointer exception on construction. This has been fixed.

### 2.75.3 Additional Functionality and Features

- The BigInteger library now uses Montgomery numbers for modPow and is substantially faster.
- SMIMECapabilities, and SMIMEEncryptionKeyPreference attributes added to S/MIME.
- Increased range of key sizes available in S/MIME.
- getInstance(ASN1TaggedObject, boolean) methods have been added to most ASN1 types. These deal with implicit/explicit tagging ambiguities with constructed types.
- Added EncryptedPrivateKeyInfo object to the clean room JCE.
- A PEMReader has been added for handling some of the openSSL PEM files.
- The X.509 certificate factory supports a wider range of encodings and object identifiers.

### 2.76.1 Version

Release: 1.13
Date: 2002, April 19

### 2.76.2 Defects Fixed

- The TBSCertificate object in the ASN.1 library now properly implements the Time object, rather returning UTC time.
- The DESedeKeyGenerator now supports 112 and 168 bit key generation.
- Certificates with the keyId set to null in the AuthorityKeyIdentifier extensions would sometimes cause the PKCS12 store to throw a NullPointer exception. This has been fixed.
- toByteArray in the big integer class was not always producing correct results for negative numbers. This has been Fixed.

### 2.76.3 Additional Functionality and Features

- The key to keySpec handling of the secret key factories has been improved.
- There is now a SMIME implementation and a more complete CMS implementation (see CONTRIBUTORS file for additonal details).
- A CertPath implementation that runs under jdk1.1 and jdk1.4 has also being contributed. A work around to allow it to be used with jdk1.2 and jdk1.3 has also been added. Note: the implementation is not quite complete because policymapping, name and subtree constraints are not yet implemented.
- The API now supports the generation of PKCS7 signed objects. Note: this is still beta code - one known issue is that it doesn't support single length certificate chains for signing keys.

### 2.77.1 Version

Release: 1.12
Date: 2002, February 8

### 2.77.2 Defects Fixed

- The ASN.1 library was unable to read an empty set object. This has been fixed.
- Returning sets of critical and non-critical extensions on X.509 certificates could result in a null pointer exception if the certificate had no extensions. This has been fixed.
- The BC JKS implementation does not follow the conventional one - it has been renamed BKS, an attempt to create a JKS keystore using the BC provider will now result in an exception.
- The PKCS 10 generator verify(provider) method was ignoring the provider when generating the public key. This has been fixed.
- The PKCS12 store would throw an OutOfMemoryException if passed a non-PKCS12 file. This has been fixed.
- In the case where there was no AuthorityKeyIdentifier the PKCS12 store would fail to find certificates further up the signing chain. The store now uses the IssuerDN if no AuthorityKeyIdentifier is specified and the IssuerDN is different from the SubjectDN,
- PKCS10/CertificationRequestInfo objects with only a single attribute wer not being handled properly. This has been fixed.
- getExtensionValue for X.509 CRLs was returning the value of the DER-Encoded octet string not the DER-Encoded octet string as required. This has been fixed.
- the IV algorithm parameters class would improperly throw an exception on initialisation. This has been fixed.

### 2.77.3 Additional Functionality and Features

- The AESWrap ciphers will now take IV's.
- The DES-EDEWrap algorithm described in https://www.ietf.org/internet-drafts/draft-ietf-smime-key-wrap-01.txt is now supported.
- Support for the ExtendedKeyUsageExtension and the KeyPurposeId has been added.
- The OID based alias for DSA has been added to the JCE provider.
- BC key stores now implement the BCKeyStore interface so you can provide your own source of randomness to a key store.
- The ASN.1 library now supports GeneralizedTime.
- HMACSHA256, HMACSHA384, and HMACSHA512 are now added.
- PSS has been added to the JCE, PSS and ISO9796 signers in the lightweight api have been rewritten so they can be used incrementally. SHA256withRSA, SHA384withRSA, and SHA512withRSA have been added.
- Base support for CMS (RFC 2630) is now provided (see CONTRIBUTORS file for details).

### 2.78.1 Version

Release: 1.11
Date: 2001, December 10

### 2.78.2 Defects Fixed

- X9.23 padding of MACs now works correctly with block size aligned data.
- Loading a corrupted "UBER" key store would occasionally cause the appearance of hanging. This has been fixed.
- Loading a PKCS12 store where not all certificates had PKCS9 attributes assigned to them would cause a NullPointerException. This has been fixed.
- The PKCS12 store wasn't correctly recovering certificate chains of length less than 2 on calling the getCertificateChain method. This has been fixed.
- Lone certificates were not been stored in the PKCS12 store. This has been fixed.
- CFB and OFB modes weren't padding iv's more than 1 byte less than the block size of the cipher if the mode was reused with a shorter IV. This has been fixed.
- IV handling and block size return values for CFB and OFB modes wasn't being handled in the same way as the Sun reference implementation. This has been fixed.
- CertificateInfoRequests were not handling null attributes correctly. This has been fixed.
- Tags for the X.509 GeneralName structure were wrongly encoded. This has been fixed.
- getExtensionValue for X.509 certificates was returning the value of the DER-Encoded octet string not the DER-Encoded octet string as required. This has been fixed.
- reset on the version 3 X.509 certificate generator was not flushing the extensions. This has been fixed.
- The NetscapeCert type bits were reversed! This has been fixed.

### 2.78.3 Additional Functionality and Features

- The lightweight API and the JCE provider now support ElGamal.
- X509Principal, and X509Name now supports the "DC" attribute and the creation of directory names from vectors.
- RSA-PSS signature padding has been added to the lightweight API.
- EC Public/Private keys are now encoded in accordance with SEC 1. The library will still read older keys as well.
- Added PKCS12-DEF a pkcs12 based key store which works around a bug in the Sun keytool - it always uses the default provider for creating certificates.
- A cut down version of the Rijndael has been added that provides the functionality required to conform the the AES. It is designed to fully support FIPS-197. A fips AES wrapper (AESWrap in the JCE, AESWrapEngine in the lightweight library has also been added).
- Elliptic curve routines now handle uncompressed points as well as the compressed ones.

### 2.78.4 Other changes

- As the range of public key types supported has expanded the getPublicKey method on the SubjectPublicKeyInfo class is not always going to work. The more generic method getPublicKeyData has been added and getPublicKey now throws an IOException if there is a problem.

### 2.79.1 Version

Release: 1.10
Date: 2001, October 20

### 2.79.2 Defects Fixed

- The PKCS12 Key Store now interoperates with the JDK key tool. Note: this does mean the the key name passed to the setKeyEntry calls has become significant.
- The "int" constructor for DERInteger only supported ints up to 128. This has been fixed.
- The ASN.1 input streams now handle zero-tagged zero length objects correctly.

### 2.79.3 Additional Functionality and Features

- The JCE Provider and the lightweight API now support Serpent, CAST5, and CAST6.
- The JCE provider and the lightweight API now has an implementation of ECIES. Note: this is based on a draft, don't use it for anything that needs to be kept long term as it may be adjusted.
- Further work has been done on performance - mainly in the symmetric ciphers.
- Support for the generation of PKCS10 certification requests has been added.

### 2.80.1 Version

Release: 1.09
Date: 2001, October 6

### 2.80.2 Defects Fixed

- failure to pass in an RC5 parameters object now results in an exception at the upper level of the JCE, rather than falling over in the lightweight library.
- ISO10126Padding now incorporates the correct amount of random data.
- The PKCS12 key store wasn't picking up certificate chains properly when being used to write PKCS12 files. This has been fixed.
- The Twofish engine would call System.exit if the key was too large. This has been fixed.
- In some cases the ASN.1 library wouldn't handle implicit tagging properly. This has been fixed.

### 2.80.3 Additional Functionality and Features

- Support for RC5-64 has been added to the JCE.
- ISO9796-2 signatures have been added to the JCE and lightweight API.
- A more general paddings packge for use with MACs and block ciphers had been aded to the lightweight API. MACs now allow you to specify padding.
- X9.23 Padding has been added to the JCE and lightwieght API. The old PaddedBlockCipher class is now deprecated see org.bouncycastle.crypto.paddings for details.
- SHA-256, SHA-384, and SHA-512 are now added. Note: while the public review period has finished, these algorithms have not yet been standardised, in the event that final standardisation changes the algorithms these implementations will be changed.
- It's now possible to set bag attributes on items to go into a PKCS12 store, using the org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier interface.
- More classses have been added to the ASN.1 package for dealing with certificate extensions and CRLs including a CRL generator. Note: the CRL generators should be regarded as under development and subject to change.
- There's now an examples package for the JCE (in addition to the examples in org.bouncycastle.jce.provider.test) - org.bouncycastle.jce.examples. It currently consists of a class showing how to generate a PKCS12 file.
- The X.509 CertificateFactory now includes CRL support. DER or PEM CRLs may be processed.
- The BigInteger library has been written with a view to making it less resource hungry and faster - whether it's fast enough remains to be seen!

### 2.81.1 Version

Release: 1.08
Date: 2001, September 9

### 2.81.2 Defects Fixed

- It wasn't possible to specify an ordering for distinguished names in X509 certificates. This is now supported.
- In some circumstances stream Ciphers in the JCE would cause null pointer exceptions on doFinal. This has been fixed.
- Unpadded ciphers would sometimes buffer the last block of input, even if it could be processed. This has been fixed.
- The netscape certificate request class wouldn't compile under JDK 1.1. This has been fixed.

### 2.81.3 Additional Functionality and Features

- ISO 9796-1 padding is now supported with RSA in the lightweight API and the JCE.
- support classes have been added for reading and writing PKCS 12 files, including a keystore for the JCA.
- The message digests MD4, Tiger, and RIPEMD128 have been added to the JCE and the lightweight API. Note: MD4 and RIPEMD128 have been added for compatibility purposes only - we recommend you don't use them for anything new!
- The JDK 1.1 certificate classes didn't conform to the JDK 1.2 API as the collections class was not present. Thanks to a donated collections API this is fixed.

### 2.82.1 Version

Release: 1.07
Date: 2001, July 9

### 2.82.2 Defects Fixed

- It turned out that the setOddParity method in the DESParameter class was indeed doing something odd but not what was intended. This is now fixed. Note:This will affect some PBE encryptions that were carried out with DES, equivalent PBE ciphers to the old PBE DES cipher can be accessed by prepending the work "Broken" in front of the original PBE cipher call. If you want an example of how to deal with this as a migration issue have a look in org.bouncycastle.jce.provider.JDKKeyStore lines 201-291.

### 2.83.1 Version

Release: 1.06
Date: 2001, July 2

### 2.83.2 Defects Fixed

- Diffie-Hellman keys are now properly serialisable as well as encodable.
- Three of the semi-weak keys in the DESParameters, and the DESKeySpec look up table, were incorrect. This has been fixed.
- DESEDE key generators now accept 112 and 168 as the key sizes, as well as 128 and 192 (for those people who don't like to count the parity bits).
- Providing no strength parameter is passed to the DESede key generator in the JCE provider, the provider now generates DESede keys in the k1-k2-k1 format (which is compatible with the Sun reference implementation), otherwise you get what you ask for (3-DES or 2-DES in the minimum number of bytes).
- Base Diffie-Hellman key agreement now works correctly for more than two parties.
- Cipher.getAlgorithmParameters was returing null in cases where a cipher object had generated it's own IV. This has been fixed.
- An error in the key store occasionally caused checks of entry types to result in a null pointer exception. This has been fixed.
- RSA key generator in JCE now recognises RSAKeyGenerationParameterSpec.
- Resetting and resusing HMacs in the lightweight and heavyweight libraries caused a NullPointer exception. This has been fixed.

### 2.83.3 Additional Functionality

- ISO10126Padding is now recognised explicitly for block ciphers as well.
- The Blowfish implementation is now somewhat faster.

### 2.84.1 Version

Release: 1.05
Date: 2001, April 17

### 2.84.2 Defects Fixed

- The DESEDE key generator can now be used to generate 2-Key-DESEDE keys as well as 3-Key-DESEDE keys.
- One of the weak keys in the DESParameters, and the DESKeySpec look up table, was incorrect. This has been fixed.
- The PKCS12 generator was only generating the first 128-160 bits of the key correctly (depending on the digest used). This has been fixed.
- The ASN.1 library was skipping explicitly tagged objects of zero length. This has been fixed.

### 2.84.3 Additional Functionality

- There is now an org.bouncycastle.jce.netscape package which has a class in for dealing with Netscape Certificate Request objects.

### 2.84.4 Additional Notes

Concerning the PKCS12 fix: in a few cases this may cause some backward compatibility issues - if this happens to you, drop us a line at feedback-crypto@bouncycastle.org and we will help you get it sorted out.

### 2.85.1 Version

Release: 1.04
Date: 2001, March 11

### 2.85.2 Defects Fixed

- Signatures generated by other providers that include optional null parameters in the AlgorithmIdentifier are now handled correctly by the provider.
- The JCE 1.2.1 states that the names of algorithms associated with the JCE are case insensitive. The class that matches algorithms to names now tries to match the name given with it's equivalent in upper case, before trying to match it as given. If you write a provider and include versions of your algorithm names in uppercase only, this JCE implementation will always match a getInstance regardless of the case of the algorithm passed into the getInstance method.
- If the JCE API and the Provider were in a different class path, the class loader being used sometimes failed to find classes for JCE Ciphers, etc. This has been fixed.
- An error in the ASN.1 library was causing problems serialising Diffie-Hellman keys. This has been fixed.
- The agreement package was left out of the j2me bat file. This has been fixed.
- The BigInteger class for 1.0 and the j2me wasn't able to generate random integers (prime or otherwise). This has been fixed.
- The BigInteger class would sometimes go into a death spiral if the any 32nd bit of an exponent was set when modPow was called. This has been fixed.
- Cipher.getInstance would treat "//" in a transformation as a single "/". This has been fixed.
- PBEWithSHAAndIDEA-CBC was throwing an exception on initialisation. This has been fixed.
- The X509Name class in the asn1.x509 package wasn't initialising its local hash table when the hash table constructor was called. This has been fixed.

### 2.85.3 Additional Functionality

- Added Elliptic Curve DSA (X9.62) - ECDSA - to provider and lightweight library.
- Added Elliptic Curve basic Diffie-Hellman to provider and lightweight library.
- Added DSA support to the provider and the lightweight library.
- Added super class interfaces for basic Diffie-Hellman agreement classes to lightweight library.
- The certificate generators now support ECDSA and DSA certs as well.

### 2.86.1 Version

Release: 1.03
Date: 2001, January 7

### 2.86.2 Defects Fixed

- CFB and OFB modes when specified without padding would insist on input being block aligned. When specified without padding CFB and OFB now behave in a compatible fashion (a doFinal on a partial block will yield just the data that could be processed). In short, it provides another way of generating cipher text the same length as the plain text.

### 2.87.1 Version

Release: 1.02
Date: 2000, November 7

### 2.87.2 Defects Fixed

- The RSA key pair generator occasionally produced keys 1 bit under the requested size. This is now fixed.

### 2.88.1 Version

Release: 1.01
Date: 2000, October 15

### 2.88.2 Defects Fixed

- Buffered ciphers in lightweight library were not resetting correctly on a doFinal. This has been fixed.

### 2.89.1 Version

Release: 1.00
Date: 2000, October 13

### 2.89.2 Defects Fixed

- JDK1.2 version now works with keytool for certificate generation.
- Certificate toString method no longer throws a null pointer exception if a group [3] extension has not been added.
- Under some circumstances the NullCipher would throw a NullPointerException, this has been fixed.
- Under some circumstances CipherInputStream would throw a NullPointerException, this has been fixed.
- OpenSSL/SSLeay private key encodings would cause an exception to be thrown by the RSA key factory. This is now fixed.
- The Cipher class always used the default provider even when one was specified, this has been fixed.
- Some DES PBE algorithms did not set the parity correctly in generated keys, this has been fixed.

### 2.89.3 Additional functionality

- Argument validation is much improved.
- An X509KeyUsage class has been added to the JCE class to make it easier to specify the KeyUsage extension on X.509 certificates.
- The library now allows creation of version 1 certificates as well.

### 3.0 Notes

The J2ME is only supported under Windows.

If you are trying to use the lightweight provider in a JDK 1.0 applet, you need to change the package names for java.math.BigInteger, java.lang.IllegalStateException, and java.security.SecureRandom

The RSA test under JDK 1.0 and J2ME takes a while to run...