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
来源:https://stackoverflow.com/questions/46812752/error0c0890baasn-1-encoding-routinesasn1-check-tlenwrong-tag