I've read plenty of stuff to setup my SSL client/server system (no HTTP).
I inspired myself from the secure chat example and the websocket ssl server example. Already created my cert.jks file with the command
keytool -genkey -alias app-keysize 2048 -validity 36500
-keyalg RSA -dname "CN=app"
-keypass mysecret-storepass mysecret
-keystore cert.jks
In the secure chat example there is this class:
public class SecureChatTrustManagerFactory extends TrustManagerFactorySpi {
private static final TrustManager DUMMY_TRUST_MANAGER = new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
@Override
public void checkClientTrusted(
X509Certificate[] chain, String authType) throws CertificateException {
// Always trust - it is an example.
// You should do something in the real world.
// You will reach here only if you enabled client certificate auth,
// as described in SecureChatSslContextFactory.
System.err.println(
"UNKNOWN CLIENT CERTIFICATE: " + chain[0].getSubjectDN());
}
@Override
public void checkServerTrusted(
X509Certificate[] chain, String authType) throws CertificateException {
// Always trust - it is an example.
// You should do something in the real world.
System.err.println(
"UNKNOWN SERVER CERTIFICATE: " + chain[0].getSubjectDN());
}
};
public static TrustManager[] getTrustManagers() {
return new TrustManager[] { DUMMY_TRUST_MANAGER };
}
@Override
protected TrustManager[] engineGetTrustManagers() {
return getTrustManagers();
}
@Override
protected void engineInit(KeyStore keystore) throws KeyStoreException {
// Unused
}
@Override
protected void engineInit(ManagerFactoryParameters managerFactoryParameters)
throws InvalidAlgorithmParameterException {
// Unused
}
}
How do you implement this class properly?
And in this code (in the SecureChatSslContextFactory class):
SSLContext serverContext = null;
SSLContext clientContext = null;
try {
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(SecureChatKeyStore.asInputStream(),
SecureChatKeyStore.getKeyStorePassword());
// Set up key manager factory to use our key store
KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
kmf.init(ks, SecureChatKeyStore.getCertificatePassword());
// Initialize the SSLContext to work with our key managers.
serverContext = SSLContext.getInstance(PROTOCOL);
serverContext.init(kmf.getKeyManagers(), null, null);
} catch (Exception e) {
throw new Error(
"Failed to initialize the server-side SSLContext", e);
}
try {
clientContext = SSLContext.getInstance(PROTOCOL);
clientContext.init(null, SecureChatTrustManagerFactory.getTrustManagers(), null);
} catch (Exception e) {
throw new Error(
"Failed to initialize the client-side SSLContext", e);
}
Why do they put null
instead of tmf.getTrustManagers()
in the line serverContext.init(kmf.getKeyManagers(), null, null);
?
How do you implement this class properly?
You need to define a way to check that you trust the certificate at chain[0]
one way or another. If you don't, throw a CertificateException
. (Here the SecureChatTrustManagerFactory
never throws anything, so it bypasses the verification, which can make the connection open to MITM attacks.)
If you want to do this verification semi-manually, you can use the Java PKI API, although it can be a bit tedious, even on relatively simple use cases.
Generally speaking, the right thing to do is not to implement your own. Leave that to the TrustManagerFactory
(more or less in the same way as it's done with the KeyManagerFactory
). By the way, in both cases, I'd recommend using Key/TrustManagerFactory.getDefaultAlgorithm()
for the value of algorithm
, unless you have a good reason not to. It's at least a better default value than SunX509
which I've seen hard-coded in many cases (and which in fact isn't the default TMF algorithm value).
You can initialise a TMF from your own truststore (an instance of KeyStore
that you can load specifically for this connection, for example).
Why do they put null instead of tmf.getTrustManagers() in the line serverContext.init(kmf.getKeyManagers(), null, null); ?
null
for the trust managers and null
for the SecureRandom
fall back to the default values. This will be a default trust manager initialised with the default TMF algorithm (usually PKIX
), using the default trust store (using the location in javax.net.ssl.trustStore
, or falling back to the jssecacerts
file or cacerts
). More details in the JSSE reference guide.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With