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 :)
I am sending an ssl message to my browser, the browser then returns with a message but i do not know how to decrypt it?
CODE:
import java.io.*;
import javax.net.ssl.*;
public class Server{
public static void main(String[] args) throws IOException{
int port = 8080;
System.setProperty("javax.net.ssl.keyStore", "keys2/newLocal.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "password");
System.getProperty("java.net.debug", "all");
SSLServerSocketFactory sslServerSocketFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(port);
while(true){
System.out.println("listening on port: " + port);
SSLSocket sslsocket = (SSLSocket) sslServerSocket.accept();
PrintStream out = new PrintStream(sslsocket.getOutputStream(), true);
var protocol = sslsocket.getSSLParameters();
System.out.println(protocol);
BufferedInputStream bufferedInputStream= new BufferedInputStream(sslsocket.getInputStream());
System.out.println(bufferedInputStream);
String msg = "Hello World";
out.println("HTTPS/1.0 200 OK");
out.println("Content-Type: text/html");
out.println();
out.print(msg);
out.close();
}
}
}
The Message returned is:
java.io.BufferedInputStream#1bce4f0a
I assume that i need to get the public key from the browser to decrypt.
Hello i'm trying to run a SSL server and client program. I'm first creating a certificate with the cmd command "keytool -genkey -keystore mySrvKeyStore -keyalg RSA". 123456 is the password after i fill in the info. I put the certificate in the same folder as the server and client, i run the server and I get this error:
"java.lang.IllegalStateException: SSLContext is not initialized"
The server:
public class SSLServer {
private static int port = 4000;
private static SSLServerSocketFactory sf;
private static SSLServerSocket ss;
public static void StabilireConexiune(int nrPort) {
try {
sf = (SSLServerSocketFactory) SSLServer.getServerSocketFactory();
ss = (SSLServerSocket) sf.createServerSocket(nrPort);
System.out.println("Server connected ready to accept new connections at the address " + ss.getLocalPort());
String[] enable = {"TLS_DH_anon_WITH_AES_128_CBC_SHA"};
ss.setEnabledCipherSuites(enable);
String[] cipherSuites = ss.getEnabledCipherSuites();
System.out.println("CipherSuites: ");
for (int i = 0; i < cipherSuites.length; i++) {
System.out.println(cipherSuites[i]);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private static SSLSocket clientSocket;
public static void ConectareClient(){
try{
clientSocket = (SSLSocket) ss.accept();
System.out.println("Client connected succesfully");
InputStream input = clientSocket.getInputStream();
InputStreamReader inputreader = new InputStreamReader(input);
BufferedReader br = new BufferedReader(inputreader);
String string = null;
while( (string = br.readLine()) != null){
System.out.println(string);
System.out.flush();
}
}catch(Exception ex){
ex.printStackTrace();
}
finally{
try{
clientSocket.close();
}catch(IOException ex){
ex.printStackTrace();
}
}
}
private static ServerSocketFactory getServerSocketFactory() throws NoSuchAlgorithmException{
SSLServerSocketFactory ssf = null;
try{
KeyManagerFactory kmf;
KeyStore ks;
SSLContext ctx;
char[] passphrase = "123456".toCharArray();
ctx = SSLContext.getInstance("TLS");
kmf = KeyManagerFactory.getInstance("SunX509");
ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("mySrvKeystore"), passphrase);
kmf.init(ks, passphrase);
ctx.getServerSocketFactory();
return ssf;
}catch(Exception ex){
ex.printStackTrace();
}
return null;
}
public static void main(String args[]){
if(args.length != 0){
port = Integer.parseInt(args[0]);
}
StabilireConexiune(port);
while(true){
ConectareClient();
}
}}
The client:
public class SSLClient {
public static void main(String args[]) {
conectare("127.0.0.1", 4000);
}
private static SSLSocket socket;
public static void conectare(String host, int port) {
try {
SSLSocketFactory factory = (SSLSocketFactory) SSLClient.getSocketFactory();
socket = (SSLSocket) factory.createSocket(host, port);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] enable = {"TLS_DH_anon_WITH_AES_128_CBC_SHA"};
socket.setEnabledCipherSuites(enable);
String[] cipherSuites = socket.getEnabledCipherSuites();
for (int i = 0; i < cipherSuites.length; i++) {
System.out.println(cipherSuites[i]);
}
socket.addHandshakeCompletedListener(new HandshakeCompletedListener() {
public void handshakeCompleted(HandshakeCompletedEvent event) {
System.out.println("handshake done");
}
});
socket.startHandshake();
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));
System.out.println("Give a message to the server...");
String string = br.readLine();
out.println("Message to the server..." + string);
out.println();
out.flush();
}catch(IOException ex){
ex.printStackTrace();
}
finally{
try{
socket.close();
}catch(IOException ex){
ex.printStackTrace();
}
}
}
private static SocketFactory getSocketFactory(){
SSLSocketFactory ssf = null;
try{
SSLContext ctx;
KeyManagerFactory kmf;
KeyStore ks;
char[] passphrase = "123456".toCharArray();
ctx = SSLContext.getInstance("TLS");
kmf = KeyManagerFactory.getInstance("SunX509");
ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("mySrvKeystore"), passphrase);
kmf.init(ks, passphrase);
ctx.init(kmf.getKeyManagers(), null, null);
ssf = ctx.getSocketFactory();
return ssf;
}catch(Exception e){
e.printStackTrace();
}
return null;
}}
Please help me, what is the problem?
The error is in these two lines:
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.getServerSocketFactory();
Why does it throw this Exception? Method getServerSocketFactory() states:
Throws:
IllegalStateException - if the SSLContextImpl requires initialization and the init() has not been called
In the client, you do indeed call ctx.init(kmf.getKeyManagers(), null, null); before you call ctx.getServerSocketFactory();
But in the server you do not call this - you only initialise the KeyManagerFactory.
I am very new to Cryptography using Java. I have to build a program that exchanges certificate before any data communication takes place. I am using sslSockets to build basic client-server program and I am not using HTTP/S, this is just to get extra security. (Would like to know difference between Socket and SSLSocket.. does it mean everything is automatically encrypted?)
Here's my UPDATED Server Code:
public class SSLServerExample {
final static String pathToStores = "C:/Users/XXX/Desktop/sslserverclientprogram";
final static String keyStoreFile = "keystore.jks";
final static String passwd = "changeit";
final static int theServerPort = 8443;
static boolean debug = false;
public static void main(String args[]) throws Exception {
String trustFilename = pathToStores + "/" + keyStoreFile;
// System.out.println("Verifying KeyStore File of Client..");
System.setProperty("javax.net.ssl.keyStore", trustFilename);
System.setProperty("javax.net.ssl.keyStorePassword", passwd);
if (debug)
System.setProperty("javax.net.debug", "all");
System.out.println("Setting up SSL parameters");
// Initialize socket connection
SSLServerSocketFactory sslssf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket sslServerSocket = (SSLServerSocket)sslssf.createServerSocket(theServerPort);
System.out.println("Server Started..Waiting for clients");
sslServerSocket.setNeedClientAuth(true);
SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept();
//sslSocket.startHandshake();
System.out.println("Client Connected!");
InputStream sslIS = sslSocket.getInputStream();
OutputStream sslOS = sslSocket.getOutputStream();
sslServerSocket.setNeedClientAuth(true);
final int RSAKeySize = 1024;
final String newline = "\n";
Key pubKey = null;
Key privKey = null;
boolean flag = sslSocket.getNeedClientAuth();
System.out.println("Flag value: "+ flag);
The flag results in False, even though I set it as true and client sends data which is decrypted by the server without authenticating each other.
Am I missing something?
Please help.
PS: My Client code:
public class SSLClientExample {
final static String pathToStores = "C:/Users/XXX/Desktop/sslserverclientprogram";
final static String trustStoreFile = "cacerts.jks";
final static String passwd = "changeit";
final static String INPUT_FILE = "E:/workspace/input.txt";
final static String theServerName = "localhost";
final static int theServerPort = 8443;
static boolean debug = false;
public static void main(String args[]) throws Exception {
String trustFilename = pathToStores + "/" + trustStoreFile;
System.out.println("Validating KeyStore file of Server..");
System.setProperty("javax.net.ssl.trustStore", trustFilename);
System.setProperty("javax.net.ssl.trustStorePassword", passwd);
if (debug)
System.setProperty("javax.net.debug", "all");
SSLSocketFactory sslssf = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslSocket = (SSLSocket)sslssf.createSocket(theServerName, 8443);
System.out.println("Connected to Server!");
You have to invoke sslServerSocket.setNeedClientAuth(true); before accepting incoming client connections. You are modifying the server socket's configuration after the connection has already been established.
I'm trying to make an https server on Android with a programmatically generated self signed certificate. I feel like I'm pretty close but I still can't connect to the https server. When I attempt to connect to the server with openssl I get the following:
openssl s_client -connect 192.168.1.97:8888
CONNECTED(00000003)
2895:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:/SourceCache/OpenSSL098/OpenSSL098-50/src/ssl/s23_clnt.c:602:
The code is the following:
public class HttpsHello {
private static String domainName = "localhost";
static {
Security.addProvider(new BouncyCastleProvider());
}
public static void test(String[] args) {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair KPair = keyPairGenerator.generateKeyPair();
X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator();
int ran = new SecureRandom().nextInt();
if (ran < 0) ran = ran * -1;
BigInteger serialNumber = BigInteger.valueOf(ran);
v3CertGen.setSerialNumber(serialNumber);
v3CertGen.setIssuerDN(new X509Principal("CN=" + domainName + ", OU=None, O=None L=None, C=None"));
v3CertGen.setNotBefore(new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30));
v3CertGen.setNotAfter(new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 365 * 10)));
v3CertGen.setSubjectDN(new X509Principal("CN=" + domainName + ", OU=None, O=None L=None, C=None"));
v3CertGen.setPublicKey(KPair.getPublic());
// v3CertGen.setSignatureAlgorithm("MD5WithRSAEncryption");
v3CertGen.setSignatureAlgorithm("SHA1WithRSAEncryption");
X509Certificate pkcert = v3CertGen.generateX509Certificate(KPair.getPrivate());
// FileOutputStream fos = new FileOutputStream("/path/to/testCert.cert");
// fos.write(pkcert.getEncoded());
// fos.close();
ByteArrayInputStream cert = new ByteArrayInputStream(pkcert.getEncoded());
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null);
ks.setCertificateEntry("localhost", pkcert);
// ks.load(cert,null);
KeyManagerFactory kmf =
KeyManagerFactory.getInstance("X509");
kmf.init(ks, null);
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(kmf.getKeyManagers(), null, null);
SSLServerSocketFactory ssf = sc.getServerSocketFactory();
SSLServerSocket s
= (SSLServerSocket) ssf.createServerSocket(8888);
s.setEnabledCipherSuites(s.getSupportedCipherSuites());
// s.setEnabledCipherSuites(new String[]{"SSL_DH_anon_WITH_RC4_128_MD5"});
// s.setEnabledCipherSuites(new String[]{"SHA1WithRSAEncryption"});
System.out.println("Server started:");
printServerSocketInfo(s);
// Listening to the port
SSLSocket c = (SSLSocket) s.accept();
printSocketInfo(c);
BufferedWriter w = new BufferedWriter(
new OutputStreamWriter(c.getOutputStream()));
BufferedReader r = new BufferedReader(
new InputStreamReader(c.getInputStream()));
String m = r.readLine();
w.write("HTTP/1.0 200 OK");
w.newLine();
w.write("Content-Type: text/html");
w.newLine();
w.newLine();
w.write("<html><body>Hello world!</body></html>");
w.newLine();
w.flush();
w.close();
r.close();
c.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void printSocketInfo(SSLSocket s) {
System.out.println("Socket class: " + s.getClass());
System.out.println(" Remote address = "
+ s.getInetAddress().toString());
System.out.println(" Remote port = " + s.getPort());
System.out.println(" Local socket address = "
+ s.getLocalSocketAddress().toString());
System.out.println(" Local address = "
+ s.getLocalAddress().toString());
System.out.println(" Local port = " + s.getLocalPort());
System.out.println(" Need client authentication = "
+ s.getNeedClientAuth());
SSLSession ss = s.getSession();
System.out.println(" Cipher suite = " + ss.getCipherSuite());
System.out.println(" Protocol = " + ss.getProtocol());
}
private static void printServerSocketInfo(SSLServerSocket s) {
System.out.println("Server socket class: " + s.getClass());
System.out.println(" Socker address = "
+ s.getInetAddress().toString());
System.out.println(" Socker port = "
+ s.getLocalPort());
System.out.println(" Need client authentication = "
+ s.getNeedClientAuth());
System.out.println(" Want client authentication = "
+ s.getWantClientAuth());
System.out.println(" Use client mode = "
+ s.getUseClientMode());
}
}
Thank you.
EDIT: I looked at two keytool generated keystores, one which worked and one that didn't. The one keystore which works has an entry in there for a PrivateKeyEntry where as the one which doesn't work has a trustedCertEntry. I then changed this code to print out the entry for the "localhost" alias and below is what I got, I'm guessing the issue is that it is a Trusted certificate entry and not a private key entry. How do I change that?
Trusted certificate entry:
[0] Version: 3
SerialNumber: 752445443
IssuerDN: CN=localhost,OU=None,O=None L,C=None
Start Date: Mon May 26 09:17:01 CDT 2014
Final Date: Sat Jun 22 09:17:01 CDT 2024
SubjectDN: CN=localhost,OU=None,O=None L,C=None
Public Key: RSA Public Key
modulus: b75870cd29db79f8c015d440a27cc1e81c9dd829268efa2ce48efc596b33e9c60e1d1621e10aba34472b6f7890b16392db021c0358e665b1bf58a426fbc47e7c135da583e4cd6bb9c69668ee4ff1e05b1de8e7f5fb5604044a1087ac0181ba09f61ab5345d9be5d930889b7c328329d0d18cf53f4c5af6bff1f0e488744ea1fb
public exponent: 10001
Signature Algorithm: SHA1WITHRSA
Signature: 83df0e761e9df2e61d5354ca58379975e0d97fcd
5201f8904b695d7bdbe08c5dfdfb8bcd6447657c
19740797a66314b2547a45985166c11ebadc16c6
c24b8e1d3c5de83ec1ac2c1c1092c3d06ed33408
4cf2811c5f9dba8a9d3ef0dcb8fef760e4d1d704
8fbb60eaa83eec23426fb9d8589e859a21a5ecce
951901f8e16ab6cd
s.setEnabledCipherSuites(s.getSupportedCipherSuites());
Remove this line.
The handshake failure usually means there's no shared cipher suite:
2895:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
SSL_NULL_WITH_NULL_NULL looks like its both eNULL and aNULL. Did BouncyCastle not load any ciphers?
Below is the code I use for a hardened SSLSocketFactoryEx. It only provides TLS (getInstance("TLS")will still return a SSLv3 socket), and it only provides approved cipher suites (approved by me). Its not enough to provide approved ciphers - the list must intersect with what's available else there's an exception. There are a few fallback cipher suites to ensure a shared cipher suite between old servers like those provided by Microsoft.
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.io.IOException;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.net.Socket;
import java.net.InetAddress;
import javax.net.SocketFactory;
import javax.net.ssl.KeyManager;
import javax.net.ssl.TrustManager;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
class SSLSocketFactoryEx extends SSLSocketFactory
{
public SSLSocketFactoryEx() throws NoSuchAlgorithmException, KeyManagementException
{
initSSLSocketFactoryEx(null,null,null);
}
public SSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random) throws NoSuchAlgorithmException, KeyManagementException
{
initSSLSocketFactoryEx(km, tm, random);
}
public SSLSocketFactoryEx(SSLContext ctx) throws NoSuchAlgorithmException, KeyManagementException
{
initSSLSocketFactoryEx(ctx);
}
public String[] getDefaultCipherSuites()
{
return m_ciphers;
}
public String[] getSupportedCipherSuites()
{
return m_ciphers;
}
public String[] getDefaultProtocols()
{
return m_protocols;
}
public String[] getSupportedProtocols()
{
return m_protocols;
}
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException
{
SSLSocketFactory factory = m_ctx.getSocketFactory();
SSLSocket ss = (SSLSocket)factory.createSocket(s, host, port, autoClose);
ss.setEnabledProtocols(m_protocols);
ss.setEnabledCipherSuites(m_ciphers);
return ss;
}
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException
{
SSLSocketFactory factory = m_ctx.getSocketFactory();
SSLSocket ss = (SSLSocket)factory.createSocket(address, port, localAddress, localPort);
ss.setEnabledProtocols(m_protocols);
ss.setEnabledCipherSuites(m_ciphers);
return ss;
}
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException
{
SSLSocketFactory factory = m_ctx.getSocketFactory();
SSLSocket ss = (SSLSocket)factory.createSocket(host, port, localHost, localPort);
ss.setEnabledProtocols(m_protocols);
ss.setEnabledCipherSuites(m_ciphers);
return ss;
}
public Socket createSocket(InetAddress host, int port) throws IOException
{
SSLSocketFactory factory = m_ctx.getSocketFactory();
SSLSocket ss = (SSLSocket)factory.createSocket(host, port);
ss.setEnabledProtocols(m_protocols);
ss.setEnabledCipherSuites(m_ciphers);
return ss;
}
public Socket createSocket(String host, int port) throws IOException
{
SSLSocketFactory factory = m_ctx.getSocketFactory();
SSLSocket ss = (SSLSocket)factory.createSocket(host, port);
ss.setEnabledProtocols(m_protocols);
ss.setEnabledCipherSuites(m_ciphers);
return ss;
}
private void initSSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random)
throws NoSuchAlgorithmException, KeyManagementException
{
m_ctx = SSLContext.getInstance("TLS");
m_ctx.init(km, tm, random);
m_protocols = GetProtocolList();
m_ciphers = GetCipherList();
}
private void initSSLSocketFactoryEx(SSLContext ctx)
throws NoSuchAlgorithmException, KeyManagementException
{
m_ctx = ctx;
m_protocols = GetProtocolList();
m_ciphers = GetCipherList();
}
protected String[] GetProtocolList()
{
String[] preferredProtocols = { "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3" };
String[] availableProtocols = null;
SSLSocket socket = null;
try
{
SSLSocketFactory factory = m_ctx.getSocketFactory();
socket = (SSLSocket)factory.createSocket();
availableProtocols = socket.getSupportedProtocols();
Arrays.sort(availableProtocols);
}
catch(Exception e)
{
return new String[]{ "TLSv1" };
}
finally
{
if(socket != null)
socket.close();
}
List<String> aa = new ArrayList<String>();
for(int i = 0; i < preferredProtocols.length; i++)
{
int idx = Arrays.binarySearch(availableProtocols, preferredProtocols[i]);
if(idx >= 0)
aa.add(preferredProtocols[i]);
}
return aa.toArray(new String[0]);
}
protected String[] GetCipherList()
{
String[] preferredCiphers = {
// *_CHACHA20_POLY1305 are 3x to 4x faster than existing cipher suites.
// http://googleonlinesecurity.blogspot.com/2014/04/speeding-up-and-strengthening-https.html
// Use them if available. Normative names can be found at (TLS spec depends on IPSec spec):
// http://tools.ietf.org/html/draft-nir-ipsecme-chacha20-poly1305-01
// http://tools.ietf.org/html/draft-mavrogiannopoulos-chacha-tls-02
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_ECDSA_WITH_CHACHA20_SHA",
"TLS_ECDHE_RSA_WITH_CHACHA20_SHA",
"TLS_DHE_RSA_WITH_CHACHA20_POLY1305",
"TLS_RSA_WITH_CHACHA20_POLY1305",
"TLS_DHE_RSA_WITH_CHACHA20_SHA",
"TLS_RSA_WITH_CHACHA20_SHA",
// Done with bleeding edge, back to TLS v1.2 and below
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
// TLS v1.0 (with some SSLv3 interop)
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA384",
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
"TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
"TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
"SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA",
"SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA",
// RSA key transport sucks, but they are needed as a fallback.
// For example, microsoft.com fails under all versions of TLS
// if they are not included. If only TLS 1.0 is available at
// the client, then google.com will fail too. TLS v1.3 is
// trying to deprecate them, so it will be interesteng to see
// what happens.
"TLS_RSA_WITH_AES_256_CBC_SHA256",
"TLS_RSA_WITH_AES_256_CBC_SHA",
"TLS_RSA_WITH_AES_128_CBC_SHA256",
"TLS_RSA_WITH_AES_128_CBC_SHA"
};
String[] availableCiphers = null;
try
{
SSLSocketFactory factory = m_ctx.getSocketFactory();
availableCiphers = factory.getSupportedCipherSuites();
Arrays.sort(availableCiphers);
}
catch(Exception e)
{
return new String[] {
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_RSA_WITH_AES_256_CBC_SHA256",
"TLS_RSA_WITH_AES_256_CBC_SHA",
"TLS_RSA_WITH_AES_128_CBC_SHA256",
"TLS_RSA_WITH_AES_128_CBC_SHA",
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV"
};
}
List<String> aa = new ArrayList<String>();
for(int i = 0; i < preferredCiphers.length; i++)
{
int idx = Arrays.binarySearch(availableCiphers, preferredCiphers[i]);
if(idx >= 0)
aa.add(preferredCiphers[i]);
}
aa.add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV");
return aa.toArray(new String[0]);
}
private SSLContext m_ctx;
private String[] m_ciphers;
private String[] m_protocols;
}