Java 错误:0c0890ba:ASN.1编码例程:asn1\u检查\t错误\u标记

Java 错误:0c0890ba:ASN.1编码例程:asn1\u检查\t错误\u标记,java,android,ssl,ssl-certificate,boringssl,Java,Android,Ssl,Ssl Certificate,Boringssl,我正在尝试在我的截击请求中实现ssl支持(我在SO中也看到了类似问题的答案,但这对我没有帮助) 在的帮助下,我将证书扩展名从.cer转换为.bks 根据我下一步做的 mRequestQueue = Volley.newRequestQueue(this, hurlStack); private HurlStack hurlStack = new HurlStack() { @Override protected HttpURLConnection createConnectio

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

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

根据我下一步做的

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.concrypt.OpenSSLX509CertificateFactory$ParsingException:com.android.org.concrypt.OpenSSLX509CertificateFactory$ParsingException:java.lang.RuntimeException:错误:0c0890ba:ASN.1编码例程:asn1\U检查\tlen:错误的\U标记

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

错误的请求 错误的请求-无效的标头 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();
}
现在我没有收到关于错误标签的消息,但我仍然收到
错误响应

ResponseJsonString= 错误的请求 错误的请求-无效的标头 HTTP错误400。请求的标头名称无效


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

因此,请关注本文

此外,如果在将
.cer
转换为
.bks
方面存在任何问题,请在此回答我的问题


在这段代码中,您似乎以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();

从不同的来源来看,此问题与在用于转换的证书末尾提取尾随空格有关。仔细检查你的起始证书,确保它没有尾随空格或换行符。问题其实很简单。查看divanov的答案。@Nico我在
divanov
answer下留下了评论,你能看一下吗?但是根据你的答案,没有使用
cert
值。我想你忘了提到这一行
ks.setCertificateEntry(“ca”,cert),是吗?我想他确实忘了在他的示例中添加这一行。那么它应该像预期的那样工作。为什么要将证书添加到已有的密钥库中?我提取证书只是为了能够交叉检查密钥库是否确实有证书,并使其与被替换的代码类似。@divanov因此,如果我理解正确,我就不需要调用
.setCertificateEntry()
方法了?不管怎样,我对我的编辑1提出了疑问,你能看一下吗?这个方法在密钥存储中添加了一个证书,而它原来是有证书的。我建议您收集连接尝试的tcpdump,然后与wireshark一起检查那里发生了什么。另外,原始错误错误错误请求-无效标头未更改,尽管您在TLS安装期间解决了异常。这让我怀疑这个错误是否与原来的问题有关,或者这个问题不准确。