How to connect to private url with private ssl certificate - java

I am trying to connect my android app to a url belonging to a private company in order to retrieve and send information. When I do so however I receive an error Trust anchor for certification path not found, the ssl certificate for the url is valid though, I did research and I used the following code I used to trust the certificate in a class Http TrustManager
public class HttpsTrustManager {
public void trust() throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new BufferedInputStream(new FileInputStream("load-der.crt"));
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
SSLContext context = null;
try {
context = SSLContext.getInstance("TLS");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
try {
context.init(null, tmf.getTrustManagers(), null);
} catch (KeyManagementException e) {
e.printStackTrace();
}
// Tell the URLConnection to use a SocketFactory from our SSLContext
URL url = new URL("https://systems.syspearl.com/api");
HttpsURLConnection urlConnection =
(HttpsURLConnection) url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream in = urlConnection.getInputStream();
IOUtils.copyStream(in,out);
}
And this is how I call it in the main activity
new HttpsTrusrtManger().trust();
This doesn't work however. Please render necessary help

Related

Creating a TLS/SSL server with HttpsServer

I tried all day do make a server TLS/SSL HTTPS with java. Can someone help me?
This is my code
static class MyHandler implements HttpHandler {
#Override
public void handle(HttpExchange t) throws IOException {
System.out.println("called");
String response = "This is the response";
t.sendResponseHeaders(200, response.length());
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
static HttpsServer server = null;
static int port = 9000;
public static void main(String[] args) throws Exception {
String keystoreFilename = "/home/kratess/" + "mykey.keystore";
char[] storepass = "mypassword".toCharArray();
char[] keypass = "mypassword".toCharArray();
String alias = "alias";
FileInputStream fIn = new FileInputStream(keystoreFilename);
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(fIn, storepass);
// display certificate
Certificate cert = keystore.getCertificate(alias);
System.out.println(cert);
// setup the key manager factory
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(keystore, keypass);
// setup the trust manager factory
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(keystore);
server = HttpsServer.create(new InetSocketAddress(port), 0);
// create ssl context
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
// setup the HTTPS context and parameters
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
server.setHttpsConfigurator(new HttpsConfigurator(sslContext) {
public void configure(HttpsParameters params) {
try {
// initialise the SSL context
SSLContext c = SSLContext.getDefault();
SSLEngine engine = c.createSSLEngine();
params.setNeedClientAuth(true);
params.setCipherSuites(engine.getEnabledCipherSuites());
params.setProtocols(engine.getEnabledProtocols());
// get the default parameters
SSLParameters defaultSSLParameters = c.getDefaultSSLParameters();
params.setSSLParameters(defaultSSLParameters);
} catch (Exception ex) {
ex.printStackTrace();
System.out.println("Failed to create HTTPS server");
}
}
});
System.out.println("server started at " + port);
server.createContext("/test", new MyHandler());
server.setExecutor(null);
server.start();
}
The server starts but it and the certificate doesn't work on chrome.
The certificate print in the console and is all complete.
Chrome gives that response ERR_EMPTY_RESPONSE
Also, HttpHandler isn't called.
Where am I wrong? If this solution doesn't work can someone suggest me what I have to use? I need to code this HTTPS for creating a WebHook page (required SSL)

Unable to add SSL certificate using Retrofit 2

Unable to add SSL certificate using Retrofit 2 getting below error:
java.net.UnknownHostException: Unable to resolve host "abcd.com": No address associated with hostname
Below is the code:
try {
cf = CertificateFactory.getInstance("X.509");
cert = context.getResources().openRawResource(R.raw.abcd);
ca = cf.generateCertificate(cert);
cert.close();
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
client = new OkHttpClient.Builder()
.sslSocketFactory(sslContext.getSocketFactory())
.build();
} catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException | KeyManagementException e) {
Log.e("Certificate Exception",e.toString());
e.printStackTrace();
}
catch (Exception e)
{
Log.e("Certificate Exception",e.toString());
e.printStackTrace();
}

error:0c0890ba:ASN.1 encoding routines:asn1_check_tlen:WRONG_TAG

I am trying to implement ssl support in my volley request (also I saw answers in SO with similar issues, but it does not help me)
With help of this article I converted my certificate extension from .cer to .bks
That according to this SO answer I do next
mRequestQueue = Volley.newRequestQueue(this, hurlStack);
private HurlStack hurlStack = new HurlStack()
{
#Override
protected HttpURLConnection createConnection(URL url) throws IOException
{
HttpsURLConnection httpsURLConnection = (HttpsURLConnection) super.createConnection(url);
try
{
httpsURLConnection.setSSLSocketFactory(getSSLSocketFactory());
httpsURLConnection.setHostnameVerifier(getHostnameVerifier());
}
catch (Exception e)
{
AppUtils.printLog(Log.ERROR, TAG, e.getMessage());
}
return httpsURLConnection;
}
};
private SSLSocketFactory getSSLSocketFactory() throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, KeyManagementException
{
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = getResources().openRawResource(R.raw.keystore); // this cert file stored in \app\src\main\res\raw folder path
Certificate ca = cf.generateCertificate(caInput);
caInput.close();
KeyStore keyStore = KeyStore.getInstance("BKS");
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
TrustManager[] wrappedTrustManagers = getWrappedTrustManagers(tmf.getTrustManagers());
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, wrappedTrustManagers, null);
return sslContext.getSocketFactory();
}
// Let's assume your server app is hosting inside a server machine
// which has a server certificate in which "Issued to" is "localhost",for example.
// Then, inside verify method you can verify "localhost".
// If not, you can temporarily return true
private HostnameVerifier getHostnameVerifier()
{
return new HostnameVerifier()
{
#Override
public boolean verify(String hostname, SSLSession session)
{
//return true; // verify always returns true, which could cause insecure network traffic due to trusting TLS/SSL server certificates for wrong hostnames
HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
return hv.verify("localhost", session);
}
};
}
private TrustManager[] getWrappedTrustManagers(TrustManager[] trustManagers)
{
final X509TrustManager originalTrustManager = (X509TrustManager) trustManagers[0];
return new TrustManager[] {new X509TrustManager()
{
public X509Certificate[] getAcceptedIssuers()
{
return originalTrustManager.getAcceptedIssuers();
}
public void checkClientTrusted(X509Certificate[] certs, String authType)
{
try
{
if (certs != null && certs.length > 0)
{
certs[0].checkValidity();
}
else
{
originalTrustManager.checkClientTrusted(certs, authType);
}
}
catch (CertificateException e)
{
Log.w("checkClientTrusted", e.toString());
}
}
public void checkServerTrusted(X509Certificate[] certs, String authType)
{
try
{
if (certs != null && certs.length > 0)
{
certs[0].checkValidity();
}
else
{
originalTrustManager.checkServerTrusted(certs, authType);
}
}
catch (CertificateException e)
{
Log.w("checkServerTrusted", e.toString());
}
}
}};
}
And I get next error
com.android.org.conscrypt.OpenSSLX509CertificateFactory$ParsingException: com.android.org.conscrypt.OpenSSLX509CertificateFactory$ParsingException: java.lang.RuntimeException: error:0c0890ba:ASN.1 encoding routines:asn1_check_tlen:WRONG_TAG
And because of this I get such respond
Bad Request
Bad Request - Invalid Header
HTTP Error 400. The request has an invalid header name.
What am I doing wrong?
Feel free to ask
EDIT 1
so now my getSSLSocketFactory() method look like this
private SSLSocketFactory getSSLSocketFactory() throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, KeyManagementException
{
InputStream ksInStream = getResources().openRawResource(R.raw.keystore);
KeyStore ks = KeyStore.getInstance("BKS");
ks.load(ksInStream, SslUtils.KEYSTORE_PASSWORD_SSL.toCharArray());
// Certificate cert = ks.getCertificate("alias");
// ks.setCertificateEntry("ca", cert);
ksInStream.close();
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(ks);
TrustManager[] wrappedTrustManagers = getWrappedTrustManagers(tmf.getTrustManagers());
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, wrappedTrustManagers, null);
return sslContext.getSocketFactory();
}
Now I did not get message about wrong TAG , but I still get bad respond
ResponseJsonString =
Bad Request
Bad Request - Invalid Header
HTTP Error 400. The request has an invalid header name.
In this code you seem to load keystore in BKS format as it would be X.509 encoded certificate, which is bound to fail
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = getResources().openRawResource(R.raw.elalkeystore);
Certificate ca = cf.generateCertificate(caInput);
caInput.close();
You can load keystore like this:
InputStream ksInStream = getResources().openRawResource(R.raw.elalkeystore);
KeyStore ks = KeyStore.getInstance("BKS");
ks.load(ksInStream, keystorePasswordCharArray);
Certificate cert = ks.getCertificate("entryAlias");
ksInStream.close();
Eventually I did not find solution for the issue, I found another approach for implementation
So follow this article
http://ogrelab.ikratko.com/using-android-volley-with-self-signed-certificate/
also if there is any issue about converting .cer to .bks here my SO question and answer
Extension of certificate .cer convert to .bks

SSLHandshakeException when trying to connect to my server using self-signed certificate with Retrofit 2 on Android

I'm trying to connect to my API server using a self-signed certificate. The certificate was successfully installed on the server. I've tested it via OpenSSL and also in Firefox.
I followed the Andrey Makarov's answer to configure OkHttp. But it doesn't work. When I try to execute my request I get javax.net.ssl.SSLHandshakeException with java.security.cert.CertPathValidatorException: Trust anchor for certification path not found message.
Here is my code:
public HttpClient() {
/* ... */
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("TLSv1.2");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
KeyStore keyStore = readKeyStore();
TrustManagerFactory trustManagerFactory = null;
try {
trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, "password".toCharArray());
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
}
catch (final Exception e) {
Log.e(TAG, e.toString());
}
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
OkHttpClient client = new OkHttpClient.Builder()
.sslSocketFactory(sslContext.getSocketFactory(), trustManager)
.build();
mRetrofit = new Retrofit.Builder()
.client(client)
.baseUrl(mBaseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
private KeyStore readKeyStore() {
KeyStore ks = null;
try {
ks = KeyStore.getInstance("BKS");
}
catch (final Exception e) {
Log.e(TAG, e.toString());
}
char[] password = "password".toCharArray();
final Context context = App.app;
InputStream is = context.getResources().openRawResource(R.raw.key_sorage);
try {
ks.load(is, password);
}
catch (final Exception e) {
Log.e(TAG, e.toString());
}
finally {
if (is != null) {
try {
is.close();
}
catch (final Exception e2) {
Log.e(TAG, e2.toString());
}
}
}
return ks;
}
Retrofit version is 2.3.0.

javax.net.ssl.SSLHandshakeException: no cipher suites in common no cipher suites in common

Am trying to establish an SSL Connection between a client and a server. But anytime time i try to connect from my client, i get a javax.net.ssl.SSLHandshakeException: no cipher suites in common no cipher suites in common error on my server. I have generated a keystore with signed certificates and i am referencing the keystore on both my client and server. I have gotten fed up after numerous research on this issue and related post on this site hasn't been helpful.
Here is my Server code
public class ServerApplicationSSL {
public static void main(String[] args) {
boolean debug = true;
System.out.println("Waiting For Connection");
int intSSLport = 4444;
{
Security.addProvider(new Provider());
//Security.addProvider(new BouncyCastleProvider());
//System.setProperty("javax.net.ssl.keyStore","C:\\SSLCERT\\NEWAEDCKSSKYE");
//System.setProperty("javax.net.ssl.keyStorePassword", "skyebank");
}
if (debug) {
System.setProperty("javax.net.debug", "all");
}
FileWriter file = null;
try {
file = new FileWriter("C:\\SSLCERT\\Javalog.txt");
} catch (Exception ee) {
//message = ee.getMessage();
}
try {
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(new FileInputStream("C:\\SSLCERT\\NEWAEDCKSSKYE"), "skyebank".toCharArray());
file.write("Incoming Connection\r\n");
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory
.getDefaultAlgorithm());
kmf.init(keystore, "skyebank".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(keystore);
TrustManager[] trustManagers = tmf.getTrustManagers();
SSLContext context = SSLContext.getInstance("TLS");
context.init(kmf.getKeyManagers(), trustManagers, null);
SSLServerSocketFactory sslServerSocketfactory = (SSLServerSocketFactory) context.getServerSocketFactory();
SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketfactory.createServerSocket(intSSLport);
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
SSLServerSocket server_socket = (SSLServerSocket) sslServerSocket;
server_socket.setNeedClientAuth(true);
sslSocket.startHandshake();
System.out.println("Connection Accepted");
file.write("Connection Accepted\r\n");
while (true) {
PrintWriter out = new PrintWriter(sslSocket.getOutputStream(), true);
//BufferedReader in = new BufferedReader(new InputStreamReader(sslSocket.getInputStream()));
String inputLine;
//while ((inputLine = in.readLine()) != null) {
out.println("Hello Client....Welcome");
System.out.println("Hello Client....Welcome");
//}
out.close();
//in.close();
sslSocket.close();
sslServerSocket.close();
file.flush();
file.close();
}
} catch (Exception exp) {
try {
System.out.println(exp.getMessage() + "\r\n");
System.out.println(exp.getStackTrace() + "\r\n");
file.write(exp.getMessage() + "\r\n");
file.flush();
file.close();
} catch (Exception eee) {
//message = eee.getMessage();
}
}
}
}
Here is my clients code
public String MakeSSlCall(String meternum) {
String message = "";
FileWriter file = null;
try {
file = new FileWriter("C:\\SSLCERT\\ClientJavalog.txt");
} catch (Exception ee) {
message = ee.getMessage();
}
try {
file.write("KeyStore Generated\r\n");
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(new FileInputStream("C:\\SSLCERT\\NEWAEDCKSSKYE"), "skyebank".toCharArray());
file.write("KeyStore Generated\r\n");
Enumeration enumeration = keystore.aliases();
while (enumeration.hasMoreElements()) {
String alias = (String) enumeration.nextElement();
file.write("alias name: " + alias + "\r\n");
keystore.getCertificate(alias);
file.write(keystore.getCertificate(alias).toString() + "\r\n");
}
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory
.getDefaultAlgorithm());
kmf.init(keystore, "skyebank".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(keystore);
file.write("KeyStore Stored\r\n");
SSLContext context = SSLContext.getInstance("SSL");
TrustManager[] trustManagers = tmf.getTrustManagers();
KeyManager[] AllKeysMan = kmf.getKeyManagers();
file.write("Key Manager Length is " + AllKeysMan.length + "\r\n");
for (int i = 0; i < AllKeysMan.length; i++) {
file.write("Key Manager At This Point is " + AllKeysMan[i] + "\r\n");
}
context.init(kmf.getKeyManagers(), trustManagers, null);
SSLSocketFactory f = context.getSocketFactory();
file.write("About to Connect to Ontech\r\n");
SSLSocket c = (SSLSocket) f.createSocket("192.168.1.16", 4444);
file.write("Connection Established to 196.14.30.33 Port: 8462\r\n");
file.write("About to Start Handshake\r\n");
c.startHandshake();
file.write("Handshake Established\r\n");
file.flush();
file.close();
return "Connection Established";
} catch (Exception e) {
try {
file.write("An Error Occured\r\n");
file.write(e.getMessage() + "\r\n");
file.flush();
file.close();
} catch (Exception eee) {
message = eee.getMessage();
}
return "Connection Failed";
}
}
}
can someone please tell me what am doing wrong?
You will have to use SSLContext for this purpose. Check out the sample code which I implemented in one of my applications below. Client context means you become the client and call some back end. Server context means you accept the client requests.
public class SSLUtil {
private static String KEY_STORE_TYPE = "JKS";
private static String TRUST_STORE_TYPE = "JKS";
private static String KEY_MANAGER_TYPE = "SunX509";
private static String TRUST_MANAGER_TYPE = "SunX509";
private static String PROTOCOL = "TLS";
private static SSLContext serverSSLCtx = null;
private static SSLContext clientSSLCtx = null;
public static SSLContext createServerSSLContext(final String keyStoreLocation,
final String keyStorePwd)
throws KeyStoreException,
NoSuchAlgorithmException,
CertificateException,
FileNotFoundException,
IOException,
UnrecoverableKeyException,
KeyManagementException {
if (serverSSLCtx == null) {
KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE);
keyStore.load(new FileInputStream(keyStoreLocation), keyStorePwd.toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KEY_MANAGER_TYPE);
keyManagerFactory.init(keyStore, keyStorePwd.toCharArray());
serverSSLCtx = SSLContext.getInstance(PROTOCOL);
serverSSLCtx.init(keyManagerFactory.getKeyManagers(), null, null);
}
return serverSSLCtx;
}
public static SSLContext createClientSSLContext(final String trustStoreLocation,
final String trustStorePwd)
throws KeyStoreException,
NoSuchAlgorithmException,
CertificateException,
FileNotFoundException,
IOException,
KeyManagementException {
if (clientSSLCtx == null) {
KeyStore trustStore = KeyStore.getInstance(TRUST_STORE_TYPE);
trustStore.load(new FileInputStream(trustStoreLocation), trustStorePwd.toCharArray());
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TRUST_MANAGER_TYPE);
trustManagerFactory.init(trustStore);
clientSSLCtx = SSLContext.getInstance(PROTOCOL);
clientSSLCtx.init(null, trustManagerFactory.getTrustManagers(), null);
}
return clientSSLCtx;
}
}
Finally make sure you import the trusted server certificate to the client key store. Literally server and client should have different key stores. The key store used in the client side is referred to as client trust store since we are trusting the server certificate here. This article may help.

Categories

Resources