Keystore loading - java

I would like to know what's the equivalent in java of the following :
-Djavax.net.ssl.trustStore=keystore.jks -Djavax.net.ssl.keyStore=keystore.jks
-Djavax.net.debug=ssl -Djavax.net.ssl.keyStorePassword=test JavaFile
I would like to load the keystore otherwise than sending it as arguments from the command line. I've been working with :
private TcpLink createSSL() {
KeyStore keyStore = null;
TrustManagerFactory tmf = null;
SSLContext ctx = null;
SSLSocket socket = null;
TcpLink smscLink = null;
try {
keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
LOGGER.info("Got keystore");
keyStore.load(new FileInputStream("/root/keystore.jks"), "test".toCharArray());
LOGGER.info("Loaded keystore");
tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
LOGGER.info("Inited keystore");
ctx = SSLContext.getInstance("TLSv1");
ctx.init(null, tmf.getTrustManagers(), null);
SSLSocketFactory factory = ctx.getSocketFactory();
socket = (SSLSocket)factory.createSocket("100.100.201.189", 8807);
LOGGER.info("Got socket");
smscLink = new TcpLink(socket);
return smscLink;
} catch (KeyStoreException e) {
LOGGER.error("Key store exception : " + e);
} catch (NoSuchAlgorithmException e) {
LOGGER.error("NoSuchAlgorithmException : " + e);
} catch (CertificateException e) {
LOGGER.error("CertificateException : " + e);
} catch (FileNotFoundException e) {
LOGGER.error("FileNotFoundException : " + e);
} catch (IOException e) {
LOGGER.error("FileNotFoundException : " + e);
} catch (KeyManagementException e) {
LOGGER.error("KeyManagementException : " + e);
} catch (Exception e) {
LOGGER.error("Exception : " + e);
}
return null;
}
but I get :
javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.checkEOF(SSLSocketImpl.java:1293)
at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:65)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
Any ideas are welcome !
Thx

You can set the System properties this way:
System.setProperty("javax.net.ssl.keyStore", '/path/to/keystore.jks');
System.setProperty("javax.net.ssl.keyStorePassword", 'your-password-here');
They will be used system-wide (in this instance of JVM), so probably you want to do it at initialisation time.

It works using this piece of code :
KeyManagerFactory kmf =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(this.getCertificateContent(), "test".toCharArray());
kmf.init(keyStore, "test".toCharArray());
TrustManagerFactory tmf =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
SSLContext ctx = SSLContext.getInstance("TLSv1");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
SSLSocketFactory factory = ctx.getSocketFactory();
socket = (SSLSocket)factory.createSocket("100.125.100.1", 8775);

If you want, here's an API to create SSLSocket and SSLServerSocket easyly:
https://github.com/gpotter2/SSLKeystoreFactories
It does not require any other jars.... just get the files and use them like:
SSLSocket s = SSLSocketKeystoreFactory.getSocketWithCert(ip, port, Main.class.getResourceAsStream("/mykey.jks"), "password")
Or:
SSLServerSocket s = SSLServerSocketKeystoreFactory.getSocketWithCert(port, Main.class.getResourceAsStream("/mykey.jks"), "password")
That's much easier to use :)

Related

Received fatal alert, bad_certificate

I am trying to make an SSL conection to a server. I have created a Truststore and imported the server's certificate as well as mine as trusted entries into the Keystore. The server guys also have imported my certificate into their keystore. But when i try to connect, i get this error:
Received fatal alert: bad_certificate
On the server, they are getting this error:
javax.net.ssl.SSLHandshakeException: null cert chain
What could i be possibly be doing wrong?, How do i fix this error? I have been battling this issue for a very long time now.
My Client Code
import java.io.*;
import java.net.*;
import java.security.*;
import java.util.Enumeration;
import javax.net.ssl.*;
public class SSLConnect {
public String MakeSSlCall(String meternum) {
String message = "";
FileWriter file = null;
try {
file = new FileWriter("C:\\SSLCERT\\ClientJavalog.txt");
} catch (Exception ee) {
message = ee.getMessage();
}
//writer = new BufferedWriter(file );
try {
file.write("KeyStore Generated\r\n");
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(new FileInputStream("C:\\SSLCERT\\newclientkeystore"), "client".toCharArray());
file.write("KeyStore Generated\r\n");
Enumeration enumeration = keystore.aliases();
while (enumeration.hasMoreElements()) {
String alias = (String) enumeration.nextElement();
file.write("alias name: " + alias + "\r\n");
keystore.getCertificate(alias);
file.write(keystore.getCertificate(alias).toString() + "\r\n");
}
TrustManagerFactory tmf =TrustManagerFactory.getInstance("SunX509");
tmf.init(keystore);
file.write("KeyStore Stored\r\n");
SSLContext context = SSLContext.getInstance("SSL");
TrustManager[] trustManagers = tmf.getTrustManagers();
context.init(null, trustManagers, null);
SSLSocketFactory f = context.getSocketFactory();
file.write("About to Connect to Ontech\r\n");
SSLSocket c = (SSLSocket) f.createSocket("192.168.1.16", 4447);
file.write("Connection Established to 196.14.30.33 Port: 8462\r\n");
file.write("About to Start Handshake\r\n");
c.startHandshake();
file.write("Handshake Established\r\n");
file.flush();
file.close();
return "Connection Established";
} catch (Exception e) {
try {
file.write("An Error Occured\r\n");
file.write(e.getMessage() + "\r\n");
file.flush();
file.close();
} catch (Exception eee) {
message = eee.getMessage();
}
return "Connection Failed";
}
}
}
Keytool commands for creating my truststore
keytool -import -alias client -file client.cer -keystore MyKeystore -storepass mystore
keytool -import -alias server -file server.cer -keystore MyKeystore -storepass mystore
And i have also added the two certificates to my cacerts keystore
It's been a while, but I had to face similar issue. Here is my working code:
Properties systemProps = System.getProperties();
systemProps.put("javax.net.debug","ssl");
systemProps.put("javax.net.ssl.trustStore","<path to trustore>");
systemProps.put("javax.net.ssl.trustStorePassword","password");
System.setProperties(systemProps);
SSLContext sslcontext;
KeyStore keyStore;
final char[] JKS_PASSWORD = "password".toCharArray();
final char[] KEY_PASSWORD = "password".toCharArray();
try {
final InputStream is = new FileInputStream("<path_to_keystore.pkcs12>");
keyStore = KeyStore.getInstance("pkcs12");
keyStore.load(is, JKS_PASSWORD);
final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, KEY_PASSWORD);
sslcontext=SSLContext.getInstance("TLS");
sslcontext.init(kmf.getKeyManagers(), null, new java.security.SecureRandom());
} catch (Exception ex) {
throw new IllegalStateException("Failure initializing default SSL context", ex);
}
SSLSocketFactory sslsocketfactory = sslcontext.getSocketFactory();
DataOutputStream os = null;
try {
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket();
sslsocket.connect(new InetSocketAddress(host, port), connectTimeout);
sslsocket.startHandshake();
os = new DataOutputStream(sslsocket.getOutputStream());
// log.info("Sending echo packet");
String toSend = "{\"echo\":\"echo\"}";
os.writeBytes(toSend);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Error while connecting Https Socket in android

I am using socket.io-client-java library for socket in android app but in application some error occurred which is given below
Code:-
KeyStore keyStore = KeyStore.getInstance("BKS");
InputStream is = context.getResources().openRawResource(R.raw.bks);
keyStore.load(is, "Password".toCharArray());
is.close();
//create a factory
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
//get context
SSLContext mySSLContext = SSLContext.getInstance("TLS");
//init context
mySSLContext.init(
null,
trustManagerFactory.getTrustManagers(),
new SecureRandom()
);
HostnameVerifier myHostnameVerifier = SSLSocketFactory.STRICT_HOSTNAME_VERIFIER;
// set as an option
IO.Options opts = new IO.Options();
opts.sslContext = mySSLContext;
opts.hostnameVerifier = myHostnameVerifier;
socket = IO.socket("https://demo.in:9898", opts);
socket.connect();
Here is my Error:-
java.io.IOException: KeyStore integrity check failed.
at com.android.org.bouncycastle.jcajce.provider.keystore.bc.BcKeyStoreSpi.engineLoad(BcKeyStoreSpi.java:862)
at java.security.KeyStore.load(KeyStore.java:590)
at drawgraph.hospisoft.com.bluetootheds.SocketConnetion.ConnectSocket(SocketConnetion.java:46)
at drawgraph.hospisoft.com.bluetootheds.MainActivity.initSocket(MainActivity.java:1095)
at drawgraph.hospisoft.com.bluetootheds.MainActivity.onCreate(MainActivity.java:250)
at android.app.Activity.performCreate(Activity.java:6100)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1112)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2481)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2614)
at android.app.ActivityThread.access$800(ActivityThread.java:178)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1470)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5643)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:960)
Github Link
I think its password problem but i check BKS password many time
The password is wrong or the keystore is corrupt.
Sorry for late answer but below code working fine for me.
try {
String sslCertificateString= context.getResources().getString(R.string.certifiacte);
InputStream certFile = new ByteArrayInputStream(sslCertificateString.getBytes(StandardCharsets.UTF_8));
java.security.cert.Certificate ca = CertificateFactory.getInstance("X.509").generateCertificate(certFile);
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
//create a factory
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
//get context
SSLContext mySSLContext = SSLContext.getInstance("TLS");
//init context
mySSLContext.init(
null,
trustManagerFactory.getTrustManagers(),
new SecureRandom()
);
IO.Options opts = new IO.Options();
opts.sslContext = mySSLContext;
opts.secure = true;
socket = IO.socket("https://demo.com:3000", opts);
socket.connect();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (GeneralSecurityException e) {
e.printStackTrace();
}

Android to JAVA SSL

i am a relative novice at Android and have had issues getting a simple SSL connection working to a java server.
I know the java server works as I tested it using the same keystore as the server and a java client.
The Android client does send something as the java server accepts a connection and displays a null value for a readline variable, and no error message.
I have my keystore, and truststore in bks format, and added to the res/raw folder.
Android Client:
SSLContext sslContext = SSLContext.getDefault();
KeyStore trustSt = KeyStore.getInstance("BKS");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
InputStream trustStoreStream = this.getResources().openRawResource(R.raw.truststore);
trustSt.load(trustStoreStream, "password".toCharArray());
trustManagerFactory.init(trustSt);
KeyStore keyStore = KeyStore.getInstance("BKS");
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
InputStream keyStoreStream = this.getResources().openRawResource(R.raw.keystore);
keyStore.load(keyStoreStream, "password".toCharArray());
keyManagerFactory.init(keyStore, "password".toCharArray());
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
}
catch (NoSuchAlgorithmException nsae){Log.d("SSL", nsae.getMessage());}
catch (KeyStoreException kse){Log.d("SSL", kse.getMessage());}
catch (IOException ioe){Log.d("SSL", ioe.getMessage());}
catch (CertificateException ce){Log.d("SSL", ce.getMessage());}
catch (KeyManagementException kme){Log.d("SSL", kme.getMessage());}
catch(AccessControlException ace){Log.d("SSL", ace.getMessage());}
catch(UnrecoverableKeyException uke){Log.d("SSL", uke.getMessage());}
try{
//error catch
String error = "test";
sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
s = (SSLSocket) sslsocketfactory.createSocket("192.168.2.101", port);
outStream = s.getOutputStream();
outStreamWriter = new OutputStreamWriter(outStream);
bufferedWriter = new BufferedWriter(outStreamWriter);
bufferedWriter.write(error + "\n");
bufferedWriter.flush();
} //end try
catch (UnknownHostException e) {e.printStackTrace();}
catch (IOException e) {e.printStackTrace();}
finally{
if (s != null){
try {s.close();}
catch (IOException e) {e.printStackTrace();}
}
}//end finally
}
I have specified a truststore but do not not how to initialise the truststore on the socket.
Any help would be appreciated.
I think changing this line
sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
to use the SSLSocketFactory(KeyStore truststore) constructor may solve your problem.
sslsocketfactory = new SSLSocketFactory(trustSt);

Setting the certificate used by a Java SSL ServerSocket

I want to open a secure listening socket in a Java server application. I know that the recommended way to do that is to just do this:
SSLServerSocketFactory ssf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
ServerSocket ss = ssf.createServerSocket(443);
But this requires to pass the certificate of the server to the JVM when launching java. Because this would make some things in deployment more complicated for me, I would prefer to load the certificate at runtime.
So I have a key file and a password and I want a server socket. How do I get there? Well, I read the documentation and the only way I could find is this:
// these are my parameters for SSL encryption
char[] keyPassword = "P#ssw0rd!".toCharArray();
FileInputStream keyFile = new FileInputStream("ssl.key");
// init keystore
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(keyFile, keyPassword);
// init KeyManagerFactory
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, keyPassword);
// init KeyManager
KeyManager keyManagers[] = keyManagerFactory.getKeyManagers();
// init the SSL context
SSLContext sslContext = SSLContext.getDefault();
sslContext.init(keyManagers, null, new SecureRandom());
// get the socket factory
SSLServerSocketFactory socketFactory = sslContext.getServerSocketFactory();
// and finally, get the socket
ServerSocket serverSocket = socketFactory.createServerSocket(443);
And that doesn't even have any error handling. Is it really that complicated? Isn't there an easier way to do it?
But this requires to pass the certificate of the server to the JVM when launching java.
No it doesn't. Just set these system properties before you create the SSLServerSocket:
javax.net.ssl.keyStore ssl.key
javax.net.ssl.keyStorePassword P#ssw0rd!
You can do that with System.setProperties() or on the command line.
If you look at the code, you can see why it's necessarily complicated. This code decouples the implementation of the SSL protocol from:
the source of your key material (KeyStore)
certificate algorithm choice and key management (KeyManager)
management of peer trust rules (TrustManager) - not used here
secure random algorithm (SecureRandom)
NIO or socket implementation (SSLServerSocketFactory) - could use SSLEngine for NIO
Consider what your own implementation would look like if you were trying to reach the same goals!
Use this.
public class KeyMaster
{
public static SSLSocketFactory getSSLSocketFactory(KeyStore trustKey, String sslAlgorithm)
{
try
{
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustKey);
SSLContext context = SSLContext.getInstance(sslAlgorithm);//"SSL" "TLS"
context.init(null, tmf.getTrustManagers(), null);
return context.getSocketFactory();
}
catch(Exception e)
{
Assistance.log("Err: getSSLSocketFactory(), ");
}
return null;
}
public static SSLServerSocketFactory getSSLServerSocketFactory(KeyStore trustKey, String sslAlgorithm)
{
try
{
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustKey);
SSLContext context = SSLContext.getInstance(sslAlgorithm);//"SSL" "TLS"
context.init(null, tmf.getTrustManagers(), null);
return context.getServerSocketFactory();
}
catch(Exception e)
{
Assistance.log("Err: getSSLSocketFactory(), ");
}
return null;
}
public static SSLServerSocket getSSLServerSocket(SSLServerSocketFactory socketFactory, int port)
{
try
{
return (SSLServerSocket) socketFactory.createServerSocket(port);
}
catch(Exception e)
{Assistance.log("Err: getSSLSocket(), ");}
return null;
}
public static KeyStore getFromPath(String path, String algorithm, String filePassword)//PKSC12
{
try
{
File f = new File(path);
if(!f.exists())
throw new RuntimeException("Err: File not found.");
FileInputStream keyFile = new FileInputStream(f);
KeyStore keystore = KeyStore.getInstance(algorithm);
keystore.load(keyFile, filePassword.toCharArray());
keyFile.close();
return keystore;
}
catch(Exception e)
{
Assistance.log("Err: getFromPath(), " + e.toString());
}
return null;
}
and in main.
KeyStore key = KeyMaster.getFromPath(".\\cssl.pfx", "PKCS12", "123");
SSLServerSocketFactory fac = KeyMaster.getSSLServerSocketFactory(key, "TLS");
listener = KeyMaster.getSSLServerSocket(fac, 49015);

SSL connection failure between java server and android client

I am trying to setup mutual authentication SSL connection between java host and android client. Don't know why its not getting connected. Below are the code of Android client app and Java server.
Client code:
private SSLContext createSSLContext(final Context cont){
SSLContext ssl_cont = null;
try {
Log.d(TAG, "TrustStore - Initializing");
KeyStore trustStore = KeyStore.getInstance("BKS");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
InputStream trustStoreStream = cont.getResources().openRawResource(R.raw.myclienttruststore);
trustStore.load(trustStoreStream, "client".toCharArray());
trustManagerFactory.init(trustStore);
Log.d(TAG, "TrustStore - Initialized");
// Setup keystore
Log.d(TAG, "KeyStore - Initializing");
KeyStore keyStore = KeyStore.getInstance("BKS");
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
InputStream keyStoreStream = cont.getResources().openRawResource(R.raw.myclient);
keyStore.load(keyStoreStream, "client".toCharArray());
keyManagerFactory.init(keyStore, "client".toCharArray());
Log.d(TAG, "KeyStore - Initialized");
ssl_cont = SSLContext.getInstance("TLS");
ssl_cont.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
} catch (Exception e) {
// TODO Auto-generated catch block
alertbox("SSLClient", "ERROR: " + e.getMessage());
Log.d(TAG, "ERROR: " + e.getMessage());
}
return ssl_cont;
}
OnClickListener onConnClick = new OnClickListener() {
public void onClick(View arg0) {
// TODO Auto-generated method stub
try {
// Setup the SSL context to use the truststore and keystore
Log.d(TAG, "Started..");
SSLContext ssl_context = createSSLContext(cont);
Log.d(TAG,"here 1...");
SSLSocketFactory socketFactory = (SSLSocketFactory) ssl_context.getSocketFactory();
Log.d(TAG,"here 2...");
socket = (SSLSocket) socketFactory.createSocket(ipadd.getText().toString().trim(), Integer.parseInt(port.getText().toString().trim()));
Log.d(TAG,"here 3...");
dataOut = new DataOutputStream(socket.getOutputStream());
dataIn = new DataInputStream(socket.getInputStream());
dataOut.writeUTF("Hello !!");
msgin.setText("Connected");
Log.d(TAG, "Completed..");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
msgin.setText("Not connected");
alertbox("Main", "ERROR: " + e.getMessage());
Log.d(TAG, "ERROR: " + e.getMessage());
}
}
};
Server code:
try {
mySSLServerFac = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
mySSLServerSocket = (SSLServerSocket) mySSLServerFac.createServerSocket(9999);
System.out.println("Listening on 9999\n");
mySSLSocket = (SSLSocket) mySSLServerSocket.accept();
DataInputStream input = new DataInputStream(mySSLSocket.getInputStream());
DataOutputStream output = new DataOutputStream(mySSLSocket.getOutputStream());
do{
System.out.println("Remote IP Address : " + mySSLSocket.getInetAddress());
msg = input.readUTF().toString();
System.out.println(msg);
java.util.Scanner sc = new java.util.Scanner(System.in);
output.writeUTF(sc.nextLine());
}while(msg != "exit");
System.out.println(msg);
} catch (Exception e) {
e.printStackTrace();
}
I am stuck with "No cipher suites in common" error at server. Since i am nowhere in SSL connection setup. Let me help if you find out the bug or major problem.
Here is the link i followed to create certificate and truststore. Truststore and kestore i have created are here
I am using Android 2.2 and BKSProvider 1.46, please let know where i am going wrong. I have to wind up this project as soon as possible.
Thanks in advance.
From the stack trace it looks like exception you caught does not contain a message.
Log.d(TAG, e.getMessage());
It has nothing to do with SSL.
It's solved ! Problem was with the truststore of java host, followed this post.
The trustStore needs to be specified for client/server as they are using the default trustStore, causing failure. Using -Djavax.net.ssl.trustStore=servertruststore.jks -Djavax.net.ssl.trustStorePassword=server on the server and creating own keystore & truststore at client allows the session to complete. It was the -Djavax.net.debug=ssl,handshake which helped lot.
The entire command is : java -Djavax.net.ssl.keyStore=server.jks -Djavax.net.ssl.keyStorePassword=server -Djavax.net.ssl.trustStore=servertruststore.jks -Djavax.net.ssl.trustStorePassword=server SSLServer
Now i am on to creating sslsession and multi-threaded programming.

Categories