packaged by Chainguard
Contact our team to test out this image for free. Please also indicate any other images you would like to evaluate.
Minimal Adoptium JDK image whose FIPS cryptography comes from the OpenSSL-backed Jipher JCE provider. Used for compiling Java applications.
Chainguard Containers are regularly-updated, secure-by-default container images.
For those with access, this container image is available on cgr.dev:
Be sure to replace the ORGANIZATION placeholder with the name used for your organization's private repository within the Chainguard Registry.
adoptium-jdk-openssl-fips is a variant of cgr.dev/ORGANIZATION/adoptium-jdk
that gets its FIPS cryptography from Jipher, an OpenSSL-backed JCE provider,
instead of from BouncyCastle FIPS as adoptium-jdk-fips does. Jipher
is compiled into the Adoptium JDK (jlinked) and delegates cryptography
to the system Chainguard FIPS Provider for OpenSSL.
It is the Adoptium counterpart of cgr.dev/ORGANIZATION/jdk-openssl-fips,
and Java 25 and newer streams are available.
Unlike the BouncyCastle FIPS based adoptium-jdk-fips, this image needs
no FIPS-specific configuration: the hardened Jipher provider is the JDK
default, so there is no module path, no classpath, and no environment variable
to set. Build and run Java code exactly as you would with the non-FIPS
cgr.dev/ORGANIZATION/adoptium-jdk image.
java -jar works as-is here, whereas on adoptium-jdk-fips it needs an
explicit --module-path for the BouncyCastle libraries.
The following tables enumerate every JCA service, algorithm alias, and TLS default that each image actually installs, on the same Java base:
| Column | Image | FIPS provider |
|---|---|---|
SUN |
| none (upstream OpenJDK SUN providers) |
BC-FIPS |
| BouncyCastle FIPS ( |
Chainguard OpenSSL |
| Jipher over OpenSSL ( |
Marker meanings:
NoSuchAlgorithmException.| Feature | SUN | BC-FIPS | Chainguard OpenSSL |
|---|---|---|---|
FIPS validation | 🚫 none | ✅ CMVP | ✅ CMVP |
CVEs in the crypto module | ✅ none known | ⚠️ known CVEs | ✅ none known |
Entropy source | 🚫 kernel entropy | ✅ ESV | ✅ ESV |
Default truststore format | JKS | JKS | JKS |
Default keystore format | ⚠️ PKCS#12 legacy PBE | ⚠️ BCFKS | ✅ PKCS#12 PBMAC1 |
PBKDF2 minimum password length | ⚠️ 1 | ⚠️ 14 | ✅ 8 |
Post-quantum algorithms | ✅ ML-KEM and ML-DSA | 🚫 not available | ✅ ML-KEM and ML-DSA |
Non-approved algorithms | ⚠️ reachable | ⚠️ reachable | ✅ compat non-security digests only |
All three images share the same truststore: the java-cacerts package installs
a JKS cacerts at /etc/ssl/certs/java/cacerts, extracted from the system
truststore, and all three symlink $JAVA_HOME/lib/security/cacerts at it.
The keystore difference is the one most likely to show up in practice. Stock
Adoptium writes PKCS#12 keystores MAC'd with HmacPBESHA256, which is the
legacy PKCS#12 v1 KDF and not FIPS-approved. adoptium-jdk-openssl-fips sets
keystore.pkcs12.macAlgorithm=PBEWithHmacSHA256, which selects PBMAC1 —
Mac.HmacSHA256 over SecretKeyFactory.PBKDF2WithHmacSHA256, both from
Jipher. So keystores stay in the standard, interoperable PKCS#12 container,
unlike adoptium-jdk-fips, which needs them converted to BCFKS.
CVE counts are point-in-time; the per-tag view in the Chainguard Containers Directory is authoritative. The durable difference is revalidation: a fix to a validated module normally invalidates its certificate, so the BC-FJA jars carry their known issues, whereas the Chainguard OpenSSL FIPS provider is revalidated as it is patched.
The BC-FIPS image also installs the OpenSSL FIPS provider for its native, non-Java consumers; the FIPS validation row in the preceding table covers its Java cryptography.
Service counts are the algorithms each provider registers, in provider
precedence order. The first provider that offers an algorithm is the one that
serves an unqualified getInstance() call.
| Provider | SUN | BC-FIPS | Chainguard OpenSSL |
|---|---|---|---|
| 🚫 | 🚫 | ✅ 1st — 151 services |
| 🚫 | ✅ 1st — 560 services | 🚫 |
| 🚫 | ✅ 2nd — 9 services | 🚫 |
| 🚫 | ✅ 3rd — 0 services | 🚫 |
| ✅ 1st — 68 services | ⚠️ loadable | ✅ 2nd — 12 services |
| ✅ 19 services | ⚠️ loadable | ✅ 0 services |
| ✅ 42 services | ⚠️ loadable | ✅ 0 services |
| ✅ 195 services | ⚠️ loadable | ✅ 0 services |
| ✅ 15 services | ⚠️ loadable | ✅ 12 services |
| ✅ | ✅ | ✅ |
| ✅ 8 services | ✅ 8 services | ✅ 2 services |
The two FIPS stacks take opposite approaches to the JDK's own crypto providers.
The BC-FIPS stack unregisters rather than removes them: SUN,
SunRsaSign, SunEC, SunJCE, and SunJSSE are absent from the default
provider list, but the implementations are still in the runtime, so an
application can put any of them back using, for example,
Security.addProvider(), Security.insertProviderAt(), or its own
java.security overrides. That is what the ⚠️ marks: nothing in the image
prevents a non-validated RSA, EC, or AES implementation from being reinstated,
ahead of BouncyCastle if inserted at position 1, which takes the application
outside the FIPS boundary.
The Chainguard OpenSSL stack closes that door twice over. The Sun providers are
still on the list, but register no algorithms at all — the image empties
out SunRsaSign, SunEC, and SunJCE, so re-registering one gains nothing.
SUN keeps only PKI plumbing (X.509, PKIX, keystores, and JAAS config) plus
the MD5 and SHA-1 digests, and SunJSSE keeps the TLS engine, which calls into
Jipher for every primitive.
Separately, the image restricts provider installation to providers whose class
comes from a module baked into the runtime image: the runtime refuses an
application-supplied provider — a class-path jar, an application module, or a
class from a custom loader — with a SecurityException, at both the
Security.insertProviderAt() path and the configured security.provider.N
path. The check is on where the class came from, not what it is called, so
shading or renaming cannot sidestep it.
| Algorithm | SUN | BC-FIPS | Chainguard OpenSSL |
|---|---|---|---|
SHA-1 (non-security) | ✅ | ✅ | ✅ |
SHA-1 (security) | ⚠️ | ⚠️ | 🚫 |
SHA-2 | ✅ | ✅ | ✅ |
SHA-3 | ✅ | ✅ | ✅ |
MD5 (non-security) | ✅ | ✅ | ✅ |
MD2 | ⚠️ | 🚫 | 🚫 |
HMAC-SHA1 | ✅ | ✅ | 🚫 |
HMAC-SHA2 | ✅ | ✅ | ✅ |
HMAC-MD5 | ⚠️ | 🚫 | 🚫 |
Raw MD5 and SHA-1 digests stay reachable in all three for legacy,
non-security uses such as checksums, which FIPS 140-3 I.G. 2.4.A permits. For
more information, refer to
non-approved algorithms.
What matters is their use in HMAC and signatures, and there the three diverge:
both FIPS images drop HMAC-MD5 and MD5 signatures, and adoptium-jdk-openssl-fips goes
further by turning SHA-1 digest signatures off entirely, alongside 3DES and
DSA. Jipher still registers a SHA1withECDSA service name, but disables the
capability behind it, so it refuses the signature. Stock Adoptium and
adoptium-jdk-openssl-fips separately disable SHA-1 handshake signatures in TLS, via
the rsa_pkcs1_sha1, ecdsa_sha1, and dsa_sha1 usage HandshakeSignature
entries in jdk.tls.disabledAlgorithms; the BC-FIPS list carries no equivalent
entry.
| Algorithm | SUN | BC-FIPS | Chainguard OpenSSL |
|---|---|---|---|
AES (ECB, CBC, CFB, OFB) | ✅ | ✅ | ✅ |
AES-GCM | ✅ | ✅ | ✅ |
AES-CCM | 🚫 | ✅ | 🚫 |
AES key wrap (KW, KWP) | ✅ | ✅ | ✅ |
ChaCha20-Poly1305 | ✅ | 🚫 | 🚫 |
Triple DES (3DES / DESede) | ⚠️ | ⚠️ | 🚫 |
DES, RC2, RC4/ARCFOUR, Blowfish | ⚠️ | 🚫 | 🚫 |
PBES2 ciphers ( | ✅ | 🚫 | ✅ |
| Algorithm | SUN | BC-FIPS | Chainguard OpenSSL |
|---|---|---|---|
RSA keys | ✅ | ✅ | ✅ |
RSA-OAEP encryption | ✅ | ✅ | ✅ |
RSA PKCS#1 v1.5 encryption | ⚠️ | ⚠️ | 🚫 |
RSA signatures with SHA-2 | ✅ | ✅ | ✅ |
RSA signatures with SHA-3 | ✅ | ✅ | 🚫 |
RSASSA-PSS | ✅ | ✅ | ✅ |
RSA signatures with SHA-1 | ⚠️ | ⚠️ | 🚫 |
RSA signatures with MD5 | ⚠️ | 🚫 | 🚫 |
ECDSA with SHA-2 | ✅ | ✅ | ✅ |
ECDSA with SHA-1 | ⚠️ | ⚠️ | 🚫 |
ECDSA with SHA-3 | ✅ | ✅ | 🚫 |
DSA | ⚠️ | ⚠️ | 🚫 |
EdDSA (Ed25519, Ed448) | ✅ | ✅ | ✅ |
ML-DSA (FIPS 204) | ✅ | 🚫 | ✅ |
LMS / HSS hash-based signatures | ✅ |