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.
Minimus Java FIPS images use the Minimus Cryptographic Module for Java module, validated under CMVP certificate #5142. This certificate covers the CCJ Provider and defines the approved algorithms, operational environments, and hardware requirements under which the module is validated.
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.
# Run a Java application with FIPS compliancedocker run --rm reg.mini.dev/openjdk-fips:21 java -version# Compile and run Java codedocker run --rm -v $(pwd):/home/build reg.mini.dev/openjdk-fips:21 \ javac MyApp.java && java MyApp
You can verify FIPS compliance by creating a test program. For example, save the following code as the file TestFIPS.java:
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 ===