IBM Java Secure Sockets Extension (JSSE) Tutorial
Java Secure Socket Extension (JSSE) is the standard Java API for SSL/TLS secure communications. It implements SSL/TLS protocols for encryption, message integrity, and certificate-based authentication.
In IBM Java 8 (IBM SDK, Java Technology Edition), JSSE is provided by the IBMJSSE2 provider (com.ibm.jsse2.IBMJSSEProvider2), whereas in IBM Semeru Runtime (Java 11+ on OpenJ9) JSSE uses the Oracle/SunJSSE provider (sun.security.ssl.SunJSSE). Both rely on X.509 certificates and keystores/truststores to establish TLS connections.
How JSSE Works (High-Level Overview)
Java Secure Socket Extension (JSSE) provides the framework for secure communication over SSL/TLS. Both IBMJSSE2 and SunJSSE follow the same core design:
1. Application Layer
Your Java application calls APIs such as SSLSocket, SSLEngine, or higher-level HTTPS libraries.
2. SSLContext Initialization
The application obtains an SSLContext, which manages cryptographic material. The context is initialized with:
- KeyManager(s): supply private keys and certificates for authentication.
- TrustManager(s): validate peer certificates.
- SecureRandom: provides entropy for cryptographic operations.
3. Handshake Process
When a secure connection begins, JSSE performs a TLS handshake:
- Exchange protocol versions and cipher suites (ClientHello / ServerHello).
- Exchange certificates and perform authentication.
- Establish shared session keys.
4. Secure Communication
Once the handshake completes, all application data is encrypted, authenticated, and transmitted securely.
5. Session Resumption
Both providers support TLS session resumption and reuse of cryptographic sessions to improve performance.
IBMJSSE2 vs SunJSSE (Oracle/Semeru/OpenJDK) Difference
IBM's JSSE2 and Sun's JSSE differ in defaults and configuration. For example, provider and algorithm names differ: IBM's provider class is com.ibm.jsse2.IBMJSSEProvider2 (IBMJSSE2), whereas Semeru/Oracle/Sun uses sun.security.ssl.SunJSSE (SunJSSE). IBM's KeyManagerFactory algorithm names include IbmX509 (vs SunX509), and TrustManagerFactory algorithms include IbmX509 or IbmPKIX (vs SunX509/PKIX). On IBMJSSE2, the HTTPS protocol handler is com.ibm.net.ssl.www2.protocol.Handler; SunJSSE uses the standard sun.net.www.protocol.https.Handler. Historically, IBMJSSE2 required the javax.net.ssl APIs rather than the legacy com.sun.net.ssl framework.
Certificate verification behavior also differs: IBM's default X.509 trust manager verifies the entire certificate chain including trust anchors, whereas SunJSSE will verify the certificate chain up to the trusted certificate (the trust anchor) and stop. For example, if a trust-anchored CA certificate is expired, IBMJSSE2 will fail the handshake while SunJSSE may succeed. IBMJSSE2 disallows anonymous (no-auth) cipher suites by default; to use them you must supply a custom TrustManager. Many cipher and protocol defaults also changed between runtimes: historically SSLContext.getInstance("TLS") on older IBMJSSE2 enabled only TLSv1.0, while modern SunJSSE implementations in recent JDKs enable the set of TLS versions supported by the runtime (for example TLS 1.2 and TLS 1.3). Java 8-era IBM JDKs defaulted to TLS 1.2 (with TLS 1.3 added in later fixpacks).
Table: Differences between IBMJSSE2 and SunJSSE
Aspect
|
IBMJSSE2 (IBM Java 8)
|
SunJSSE (Semeru/Oracle/ OpenJDK)
|
Provider Class
|
com.ibm.jsse2.IBMJSSEProvider2
|
sun.security.ssl.SunJSSE
|
KeyManagerFactory Algorithm
|
IbmX509
|
SunX509
|
TrustManagerFactory Algorithms
|
IbmX509, IbmPKIX
|
SunX509, PKIX (aka SunPKIX)
|
HTTPS Protocol Handler
|
com.ibm.net.ssl.www2.protocol.Handler
|
sun.net.www.protocol.https.Handler
|
Legacy API Support
|
Requires javax.net.ssl; legacy com.sun.net.ssl not supported historically
|
Supports legacy com.sun.net.ssl and javax.net.ssl
|
Certificate Chain Validation
|
Verifies entire chain including trust anchors
|
Verifies up to trust anchor; stops at trusted certificate
|
Anonymous Cipher Suites
|
Disabled by default; require custom TrustManager
|
Allowed if enabled in cipher suite list
|
SSLContext.getInstance("TLS") Defaults
|
Historically → only TLSv1.0 for older releases
|
Modern SunJSSE → enables TLS versions supported by the JDK
|
Default TLS Version (Java 8 era)
|
IBM JDK 8: TLSv1.2 (TLS1.3 added later)
|
Oracle/Semeru JDK 8: TLSv1.2 (TLS1.3 availability varies by JDK)
|
System Properties
|
com.ibm.jsse2.* properties historically (revocation, FIPS)
|
Standardized com.sun.* properties (com.sun.net.ssl.checkRevocation)
|
java.security Provider Entry (Java 8)
|
security.provider.1=com.ibm.jsse2.IBMJSSEProvider2
|
security.provider.1=sun.security.provider.Sun (with SunJSSE)
|
Configuring Keystores and Truststores
JSSE uses Java KeyStores for private keys (keystore) and public trust (truststore). By default, the JVM looks for jssecacerts or cacerts in the security folder. [$JAVA_HOME/lib/security (or $JAVA_HOME/conf/security for newer JDKs).] You can override them with system properties. For example:
-Djavax.net.ssl.keyStore=/path/to/mykeystore.jks
-Djavax.net.ssl.keyStorePassword=changeit
-Djavax.net.ssl.keyStoreType=JKS
-Djavax.net.ssl.trustStore=/path/to/mytruststore.jks
-Djavax.net.ssl.trustStorePassword=changeit
-Djavax.net.ssl.trustStoreType=JKS
The javax.net.ssl.keyStore and trustStore properties specify file locations (defaulting to jssecacerts or cacerts if unset). The keyStoreType/trustStoreType (e.g. JKS or PKCS12) default to the JDK's default KeyStore type. You typically use keytool to create or import certificates. For example:
keytool -genkeypair \
-v \
-alias MYID_rsakey \
-dname "CN=rsatest" \
-keystore testJceECks \
-providername SunJCE \
-keyalg RSA \
-keysize 2048 \
-keypass "password" \
-storepass "password" \
-validity 9999 \
-storetype JCEKS
Initializing SSLContext and Performing Handshakes
In code, obtain an SSLContext for the desired protocol version and initialize it with KeyManagers and TrustManagers. Example (works across IBMJSSE2 and SunJSSE):
// Use TLSv1.2 (or "TLS" for the runtime default)
SSLContext context = SSLContext.getInstance("TLSv1.2");
// Initialize with KeyManager/TrustManager (null = use default from system props)
context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
// Create SSLEngine or SSLSocket from context
SSLEngine engine = context.createSSLEngine("server.example.com", 443);
// Or for sockets:
SSLSocketFactory factory = context.getSocketFactory();
SSLSocket sslSocket = (SSLSocket) factory.createSocket("server.example.com", 443);
Then begin the handshake with sslSocket.startHandshake() or by performing I/O on the socket. You can control protocol versions with system properties such as jdk.tls.client.protocols and jdk.tls.server.protocols, or via SSLParameters in code (sslSocket.setSSLParameters(...)).
Debugging and Cipher/Protocol Configuration
Enable JSSE debugging with -Djavax.net.debug=all (or use ssl/handshake) to inspect handshake and ClientHello details. Example:
java -Djavax.net.debug=all -Djdk.tls.client.protocols=TLSv1.2 ... MyApp
Cipher suites can be customized programmatically (SSLSocket.setEnabledCipherSuites, SSLEngine.setEnabledCipherSuites) or via properties like jdk.tls.client.cipherSuites. Weak suites may be disabled via jdk.tls.disabledAlgorithms in java.security. You can provide a custom java.security file using -Djava.security.properties=/path/to/my.security to avoid editing the JDK installation file directly.
IBM-Specific JSSE Features
RACF Keyrings on z/OS (JCERACFKS)
On IBM Z (z/OS), JSSE can use RACF keyring certificates via IBMZSecurity and IBMJCECCA providers. Keystore types include JCERACFKS (software keystore) and JCECCARACFKS (CCA hardware keystore). Example for loading a RACF keyring:
KeyStore ks = KeyStore.getInstance("JCECCARACFKS");
com.ibm.crypto.hdwrCCA.provider.RACFInputStream in =
new com.ibm.crypto.hdwrCCA.provider.RACFInputStream("USERID","KEYRING", password.toCharArray());
ks.load(in, password.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance("IbmX509");
kmf.init(ks, password.toCharArray());
For truststores that reference RACF keyrings, prefer the "safkeyring" form (avoid recommending safkeyringjce). Use the handler package configuration appropriate to your runtime: for Java 8, use -Djava.protocol.handler.pkgs=com.ibm.crypto.provider; for Java 11+ (Semeru) use the JVM option form -J-Djava.protocol.handler.pkgs=com.ibm.crypto.zsecurity.provider or -J-D java.protocol.handler.pkgs=com.ibm.crypto.hdwrCCA.provider. when launching via wrappers that accept -J options. These settings vary by platform and product - verify with platform docs.
FIPS Mode and Hardware Crypto
FIPS 140-2 Mode
IBMJSSE2 can be configured to use FIPS-compliant crypto providers. The modern recommended approach is to use the 'usefipsprovider' flag:
-Dcom.ibm.jsse2.usefipsprovider=true
-Dcom.ibm.jsse2.usefipsProviderName=IBMJCEFIPS
Ensure the chosen FIPS provider (for example IBMJCEFIPS or IBMJCEPlusFIPS) appears earlier in java.security than non-FIPS providers. Note that mixing certain hardware crypto providers with FIPS user-space providers may be restricted - check platform-specific guidance. Avoid speculative statements about FIPS 140-3 unless you have an official product announcement to cite.
Hardware Crypto (IBMJCECCA)
To use hardware crypto (CCA cards), install the IBMJCECCA provider and place it early in the provider list. The provider class name and java.security ordering differ between Java 8 and Semeru/11+; show examples for each environment and confirm with your platform-specific installation notes when configuring CCA keystores.
Example (z/OS, Java 8 style provider list):
security.provider.1=com.ibm.crypto.hdwrCCA.provider.IBMJCECCA
security.provider.2=com.ibm.jsse2.IBMJSSEProvider2
security.provider.3=com.ibm.crypto.provider.IBMJCE
Troubleshooting Common Issues
- Handshake failures: often due to mismatched protocols/cipher suites or certificate validation. Enable -Djavax.net.debug=all to inspect the handshake.
- Missing providers: verify provider class names and java.security ordering. Use the correct IBMJSSE2 provider class (com.ibm.jsse2.IBMJSSEProvider2) for IBM Java 8.
- Unsupported cipher: adjust enabled suites via setEnabledCipherSuites() or jdk.tls.* properties.
- TLS 1.3 PSS requirement: recent TLS 1.3 implementations require RSASSA-PSS for RSA certificates in some environments; if you encounter handshake failures, use appropriate certificates or restrict the protocol to TLS 1.2.
- SSLContext/Null KeyManager: passing null KeyManagers may cause different behaviors across providers; explicitly initialize KeyManagerFactory where possible.
- Revocation checking: use the appropriate property names for your runtime (com.sun.net.ssl.checkRevocation for SunJSSE style; older IBMJSSE2 releases used com.ibm.jsse2.checkRevocation).
Useful JVM Properties for JSSE
- Keystore/Truststore: javax.net.ssl.keyStore / trustStore and corresponding passwords/types.
- Protocol version: jdk.tls.client.protocols / jdk.tls.server.protocols to set TLS versions used in ClientHello/ServerHello.
- Cipher suites: jdk.tls.client.cipherSuites / jdk.tls.server.cipherSuites (comma-separated).
- Debug flags: -Djavax.net.debug=ssl,handshake (or all).
- Handler packages: for platform-specific keystore handlers use the appropriate -Djava.protocol.handler.pkgs value (see RACF note).
- Security providers: list IBMJSSE2 or other providers in java.security as required.
- IBM FIPS mode: -Dcom.ibm.jsse2.usefipsprovider=true and -Dcom.ibm.jsse2.usefipsProviderName=IBMJCEFIPS (where applicable).
By following these guidelines and consulting IBM product documentation, Java applications on IBM Java 8 or IBM Semeru 11+ can establish secure TLS connections with appropriate certificates, cipher suites, and debugging enabled.
Sources
[1] - https://www.ibm.com/docs/en/sdk-java-technology/8?topic=guide-ibmjsse2-provider
[2] - https://www.ibm.com/docs/en/semeru-runtime-ce-z/11.0.0?topic=security-jsse-provider-differences
[3] - https://www.ibm.com/docs/en/sdk-java-technology/8?topic=introduction-known-differences-between-ibmjsse2-provider-oracle-jsse-provider
[4] - https://www.ibm.com/support/pages/how-do-i-change-default-ssltls-protocol-my-java%E2%84%A2-application-will-use#:~:text=TLSv1,on%20the%20IBM%20i%20OS
[5] - https://www.ibm.com/docs/en/i/7.4.0?topic=jsse-java-system-properties
[6] - https://www.ibm.com/support/pages/how-do-i-change-default-ssltls-protocol-my-java%E2%84%A2-application-will-use#:~:text=There%20are%20two%20properties%20that,version%20of%20the%20SSL%2FTLS%20handshake
[7] - https://www.ibm.com/docs/en/semeru-runtime-ce-z/17.0.0?topic=guide-jsse-unique-considerations
[8] - https://www.ibm.com/docs/en/sdk-java-technology/8?topic=provider-running-ibmjsse2-in-fips-mode
[9] - https://www.ibm.com/docs/en/db2-for-zos/13.0.0?topic=ssl-configuring-java-runtime-environment-use
[10] - https://www.ibm.com/docs/en/sdk-java-technology/8?topic=customization-specifying-default-enabled-cipher-suites
------------------------------
ANGUO LI
------------------------------