How to use SSL in Java correctly? - java

Unfortunately I'm completely new to SSL. Currently I'm trying to set up a secure connection between a client and a server application in Java and the following code works for me (transmitted data is encrypted), but I don't know if this is a correct and secure solution.
Client side:
socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(host, port);
socket.setUseClientMode(true);
socket.setEnabledCipherSuites(socket.getSupportedCipherSuites());
socket.startHandshake();
Server side:
sslServerSocket = (SSLServerSocket) serverSocketFactory.createServerSocket(requestPort());
sslServerSocket.setUseClientMode(false);
sslServerSocket.setEnabledCipherSuites(sslServerSocket.getSupportedCipherSuites());

It is not advisable to enable all ciphers/protocols. Better that you enabled only the ciphers and protocols you want. If both server and server is written by you, choose what you want and configure only that.
socket.setEnabledCipherSuites(...);
socket.setEnabledProtocols(...);
Supported ciphers and protocols can be seen in JSSE documentation
Or you can use "jdk.tls.disabledAlgorithm" to control what algs you want to use.

Related

JAVA SSL: how to get client certificate information

I have an SSL-enabled tcp server that can listen to multiple rsyslog clients. Each client has its own certificate that is added in the server's truststore. This setup is working fine. TThe question is whether there is a way to get the client certificate information like CN, location etc. after the socket accepts connection?
Below is the code sample of simple tcp server.
SSLServerSocketFactory sf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
ServerSocket ss = sf.createServerSocket(514);
while(true){
SSLSocket s = (SSL)ss.accept();
// here I need to get client certificate information
}
You need to configure the SSLServerSocket to need or want client authentication, depending on which of those applies. Then you can get the peer certificates out of the SSLSocket's SSLSession, if they were sent.

Creating an SSL connection between an Android app and TCP server

I have an Android app which uses a Java TCP client to connect to a Java TCP application server.
In some cases I noticed firewalls or routers that block the port I am using can cause issues so I am trying to use a secure connection.
I have tried using the examples from this link:
SSLServerSocket but I am always getting a connection timeout.
Server code:
ServerSocketFactory sslServerSocketFactory = SSLServerSocketFactory.getDefault();
serverSocket = sslServerSocketFactory.createServerSocket(port, backlog);
Socket socket = serverSocket.accept(); ---> in a new thread
Client code:
SocketFactory socketFactory = SSLSocketFactory.getDefault();
clientSocket = socketFactory.createSocket();
clientSocket.connect(new InetSocketAddress(host, port), READ_TIMEOUT); ---> timeout on this line
I also tried the more complicated examples in the link but all resulted in a timeout.
I really want to understand what's wrong with this very simple example.
If it's not the way to work with SSL (I see no mention of certificates in this code at all, which I think is necessary in SSL) then why is it given as a working example?
Any help would be appreciated.

How to enable GOST ciphers in Java client

I want to make an SSL connection to some web servers using Java client while using GOST ciphers in my client cipher list. I tried to check the enabled and supported ciphersuites in Java using: getEnabledCipherSuites() and getSupportedCipherSuites() and none has returned GOST ciphers. How can I make SSL connection from my Java client to a web server using GOST ciphers? Is there any way to specify my client's list of ciphers to include GOST ciphers ?
Try BouncyCastle SSL library, they support GOST ciphers as far as I remember.

How can I reduce the waiting time for ssl handshake?

I have the following code from http://sanjaal.com/java/tag/get-public-key-of-ssl-certificate-in-java/ that creates a socket and initiate ssl handshake.
SSLSocketFactory factory = HttpsURLConnection
.getDefaultSSLSocketFactory();
System.out.println("Creating a SSL Socket For "+hostname+" on port "+port);
SSLSocket socket = (SSLSocket) factory.createSocket(hostname, port);
socket.startHandshake();
System.out.println("Handshaking Complete");
The problem is that if the handshake could not establish, there is a long waiting time before I see the exception: Connection timed out
How can I set a maximum waiting time ? and what is the suitable minimum amount of time that ensures me that ssl handshake is not going to be successful.
'Connection timeout' has nothing to do with the handshake, or even SSL. It doesn't happen when you call startHandshake(): it happens when you create the socket. Your stack trace would have told you that.
To reduce it, create a Socket() using the default constructor; call connect(SocketAddress address, long timeout); then if that succeeds call SSLSocketFactory.createSocket(Socket, ...) to wrap it in an SSLSocket.
NB the blog you cited is very poor quality indeed. Some of the problems with it:
An SSL certificate does not 'enable encryption'. It is there primarily for authentication. It also plays a minor, inessential role in the handshake leading to the session key.
TLS offers a lot more than just 'prevent[ing] eavesdropping, tampering, and message forgery': it also prevents replay and man-in-the-middle attacks too, for example; and it offers many more encryption possibilities than just RSA with 1024 or 2048 byte keys.
The suggestion that 'At the browser level, it only means that the browser has validated the server’s certificate', and that for security the user/application must 'cipher something using the public key contained in the certificate and assure that the server can understand it' is complete nonsense. The browser has already checked that the server owns that certificate, via the digital-signature mechanism, during the SSL handshake.
All this: 'the “locked padlock” icon has no relationship to the URL, DNS name or IP address of the server – thinking otherwise is a common misconception. Such a binding can only be securely established if the URL, name or address is specified in the server’s certificate itself. ' is completely incorrect. HTTPS includes checking the hostname against what is embedded in the certificate: and what is embedded in the certificate is put there and checked by the signing authority.
Don't rely on unrefereed unreviewed sites like that. Use the official product documentation.
Before performing sslSocket.startHandshake(); use sslSocket.setSoTimeout(timeout);
setSoTimeout is an read timeout so the timeout value which you provide in setSoTimeout will work with handshake also.

How to avoid Diffie-Hellman for SSL connections with Java/Netty?

I am using Netty as backend in a Java-based Usenet client. The library is working fine, however, in some circumstances I can't connect to a remote server via SSL, because of exactly this error:
Java: Why does SSL handshake give 'Could not generate DH keypair' exception?
Unfortunately, it seems that for whatever reason this Java error still has not been fixed yet. And since the remote server is not under my control, I need a workaround here. One such "solution", according to the link above, is to avoid DH during SSL handshake at all (not very pretty, but maybe better than nothing).
However, I am no SSL expert, so I am not really sure how I can implement that within Netty; or better: within my solution that is based on Netty. By now I am creating connections as this:
// configure the Netty client
ClientBootstrap bootstrap = new ClientBootstrap(clSockChannelFactory);
// configure the pipeline factory
bootstrap.setPipelineFactory(channelPipelineFactory);
bootstrap.setOption("tcpNoDelay", true);
bootstrap.setOption("keepAlive", true);
bootstrap.setOption("child.receiveBufferSizePredictorFactory",
new AdaptiveReceiveBufferSizePredictorFactory());
// start the connection attempt
InetSocketAddress isa = new InetSocketAddress(serverAddress, port);
ChannelFuture future = bootstrap.connect(isa);
...
channel = future.getChannel();
...
Ok, that's fine, but where can I disable cipher suites before I connect the SSL socket, as desribed in the thread above?
Thanks in advance for all your help!
Kind regards, Matthias
PS: By the way, any ideas why this problem has not been addressed in Java yet?
I'm not familiar with Netty, but I would suggest following the approach in the secure chat example.
I'm not sure what default SSL/TLS keys/trust settings you have, but if you don't have a custom SSLContext, try SSLContext.getDefault().
Then, create an SSLEngine using SSLContext.createSSLEngine(). On this SSLEngine, you should be able to enable the cipher suites you want. Assuming you're using the Oracle JRE (or OpenJDK), you'll find the list of cipher suites in the Sun Provider documentation.
After this (this is the Netty-specific part), set an SslHandler using something like this (see Netty example):
pipeline.addLast("ssl", new SslHandler(engine));

Categories

Resources