SSL exceptions with existing certfiicates - java

Below is our code snippet to connect to a third party using SSL. Most of the solutions I found at SOF are for importing the certs to truststore, which I belive I am already doing as part of the below code. Nothing had changed and the certificate is still valid.
I had this code working until last week and now I am receving the below SSLHandShakeException. Any clues on what might have went wrong would be greatly appreciated.
javax.net.ssl.SSLHandshakeException:
sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to
find valid certification path to requested target
System.setProperties(newprops);
URL url = new URL(getURL());
File inFile = new File(FileLocation);
String path = inFile.getAbsolutePath();
System.out.print("Absolute Pathname "+ path);
KeyStore clientStore = KeyStore.getInstance("PKCS12");
clientStore.load(new FileInputStream(path), Password.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(clientStore, Password.toCharArray());
KeyManager[] kms = kmf.getKeyManagers();
SSLContext sslContext = null;
sslContext = SSLContext.getInstance("TLS");
sslContext.init(kms, null, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
System.out.print("connection "+ connection);
//URLConnection connection = url.openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type","application/json");
connection.setConnectTimeout(getConnectionTimeout());
connection.setReadTimeout(getReadTimeout());
connection.connect();
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
out.write(jsonObjectStr.toString());
System.out.println("OutputStreamWriter : > " + out.toString());
out.close();

Related

Update Ciphers list in JAVA windows

I need to send a secured request using java(jre1.8.0_65) on my Windows,
I used the below code to configure my certs and key factory.
KeyStore ks = KeyStore.getInstance("PKCS12");
//FileInputStream fis = new FileInputStream("certs/tester1024.pfx");
InputStream ins = this.getClass().getClassLoader()
.getResourceAsStream("certs/tester1024.pfx");
ks.load(ins, "1234".toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SUNX509");
kmf.init(ks, "1234".toCharArray());
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(kmf.getKeyManagers(), null, null);
URL obj = new URL(httpURL);
HttpURLConnection connection = (HttpURLConnection) obj.openConnection();
if (connection instanceof HttpsURLConnection) {
((HttpsURLConnection)connection)
.setSSLSocketFactory(sc.getSocketFactory());
}
connection.setRequestMethod(method);
responseCode = connection.getResponseCode();
the above code works but the list of Ciphers sent Client in the "CLIENT HELLO" does not include the Cipher TLS_RSA_WITH_AES_256_CBC_SHA256.
it includes this TLS_RSA_WITH_AES_128_CBC_SHA256
In the Client Hello Ciper list, I want this Cipherto be included.
Please let me do I need to update any thing related to JAVA on windows, because on linux same java application includes both the Ciphers.

Explain the code - SSL

Can any one please explain the below code (labeled "HERE").
Keystore.load() performs what?
Why KeyManagerFactory is used?
I need practical oriented solution.
System.setProperty("1", "/Library/Java/JavaVirtualMachines/jdk1.8.0_51.jdk/Contents/Home/jre");
String jrehome = System.getProperty("1");
String path = jrehome + "/" + "lib" + "/" + "security" + "/" + "cacerts";
char[] ksPass= "changeit".toCharArray();
try {
KeyStore ks = KeyStore.getInstance("JKS"); // <- HERE
System.out.println(ks.toString());
ks.load(new FileInputStream(path), ksPass);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, ksPass);
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
System.out.println(ks.getCertificate("SunX509"));
tmf.init(ks);
SSLContext sc = SSLContext.getInstance("TLS");
sc.getClientSessionContext().setSessionCacheSize(1);
sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
SSLServerSocketFactory ssf = sc.getServerSocketFactory();
SSLServerSocket s = (SSLServerSocket) ssf.createServerSocket(8888); // <-- HERE
System.out.println("Server started:");
}
Keystore.load() is a mandatory call for accessing a keystore else you cannot acces it. The Javadoc says so. Once the keystore has been loaded, it is possible to read existing entries from the keystore, or to write new entries into the keystore. You have some overloaded method for load().
KeyManagerFactory is a class that follows Factory pattern which creates Key Manager instances for managing a specific type of key material for use by secure sockets.

java establish sslsocket use .cer file

I am new to Java and SSLSocket. I want to use a specified .cer file to establish a SSLSocket in client part. I search it in google, but doesn't find good solution to it. And here is my code:
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new BufferedInputStream(new FileInputStream("myCer.cer"));
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
SSLSocket sock = (SSLSocket)context.getSocketFactory().createSocket("...",21000); //"...": here I ignore the host name. The address and port is right.
sock.setUseClientMode(true);
if(sock.isConnected()) {
System.out.println("Connected...");
}
else
{
System.out.println("Connect Fails...");
}
Login.pbLogin login = Login.pbLogin.newBuilder().setUserID("dbs")
.setPassword("abcd1234")
.setNewPassword("")
.setClientVersion("1.0.0.0")
.setRestarted(true)
.build();
OutputStream outputStream =sock.getOutputStream();
byte[] b1=login.getClass().getSimpleName().getBytes("UTF-8");
byte[] b2=login.toByteArray();
byte[] bytes = ByteBuffer.allocate(4).putInt(b1.length + b2.length).array();
outputStream.write(bytes);
outputStream.write(b1); //login.getClass().getSimpleName().getBytes("UTF-8")
outputStream.write(b2); //login.toByteArray()
outputStream.flush();
byte[] content = new byte[100];
int bytesRead = -1;
InputStream inputStream = sock.getInputStream();
String str;
while(( bytesRead = inputStream.read( content) ) != -1){
System.out.println("OK ,receive.....");
// str = new String(Arrays.copyOfRange(content,0,bytesRead), StandardCharsets.UTF_8);
//System.out.println(str);
}
I use TCPViewer to see, the SSLSocket is in Established state, but when executing outstream.write , the SSLsocket will be Close_wait state and cause exception:
Exception in thread "main" java.net.SocketException: Software caused connection abort: socket write error.
So I couldn't write the info to server, and exit program. I guess the SSLSocket is not established successfully, but Tcpviewer show it is established early, and it's in Connected state(print "connected."). But when try to write the outputstream, it will in Close_wait state. Could you help me to sort it out?
Then I found the reason today. The code has no issue, the reason is that server part can't parse the protocol buffer (pblogin) correctly, which causes exception, so it close the socket. As a result , the state will be in close_wait.Since I find the reason , wish I can solve it by myself.

SSL server socket and handshake with known certificate

I am new to SSl server sockets. All I am tying to do is to read data over SSL.
My application listens on port 8000. Please give me few steps on how I can do this. When I have a certificate (on my disc), how can I establish the SSL server socket and read from client ?
Here are my steps
1) reading server.crt from file and making X509Certificate (has public certificate and private key)
2) Getting instance of JKS keystore
3) Get instance of context
4) create server socket over the port (8000)
InputStream in = new DataInputStream(new FileInputStream(new File("server.crt")));
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(null, null);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(in);
in.close();
ks.setCertificateEntry("dts", cert);
char[] newpass = "password".toCharArray();
String name = "mykeystore.ks";
FileOutputStream output = new FileOutputStream(name);
ks.store(output, newpass);
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, "password".toCharArray());
try{
System.setProperty("javax.net.ssl.keyStore","mykeystore.ks");
System.setProperty("javax.net.ssl.keyStorePassword","password");
System.setProperty("javax.net.debug","all");
SSLContext context = SSLContext.getInstance("TLSv1.2");
context.init(kmf.getKeyManagers(), null, null);
SSLServerSocketFactory sslServerSocketfactory = context.getServerSocketFactory();
SSLServerSocket sslServerSocket = (SSLServerSocket)sslServerSocketfactory.createServerSocket(8000);
SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept();
InputStream dataIN = sslSocket.getInputStream();
byte[] hello = new byte[20];
dataIN.read(hello);
System.out.println(new String(hello));
dataIN.close();
} catch (IOException e){
e.printStackTrace();
}
I got the answer for my question, I did research on how to setup my own keystore with self signed certificate. This way helped me.
ping me for a detailed solutions.

file upload using https error?

My code is,
Properties systemProps = System.getProperties();
systemProps.put( "javax.net.ssl.trustStore",
System.getProperty("catalina.home")+fs+".keystore");
System.setProperties(systemProps);
try {
// Open a secure connection.
URL url = new URL( "https://192.168.6.45:8181/erp_adapter/UploadFile" );
String requestParams = "uid=sdfn&password=rsdftesan&active=y&type=F";
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
// Set up the connection properties
con.setRequestProperty( "Connection", "close" );
con.setDoInput(true);
con.setDoOutput(true);
con.setUseCaches(false);
con.setConnectTimeout( 30000 );
con.setReadTimeout( 30000 );
con.setRequestMethod( "POST" );
con.setRequestProperty( "Content-Type", "application/x-www-form-urlencoded" );
con.setRequestProperty( "Content-Length", Integer.toString(requestParams.length()) );
// Set up the user authentication portion of the handshake with the private
// key provided by NAIMES Tech Support.
// Based on an example posted by Torsten Curdt on his blog:
// http://vafer.org/blog/20061010073725 (as of Nov, 2009)
File pKeyFile = new File(System.getProperty("catalina.home")+fs+".keystore");
String pKeyPassword = "UB#20abba";
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
KeyStore keyStore = KeyStore.getInstance("PKCS12");
InputStream keyInput = new FileInputStream(pKeyFile);
//byte[] Password=pKeyPassword.getBytes();
keyStore.load(keyInput, pKeyPassword.toCharArray());
keyInput.close();
Here it shows an error as,
java.io.IOException: DerInputStream.getLength(): lengthTag=109, too big.
at sun.security.util.DerInputStream.getLength(Unknown Source)
at sun.security.util.DerValue.init(Unknown Source)
at sun.security.util.DerValue.(Unknown Source)
at com.sun.net.ssl.internal.pkcs12.PKCS12KeyStore.engineLoad(Unknown Source)
at java.security.KeyStore.load(Unknown Source)
at com.gofrugal.raymedi.erp.util.AidapClient.main(AidapClient.java:58)
Can any one help me what is the problem and to resolve it?
The keystore you're trying to load probably isn't an instance of a Sun PKCS12 keystore. Issue the following command to find out the type of the keystore...
keytool -list -keystore <keystore_location>
You'll find output that looks like...
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 76 entries
...
In this case the Keystore is a JKS keystore (which I'm guessing yours is too) and you'll want to do
KeyStore.getInstance("JKS");
Instead of what you have.

Categories