getLocalCertificates() return null - java

I'm trying to write a simple ssl server socket and client socket program. first i get some real certificate and then i used the first code to generate keystore for it. then i wrote server and client code so my server use that keystore as server certificate but no certificate sent during connection and session.getLocalCertificates() only return null
my keystore generating code:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.security.KeyStore;
import java.security.cert.CertPath;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
public class MainClass {
public static void main(String args[]) throws Exception {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
List mylist = new ArrayList();
FileInputStream in = new FileInputStream("C:\\Users\\nima\\Downloads\\72315359_example.com.cert");
Certificate cr = cf.generateCertificate(in);
mylist.add(cr);
CertPath cp = cf.generateCertPath(mylist);
System.out.println(cp);
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(null, null);
List cplist = cp.getCertificates();
Object[] o = cplist.toArray();
for (int i = 0; i < o.length; i++) {
X509Certificate c = (X509Certificate) o[i];
ks.setCertificateEntry("my" + i, c);
}
FileOutputStream output = new FileOutputStream("C:\\Users\\nima\\Downloads\\test.dat");
ks.store(output, "mypass".toCharArray());
output.close();
}
}
my server code:
import java.io.PrintStream;
import java.math.BigInteger;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
public class MainClass {
public static void main(String args[]) throws Exception {
System.setProperty("javax.net.ssl.keyStore", "C:\\Users\\nima\\Downloads\\test.dat");
System.setProperty("javax.net.ssl.keyStorePassword", "mypass");
SSLServerSocketFactory ssf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
ServerSocket ss = ssf.createServerSocket(5432);
while (true) {
Socket s = ss.accept();
SSLSession session = ((SSLSocket) s).getSession();
Certificate[] cchain2 = session.getLocalCertificates();
for (int i = 0; i < cchain2.length; i++) {
System.out.println(((X509Certificate) cchain2[i]).getSubjectDN());
}
System.out.println("Peer host is " + session.getPeerHost());
System.out.println("Cipher is " + session.getCipherSuite());
System.out.println("Protocol is " + session.getProtocol());
System.out.println("ID is " + new BigInteger(session.getId()));
System.out.println("Session created in " + session.getCreationTime());
System.out.println("Session accessed in " + session.getLastAccessedTime());
PrintStream out = new PrintStream(s.getOutputStream());
out.println("Hi");
out.close();
s.close();
}
}
}
my client code:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.net.Socket;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
public class MainClass {
public static void main(String args[]) throws Exception {
System.setProperty("javax.net.ssl.trustStore", "C:\\Users\\nima\\Downloads\\test.dat");
SSLSocketFactory ssf = (SSLSocketFactory) SSLSocketFactory.getDefault();
Socket s = ssf.createSocket("127.0.0.1", 5432);
SSLSession session = ((SSLSocket) s).getSession();
Certificate[] cchain = session.getPeerCertificates();
System.out.println("The Certificates used by peer");
for (int i = 0; i < cchain.length; i++) {
System.out.println(((X509Certificate) cchain[i]).getSubjectDN());
}
System.out.println("Peer host is " + session.getPeerHost());
System.out.println("Cipher is " + session.getCipherSuite());
System.out.println("Protocol is " + session.getProtocol());
System.out.println("ID is " + new BigInteger(session.getId()));
System.out.println("Session created in " + session.getCreationTime());
System.out.println("Session accessed in " + session.getLastAccessedTime());
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
String x = in.readLine();
System.out.println(x);
in.close();
}
}
my server code is from here and in both server and client side i get null from getLocalCertificates. It's also possible that all of my code would be wrong.

(From comments, expanded slightly)
If SSLSocket.getSession() is called before the handshake is done, it tries to do it, but if the handshake fails getSession() swallows the exception and just returns a 'nullSession' object which doesn't have the data a real session object would. Either (1) set sysprop javax.net.debug=ssl (at startup, usually on commandline with -D) and look at what it logs to see what is wrong with your handshake or (2) explicitly call ((SSLSocket)s).startHandshake() (which in spite of the name actually runs the handshake to completion, successful or not) and see what it throws.
In particular if you use the keystore file created by the first code shown, that contains only a certificate (trustedCertEntry) NOT a privateKeyEntry (with both privatekey and certificate/chain) as is necessary and required for an SSL/TLS server to use any of the common and default-enabled suites; this error will usually manifest, somewhat confusingly, as a handshake failure with 'no cipher[suite] in common' or 'no cipher[suite] overlap'.
That second part (SSL/TLS server without a privatekey doesn't work) has been asked and answered many times, but I don't recall any dupes that also include the 'getSession masks the error' part.

Related

Unsupported or unrecognized SSL message, cannot be read

I am trying to display the date on an HTTPS website via an SSL server.
I am getting an error thrown on line 31 (I have marked where it is).
I reckon it might be to do with the browser and how it is set up. Since the error is coming from an unsupported message.
Code:
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Date;
public class SSLServer {
final static String pathToStores = "keys";
final static String keyStoreFile = "server-key.pem";
final static String password = "";
final static int port = 8080;
static boolean debug = false;
void doServerSide() throws Exception {
SSLServerSocketFactory sslServerSocketFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(port);
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
InputStream inputStream = sslSocket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line = "";
///////////////////// exception thrown on the line below /////////////////////
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
OutputStream outputStream = sslSocket.getOutputStream();
String httpResponce = "HTTP/1.1 200 OK\r\n\r\n" + new Date();
outputStream.write(httpResponce.getBytes(StandardCharsets.UTF_8));
sslSocket.close();
}
public static void main(String[] args) throws Exception {
String trustFilename = pathToStores + "/" + keyStoreFile;
System.setProperty("java.net.ssl.keyStore", trustFilename);
System.setProperty("javax.net.ssl.keyStorePassword", password);
if (debug) System.getProperty("java.net.debug", "all");
new SSLServer().doServerSide();
}
}
Exception:
Exception in thread "main" javax.net.ssl.SSLException: Unsupported or unrecognized SSL message
at java.base/sun.security.ssl.SSLSocketInputRecord.handleUnknownRecord(SSLSocketInputRecord.java:451)
at java.base/sun.security.ssl.SSLSocketInputRecord.decode(SSLSocketInputRecord.java:175)
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:110)
at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1497)
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1403)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:441)
at java.base/sun.security.ssl.SSLSocketImpl.ensureNegotiated(SSLSocketImpl.java:903)
at java.base/sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:994)
at java.base/sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:297)
at java.base/sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:339)
at java.base/sun.nio.cs.StreamDecoder.read(StreamDecoder.java:188)
at java.base/java.io.InputStreamReader.read(InputStreamReader.java:178)
at java.base/java.io.BufferedReader.fill(BufferedReader.java:161)
at java.base/java.io.BufferedReader.readLine(BufferedReader.java:329)
at java.base/java.io.BufferedReader.readLine(BufferedReader.java:396)
at SSLServer.doServerSide(SSLServer.java:31)
at SSLServer.main(SSLServer.java:51)
I am using firefox and chrome for testing.
Thanks :)

Web View in Java doesn't load Images when using loadContent

Background: I'm getting introduced to clients and servers, and decided to make a simple proxy server.
What the code does as of now: The client side asks for a www.(enter site here).whatever (org, com, edu, etc.) then, the server takes that input in, and calls my WebsiteToHTML class, which converts that whole page to a byte array. The server then stores that byte array to it's own byte array variable. The server then sends the size of that array back to the client, and then sends the byte array itself back to the client. Then, the client makes a byte array of the size sent from the server, and then makes the byte array equal to the byte array that the server sent back. I then have an html string that is made from looping through the byte array and appending all of the chars to the String. I then use WebView to output that String using the loadContent function.
My Problem: My problem lies in outputting images. For instance, if I wanted to go to www.google.com, my code would run perfectly, and the WebView does indeed output the google page. However, the big "Google" logo simply just says "google" in text. My guess is that the WebView doesn't pull the images from the href in the html. Thus, I am here.
My Code:
ProxyClient:
package proxy;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
import java.awt.AWTEvent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
import javax.swing.JButton;
import javafx.application.*;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
#SuppressWarnings("restriction")
public class ProxyClient extends Application{
public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
final String IP = "localhost";
byte[] b;
final int PORT = 4444;
String input;
Socket s = new Socket(IP,PORT);
DataOutputStream out = new DataOutputStream(s.getOutputStream());
Scanner scan = new Scanner(System.in);
InputStream inFromServer = s.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
String html = "";
System.out.println("Enter URL: ");
input = scan.next();
out.writeUTF(input);
System.out.println("output sent: " + input);
byte[] htmlBytes = new byte[in.readInt()];
in.read(htmlBytes);
for(int i = 0; i < htmlBytes.length; i++) {
char c = (char)(htmlBytes[i] >= 0 ? htmlBytes[i] : htmlBytes[i]+256);
html += c;
}
System.out.println(html);
primaryStage.setTitle("Proxy Client");
WebView webView = new WebView();
webView.getEngine().loadContent(html);
VBox vBox = new VBox(webView);
Scene scene = new Scene(vBox, 960, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
}
Proxy Server:
package proxy;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
public class ProxyServer {
public static void main(String[] args) throws IOException, InterruptedException {
final int PORT = 4444;
ServerSocket ss = new ServerSocket(PORT);
Socket s = ss.accept();
System.out.println("Connection Established");
DataInputStream in = new DataInputStream(s.getInputStream());
DataOutputStream out = new DataOutputStream(s.getOutputStream());
WebsiteToHTML converter;
String site;
site = "https://"+in.readUTF();
converter = new WebsiteToHTML(site);
byte[] html = converter.write();
System.out.println("Link Receieved received: " + site);
System.out.println("Converted HTMLto byte array: " + Arrays.toString(html));
while(true) {
out.writeInt(html.length);
out.write(html);
}
}
}
WebsiteToHTML:
package proxy;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import javax.net.ssl.HttpsURLConnection;
public class WebsiteToHTML {
URL myurl;
String html;
HttpsURLConnection con;
InputStream ins;
InputStreamReader isr;
BufferedReader in;
String masterString = "";
byte[] b;
public WebsiteToHTML(String httpsURL) throws IOException {
myurl = new URL(httpsURL);
con = (HttpsURLConnection) myurl.openConnection();
ins = con.getInputStream();
isr = new InputStreamReader(ins);
in = new BufferedReader(isr);
}
public byte[] write() throws IOException {
String inputLine;
while ((inputLine = in.readLine()) != null) {
masterString += inputLine + "\n";
}
b = masterString.getBytes();
b = masterString.getBytes(Charset.forName("UTF-8"));
in.close();
return b;
}
}

Java to Android Code

I have coded this client ssl code for java which works great and sends the wave file to a server. I am trying now to change or use this code on Android but I am having problems doing so. The questions that I have are things such as:
How do I set the pathStore and trustStoreFile(which directories are these on the android)?
Where do I upload the certificate file to(trustStoreFile) ?
Are there any settings that I need to configure?
Is this code what I need to use to accomplish the task of sending the wav file to the server that is listening?
Thanks so much !
Please Help !
Here is the ssl client code in :
package admir.network.ssl.client;
import android.provider.Settings;
import java.io.*;
import java.net.*;
import java.security.*;
import javax.net.ssl.SSLSocketFactory;
import org.apache.commons.io.IOUtils;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.TrustManager;
//import com.sun.net.ssl.SSLContext;
//import com.sun.net.ssl.TrustManagerFactory;
//import com.sun.net.ssl.TrustManager;
public class test2 {
private static final String HOST = "X.X.X.X";
private static final int PORT = 5000;
String pwd = System.getProperty("user.dir");
final static String pathToStores = System.setProperty("user.dir","user.dir"+"/java/admir.network.ssl.client/");
final static String trustStoreFile = "cert.jks" ; // filename
public String app = System.setProperty("user.dir",pwd);
public static void main(String[] args) throws Exception {
String trustFileName = pathToStores + "/" + trustStoreFile;
char[] passphrase = "xxxxx".toCharArray();
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(new FileInputStream(trustFileName), passphrase);
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(keystore);
SSLContext context = SSLContext.getInstance("TLS");
TrustManager[] trustManagers = tmf.getTrustManagers();
context.init(null, trustManagers, null);
SSLSocketFactory sf = context.getSocketFactory();
Socket s = sf.createSocket(HOST, PORT);
String FILE_TO_SEND = ""+ System.getProperty("user.dir")+"/"+"src"+"/"+"Voice 005.wav"+"";
File soundFile = AudioUtil.getSoundFile(FILE_TO_SEND);
if (s.isBound()){
OutputStream out = s.getOutputStream();
InputStream in = new FileInputStream(soundFile);
IOUtils.copy(in, out);
System.out.println("Done Sending.");
out.close();
}
s.close();
}
}

Creation of an HTTPS server in Java

I have been trying to create a simple HTTPS server in my application. I am able to get the server running while also finishing the 'SSL context creation' without errors( where I have included the System.out.println("SSL context created ...\n");).
However, I am unable to connect to it through a browser or even a java written client. a java written client returns a NoHttpResponseException when I attempt to connect to this application.
" Exception in thread "main" org.apache.http.NoHttpResponseException: localhost:8000 failed to respond "
So, is it possible to point out what I am missing in the below code? Thanks
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsParameters;
import com.sun.net.httpserver.HttpsServer;
import java.io.FileInputStream;
import java.security.KeyStore;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.TrustManagerFactory;
public class HTTPSserver {
public static void main(String[] args) throws Exception {
char[] password = "SSLauthentication".toCharArray();
KeyStore ks = KeyStore.getInstance("JKS");
FileInputStream fileInput = new FileInputStream("C:\\Files\\Certificates\\clientkeystore");
ks.load(fileInput, password);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, password);
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ks);
SSLContext ssl = SSLContext.getInstance("TLS");
ssl.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
HttpsServer server = HttpsServer.create(new InetSocketAddress(8000), 0);
server.setHttpsConfigurator (new HttpsConfigurator(ssl)
{
#Override
public void configure (HttpsParameters params)
{
try
{
SSLContext c = getSSLContext();
SSLParameters sslparams = c.getDefaultSSLParameters();
params.setSSLParameters(sslparams);
System.out.println("SSL context created ...\n");
}
catch(Exception e2)
{
System.out.println("Invalid parameter ...\n");
e2.printStackTrace();
}
}
});
server.createContext("/test", new MyHandler());
server.setExecutor(null);
server.start();
}
static class MyHandler implements HttpHandler {
#Override
public void handle(HttpExchange HTTPmessage) throws IOException {
if("GET".equals(HTTPmessage.getRequestMethod()))
{
String response = "This is aaa response";
HTTPmessage.sendResponseHeaders(200, response.length());
OutputStream os = HTTPmessage.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
}
}

Soap Server WSDL viewable in browser, but wont load any functions in SoapUI

I just recently installed BoneCP on my soap server to prevent too many mysql connections being made when people hit the soap server. Before I switched over to boneCP the soap server was working, however now after I've installed boneCP I can see the WSDL if I go directly to the link for it, but when I load that same link into soapUI it loads the wsdl but does not show any functions at all. My code is below:
package testing;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import javax.xml.ws.Endpoint;
import com.jolbox.bonecp.BoneCP;
import com.jolbox.bonecp.BoneCPConfig;
import com.sun.net.httpserver.*;
#WebService
public class test {
static BoneCP connectionPool = null;
static Connection con = null;
#WebMethod
public String login(#WebParam(name="username")String username,#WebParam(name="password") String password) throws SQLException {
con = connectionPool.getConnection();
Statement stmt = null;
String query = " CALL authorize_user('" + username + "','" + password + "')";
try {
stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
String login = rs.getString("au_result");
if (login != null){
con.close();
return login;
}
else {
con.close();
return "Login Failed";
}
}
} catch (SQLException e) {
System.out.println("Error: " + e);
} finally {
if (stmt != null) {
stmt.close();
}
}
con.close();
return "Login Failed";
}
public static void main(String[] args) throws NoSuchAlgorithmException, KeyStoreException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException, KeyManagementException, NoSuchProviderException {
try{
Class.forName("com.mysql.jdbc.Driver");
}catch(Exception e){
e.printStackTrace();
return;
}
try{
BoneCPConfig config = new BoneCPConfig();
config.setJdbcUrl("jdbc:mysql://localhost:" + port + "/test");
config.setUsername(username);
config.setPassword(password);
config.setMinConnectionsPerPartition(5);
config.setMaxConnectionsPerPartition(10);
config.setPartitionCount(1);
connectionPool = new BoneCP(config);
if(con != null){
System.out.println("Connection successful");
}
}catch(Exception e){
e.printStackTrace();
}
test test = new test();
Endpoint endpoint = Endpoint.create(test);
String uri = "/testing";
String keystoreFile = "keystore.jks";
String keyPass = "test_pass";
int port = 8080;
SSLContext ssl = SSLContext.getInstance("TLS");
KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
KeyStore store = KeyStore.getInstance("JKS");
store.load(new FileInputStream(keystoreFile),keyPass.toCharArray());
keyFactory.init(store, keyPass.toCharArray());
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(store);
ssl.init(keyFactory.getKeyManagers(),
trustFactory.getTrustManagers(), new SecureRandom());
HttpsConfigurator configurator = new HttpsConfigurator(ssl);
HttpsServer httpsServer = HttpsServer.create(new InetSocketAddress(port), 50);
System.out.println("https server: " + httpsServer.getAddress());
httpsServer.setHttpsConfigurator(configurator);
com.sun.net.httpserver.HttpContext httpContext = httpsServer.createContext(uri);
httpsServer.start();
endpoint.publish(httpContext);
}
}
This code is basically exactly the same as the working code I was using a week ago except for the boneCP section in the main method.
For anyone who is intersted and may have this problem in the future: I found the error within my code, it wasn't actually realated to boneCP at all, instead of had to do with the #webparam(name = "") code on some of the other functions in my code. These had spaces in the name, and so were causing problems within the soap server.

Categories

Resources