SSL Server/Client using Java - java

I'm trying to create a secure connection in Java. For that I created following server and client
Server:
public static void main(String[] args){
try {
// relative keystorepath
String certificateChain = "keystore";
String password = "***";
System.setProperty("javax.net.ssl.keyStore", certificateChain);
System.setProperty("javax.net.ssl.keyStorePassword", password);
SSLServerSocketFactory sslserversocketfactory =
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket sslserversocket =
(SSLServerSocket) sslserversocketfactory.createServerSocket(9999);
SSLSocket sslsocket = (SSLSocket) sslserversocket.accept();
InputStream inputstream = sslsocket.getInputStream();
InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
String string = null;
while ((string = bufferedreader.readLine()) != null) {
System.out.println(string);
System.out.flush();
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
Client:
public static void main(String[] arstring) {
try {
// Pfad zum Truststore
String certificateChain = "/usr/lib64/jvm/java-1.7.0-openjdk-1.7.0/jre/lib/security/cacerts";
String password = "***";
System.setProperty("javax.net.ssl.trustStore", certificateChain);
System.setProperty("javax.net.ssl.trustStorePassword", password);
SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("localhost", 9999);
OutputStream outputstream = sslsocket.getOutputStream();
OutputStreamWriter outputstreamwriter = new OutputStreamWriter(outputstream);
BufferedWriter bufferedwriter = new BufferedWriter(outputstreamwriter);
String string = "testmessage";
bufferedwriter.write(string + '\n');
bufferedwriter.flush();
} catch (Exception exception) {
exception.printStackTrace();
}
}
After that I tried adding my certificate to the Truststore at the specific path.
The generated key was added to the keystore in the working directory.
If tried to follow all the tutorials and instructions on the first 5 pages of google using many different keywords, without luck. I'm always getting the handshake_failure Exception:
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:1959)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1077)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:702)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:122)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
at java.io.BufferedWriter.flush(BufferedWriter.java:254)
at client.SSLClientMain.main(SSLClientMain.java:151)
Since the code is just copy-pasted I think it's not a codeproblem, but a certificate problem. So my question is:
what am I doing wrong, what do I need to do more?

You may be using a certificate in Server side which may not be in Client side and vice versa.
Try it out with same certificate for server and client.

Related

ServerSocket Not Accepting Upon Conversion to SSLSocket(Null Pointer Exception) [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 4 years ago.
I've been trying to convert a Client/Server model I made in Java using sockets to SSL. After generating my PKCS12 file containing the server's root and intermediate files, I used System.setProperty to change the trust and keystores in the client and server files to the PKCS file. I'm not really sure if that's what your meant to do. I also made the changes to my sockets, using an SSLSocketFactory to create the necessary sockets.
Here is the Code Below.
Client:
`public class Client
{
private SSLSocket client_socket;
private DataOutputStream output_stream;
private FileReader reader;
private BufferedReader buffer_reader;
public Client(String address, int port)
{
System.setProperty("javax.net.ssl.keyStore", "wa.p12");
System.setProperty("javax.net.ssl.keyStorePassword", "namihana");
System.setProperty("javax.net.ssl.keyStoreType", "PKCS12");
System.setProperty("javax.net.ssl.trustStore", "wa.p12");
System.setProperty("javax.net.ssl.trustStorePassword", "namihana");
System.setProperty("javax.net.ssl.TrustStoreType", "PKCS12");
// System.setProperty("javax.net.ssl.trustStoreType", "PKCS12");
Security.addProvider(new Provider());
try
{
SSLSocketFactory ssf = (SSLSocketFactory) SSLSocketFactory.getDefault();
client_socket = (SSLSocket) ssf.createSocket("127.0.0.1", 8072);
client_socket.startHandshake();
public class Server
{
public Socket socket_2;
public SSLServerSocket server_socket;
public InputStreamReader input_stream;
private BufferedReader buffer_reader;
private DataOutputStream output_sender;
private PrintWriter output_writer;
private boolean result;
private char[] multichoice_answers;
Server:
public Server(int port)
{
System.setProperty("javax.net.ssl.keyStore", "wa.p12");
System.setProperty("javax.net.ssl.keyStorePassword", "namihana");
System.setProperty("javax.net.ssl.keyStoreType", "PKCS12");
System.setProperty("javax.net.ssl.trustStore", "wa.p12");
System.setProperty("javax.net.ssl.trustStorePassword", "namihana");
System.setProperty("javax.net.ssl.TrustStoreType", "PKCS12");
multichoice_answers = new char[30];
multichoice_answers[0] = 'A';
multichoice_answers[1] = 'A';
multichoice_answers[2] = 'D';
multichoice_answers[3] = 'C';
multichoice_answers[4] = 'C';
multichoice_answers[5] = 'C';
multichoice_answers[6] = 'D';
multichoice_answers[7] = 'B';
multichoice_answers[8] = 'D';
multichoice_answers[9] = 'B';
multichoice_answers[10] = 'C';
multichoice_answers[11] = 'D';
multichoice_answers[12] = 'A';
multichoice_answers[13] = 'D';
multichoice_answers[14] = 'C';
try
{
SSLServerSocketFactory ssf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket server_socket = (SSLServerSocket) ssf.createServerSocket(port);
System.out.println("Server_socket made");
Security.addProvider(new Provider());
//server_socket.setSoTimeout(100000);
}
catch(Exception e)
{
e.printStackTrace();
}
}
public void receive()
{
try
{
System.out.println("Server connected2");
socket_2 = server_socket.accept();
You have a local ServerSocket variable in your try block that is shadowing the class member.

Java SSL for WebService with Grizzly and HttpsURLConnection

I am writing a web service using Jersey and Grizzly. I want to run it using SSL. I have created server.jks and client.jks just like described here.
Running the web service:
public static HttpServer startServer() {
final ResourceConfig rc = new ResourceConfig().packages("com.mypackage");
SSLContextConfigurator sslContextConfigurator = new SSLContextConfigurator();
sslContextConfigurator.setKeyStoreFile("server.jks");
sslContextConfigurator.setKeyStorePass("changeit");
SSLEngineConfigurator sslEngineConfigurator = new SSLEngineConfigurator(sslContextConfigurator);
return GrizzlyHttpServerFactory.createHttpServer(URI.create(getURI().toString()), rc, true,
sslEngineConfigurator);
}
private static URI getURI() {
URI uri;
// Running on localhost
uri = UriBuilder.fromUri("https://" + "localhost/" + ConstApp.APP_PATH).port(ConstApp.PORT)
.build();
return uri;
}
So running the web service on localhost port 443 with the server.jks.
Now I want to check and test the web service.
Java HTTPClient class:
String https_url = "https://localhost:443/myapp";
URL url;
try {
url = new URL(https_url);
HttpsURLConnection sslCon = (HttpsURLConnection) url.openConnection();
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream stream = new FileInputStream("client.jks");
keyStore.load(stream, "changeit".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, tmf.getTrustManagers(), null);
SSLSocketFactory sslSocketFactory = ctx.getSocketFactory();
sslCon.setSSLSocketFactory(sslSocketFactory);
sslCon.setRequestMethod("GET");
// add request header
sslCon.setRequestProperty("User-Agent", "Mozilla/5.0");
int responseCode = sslCon.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(new InputStreamReader(sslCon.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
// print result
System.out.println(response.toString());
} catch (Exception e) {
e.printStackTrace();
}
Running the HTTPClient result in an exception:
javax.net.ssl.SSLProtocolException: Handshake message sequence violation, 1
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:196)
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.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1513)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338)
at httpClient.HTTPClient.testIt(HTTPClient.java:158)
at httpClient.HTTPClient.main(HTTPClient.java:36)
Can anyone please help me out here and tell me what am I doing wrong?

SOAP - PKIX path building failed

I'm building a server that has to call two webservices. Webservices have the same CA certificate (PKCS12).
the first one receives request by GET, the other one by SOAP call.
follow a part of code that creates connection for GET request
InputStream inputStream = null;
// is https protocol?
if (url.getProtocol().toLowerCase().equals("https")) {
trustAllHosts();
// create connection
HttpsURLConnection httpsUrlConnection = null;
if(proxy != null){
httpsUrlConnection = (HttpsURLConnection) url.openConnection(proxy);
} else {
httpsUrlConnection = (HttpsURLConnection) url.openConnection();
}
// set the check to: do not verify
httpsUrlConnection.setHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
setHeaders(httpsUrlConnection, headers);
//set del certificato
log.debug("set certificate for get...");
File cerp12 = new File(Utils.getWebAppLocalPath(),"WEB-INF"+String.valueOf(File.separatorChar)+PropConfig.getProperty("cer.p12"));
((HttpsURLConnection) httpsUrlConnection).setSSLSocketFactory(security(cerp12,PropConfig.getProperty("cer.pwd")));
httpsUrlConnection.connect();
inputStream = httpsUrlConnection.getInputStream();
} else {
HttpURLConnection httpUrlConnection = null;
if(proxy != null){
httpUrlConnection = (HttpURLConnection) url.openConnection(proxy);
} else {
httpUrlConnection = (HttpURLConnection) url.openConnection();
}
setHeaders(httpUrlConnection, headers);
inputStream = httpUrlConnection.getInputStream();
}
in = new BufferedReader(new InputStreamReader(inputStream));
String inputLine;
while ((inputLine = in.readLine()) != null) {
result.append(inputLine);
}
and this part is for SOAP request
InputStream inputStream = null;
// is https protocol?
if (url.getProtocol().toLowerCase().equals("https")) {
trustAllHosts();
// create connection
HttpsURLConnection httpsUrlConnection = null;
if(proxy != null){
httpsUrlConnection = (HttpsURLConnection) url.openConnection(proxy);
} else {
httpsUrlConnection = (HttpsURLConnection) url.openConnection();
}
// set the check to: do not verify
httpsUrlConnection.setHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
setHeaders(httpsUrlConnection, headers);
//set del certificato
log.debug("set certificate for get...");
File cerp12 = new File(Utils.getWebAppLocalPath(),"WEB-INF"+String.valueOf(File.separatorChar)+PropConfig.getProperty("cer.p12"));
((HttpsURLConnection) httpsUrlConnection).setSSLSocketFactory(security(cerp12,PropConfig.getProperty("cer.pwd")));
httpsUrlConnection.connect();
inputStream = httpsUrlConnection.getInputStream();
} else {
HttpURLConnection httpUrlConnection = null;
if(proxy != null){
httpUrlConnection = (HttpURLConnection) url.openConnection(proxy);
} else {
httpUrlConnection = (HttpURLConnection) url.openConnection();
}
setHeaders(httpUrlConnection, headers);
inputStream = httpUrlConnection.getInputStream();
}
in = new BufferedReader(new InputStreamReader(inputStream));
String inputLine;
while ((inputLine = in.readLine()) != null) {
result.append(inputLine);
}
the code is almost the same
with GET request I have no problem, but with SOAP request httpsUrlConnection.connect(); throws
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Here is howto create ssl context for HTTPS connection.
SSLSocketFactory socketFactory = createSSLContext().getSocketFactory();
HttpsURLConnection connection = (HttpsURLConnection) (url).openConnection();
connection.setSSLSocketFactory(socketFactory);
And method to create SSL context. Note, it load root server certificate from .pem file (x509 format) and client certificate from .p12 (pkcs12 format). If server don't required client certificate, pass null for key managers. If server sertificate issued by authority, which already in $JRE_HOME/lib/security/cacerts, pass null as trust managers.
And one more note: in .pem file you should store root certificate in PKIX path of server certificate. For example, github.com That site has PKIX path CN = github.com -> CN = DigiCert High Assurance EV CA-1 -> CN = DigiCert High Assurance EV Root CA -> CN = GTE CyberTrust Global Root. So you store GTE CyberTrust Global Root
private final SSLContext createSSLContext()
throws NoSuchAlgorithmException, KeyStoreException,
CertificateException, IOException,
UnrecoverableKeyException, KeyManagementException {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream fis = null;
try {
fis = new FileInputStream(new File(Config.getString(Config.KEYSTORE_PATH)));
} catch (Exception ex) {
throw new IOException("not found keystore file: " Config.getString(Config.KEYSTORE_PATH), ex);
}
try{
keyStore.load(fis, Config.getString(Config.KEYSTORE_PASSWORD).toCharArray());
}finally {
IOUtils.closeQuietly(fis);
}
CertificateFactory cf = CertificateFactory.getInstance("X.509");
FileInputStream in = new FileInputStream(Config.getString(Config.HTTPS_SERVER_CERT));
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(null);
try {
X509Certificate cacert = (X509Certificate) cf.generateCertificate(in);
trustStore.setCertificateEntry("alias", cacert);
} finally {
IOUtils.closeQuietly(in);
}
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(trustStore);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(keyStore, Config.getString(Config.KEYSTORE_PASSWORD).toCharArray());
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
return sslContext;
}

Connect to twitter after use SSLSocketFactory

I'm trying to retrieve tweets from the Twitter streaming API using Twitter4J. The project connects to a remote server using an SSLSocket to retrieve some data and, after this, the Twitter4J is called. The problem is that if I establish this connection the Twitter4J arise this exception:
[Wed Feb 20 11:32:02 CET
2013]sun.security.validator.ValidatorException: PKIX path building
failed: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
This doesn't happen if I don't make the connection and I clean the keystore defined with the next lines:
System.clearProperty("javax.net.ssl.trustStore");
System.clearProperty("javax.net.ssl.trustStorePassword");
The code to connect is this one:
private String publishFetcher() throws UnknownHostException, IOException {
// Set trustStore.
System.setProperty("javax.net.ssl.trustStore", properties.getProperty("trustedStore"));
System.setProperty("javax.net.ssl.trustStorePassword", properties.getProperty("trustedStorePassword"));
String host = properties.getProperty("host");
int hostPort = Integer.parseInt(properties.getProperty("host_port"));
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) factory.createSocket(host, hostPort);
// Get input and output streams from socket connection.
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter output = new PrintWriter(socket.getOutputStream());
// Request connection token to controller
String connectionToken = getConnectionToken(input, output);
// Publish fetcher
final int rmiPort = Integer.parseInt(properties.getProperty("rmi_port"));
TwitterFetcher fetcher = new TwitterFetcher(connector);
Fetcher stub = (Fetcher) UnicastRemoteObject.exportObject(fetcher, 0);
Registry registry = LocateRegistry.createRegistry(rmiPort);
registry.rebind(connectionToken, stub);
// Send RMI port
output.write(String.valueOf(rmiPort) + "\n");
output.flush();
input.close();
output.close();
// Clean trusteStore properties.
System.clearProperty("javax.net.ssl.trustStore");
System.clearProperty("javax.net.ssl.trustStorePassword");
return connectionToken;
}
I think that the problem is related with SSLSocketFactory because I tested somethings in a different project. For example, this code works like a charm:
SSLSocketFactory deffactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
System.setProperty("javax.net.ssl.trustStore", "sttv_keystore");
System.setProperty("javax.net.ssl.trustStorePassword", "Smart.Table");
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
factory = deffactory;
// Twitter4J code...
But this code doesn't work:
System.setProperty("javax.net.ssl.trustStore", "sttv_keystore");
System.setProperty("javax.net.ssl.trustStorePassword", "Smart.Table");
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
// Twitter4J code...
I can't do the same in my real project because breaks... almost everything ^^
What could be the problem? and the solution?
The problem with the code is that I was replacing the trust store instead of creating a new one for my app. The code that solves the problems is the next one:
private SSLSocket getSSLSocket() throws TrackerSSLConnectionException {
try {
// Load properties.
String keystore = properties.getProperty("keystore");
String passphrase = properties.getProperty("keystorePassphrase");
String host = properties.getProperty("host");
int hostPort = Integer.parseInt(properties.getProperty("host_port"));
// Create keystore.
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(new FileInputStream(keystore), passphrase.toCharArray());
// Get factory for the given keystore.
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
SSLContext ctx = SSLContext.getInstance("SSL");
ctx.init(null, tmf.getTrustManagers(), null);
SSLSocketFactory factory = ctx.getSocketFactory();
return (SSLSocket) factory.createSocket(host, hostPort);
} catch (Exception e) {
throw new TrackerSSLConnectionException(e.getMessage(), e.getCause());
}
}
private String publishFetcher() throws TrackerSSLConnectionException, IOException {
// Get socket connection.
SSLSocket socket = getSSLSocket();
// Get input and output streams from socket.
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter output = new PrintWriter(socket.getOutputStream());
// Request connection token to controller.
String connectionToken = getConnectionToken(input, output);
// Publish fetcher.
final int rmiPort = Integer.parseInt(properties.getProperty("rmi_port"));
TwitterFetcher fetcher = new TwitterFetcher(connector);
Fetcher stub = (Fetcher) UnicastRemoteObject.exportObject(fetcher, 0);
Registry registry = LocateRegistry.createRegistry(rmiPort);
registry.rebind(connectionToken, stub);
// Send RMI port.
output.write(String.valueOf(rmiPort) + "\n");
output.flush();
input.close();
output.close();
return connectionToken;
}

Why is FileInputStream closing

I am trying to read a video file from local storgae by chunks and upload to a server. I have this code working in another java platform so i thought it would be quite simple.
When i try to open the File using
File f = new File(filePath);
fileIn = new FileInputStream(f);
it opens and i can read whatever i need from the file, further down in my code though i call
SocketFactory socketFactory = SSLSocketFactory.getDefault();
Socket socket = socketFactory.createSocket(url, 443);
_in = new InputStreamReader(socket.getInputStream());
_out = (OutputStream)socket.getOutputStream();
The socket connects fine but when I then come to read the FileInputStream after this bit of code I get stream closed exception.
Any ideas? I don't see anything in the log to show anything is failing but i can't read from the fileinputstream once i have conencted to the server??
Let me know if you need to know anything else to help.
This example worked for me:
public class MainClass {
public static void main(String[] args) {
String host = args[0];
int port = Integer.parseInt(args[1]);
try {
System.out.println("Locating socket factory for SSL...");
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
System.out.println("Creating secure socket to " + host + ":" + port);
SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
System.out.println("Enabling all available cipher suites...");
String[] suites = socket.getSupportedCipherSuites();
socket.setEnabledCipherSuites(suites);
System.out.println("Registering a handshake listener...");
socket.addHandshakeCompletedListener(new MyHandshakeListener());
System.out.println("Starting handshaking...");
socket.startHandshake();
System.out.println("Just connected to " + socket.getRemoteSocketAddress());
} catch (IOException e) {
e.printStackTrace();
}
}
}
class MyHandshakeListener implements HandshakeCompletedListener {
public void handshakeCompleted(HandshakeCompletedEvent e) {
System.out.println("Handshake succesful!");
System.out.println("Using cipher suite: " + e.getCipherSuite());
}
}
As snicolas said, socket.startHandshake() could fix your prob.
you didn't call socket.startHandshake();

Categories