Bouncy Castle Java Distribution (Mirror)
The Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms, it was developed by the Legion of the Bouncy Castle, a registered Australian Charity, with a little help! The Legion, and the latest goings on with this package, can be found at https://www.bouncycastle.org.
The Legion also gratefully acknowledges the contributions made to this package by others (see here for the current list). If you would like to contribute to our efforts please feel free to get in touch with us or visit our donations page, sponsor some specific work, or purchase a support contract through Crypto Workshop (now part of Keyfactor).
The package is organised so that it contains a light-weight API suitable for use in any environment (including the newly released J2ME) with the additional infrastructure to conform the algorithms to the JCE framework.
Except where otherwise stated, this software is distributed under a license based on the MIT X Consortium license. To view the license, see here. The OpenPGP library also includes a modified BZIP2 library which is licensed under the Apache Software License, Version 2.0.
Note: this source tree is not the FIPS version of the APIs - if you are interested in our FIPS version please contact us directly at [email protected].
The Bouncy Castle artifacts are published to Maven Central under the org.bouncycastle group. Pick the artifacts you need, then add them to your build using the latest released version.
For the lightweight crypto API plus the JCA/JCE provider — the most common starting point — add bcprov-jdk18on:
Maven:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.85.2</version>
</dependency>
Gradle:
implementation 'org.bouncycastle:bcprov-jdk18on:1.85.2'
If you need functionality beyond what bcprov provides, add the appropriate companion artifacts. They all share the same org.bouncycastle group, the same -jdk18on suffix, and the same version — pull each one in the same way as the snippets above:
| Artifact | What it covers |
|---|---|
bcprov-jdk18on |
Lightweight crypto API plus the BC / BCPQC JCA/JCE providers. Required by every other module. |
bcpkix-jdk18on |
X.509 / PKCS#10 / PKCS#12, CMS, S/MIME helpers (top-level only), TSP, OCSP, CMP / CRMF, certificate path validation. |
bcpg-jdk18on |
OpenPGP (RFC 4880 / RFC 9580). |
bctls-jdk18on |
Standalone TLS 1.0 – 1.3 implementation plus the BCJSSE provider. |
bctls-klog-jdk18on |
Drop-in replacement for bctls-jdk18on that reports TLS connection secrets in RFC 9850 (SSLKEYLOGFILE) format for decrypting a test capture in an analyser such as Wireshark. Not for production use — see the package javadoc for why. |
bcmail-jdk18on |
S/MIME built on top of bcpkix, targeting the legacy javax.mail / javax.activation 1.x runtimes. |
bcjmail-jdk18on |
S/MIME for the Jakarta runtimes (jakarta.mail / jakarta.activation 2.x). Pick this for modern Spring Boot / Quarkus / Jakarta EE apps, and use bcmail-jdk18on for the older javax.* stack. |
bcmls-jdk18on |
Messaging Layer Security (RFC 9420). |
bcpgsc-jdk18on |
Adds an API for using OpenPGP keys held on a smart card or hardware token (e.g. a YubiKey) with bcpg's high-level OpenPGP API. |
bcutil-jdk18on |
Shared ASN.1 utility classes used by bcpkix. Pulled in transitively. |
The -jdk18on suffix means "JDK 1.8 and newer." Pre-1.71 releases shipped under a -jdk15on suffix (JDK 1.5 and newer); those artifacts are end-of-life and should not be used for new development. The 15to18 suffix you may see in this repository's local Gradle outputs reflects a transitional build flavour and is not what is published to Maven Central.
The FIPS-certified BC distribution lives in a separate source tree with separate Maven coordinates and a separate licence — it is not what this repository builds. See the BC FIPS page or contact [email protected] for additional details.
The file bc_maven_public_key.asc contains the public key used to sign our artifacts on Maven Central. You will need to use
gpg -o bc_maven_public_key.gpg --dearmor bc_maven_public_key.asc
to dearmor the key before use. Once that is done, a file can be verified by using:
gpg --no-default-keyring --keyring ./bc_maven_public_key.gpg --verify file_name.jar.asc file_name.jar
Note: the ./ is required in front of the key file name to tell gpg to look locally.
Building the project requires JDK 25 or later to drive Gradle — make sure JAVA_HOME (or whatever JVM gradlew picks up) points at a JDK 25+ installation.
If the build script detects BC_JDK8, BC_JDK11, BC_JDK17, BC_JDK21, BC_JDK25 it will add to the usual test task a dependency on test tasks that specifically use the JVMs addressed by those environmental variables.
To run the tests of the project as part of the build test data is needed. Our test data can be found at the bc-test-data repository. The tests locate the bc-test-data tree using, in order:
bc.test.data.home, if set.BC_TEST_DATA_HOME, if set.bc-test-data. The simplest configuration is therefore to check bc-test-data out as a sibling of bc-java and no further setup is required.When the property or environment variable is supplied, the named path is required to exist; a mistyped value fails fast with a FileNotFoundException naming whichever source supplied it, rather than silently falling through to the walk-up.
We support testing on specific JVMs as it is the only way to be certain the library is compatible.
The following environmental variables can optionally point to the JAVA_HOME for each JVM version.
export BC_JDK8=/path/to/java8
export BC_JDK11=/path/to/java11
export BC_JDK17=/path/to/java17
export BC_JDK21=/path/to/java21
export BC_JDK25=/path/to/java25
If your bc-test-data checkout is not a sibling of bc-java, set BC_TEST_DATA_HOME (or pass -Dbc.test.data.home=... on the command line) so the tests can find it:
export BC_TEST_DATA_HOME=/path/to/bc-test-data
The project now uses gradlew which can be invoked for example:
# from the root of the project
# Ensure JAVA_HOME points to JDK 25 or higher JAVA_HOME or that
# gradlew can find a java 25 installation to use.
./gradlew clean build
At startup the gradle script prints which of the BC_JDK environmental variables it found; it does not verify that their values point at working JDK installations.
Each module's built jars are written to its own <module>/build/libs directory (e.g. prov/build/libs/bcprov-jdk18on-<version>.jar). For convenience, a top-level copyJars task gathers the produced jars (main, sources and javadoc) for all published modules (bccore, bcutil, bcprov, bcpkix, bcpg, bctls, bcmls, bcmail, bcjmail) into a single dist directory at the project root:
./gradlew copyJars
A sibling copyMavenJars task produces the same set minus bccore (whose classes are already bundled into bcprov), matching the artifacts published to Maven Central:
./gradlew copyMavenJars
By default the jars are compiled without debug symbols and are named <module>-jdk18on-<version> (e.g. bcprov-jdk18on-<version>.jar). Setting the release.debug project property to true produces a debug build instead: every module's jar, sources jar, javadoc jar and Maven artifactId are labelled <module>-debug-jdk18on-<version> (<module>-debug-jdk15to18-<version> when Gradle is driven by a JDK 8 or earlier daemon), and the classes are compiled with full debug information (-g). This mirrors the release.debug flag the legacy Ant builds read from bc-build.properties.
The property is off by default (release.debug=false in gradle.properties). Enable it for a single invocation on the command line, applying to any build task:
# debug jars in each module's build/libs
./gradlew -Prelease.debug=true clean build
# or gather the full set of debug jars into dist/
./gradlew -Prelease.debug=true clean copyJars
To make it the default for your working copy, set release.debug=true in gradle.properties (or in a personal gradle.properties under your Gradle home) rather than passing -P each time. Because the debug label is carried on the artifact names, a debug build's outputs will not overwrite a normal build's, and vice versa.
The build can produce CycloneDX 1.6 bills of materials describing the release artifacts:
./gradlew generateSbom # -> build/reports/sbom/
./gradlew generateCbom # -> build/reports/cbom/
generateSbom writes a Software Bill of Materials (CycloneDX SBOM) mirroring the published bc-jdk18on-bom Maven BOM: one library component per published module jar, with MD5 / SHA-1 / SHA-256 hashes matching the Maven repository checksum files, the declared external dependencies, and the inter-module dependency graph as it appears in the published poms. Alongside the SBOM itself (bc-jdk18on-bom-<version>-cyclonedx.json) the task copies in the BOM's .pom and Gradle Module Metadata .module files, so the output directory holds the complete publishable set for the BOM artifact. The component set is read from the bom project's platform constraints, so the SBOM and the published Maven BOM stay in lockstep automatically.
generateCbom writes a Cryptographic Bill of Materials (CycloneDX CBOM) for the freshly built bcprov jar by introspecting the JCA service tables of the BC (BouncyCastleProvider) and BCPQC (BouncyCastlePQCProvider) providers: one cryptographic-asset component per algorithm, carrying its primitive classification (block cipher, signature, KEM, hash, MAC, KDF, DRBG, ...), the crypto functions it provides, and its OID(s), plus a provides dependency edge from the bcprov library component to every asset. The public lightweight API (org.bouncycastle.crypto.*, bundled in the same jar) is swept as well, so algorithms that ship with no JCA registration — J-PAKE, SRP-6a, OWL, HPKE, BLS12-381, Ascon-AEAD128 and the other NIST lightweight-cryptography algorithms, RSA-KEM, ECCSI/SAKKE, the SP800-90A DRBGs, KDF1/KDF2, and more — are inventoried too; each asset's bc:api property records whether it is reachable through the JCA (jca) or only through the lightweight API (lightweight), and lightweight assets name their defining classes in bc:classes. The output is build/reports/cbom/bcprov-jdk18on-<version>-cyclonedx.json.
Both BOMs are reproducible: the serial number is a name-based UUID derived from the artifact coordinates, and the timestamp is taken from the ```SOURCE_DATE_EPOCH`
No open issues yet, or sync has not completed.