Overview
Minimus provides FIPS 140-3 validated Java images that enable cryptographic operations compliant with Federal Information Processing Standards. These images are configured with FIPS-validated cryptographic providers and enforce strict FIPS compliance at runtime.
Available Java FIPS 140-3 images
Minimus offers 4 Java FIPS 140-3 image types:
openjdk-fips - OpenJDK Development Kit (JDK) with FIPS support
openjre-fips - OpenJDK Runtime Environment (JRE) with FIPS support
amazon-corretto-jdk-fips - Amazon Corretto JDK with FIPS support
amazon-corretto-jre-fips - Amazon Corretto JRE with FIPS support
The OpenJDK FIPS images are based on eclipse-temurin (Eclipse Temurin). The Amazon Corretto FIPS images are based on amazoncorretto (Amazon Corretto).
Supported Java versions
Java FIPS images support active Java versions:
- Java 25
- Java 24 (Reached EOL)
- Java 21
- Java 17
- Java 11
FIPS 140-3 configuration
Cryptographic providers
Java FIPS 140-3 images are configured with the following security providers (ordered by priority):
- SafeLogic CryptoComply FIPS Provider (CCJ) - Primary FIPS 140-3 validated provider
- Bouncy Castle JSSE Provider - FIPS-compliant TLS/SSL provider that delegates to CCJ
- Sun Provider - Loaded at low priority (required for CCJ JAR signature validation only)
- Infrastructure Providers - SunJGSS, SunSASL, XMLDSig, SunPCSC, JdkLDAP, JdkSASL (delegate crypto operations to CCJ/BCJSSE)
FIPS 140-3 libraries
The images include the following FIPS-validated libraries in /usr/share/fips-libs/:
ccj-4.0.0-fips.jar - SafeLogic CryptoComply FIPS 140-3 provider
sl-bcutil-2.0.3.jar - SafeLogic Bouncy Castle utilities
sl-bctls-2.0.21.jar - SafeLogic Bouncy Castle TLS/SSL (JSSE)
sl-bcpkix-2.0.8.jar - SafeLogic Bouncy Castle PKIX/X.509
sl-bcmail-2.0.5.jar - SafeLogic Bouncy Castle S/MIME
sl-bcpg-2.0.12.jar - SafeLogic Bouncy Castle OpenPGP
Security configuration
The images enforce FIPS compliance through:
- Approved-only mode:
com.safelogic.cryptocomply.fips.approved_only=true
- Non-FIPS providers disabled: SunRsaSign, SunEC, SunJCE, and SunJSSE are omitted
- FIPS-approved algorithms only: Non-FIPS algorithms are blocked (e.g., MD5)
- BCFKS keystore type: Required for private keys (Bouncy Castle FIPS KeyStore is a FIPS-compliant keystore format)
- Trust store types: JKS, PKCS12, and BCFKS supported for truststores
Environment variables
Minimus Java FIPS images set the following environment variables by default:
-
JAVA_HOME: Points to the default JVM installation
-
CLASSPATH: Includes FIPS libraries from /usr/share/fips-libs/*
-
JAVA_FIPS_CLASSPATH: Explicit FIPS classpath reference
-
JDK_JAVA_OPTIONS: Includes the required exports and FIPS trust store configuration:
--add-exports=java.base/sun.security.internal.spec=ALL-UNNAMED
--add-exports=java.base/sun.security.provider=ALL-UNNAMED
-Djavax.net.ssl.trustStoreType=FIPS
Verifying the Java FIPS 140-3 module
Each Java FIPS image includes automated tests that verify:
- Java version - Confirms that the correct Java version is installed
- FIPS provider availability - Verifies that SafeLogic CryptoComply and Bouncy Castle JSSE providers are loaded
- Provider priority - Ensures providers are in the correct order (CCJ at position 1, BCJSSE at position 2)
- FIPS-approved algorithms - Tests that FIPS-approved algorithms (AES, SHA-256, RSA) are available
- Non-FIPS algorithm blocking - Confirms non-FIPS algorithms (e.g., MD5) are correctly blocked
Basic verification
# Run a Java application with FIPS compliance
docker run --rm reg.mini.dev/openjdk-fips:21 java -version
# Compile and run Java code
docker run --rm -v $(pwd):/home/build reg.mini.dev/openjdk-fips:21 \
javac MyApp.java && java MyApp
FIPS compliance test
You can verify FIPS compliance by creating a test program. For example, save the following code as the file TestFIPS.java:
import java.security.Provider;
import java.security.Security;
public class TestFIPS {
public static void main(String[] args) {
System.out.println("=== FIPS Compliance Test ===");
// Check that FIPS approved only mode is enabled
String approvedOnly = Security.getProperty("com.safelogic.cryptocomply.fips.approved_only");
boolean isApprovedOnly = approvedOnly != null && approvedOnly.equals("true");
if (!isApprovedOnly) {
System.err.println("[ERROR] SafeLogic CryptoComply FIPS Approved Only Mode is disabled!");
System.exit(1);
}
// Check that providers are loaded
Provider[] providers = Security.getProviders();
boolean foundCryptoComply = false;
boolean foundBCJSSE = false;
int cryptoComplyPosition = -1;
int bcjssePosition = -1;
for (int i = 0; i < providers.length; i++) {
Provider provider = providers[i];
String name = provider.getName();
if (name.contains("CCJ") || name.contains("CryptoComply")) {
foundCryptoComply = true;
cryptoComplyPosition = i + 1;
System.out.println("[OK] SafeLogic CryptoComply provider found at position " + cryptoComplyPosition);
}
if (name.contains("BouncyCastleJsse") || name.contains("BCJSSE")) {
foundBCJSSE = true;
bcjssePosition = i + 1;
System.out.println("[OK] Bouncy Castle JSSE provider found at position " + bcjssePosition);
}
}
if (!foundCryptoComply) {
System.err.println("[ERROR] SafeLogic CryptoComply provider NOT found!");
System.exit(1);
}
if (!foundBCJSSE) {
System.err.println("[ERROR] Bouncy Castle JSSE provider NOT found!");
System.exit(1);
}
// Check provider positions
if (cryptoComplyPosition != 1) {
System.err.println("[WARNING] SafeLogic CryptoComply provider is at position " + cryptoComplyPosition + ", expected position 1");
} else {
System.out.println("[OK] SafeLogic CryptoComply provider is at correct position (1)");
}
if (bcjssePosition != 2) {
System.err.println("[WARNING] Bouncy Castle JSSE provider is at position " + bcjssePosition + ", expected position 2");
} else {
System.out.println("[OK] Bouncy Castle JSSE provider is at correct position (2)");
}
// Test FIPS-approved algorithms
try {
// Test AES (FIPS-approved)
javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding", "CCJ");
System.out.println("[OK] AES algorithm available");
// Test SHA-256 (FIPS-approved)
java.security.MessageDigest.getInstance("SHA-256", "CCJ");
System.out.println("[OK] SHA-256 algorithm available");
// Test RSA (FIPS-approved)
java.security.KeyPairGenerator.getInstance("RSA", "CCJ");
System.out.println("[OK] RSA algorithm available");
// Test that MD5 is correctly blocked (non-FIPS)
try {
java.security.MessageDigest md5 = java.security.MessageDigest.getInstance("MD5", "CCJ");
System.err.println("[ERROR] MD5 is available (provider: " + md5.getProvider().getName() + ")");
System.err.println("[ERROR] FIPS mode is not fully enforced - MD5 should be blocked!");
System.exit(1);
} catch (Exception e) {
System.out.println("[OK] MD5 correctly blocked by FIPS compliance: " + e.getMessage());
}
System.out.println("=== FIPS Compliance Test PASSED ===");
} catch (Exception e) {
System.err.println("[ERROR] FIPS algorithm test failed: " + e.getMessage());
e.printStackTrace();
System.exit(1);
}
}
}
Compile and run the FIPS test:
docker run --rm -v $(pwd):/home/build minimus/openjdk-fips:21 sh -c \
"javac TestFIPS.java && java TestFIPS"
Expected output:
=== FIPS Compliance Test ===
[OK] SafeLogic CryptoComply provider found at position 1
[OK] Bouncy Castle JSSE provider found at position 2
[OK] SafeLogic CryptoComply provider is at correct position (1)
[OK] Bouncy Castle JSSE provider is at correct position (2)
[OK] AES algorithm available
[OK] SHA-256 algorithm available
[OK] RSA algorithm available
[OK] MD5 correctly blocked by FIPS compliance: ...
=== FIPS Compliance Test PASSED ===
Notes
- FIPS compliance is enforced at runtime via Java security configurations
- Applications must use FIPS-approved algorithms and keystore formats (BCFKS)
- The Sun provider is included only for JAR signature validation and does not perform cryptographic operations
- All cryptographic operations are routed through FIPS-validated providers (CCJ and BCJSSE)
- The Java FIPS module requires specialized hardware. Learn more
Last modified on January 28, 2026