I've searched everywhere on StackOverflow but those issues seem different from mine and I'm having a lot of trouble fixing it.
For now, my program should just make a Client-Server connection with SSL Sockets where the Client sends just one message and it closes (I'll add more stuff to it later)
I get the problem with the message part and No Cipher Suites in Common error. Below I'll post my Server and Client code along with the output. I'm using Ubuntu 16.04 and Netbeans 8.2
Server code:
public static void main(String[] args)
throws IOException, KeyStoreException, NoSuchAlgorithmException,
CertificateException, UnrecoverableKeyException, KeyManagementException {
FileInputStream keyFile = new FileInputStream(archivoKey);//Server.jks with Client.crt and .key as well as Server.crt and .key
char[] archivopwd = mypassword.toCharArray();
String password = mypassword;
System.setProperty("javax.net.ssl.trustStore", archivoKey);
System.setProperty("javax.net.ssl.trustStorePassword", password);
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(keyFile, archivopwd);
KeyManagerFactory keyManagerFactory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, archivopwd);
KeyManager keyManagers[] = keyManagerFactory.getKeyManagers();
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagers, null, null);
SSLServerSocketFactory factory=(SSLServerSocketFactory)
SSLServerSocketFactory.getDefault();
SSLServerSocket ss = (SSLServerSocket) factory.createServerSocket(6000);
System.out.println("Esperando conexion...");
ss.setEnabledCipherSuites(ss.getSupportedCipherSuites());
SSLSocket so =(SSLSocket) ss.accept();
so.startHandshake();
System.out.println("Conexion realizada");
BufferedReader in = new BufferedReader
(new InputStreamReader(so.getInputStream()));
String msg = in.readLine();
System.out.println(msg);
}
Server Output:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: no cipher suites in common
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:292)
at sun.security.ssl.ServerHandshaker.chooseCipherSuite(ServerHandshaker.java:1045)
at sun.security.ssl.ServerHandshaker.clientHello(ServerHandshaker.java:741)
at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:224)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at servidorseguridad.ServidorSeguridad.main(ServidorSeguridad.java:73)
Client code
public static void main(String[] args) {
int port = 6000;
String host = "localhost";
String password = mypassword;
System.setProperty("javax.net.ssl.trustStore", archivoKey);
System.setProperty("javax.net.ssl.trustStorePassword", password);
try {
SSLContext sc = SSLContext.getInstance("TLS");
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream keyFile = new FileInputStream(archivoKey); //Client.jks, exactly the same as the Server.jks
try {
keyStore.load(keyFile, archivopwd);
} finally {
if (keyFile != null) {
keyFile.close();
}
}
KeyManagerFactory keyManagerFactory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, archivopwd);
sc.init(null, null, null);
SocketFactory factory = sc.getSocketFactory();
System.out.println("Buscando conexion...");
try (SSLSocket so = (SSLSocket) factory.createSocket(host, port)) {
so.getEnabledCipherSuites();
so.startHandshake();
System.out.println("Conexion exitosa!");
DataOutputStream os = new DataOutputStream(so.getOutputStream());
os.writeUTF("Prueba!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
Client output
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2023)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1125)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at clienteseguridad.ClienteSeguridad.main(ClienteSeguridad.java:65)
Most stuff (like the System.setProperty stuff) was me testing out several options I've read on here. The .jks were generated by getting the crt and key files to p12 ones and adding these to the .jks.
I'm really out of ideas here so any help is appreciated. Anything else you need you can just ask. Thank you
This exception usually means that the server didn't have a private key. That means it can only support the anonymous cipher suites, and if the client doesn't allow those, as it shouldn't, there are no cipher suites in common.
Your setup code is bizarre:
You are both loading the truststore and setting the system properties: you don't need to do both.
You are using the same file for the keystore and truststore, which is technically valid but never advisable.
You need to create a server-side keystore, a keypair, and then either
a self-signed certificate, whihc you need to export to the client's truststore, or better still
a CSR, get it signed by the CA, and then import the signed certificate into the server keystore using the same alias you used to create the keypair.
Finally:
ss.setEnabledCipherSuites(ss.getSupportedCipherSuites());
Remove this line. It is insecure. Never do this.
Related
I've an app that communicates with a server through an SSLSocket.
From Android 6 I receive a SSLHandshakeException
javax.net.ssl.SSLHandshakeException: Handshake failed
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:396)
at com.android.org.conscrypt.OpenSSLSocketImpl.waitForHandshake(OpenSSLSocketImpl.java:629)
at com.android.org.conscrypt.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.java:591)
at com.pandaproject.service.ClientSocket.sendPatient(ClientSocket.java:1355)
at com.pandaproject.service.ClientSocket.uploadPatient(ClientSocket.java:826)
at com.pandaproject.service.ClientSocket.<init>(ClientSocket.java:241)
at com.pandaproject.service.UploadObject.getFromServer(UploadObject.java:201)
at com.pandaproject.service.UploadObject.access$000(UploadObject.java:20)
at com.pandaproject.service.UploadObject$1.run(UploadObject.java:97)
at java.lang.Thread.run(Thread.java:818)
Caused by javax.net.ssl.SSLProtocolException: SSL handshake terminated: ssl=0x9dea4280: Failure in SSL library, usually a protocol error
error:100c5410:SSL routines:ssl3_read_bytes:SSLV3_ALERT_HANDSHAKE_FAILURE (external/boringssl/src/ssl/s3_pkt.c:972 0xaee563c0:0x00000001)
error:100c009f:SSL routines:ssl3_get_server_hello:HANDSHAKE_FAILURE_ON_CLIENT_HELLO (external/boringssl/src/ssl/s3_clnt.c:750 0xab2a450f:0x00000000)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(NativeCrypto.java)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:324)
at com.android.org.conscrypt.OpenSSLSocketImpl.waitForHandshake(OpenSSLSocketImpl.java:629)
at com.android.org.conscrypt.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.java:591)
at com.pandaproject.service.ClientSocket.sendPatient(ClientSocket.java:1355)
at com.pandaproject.service.ClientSocket.uploadPatient(ClientSocket.java:826)
at com.pandaproject.service.ClientSocket.<init>(ClientSocket.java:241)
at com.pandaproject.service.UploadObject.getFromServer(UploadObject.java:201)
at com.pandaproject.service.UploadObject.access$000(UploadObject.java:20)
at com.pandaproject.service.UploadObject$1.run(UploadObject.java:97)
at java.lang.Thread.run(Thread.java:818)
And in the server side:
javax.net.ssl.SSLHandshakeException: no cipher suites in common
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:292)
at sun.security.ssl.ServerHandshaker.chooseCipherSuite(ServerHandshaker.java:1036)
at sun.security.ssl.ServerHandshaker.clientHello(ServerHandshaker.java:739)
at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:221)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:747)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)
at java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1877)
at java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(ObjectOutputStream.java:1786)
at java.io.ObjectOutputStream.<init>(ObjectOutputStream.java:247)
This happens only with Android 6, it seems there is something different in the chiper suites
I'm pasting the Server and client code for better troubleshooting
Server code:
ServerSocket server = null;
Socket socket=null;
SSLContext ctx;
KeyManagerFactory kmf;
KeyStore ks;
try{
char[] passphrase = "password".toCharArray();
String keyfile = "keyName";
ctx = SSLContext.getInstance("TLS");
kmf = KeyManagerFactory.getInstance("SunX509");
ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(keyfile), passphrase);
kmf.init(ks, passphrase);
ctx.init(kmf.getKeyManagers(), null, null);
ServerSocketFactory ssf = ctx.getServerSocketFactory();
server = ssf.createServerSocket(port);
}catch (IOException e){
e.printStackTrace();
}
while (true) {
socket = server.accept();
new Thread(new WorkerThread(socket));
}
Android code:
Socket clientSocket = null;
KeyStore store = KeyStore.getInstance("BKS");
InputStream in2 = ctx.getResources().openRawResource(
R.raw.server);
store.load(in2, "password".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
tmf.init(store);
SSLContext sslcontext = SSLContext.getInstance("SSL");
sslcontext.init(null, tmf.getTrustManagers(),
new SecureRandom());
SSLSocketFactory sslsocketfactory = sslcontext
.getSocketFactory();
clientSocket = (SSLSocket) sslsocketfactory.createSocket(
Constants.SERVER_HOST, port);
ObjectInputStream obi = new ObjectInputStream(
clientSocket.getInputStream());
ObjectOutputStream obs = new ObjectOutputStream(
clientSocket.getOutputStream());
obs.writeObject("text");
obs.flush();
Any hint?
According to this:
https://github.com/iiordanov/remote-desktop-clients/issues/57
What seems to have happened is that annonimous DH cipher were dropped.
So, you cannot use a certificates that are not in Android keystore anymore.
After reading through numerous answers concerning these topics, I have found myself completely unable to string together the pieces of the puzzle, I hope you will excuse me for this.
I am trying to change my simple socket connection in Java to use SSL. I would like both the server and client to authenticate themselves if possible, but only server authentication would be good start.
Currently, this is the extremely simple code on the server side:
ServerSocket serverSocket = new ServerSocket(port);
Socket socket = serverSocket.accept();
And this is the code on the client side:
Socket socket = null;
while (true) {
try {
socket = new Socket(ipAddress, port);
break;
} catch (Exception e) {}
}
This works fine, but without SSL.
I have generated SSL certificates for the server and client using OpenSSL, ending up with:
A certificate for the server (PEM format)
A certificate for the client (PEM format)
A private key for the server (PEM format)
A private key for the client (PEM format)
A CA file (PEM, CER and CRT format)
From this I have used OpenSSL to create PKCS12 (.p12) keystores for both the client and the server, as follows
server.p12, made by doing openssl pkcs12 -export -in server-cert.pem -inkey server-private-key.pem -out server.p12
client.p12, made by doing openssl pkcs12 -export -in client-cert.pem -inkey client-private-key.pem -out client.p12
Then, I turned these into JKS keystores by using keytool (for the server, for example, the command was keytool -importkeystore -srckeystore server.p12 -srcstoretype PKCS12 -destkeystore server.jks -deststoretype JKS), resulting in two files named server.jks and client.jks.
I then use the following code as replacement for the previous server snippet:
char[] keyStorePassword = "JKSPassword".toCharArray();
FileInputStream keyStoreFile = new FileInputStream("somepath/server.jks");
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(keyStoreFile, keyStorePassword);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, "PKCS12Password".toCharArray());
SSLContext sslContext = SSLContext.getDefault();
ServerSocket serverSocket = sslContext.getServerSocketFactory().createServerSocket(port);
Socket socket = serverSocket.accept();
And the following code as replacement for the client snippet:
Socket socket = null;
while (true) {
try {
char[] keyStorePassword = "JKSPassword".toCharArray();
FileInputStream keyStoreFile = new FileInputStream("somepath/client.jks");
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(keyStoreFile, keyStorePassword);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, "PKCS12Password".toCharArray());
SSLContext sslContext = SSLContext.getDefault();
socket = sslContext.getSocketFactory().createSocket(ipAddress, port);
break;
} catch (Exception e) {}
}
I now still get javax.net.ssl.SSLHandshakeException: no cipher suites in common on the server (and javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure on the client).
What could be wrong?
I found the missing part of the puzzle (I believe).
Instead of the line SSLContext sslContext = SSLContext.getDefault(); on the client, I put:
BufferedInputStream serverCertificateFile = new BufferedInputStream(new FileInputStream("somepath/server-cert.der"));
X509Certificate serverCertificate = (X509Certificate)
CertificateFactory.getInstance("X.509").generateCertificate(serverCertificateFile);
sslContext.init(keyManagerFactory.getKeyManagers(), new TrustManager[] {
new X509TrustManager() {
#Override
public void checkClientTrusted(X509Certificate[] arg0,
String arg1) throws CertificateException {
throw new CertificateException();
}
#Override
public void checkServerTrusted(X509Certificate[] arg0,
String arg1) throws CertificateException {
boolean valid = false;
for (X509Certificate certificate : arg0) {
try {
certificate.verify(serverCertificate.getPublicKey());
valid = true;
break;
} catch (SignatureException e) {}
}
if (!valid) {
throw new CertificateException();
}
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
}, new SecureRandom());
server-cert.der is a file, created with openssl509 -outform der -in server-cert.pem -out server-cert.der.
I was not able to find good tutorials or question on this matter on StackOverflow, so this is what I created by attempting to understand the reference guide.
Essentially, I am creating a TrustManager that, for a server, trusts it when one of the provided certificates is the one that belongs to your own server.
It appears to work, please let me know if there is anything principally wrong with this approach (I unfortunately assume there is). Thanks for having read so much!
So I have some of the ssl server and client side code. I'm not sure what to put in some of the methods though.
public void client() throws UnknownHostException, IOException{
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream stream = new FileInputStream(new File("")); // need correct file
keyStore.load(stream, "Some Password".toCharArray());
// load in the appropriate keystore and truststore for the client
// get the X509KeyManager and X509TrustManager instances
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance("PKIX", "SunJSSE");
trustManagerFactory.init("NOT SURE WHAT TO PUT HERE");
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(new KeyManager[]{"NOT SURE WHAT TO PUT HERE"},
new TrustManager[]{"NOT SURE WHAT TO PUT HERE"}, null);
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
SSLSocket socket =
(SSLSocket) socketFactory.createSocket("localhost", 25500);
socket.setEnabledProtocols(new String[]{"TLSv1"});
// read from the socket, etc
}
public void server() throws IOException{
// load in the appropriate keystore and truststore for the server
// get the X509KeyManager and X509TrustManager instances
SSLContext sslContext = SSLContext.getInstance("TLS");
// the final null means use the default secure random source
sslContext.init(new KeyManager[]{"NOT SURE WHAT TO PUT HERE"},
new TrustManager[]{"NOT SURE WHAT TO PUT HERE"}, null);
SSLServerSocketFactory serverSocketFactory =
sslContext.getServerSocketFactory();
SSLServerSocket serverSocket =
(SSLServerSocket) serverSocketFactory.createServerSocket(25500);
serverSocket.setNeedClientAuth(true);
// prevent older protocols from being used, especially SSL2 which is insecure
serverSocket.setEnabledProtocols(new String[]{"TLSv1"});
// you can now call accept() on the server socket, etc
}
Also, how do I generate certificates in java "like the code" and print it out to a file and have it use the same certificate over and over again.
Thx for any help.
I have a Client Server Communication scenario in JBOSS and browser as client(JAVA PROGRAM). Initially when the connection is made, Client sends its Certificate to Server. Server extracts the public key of client from certificate and thus communication will continue.
Now my question is
How to send certificate(.cer) from Client to Server?
How to receive the certificate and extract its public key in Server?
How to send certificate(.cer) from Client to Server?
Client certificate (.cer, .crt, .pem) and it's corresponding private key (.key) should be packaged into PKCS#12 (.p12, .pfx) or JKS (.jks) container first (keystore). You also should have server's CA certicate packaged as JKS (truststore).
Example using HttpClient 3.x:
HttpClient client = new HttpClient();
// truststore
KeyStore trustStore = KeyStore.getInstance("JKS", "SUN");
trustStore.load(TestSupertype.class.getResourceAsStream("/client-truststore.jks"), "amber%".toCharArray());
String alg = KeyManagerFactory.getDefaultAlgorithm();
TrustManagerFactory fac = TrustManagerFactory.getInstance(alg);
fac.init(trustStore);
// keystore
KeyStore keystore = KeyStore.getInstance("PKCS12", "SunJSSE");
keystore.load(X509Test.class.getResourceAsStream("/etomcat_client.p12"), "etomcat".toCharArray());
String keyAlg = KeyManagerFactory.getDefaultAlgorithm();
KeyManagerFactory keyFac = KeyManagerFactory.getInstance(keyAlg);
keyFac.init(keystore, "etomcat".toCharArray());
// context
SSLContext ctx = SSLContext.getInstance("TLS", "SunJSSE");
ctx.init(keyFac.getKeyManagers(), fac.getTrustManagers(), new SecureRandom());
SslContextedSecureProtocolSocketFactory secureProtocolSocketFactory = new SslContextedSecureProtocolSocketFactory(ctx);
Protocol.registerProtocol("https", new Protocol("https", (ProtocolSocketFactory) secureProtocolSocketFactory, 8443));
// test get
HttpMethod get = new GetMethod("https://127.0.0.1:8443/etomcat_x509");
client.executeMethod(get);
// get response body and do what you need with it
byte[] responseBody = get.getResponseBody();
You may find working example in this project see X509Test class.
With HttpClient 4.x configuration and syntax would be slightly different:
HttpClient httpclient = new DefaultHttpClient();
// truststore
KeyStore ts = KeyStore.getInstance("JKS", "SUN");
ts.load(PostService.class.getResourceAsStream("/truststore.jks"), "amber%".toCharArray());
// if you remove me, you've got 'javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated' on missing truststore
if(0 == ts.size()) throw new IOException("Error loading truststore");
// tmf
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ts);
// keystore
KeyStore ks = KeyStore.getInstance("PKCS12", "SunJSSE");
ks.load(PostService.class.getResourceAsStream("/" + certName), certPwd.toCharArray());
// if you remove me, you've got 'javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated' on missing keystore
if(0 == ks.size()) throw new IOException("Error loading keystore");
// kmf
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, certPwd.toCharArray());
// SSL
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
// socket
SSLSocketFactory socketFactory = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Scheme sch = new Scheme("https", 8443, socketFactory);
httpclient.getConnectionManager().getSchemeRegistry().register(sch);
// request
HttpMethod get = new GetMethod("https://localhost:8443/foo");
client.executeMethod(get);
IOUtils.copy(get.getResponseBodyAsStream(), System.out);
How to receive the certificate and extract its public key in Server?
You server must be configurated to require X.509 client certificate authentication. Then during SSL handshake servlet container will recieve certificate, check it against trustore and provide it to application as a request attribute.
In usual case with single certificate you could use this method in servlet environment to extract certificate:
protected X509Certificate extractCertificate(HttpServletRequest req) {
X509Certificate[] certs = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate");
if (null != certs && certs.length > 0) {
return certs[0];
}
throw new RuntimeException("No X.509 client certificate found in request");
}
This question already has answers here:
SSLHandshakeException: no cipher suites in common
(3 answers)
Closed 5 years ago.
A server and respective client support client authentication but as noted here: SSLHandshakeException: no cipher suites in common, do not have trustStore reference, i.e. they use the default trustStore. How can the trustStore be specified?
ClassFileServer:
private static ServerSocketFactory getServerSocketFactory(String type) {
if (type.equals("TLS")) {
SSLServerSocketFactory ssf = null;
Properties systemProps = System.getProperties();
systemProps.put( "javax.net.ssl.trustStore", "cacerts.jks");
systemProps.put( "javax.net.ssl.trustStorePassword", "p#ssw0rd");
System.setProperties(systemProps);
try {
// set up key manager to do server authentication
SSLContext ctx;
KeyManagerFactory kmf;
KeyStore ks;
char[] passphrase = "p#ssw0rd".toCharArray();
ctx = SSLContext.getInstance("TLS");
kmf = KeyManagerFactory.getInstance("SunX509");
ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("keystore.jks"), passphrase);
kmf.init(ks, passphrase);
ctx.init(kmf.getKeyManagers(), null, null);
ssf = ctx.getServerSocketFactory();
return ssf;
} catch (Exception e) {
e.printStackTrace();
}
}
SSLSocketClientWithClientAuth:
try {
/*
* Set up a key manager for client authentication
* if asked by the server. Use the implementation's
* default TrustStore and secureRandom routines.
*/
Properties systemProps = System.getProperties();
systemProps.put( "javax.net.ssl.trustStore", "cacerts.jks");
systemProps.put( "javax.net.ssl.trustStorePassword", "changeit");
System.setProperties(systemProps);
SSLSocketFactory factory = null;
try {
SSLContext ctx;
KeyManagerFactory kmf;
KeyStore ks;
char[] passphrase = "changeit".toCharArray();
ctx = SSLContext.getInstance("TLS");
kmf = KeyManagerFactory.getInstance("SunX509");
ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("keystore.jks"), passphrase);
kmf.init(ks, passphrase);
ctx.init(kmf.getKeyManagers(), null, null);
factory = ctx.getSocketFactory();
} catch (Exception e) {
throw new IOException(e.getMessage());
}
SSLSocket socket = (SSLSocket)factory.createSocket(host, port);
Specify the trustStore by setting the system properties:
System.setProperty("javax.net.ssl.trustStore", "cacerts.jks");
or via command line invocation:
-Djavax.net.ssl.keyStore=path/to/keystore.jks
'No cipher suites in common' is not caused by using the default truststore. It is caused by not having a keystore, or not having a private key and certificate in it, or else by overspecifying cipher suites at one peer or the other such that there can be no agreement.
If the server doesn't have a private key, it can't use any cipher suites except the insecure anonymous ones, which are disabled by default, and should stay that way. Hence the alert.
Using the default truststore will cause a different problem if and only if you are using self-signed certificates. Simple solution: don't. More complex solution: export the respective certificates from the respective keystores and import them into the other party's truststore.
See the JSSE Reference Guide.