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.
Related
Look at the bottom of this question for more up to date information
I am trying to intercept all SSL handshakes (so that I can get information on them as well as present visual information to users, much like the green lock in browsers) that happen through my Jersey client. Unfortunately it does not seem like Jersey is using my SSLSocketFactory implementation, because none of the createSocket methods are called. No errors occur, it is just that nothing gets logged. The code should be clear:
Invocation + Instantiation:
this.httpClient = getHttpsClient(new DefaultSSLContextProvider());
Invocation.Builder invBuilder = httpClient.target(API_URL_PRIVATE + API_VERSION_2 + "markets").request(MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN, MediaType.TEXT_HTML);
invBuilder.header("Content-Type", "application/x-www-form-urlencoded");
invBuilder.header("User-Agent", USER_AGENT);
Response response = invBuilder.get();
logger.debug("response: " + response);
httpClient:
public Client getHttpsClient(SSLContextProvider sslContextProvider) throws KeyStoreException
{
ClientConfig config = new ClientConfig().connectorProvider(new HttpUrlConnectorProvider().connectionFactory(
url ->
{
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(sslContextProvider.getSSLSocketFactory());
return connection;
}));
return ClientBuilder.newBuilder()
.sslContext(sslContextProvider.getSSLContext())
.withConfig(config)
.build();
}
DefaultSSLContextProvider:
public class DefaultSSLContextProvider implements SSLContextProvider
{
private SSLContext sslContext;
private ObservableSSLSocketFactory observableSSLSocketFactory;
private static final Logger logger = LoggerFactory.getLogger(DefaultSSLContextProvider.class);
public DefaultSSLContextProvider()
{
try
{
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509");
sslContext = SSLContext.getInstance("SSL");
KeyStore keyStore = getKeyStore();
trustManagerFactory.init(keyStore);
sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
observableSSLSocketFactory = new ObservableSSLSocketFactory(sslContext);
HttpsURLConnection.setDefaultSSLSocketFactory(observableSSLSocketFactory);
SSLContext.setDefault(sslContext);
}
catch (NoSuchAlgorithmException e)
{
throw new RuntimeException(e);
}
catch (KeyManagementException | KeyStoreException e)
{
logger.error("could not create DefaultSSLContextProvider", e);
throw new IllegalStateException(e);
}
}
#Override
public SSLContext getSSLContext()
{
return sslContext;
}
#Override
public SSLSocketFactory getSSLSocketFactory()
{
return observableSSLSocketFactory;
}
#Override
public KeyStore getKeyStore()
{
// snip
}
}
ObservableSSLSocketFactory:
/**
* Based heavily on:
* http://stackoverflow.com/a/23365536/3634630
*/
public class ObservableSSLSocketFactory extends SSLSocketFactory
{
private final SSLContext sslContext;
private final String[] preferredCipherSuites;
private final String[] preferredProtocols;
private static final Logger logger = LoggerFactory.getLogger(ObservableSSLSocketFactory.class);
protected ObservableSSLSocketFactory(SSLContext sslContext)
{
logger.debug("CREATING OBSERVABLE SOCKET FACTORY!");
this.sslContext = sslContext;
preferredCipherSuites = getCiphers();
preferredProtocols = getProtocols();
logger.debug("Observable socket factory created");
logger.debug("preferredCipherSuites: " + preferredCipherSuites);
logger.debug("preferredProcotols: " + preferredProtocols);
}
#Override
public String[] getDefaultCipherSuites()
{
return preferredCipherSuites;
}
#Override
public String[] getSupportedCipherSuites()
{
return preferredCipherSuites;
}
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException
{
logger.debug("creating ssl socket");
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(s, host, port, autoClose);
sslSocket.addHandshakeCompletedListener(new HandshakeListener());
sslSocket.setEnabledProtocols(preferredProtocols);
sslSocket.setEnabledCipherSuites(preferredCipherSuites);
return sslSocket;
}
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException
{
logger.debug("creating ssl socket");
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(address, port, localAddress, localPort);
sslSocket.addHandshakeCompletedListener(new HandshakeListener());
sslSocket.setEnabledProtocols(preferredProtocols);
sslSocket.setEnabledCipherSuites(preferredCipherSuites);
return sslSocket;
}
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException
{
logger.debug("creating ssl socket");
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
SSLSocket sslSocket = (SSLSocket)sslSocketFactory.createSocket(host, port, localHost, localPort);
sslSocket.addHandshakeCompletedListener(new HandshakeListener());
sslSocket.setEnabledProtocols(preferredProtocols);
sslSocket.setEnabledCipherSuites(preferredCipherSuites);
return sslSocket;
}
public Socket createSocket(InetAddress host, int port) throws IOException
{
logger.debug("creating ssl socket");
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
SSLSocket sslSocket = (SSLSocket)sslSocketFactory.createSocket(host, port);
sslSocket.addHandshakeCompletedListener(new HandshakeListener());
sslSocket.setEnabledProtocols(preferredProtocols);
sslSocket.setEnabledCipherSuites(preferredCipherSuites);
return sslSocket;
}
public Socket createSocket(String host, int port) throws IOException
{
logger.debug("creating ssl socket");
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
SSLSocket sslSocket = (SSLSocket)sslSocketFactory.createSocket(host, port);
sslSocket.addHandshakeCompletedListener(new HandshakeListener());
sslSocket.setEnabledProtocols(preferredProtocols);
sslSocket.setEnabledCipherSuites(preferredCipherSuites);
return sslSocket;
}
private String[] getProtocols()
{
// snip
}
private String[] getCiphers()
{
// snip
}
class HandshakeListener implements HandshakeCompletedListener
{
public HandshakeListener()
{
logger.debug("Created new HandshakeListener");
}
public void handshakeCompleted(HandshakeCompletedEvent e)
{
logger.debug("Handshake successful!");
logger.debug("using cipher suite: " + e.getCipherSuite());
}
}
}
As I said, no exceptions or errors occur (and indeed the original request goes through with no problem (HTTP 200), however the only things that are logged are:
00:01:37.867 DEBUG [ObservableSSLSocketFactory] CREATING OBSERVABLE SOCKET FACTORY!
00:01:38.072 DEBUG [ObservableSSLSocketFactory] Observable socket factory created
00:01:38.073 DEBUG [ObservableSSLSocketFactory] preferredCipherSuites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
00:01:38.073 DEBUG [ObservableSSLSocketFactory] preferredProcotols: [TLSv1, TLSv1.1, TLSv1.2]
00:01:39.435 DEBUG [Exchange] response: InboundJaxrsResponse{context=ClientResponse{method=GET, uri=https://www.bitstamp.net/api/order_book/, status=200, reason=OK}}
Nothing from createSocket()'s or the HandshakeCompletedListener.
Any help would be greatly appreciated.
Update 1:
I added some additional log statements, and the situation is indeed strange. The Jersey client is in fact calling the HttpUrlConnectorProvider implementation, and in fact an instance of ObservableSSLSocketFactory is set on the connection, it appears that when the connect method is called on the HttpsURLConnection, it does not use the socket factory.
Update 2:
I found an old bug which is titled: "HttpsURLConnection not using the set SSLSocketFactory for creating all its Sockets". This seems to be my exact problem. This bug was stated to be fixed sometime in JDK7. I am using (as stated) 8u60, which is quite beyond the time this bug was fixed. I am quite puzzled. I found the java argument -Djavax.net.debug=all and set it - I did not see any errors or anything out of place, it seems to be that the HttpsUrlConnection is not using the SSLSocketFactory set on it.
Update 3:
Taking a suggestion from wyvern on #java # irc.freenode.net, I decided to use the apache-connector instead of the JDK HttpsUrlConnection connector, and finally after some smudging and coaxing, I am presented with:
[HandshakeCompletedNotify-Thread][ObservableSSLConnectionSocketFactory] Handshake successful!
So, I guess I am all set then =).
Before making the SSL handshake make sure the client and service have the correct certificates are installed on both(client and service) the server. Refer to url:http://www.programcreek.com/java-api-examples/index.php?api=javax.net.ssl.SSLSocketFactory for SSLFactory Implementation
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
I developed a Chat Server and client using Sockets and everything has been fine until I read somewhere online that ordinary Socket communication is vulnerable to attacks. After googling a while, I came across this page that showed a sample SSLServerSocket and SSLSocket implementation (code below).
I will like to know if the communication between my server and client is secure if I follow steps in the below code.
Server Code
class EchoServer {
public static void main(String[] args) throws IOException {
SSLServerSocket sslServerSocket = null;
try {
SSLServerSocketFactory sslServerSocketFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(9999);
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
PrintWriter out = new PrintWriter(sslSocket.getOutputStream(),true);
BufferedReader in = new BufferedReader(new InputStreamReader(sslSocket.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
out.println(inputLine);
}
} finally {
if (sslServerSocket != null) {
try {
sslServerSocket.close();
} catch (IOException x) {
// handle error
}
}
}
}
}
Client Code
class EchoClient {
public static void main(String[] args) throws IOException {
SSLSocket sslSocket = null;
try {
SSLSocketFactory sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
sslSocket = (SSLSocket) sslSocketFactory.createSocket("localhost", 9999);
PrintWriter out = new PrintWriter(sslSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(sslSocket.getInputStream()));
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String userInput;
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
System.out.println(in.readLine());
}
} finally {
if (sslSocket != null) {
try {
sslSocket.close();
} catch (IOException x) {
// handle error
}
}
}
}
}
You should get the peer certificate via a HandshakeCompletionListener or the SSLSession to verify that you're talking to the host you think you're talking to. Other than that your code is OK from the security point of view.
However you should also be aware that you shouldn't use PrintWriter over a network, as it swallows exceptions.
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.
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;
}
If I have:
System.setProperty("javax.net.ssl.keyStore", '/etc/certificates/fdms/WS1001237590._.1.ks');
System.setProperty("javax.net.ssl.keyStorePassword", 'DV8u4xRVDq');
System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true");
I'm able to open a secure connection without a problem.
However, I'd like to have the certificates stored directly in the war, so I use: (The file input stream will eventually become a resource stream, but I'm doing this to get it to work.)
System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true");
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("/etc/certificates/fdms/WS1001237590._.1.ks"), "DV8u4xRVDq".toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, "DV8u4xRVDq".toCharArray());
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(kmf.getKeyManagers(), null, null);
Now, if I open the same connection, I get: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
I had to do something similar a while back. I had a certificate file and I had to figure out a way to load it in and use it for an SSL connection. Hopefully what I did will help you out.
First I had to create a trust manager:
public class MyX509TrustManager implements X509TrustManager {
X509TrustManager pkixTrustManager;
MyX509TrustManager() throws Exception {
String certFile = "/certificates/MyCertFile.cer";
Certificate myCert = CertificateFactory.getInstance("X509").generateCertificate(this.getClass().getResourceAsStream(valicertFile));
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(null, "".toCharArray());
keyStore.setCertificateEntry("myCert", myCert);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX");
trustManagerFactory.init(keyStore);
TrustManager trustManagers[] = trustManagerFactory.getTrustManagers();
for(TrustManager trustManager : trustManagers) {
if(trustManager instanceof X509TrustManager) {
pkixTrustManager = (X509TrustManager) trustManager;
return;
}
}
throw new Exception("Couldn't initialize");
}
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
pkixTrustManager.checkServerTrusted(chain, authType);
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
pkixTrustManager.checkServerTrusted(chain, authType);
}
public X509Certificate[] getAcceptedIssuers() {
return pkixTrustManager.getAcceptedIssuers();
}
}
After that I had to create a socket factory that used my trust manager:
public class MySSLProtocolSocketFactory implements SecureProtocolSocketFactory {
private SSLContext sslContext = null;
public MySSLProtocolSocketFactory() {
super();
}
private static SSLContext createMySSLContext() {
try {
MyX509TrustManager myX509TrustManager = new MyX509TrustManager();
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new MyX509TrustManager[] { myX509TrustManager}, null);
return context;
}
catch(Exception e) {
Log.error(Log.Context.Net, e);
return null;
}
}
private SSLContext getSSLContext() {
if(this.sslContext == null) {
this.sslContext = createMySSLContext();
}
return this.sslContext;
}
public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException {
return getSSLContext().getSocketFactory().createSocket(host, port, clientHost, clientPort);
}
public Socket createSocket(final String host, final int port, final InetAddress localAddress, final int localPort, final HttpConnectionParams params) throws IOException {
if(params == null) {
throw new IllegalArgumentException("Parameters may not be null");
}
int timeout = params.getConnectionTimeout();
SocketFactory socketFactory = getSSLContext().getSocketFactory();
if(timeout == 0) {
return socketFactory.createSocket(host, port, localAddress, localPort);
}
else {
Socket socket = socketFactory.createSocket();
SocketAddress localAddr = new InetSocketAddress(localAddress, localPort);
SocketAddress remoteAddr = new InetSocketAddress(host, port);
socket.bind(localAddr);
socket.connect(remoteAddr, timeout);
return socket;
}
}
public Socket createSocket(String host, int port) throws IOException {
return getSSLContext().getSocketFactory().createSocket(host, port);
}
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
return getSSLContext().getSocketFactory().createSocket(socket, host, port, autoClose);
}
public boolean equals(Object obj) {
return ((obj != null) && obj.getClass().equals(MySSLProtocolSocketFactory.class));
}
public int hashCode() {
return MySSLProtocolSocketFactory.class.hashCode();
}
}
Then I used that socket factory to send my POST:
Protocol.registerProtocol("myhttps", new Protocol("myhttps", new MySSLProtocolSocketFactory(), 443));
PostMethod postMethod = new PostMethod("myhttps://some.url.here");
HttpClient client = new HttpClient();
int status = client.executeMethod(postMethod);
The only thing I couldn't figure out was how to simply add the certificate file to the regular keystore. All the example source code I found during my research pointed to creating a socket factor and then registering a protocol with that socket factory. Perhaps there is a way to simply use the socket factory to make a connection without registering a protocol; I haven't investigated that thoroughly. In my particular situation, creating a specific protocol was necessary. Hopefully this will get your further along the way. I admit it seems a bit roundabout; I felt the same way when I did it initially. But this was the only way I got it to work. Maybe other people have a better solution.
For posterity's sake, all of this was far too complicated, and we pretty much just had a check in the static block:
if( environment == 'production') {
System.setProperty("javax.net.ssl.keyStore", '/etc/certificates/prod/keystore.ks');
System.setProperty("javax.net.ssl.keyStorePassword", 'password');
System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true");
} else {
System.setProperty("javax.net.ssl.keyStore", '/etc/certificates/test/keystore.ks');
System.setProperty("javax.net.ssl.keyStorePassword", 'password');
System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true");
}
With Axis, I think you need to configure its SSLSocketFactory via:
AxisProperties.setProperty("axis.socketSecureFactory",
"com.example.MySSLSocketFactory");
where com.example.MySSLSocketFactory is your class that implements org.apache.axis.components.net.SecureSocketFactory (you could extend org.apache.axis.components.net.JSSESocketFactory perhaps).
In the create method, create a socket using the socket factory obtained from the SSLContext you've configured.
If you want, here's an API to create SSLSocket and SSLServerSocket easily:
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 :)
I had similar problem, I solved creating a function that returns an SSL context using a keystore coming from and input stream.
protected SSLContext getSslCtx(InputStream is, String password) {
try {
// Load keystore
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(is, password.toCharArray());
// Load trust manager
TrustManagerFactory trustMgrFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustMgrFactory.init(keystore);
// Load key manager
KeyManagerFactory keyMgrFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyMgrFactory.init(keystore, password.toCharArray());
// Create SSL context
SSLContext ctx = SSLContext.getInstance("TLSv1.2");
ctx.init(keyMgrFactory.getKeyManagers(), trustMgrFactory.getTrustManagers(), null);
return ctx;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Hope this helps.