错误:0c0890ba:ASN.1编码例程:asn1_check_tlen:WRONG_TAG

时间:2017-10-18 14:36:25

标签: java android ssl ssl-certificate boringssl

我正在尝试在我的截击请求中实现ssl支持(我也在SO中看到类似问题的答案,但它对我没有帮助)

this article的帮助下,我将证书扩展名从.cer转换为.bks

根据this SO answer我的下一步

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());
            }
        }
    }};
}

我得到下一个错误

  

com.android.org.conscrypt.OpenSSLX509CertificateFactory $ ParsingException:com.android.org.conscrypt.OpenSSLX509CertificateFactory $ ParsingException:java.lang.RuntimeException:error:0c0890ba:ASN.1编码例程:asn1_check_tlen:WRONG_TAG

因此,我得到了这样的回应

                                                                  错误的请求                                                                                                                                      

错误请求 - 标头无效

                                                                  

HTTP错误400.请求的标题名称无效。

                                                                  

我做错了什么?

随意询问

编辑1

所以现在我的getSSLSocketFactory()方法看起来像这样

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();
}

现在我没有收到有关错误TAG的消息,但我仍然得到bad respond

ResponseJsonString =                                                                   错误的请求                                                                                                                                      

错误请求 - 标头无效

                                                                  

HTTP错误400.请求的标题名称无效。

                                                                  

2 个答案:

答案 0 :(得分:2)

在此代码中,您似乎以BKS格式加载密钥库,因为它将是X.509编码的证书,它必然会失败

CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = getResources().openRawResource(R.raw.elalkeystore);

Certificate ca = cf.generateCertificate(caInput);
caInput.close();

您可以像这样加载密钥库:

InputStream ksInStream = getResources().openRawResource(R.raw.elalkeystore);

KeyStore ks = KeyStore.getInstance("BKS");
ks.load(ksInStream, keystorePasswordCharArray);
Certificate cert = ks.getCertificate("entryAlias");
ksInStream.close();

答案 1 :(得分:0)

最终我没有找到问题的解决方案,我找到了另一种实施方法

请遵循这篇文章

http://ogrelab.ikratko.com/using-android-volley-with-self-signed-certificate/

如果在此处将.cer转换为.bks时遇到任何问题,我的问题和回答

Extension of certificate .cer convert to .bks