> ## Documentation Index
> Fetch the complete documentation index at: https://docs.minimus.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Java FIPS Validated Module

> Understand how Minimus implements the FIPS 140-3 validated Java module in its images including OpenJDK, OpenJRE, and Amazon-Corretto

## What FIPS means for Java

FIPS (Federal Information Processing Standards) 140-3 is a federal cryptography compliance framework. FIPS validated cryptography is required by FedRAMP and is mandatory for non-military federal government agencies, contractors, and vendors. Validation is regulated by the NIST Cryptographic Module Validation Program (CMVP), which certifies cryptographic modules that meet FIPS 140-3 security standards.

Standard OpenJDK ships with built-in cryptographic providers (`SunJCE`, `SunJSSE`, `SunRsaSign`, `SunEC`) that have not been through the CMVP validation process. To be FIPS-compliant, every cryptographic operation (encryption, hashing, key generation, TLS) must go through a CMVP-certified provider.

### FIPS 140-3 certificate

Minimus Java FIPS images use the **Minimus Cryptographic Module for Java** module, validated under [CMVP **certificate #5142**](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/5142). This certificate covers the CCJ Provider and defines the approved algorithms, operational environments, and hardware requirements under which the module is validated.

## Available Java FIPS images

Minimus provides the following Java FIPS validated images:

| **Image**                               | **Base**        | Description                       | **Use**                 |
| --------------------------------------- | --------------- | --------------------------------- | ----------------------- |
| `reg.mini.dev/openjdk-fips`             | Eclipse Temurin | OpenJDK Development Kit (JDK)     | Build and compile stage |
| `reg.mini.dev/openjre-fips`             | Eclipse Temurin | OpenJDK Runtime Environment (JRE) | Production runtime      |
| `reg.mini.dev/amazon-corretto-jdk-fips` | Amazon Corretto | Amazon Corretto JDK               | Build and compile stage |
| `reg.mini.dev/amazon-corretto-jre-fips` | Amazon Corretto | Amazon Corretto JRE               | Production runtime      |

## Supported Java versions

Supported Java versions: **25, 21, 17, 11**. Java 24 has reached end-of-life.

## Cryptographic providers

Minimus Java FIPS images are configured with the following security providers, in priority order:

| **Position** | **Provider**                                         | **Role**                                                               |
| ------------ | ---------------------------------------------------- | ---------------------------------------------------------------------- |
| 1            | SafeLogic CryptoComply (CCJ)                         | Primary FIPS 140-3 validated provider for all cryptographic operations |
| 2            | Bouncy Castle JSSE (BCJSSE)                          | FIPS-compliant TLS/SSL — delegates all crypto to CCJ                   |
| 3            | SUN                                                  | Loaded at lowest priority for CCJ JAR signature validation only        |
| 4+           | SunJGSS, SunSASL, XMLDSig, SunPCSC, JdkLDAP, JdkSASL | Infrastructure providers delegate crypto operations to CCJ/BCJSSE      |

The following providers are explicitly removed from the image and are not available at runtime: `SunRsaSign`, `SunEC`, `SunJCE`, `SunJSSE`.

### FIPS 140-3 libraries

The CryptoComply and SafeLogic Bouncy Castle jars are located at `/usr/share/fips-libs/` inside the image:

| **JAR**               | **Purpose**                                      |
| --------------------- | ------------------------------------------------ |
| `ccj-4.0.0-fips.jar`  | SafeLogic CryptoComply FIPS 140-3 provider (CCJ) |
| `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                  |

### What FIPS blocks at runtime

FIPS approved-only mode (`com.safelogic.cryptocomply.fips.approved_only=true`) enforces a hard algorithm blocklist. Your application will throw a `NoSuchAlgorithmException` or `GeneralSecurityException` at runtime, not at compile time if it calls any of the following:

| **Blocked**                     | **FIPS-approved replacement**        |
| ------------------------------- | ------------------------------------ |
| MD5 (for any security purpose)  | SHA-256 or SHA-3                     |
| SHA-1 signatures                | SHA-256 or stronger                  |
| DES / 3DES                      | AES-128 or AES-256                   |
| RC4                             | AES-GCM                              |
| TLS 1.0 / TLS 1.1               | TLS 1.2 or TLS 1.3                   |
| RSA or DH keys under 2048 bits  | RSA-2048 minimum, RSA-3072 preferred |
| PKCS#12 for private key storage | BCFKS keystore format                |

Audit your codebase to search for string literals like "MD5", "SHA1", "DES", "RC4", "TLSv1", and "PKCS12" in any `getInstance()` or `KeyStore.getInstance()` calls.

## Security configuration

The images enforce FIPS 140-3 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:
  ```text theme={null}
  --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:

1. **Java version** - Confirms that the correct Java version is installed
2. **FIPS provider availability** - Verifies that SafeLogic CryptoComply and Bouncy Castle JSSE providers are loaded
3. **Provider priority** - Ensures providers are in the correct order (CCJ at position 1, BCJSSE at position 2)
4. **FIPS-approved algorithms** - Tests that FIPS-approved algorithms (AES, SHA-256, RSA) are available
5. **Non-FIPS algorithm blocking** - Confirms non-FIPS algorithms (e.g., MD5) are correctly blocked

### Basic verification

```bash theme={null}
# 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`:

```java TestFIPS.java expandable theme={null}
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:

```bash theme={null}
docker run --rm -v $(pwd):/home/build minimus/openjdk-fips:21 sh -c \
  "javac TestFIPS.java && java TestFIPS"
```

Expected output:

```bash theme={null}
=== 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](/advanced-guides/java-fips-hardware)
