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.
I need to configure TLSv1.2 for JMX communication.
Unfortunately I can not find the appropriate configuration here:
https://docs.oracle.com/javase/8/docs/technotes/guides/management/agent.html
How to configure what TLS version is used for JMX over SSL?
PCI DSS 3.1 does not allow usage of TLS 1.0.
You have obviously not read the documentation you have linked. It says:
com.sun.management.jmxremote.ssl.enabled.protocols: Default SSL/TLS protocol version.
com.sun.management.jmxremote.ssl.enabled.cipher.suites: Default SSL/TLS cipher suites.
This should solve your problem. After you have configured that, scan your JXM port with sslscan with a recent version (1.0.2+) of OpenSSL.
Is it possible from Java Bouncy Castle to connect to a remote server using SSL/TLS and then get a list of supported cipher suites by the server? I need to receive the HEX value of it and if possible also the 'string-constant' of it (maybe just for the ones that the client knows of it self).
I need to connect to whatever port using whatever protocol (HTTPS, AMQPS, STOMPS, ...).
What you can do is to write a CipherSuiteFinder class that calls a rewritten TlsClientProtocol that simply offers up a single cipher suite to the server. To do this you create a new class derived from DefaultTlsClient that extends AbstractTlsClient.
After offering up the protocol and receiving the response you close the connection. If the server didn't error out it accepted the single offered cipher suite, which means this cipher suite is present. You then nicely close the connection by following the TLS standard to close the connection, only closing the socket after everything is done.
Now the CipherSuiteFinder just has to iterate through the cipher suites and collect the results.
The top level protocols such as HTTP and STOMP do not matter; they are only invoked after the TLS connection has been established.
Whenever I try to connect with SSL from an Android App to a Tcl server, the connection fails. Both systems seem to have a very long list of supported ciphers, but they name them quite differently, so I cannot really tell which is which.
the Tcl error message is:
SSL channel "sock7": error: no shared cipher
the Android error message is:
javax.net.ssl.SSLException: Connection closed by peer
Is there any hope to find a solution for this?
The Tcl code is:
package require tls
::tls::init -ssl2 0 -ssl3 1 -tls1 1 -require 0 -request 0
set mainSock [::tls::socket -server serve 1200]
The Android Code is:
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
SocketFactory sf = SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) sf.createSocket("server.de", 1200);
Thanks everybody for help. I have figured it out with your answers.
It seems impossible to use Tcl as a server without any certificates. Not even another Tcl script can connect to the server without certificates. The client can leave out the validity checking, but the server must provide a certificate. This is not stated clearly in the documentation!
Now I can establish a connection with a home-made certificate as stated on page http://wiki.tcl.tk/15244
Unfortunately, I don't (yet) know how to tell Android to not check the validity for now (like -require 0 in Tcl). Maybe I'll just import my own CA into the Android device. Otherwise, I would have to buy a certificate signed by an official CA. Some time in the future, I'll have to do this anyway.
Cipher suites can be named differently but they share the same "value". The error message is explicit in stating that there are no common cipher suites. This could be due to many reasons. Some but not all:
The SSL certificate on the server is based on say ECC versus RSA (different algorithms).
For the TLS protocol enabled, the ends do not have any common cipher suites.
List of cipher suites with their "values":
https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4
Since your SSL server does not use any certificates the only possible ciphers are anonymous ciphers suites. Since these are insecure (open to man-in-the-middle attacks) they are not enabled by default for SSLSockets.
Thus the client will only announce support for cipher suites with proper authentication and it will not offer any ciphers usable with your TCL server. This causes the "no shared cipher" error.
If you really want to use such an insecure setup you might have a look at http://www.nickoh.com/emacs_files/ssl-examples/LdapTlsExample.java.txt for an example which uses anonymous cipher suites together with SSLSockets (I did not check if the example works, it as just one of the first hits when searching for support of anon cipher suites).
I'm looking at the JSSE reference guide, I need to obtain an instance of SSLContext in order to create a SSLEngine, so I can use it with Netty to enable security.
To obtain an instance of SSLContext, I use SSLContext.getInstance(). I see that the method is overridden multiple times, so I can chose the protocol and security provider to use.
Here, I can see the list of algorithms that can be used. Which algorithm should I use to enable secure communication?
Also, since it is possible to specify the security provider to use, which provider should I use?
Thanks
As you can see in the standard names documentation, all entries (SSLv3, TLSv1.0, TLSv1.1, ...) say that they may support other versions.
In practice, in the Oracle JDK (and OpenJDK), they all do. If you look at the source code, the TLS10Context class is what's used for TLS, SSL, SSLv3 and TLS10, TLS11Context is used for TLSv1.1 and TLS12Context for TLSv1.2. All support all versions of SSL/TLS, it's what's enabled by default that varies.
This may be different with another provider or JRE vendor. You should of course pick one that's at least going to support the protocol version you want to use.
Note that the protocol used is determined later on using SSLSocket.setEnabledProtocols(...) or its SSLEngine equivalent.
As a general rule, use the highest version number you can (SSLv3 < TLSv1.0 < TLSv1.1 ...), which may depend on what the parties with which you want to communicate support.
Which protocols are enabled by default varies depending on the exact version of the Oracle JRE.
When looking at the source code for sun.security.ssl.SunJSSE in OpenJDK 7u40-b43, TLS is simply an alias for TLSv1 (and so are SSL and SSLv3), in terms of SSLContext protocols. Looking at the various implementations of SSLContextImpl (which are inner classes of SSLContextImpl itself):
All support all protocols.
All protocols are enabled on the server side by default.
the client-side protocols enabled by default vary:
TLS10Context (used for protocol SSL, SSLv3, TLS, TLSv1) enables SSLv3 to TLSv1.0 by default on the client side.
TLS11Context (used for protocol TLSv1.1) also enables TLSv1.1 by default.
TLS12Context (used for protocol TLSv1.2) also enables TLSv1.2 by default.
If FIPS is enabled, SSL is not supported (so not enabled by default).
This changes in Java 8, in conjunction with the new jdk.tls.client.protocols system property.
Again, when looking at the source code for sun.security.ssl.SunJSSE in OpenJDK 8u40-b25, SSLContext protocols TLSv1, TLSv1.1, and TLSv1.2 also make use of TLS10Context, TLS11Context and TLS12Context, which follow the same logic as in Java 7.
However, protocol TLS is no longer aliased to any of them. Rather, it uses TLSContext which relies on the values in the jdk.tls.client.protocols system properties. From the JSSE Reference guide:
To enable specific SunJSSE protocols on the client, specify them in a comma-separated list within quotation marks; all other supported protocols are then disabled on the client. For example, if the value of this property is "TLSv1,TLSv1.1", then the default protocol settings on the client for TLSv1 and TLSv1.1 are enabled on the client, while SSLv3, TLSv1.2, and SSLv2Hello are disabled on the client.
If this property is empty, all protocols are enabled by default on both client and server side.
Of course, in recent versions of Oracle JRE 8, SSL is also completely disabled by default (so removed from those lists).
Note that in both cases (JRE 7 and 8), the SSLContext you get by default via SSLContext.getDefault() out of the box is more or less equivalent to an SSLContext obtained with protocol TLS and initialised with the default truststore parameters and so on.
There is no default for the protocol, so I would use the latest one supported by your JDK, which is either TLSv1, TLSv1.1 or TLSv1.2: see which works, or have a look at getSupportedProtocols(). The default security provider is used by avoiding all the APIs where you specify it, or else e.g. KeyStore.getDefaultType().
And when you come to get your SSLEngines, make sure you use the method that takes a hostname and port. Otherwise you will get no SSL session sharing.