In the scope of the 8.0.0 release, we've introduced several major breaking changes in the way we handle bouncy-castle dependencies. Now we no longer use
org.bouncycastle dependencies directly in our
sign modules. Instead, all the necessary bouncy-castle related classes are grouped into two new modules:
One of these modules is required to be in a classpath for the correct usage of cryptographic and signatures-related logic of our
sign modules, but by default they are not added as a dependency in order to provide the ability to choose one of them from the customer's side.
Basically, this means that in order to use any other iText product (except several products which will be mentioned later) together with cryptographic or signatures-related logic either
bouncy-castle-fips-adapter module shall be added as a dependency. Otherwise, a special log message will be sent.
Android version limitations
Android artifacts directly depend on vanilla BouncyCastle and don't support switching to BouncyCastle FIPS.
The whole idea behind adding the possibility to depend on BouncyCastle-FIPS in iText Core is that this build of Bouncy-Castle is FIPS-certified, i.e. adheres to FIPS standard as confirmed by a certification process.
Status of known vulnerability CVE-2022-45146 for FIPS Java API before 22.214.171.124
The whole idea behind adding the possibility to depend on BouncyCastle-FIPS in iText Core is that this build of Bouncy-Castle is FIPS-certified, i.e. adheres to FIPS standard as confirmed by certification process.
So, there are two reasons why iText Core keeps 126.96.36.199 dependency as the default one:
1) The only available version with the fix, 188.8.131.52, is not FIPS-certified (see https://www.bouncycastle.org/latest_releases.html#184.108.40.206-NONCERT )
2) BC-FIPS 220.127.116.11 is specifically certified against JRE 1.7, JRE 1.8, and JRE 1.11 (see https://www.bouncycastle.org/fips_java_roadmap.html ).
So, the expectation is that a user would want to opt-in to BC-FIPS dependency only with BC-FIPS 18.104.22.168 version and only for java8 or java11, while CVE-2022-45146 is only relevant to java13+.
It's also possible to switch to 22.214.171.124 by explicitly specifying this version in maven pom file.
The inside of bouncy-castle adapters
com.itextpdf:bouncy-castle-adapter maven module encapsulates bouncy-castle related classes for these two maven dependencies:
com.itextpdf:bouncy-castle-fips-adapter maven module encapsulates bouncy-castle related classes for these two maven dependencies:
itext7.bouncy-castle-adapter nuget package encapsulates bouncy-castle related classes for this nuget dependency:
itext7.bouncy-castle-fips-adapter nuget package encapsulates bouncy-castle related classes for these two assemblies (dlls taken from https://www.bouncycastle.org/fips-csharp/):
Since those two dll files are not signed, we can't use them with .NET Framework and therefore the only supported target framework for
bouncy-castle-fips-adapter project is
Ways to specify adapter
The idea of using adapters relies on the fact that only one adapter will be used in order to generate bouncy-castle related wrappers. The choose of adapter happens in separated module
bouncy-castle-connector. If for some reason both
bouncy-castle-fips-adapter dependency added, there are still ways to specify which one need to be used.
First of all, connector modules searches for the special system or environment variable called
ITEXT_BOUNCY_CASTLE_FACTORY_NAME. There are three possible values here:
- "bouncy-castle" - forces connector to first try to use
- "bouncy-castle-fips" - forces connector to first try to use
- anything else - ignored
However, related dependency still shall be added in order to successfully use related module.
Bouncy-castle-fips-adapter module operating modes
Bouncy-castle-fips-adapter module can be operated in two modes:
- General mode
- Approved mode
General mode is enabled by default. There are several ways to enable approved mode.
- Pass "
org.bouncycastle.fips.approved_only=true" VM parameter to your build configuration
- Pass environment or system variable
Ones approved mode is enabled, you can't go back to the general mode. Also this operating mode is thread local, i.e. it needs to be explicitly set per each thread.
Several algorithms are not available in the approved mode (such as
MD5 for example). You will receive a corresponding log message if an algorithm is not FIPS compliant and therefore cannot be used in approved mode.
In the scope of this changes also several public API methods definitions changed. Right now we use special interfaces instead of
org.bouncycastle classes in our API as a parameter or return values. In case when you need to work with such interfaces to either create them from actual
org.bouncycastle values or retrieve actual value, you should access classes from either
bouncy-castle-fips-adapter directly and either call the constructor to create an instance and pass it as a parameter or call the corresponding getter method to retrieve the actual value. Let's take a more precise look at one of the examples.
Let's say you need to create
IX509Certificate interface in order to pass it as a parameter to
PdfSigner#SignDetached method. Assuming you already have
X509Certificate object. Here there are two cases:
- If you are using
bouncy-castle-adapterdependency, then you should create
X509CertificateBCclass (i.e. a class with the same name with
BCpostfix) passing your original
X509Certificateas a parameter to the constructor, and then use this created wrapper as a parameter for
- If you are using
bouncy-castle-fips-adapterdependency, then you should create
X509CertificateBCFipsclass passing your actual
X509Certificateas a parameter, and then use this created wrapper as a parameter for
Correspondingly, if you for example need to retrieve actual
X509Certificate object from either
X509CertificateBCFips, you should call
This workflow is valid for each wrapper from
bouncy-castle-fips-adapter modules, with the respect of names.
Let's take a look at the code.