bouncyScatleJSSEProvider:客户端引发致命错误(2)内部错误(80)警报:读取记录失败

vjhs03f7  于 2021-07-08  发布在  Java
关注(0)|答案(1)|浏览(795)

我在使用bouncycastle库开发http客户机时遇到了一个问题。目标版本(但在Java1.8.0\u91中,使用相同版本的bouncycastle时,错误也可以重现。)
jre 1.6.0\ U 45-b06
bouncycastle jdk15to18 167(bcprov-jdk15to18-167.jar、bcpkix-jdk15to18-167.jar、bctls-jdk15to18-167.jar)
httpclient代码:

String strURL = "https://www.<WEBSITE>.com";
            // CODE to set default TrustStore, KeyStore to be used

            // setup BC as SecurityProvider and SSLSocketFactoryProvider
/*
            Security.insertProviderAt(new BouncyCastleProvider(), 1);
            Security.insertProviderAt(new BouncyCastleJsseProvider(), 2);
            Security.setProperty("ssl.KeyManagerFactory.algorithm", "PKIX");
            Security.setProperty("ssl.TrustManagerFactory.algorithm", "PKIX");  
            Security.setProperty("ssl.SocketFactory.provider", "org.bouncycastle.jsse.provider.SSLSocketFactoryImpl");
            System.setProperty("jdk.tls.trustNameService", "true");

* /

            URL url = new URL( strURL );
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setDoOutput(true);
            conn.setRequestMethod("GET");

            InputStream is = null;
            if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                System.out.println("OK");
                is = conn.getInputStream();
            } else if (conn.getResponseCode() == HttpURLConnection.HTTP_INTERNAL_ERROR) {
                System.out.println("ERROR");
                is = conn.getErrorStream();
            } else  {
                System.out.println( conn.getResponseCode() );
                System.out.println( conn.getResponseMessage() );
            }

            if (is != null) {  
                System.out.println( readFullyAsString(is, "UTF-8") );
            }
            conn.disconnect();

使用tls1.2在没有客户端身份验证的情况下访问网站上的数据可以正常工作(对于返回握手失败(40)的特定网站存在一些问题,但幸运的是在我们的情况下不是这样)。但是当需要client_auth时,代码会失败,并出现以下错误(有点神秘):

nov. 27, 2020 5:23:10 PM org.bouncycastle.jsse.provider.ProvTlsClient notifyAlertRaised
WARNING: Client raised fatal(2) internal_error(80) alert: Failed to read record
java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(Unknown Source)
    at java.net.SocketInputStream.read(Unknown Source)
    at org.bouncycastle.tls.RecordStream$Record.fillTo(RecordStream.java:429)
    at org.bouncycastle.tls.RecordStream$Record.readHeader(RecordStream.java:468)
    at org.bouncycastle.tls.RecordStream.readRecord(RecordStream.java:201)
    at org.bouncycastle.tls.TlsProtocol.safeReadRecord(TlsProtocol.java:768)
    at org.bouncycastle.tls.TlsProtocol.readApplicationData(TlsProtocol.java:731)
    at org.bouncycastle.jsse.provider.ProvSSLSocketDirect$AppDataInput.read(ProvSSLSocketDirect.java:603)
    at java.io.BufferedInputStream.fill(Unknown Source)
    at java.io.BufferedInputStream.read1(Unknown Source)
    at java.io.BufferedInputStream.read(Unknown Source)
    at sun.net.www.http.HttpClient.parseHTTPHeader(Unknown Source)
    at sun.net.www.http.HttpClient.parseHTTP(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
    at java.net.HttpURLConnection.getResponseCode(Unknown Source)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(Unknown Source)
    at HttpsClient.main(HttpsClient.java:109)

nov. 27, 2020 5:23:10 PM org.bouncycastle.jsse.provider.ProvTlsClient notifyAlertRaised
WARNING: Client raised fatal(2) internal_error(80) alert: Failed to read record
java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(Unknown Source)
    at java.net.SocketInputStream.read(Unknown Source)
    at org.bouncycastle.tls.RecordStream$Record.fillTo(RecordStream.java:429)
    at org.bouncycastle.tls.RecordStream$Record.readHeader(RecordStream.java:468)
    at org.bouncycastle.tls.RecordStream.readRecord(RecordStream.java:201)
    at org.bouncycastle.tls.TlsProtocol.safeReadRecord(TlsProtocol.java:768)
    at org.bouncycastle.tls.TlsProtocol.readApplicationData(TlsProtocol.java:731)
    at org.bouncycastle.jsse.provider.ProvSSLSocketDirect$AppDataInput.read(ProvSSLSocketDirect.java:603)
    at java.io.BufferedInputStream.fill(Unknown Source)
    at java.io.BufferedInputStream.read1(Unknown Source)
    at java.io.BufferedInputStream.read(Unknown Source)
    at sun.net.www.http.HttpClient.parseHTTPHeader(Unknown Source)
    at sun.net.www.http.HttpClient.parseHTTP(Unknown Source)
    at sun.net.www.http.HttpClient.parseHTTP(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
    at java.net.HttpURLConnection.getResponseCode(Unknown Source)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(Unknown Source)
    at HttpsClient.main(HttpsClient.java:109)

java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(Unknown Source)
    at java.net.SocketInputStream.read(Unknown Source)
    at org.bouncycastle.tls.RecordStream$Record.fillTo(RecordStream.java:429)
    at org.bouncycastle.tls.RecordStream$Record.readHeader(RecordStream.java:468)
    at org.bouncycastle.tls.RecordStream.readRecord(RecordStream.java:201)
    at org.bouncycastle.tls.TlsProtocol.safeReadRecord(TlsProtocol.java:768)
    at org.bouncycastle.tls.TlsProtocol.readApplicationData(TlsProtocol.java:731)
    at org.bouncycastle.jsse.provider.ProvSSLSocketDirect$AppDataInput.read(ProvSSLSocketDirect.java:603)
    at java.io.BufferedInputStream.fill(Unknown Source)
    at java.io.BufferedInputStream.read1(Unknown Source)
    at java.io.BufferedInputStream.read(Unknown Source)
    at sun.net.www.http.HttpClient.parseHTTPHeader(Unknown Source)
    at sun.net.www.http.HttpClient.parseHTTP(Unknown Source)
    at sun.net.www.http.HttpClient.parseHTTP(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
    at java.net.HttpURLConnection.getResponseCode(Unknown Source)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(Unknown Source)
    at HttpsClient.main(HttpsClient.java:109)

正如所料,代码在Java1.8中运行良好,没有bc作为安全提供者。。。但是在Java1.6中,TLS1.2支持需要bc。
我用wireshark查看了数据包,但是我没有足够的知识来分析服务器的ssl握手操作发生了什么(失败)。
我错过了什么?或者这只是已知的bc限制?谢谢你的建议。

trnvg8h3

trnvg8h31#

经过广泛的研究和测试(我们建立了自己的开发环境来复制端点,我们试图用客户端证书连接到),我们找到了一个解决方案(发布在下面),它在我们的开发环境中对我们有效,但无法在端点上配置。这就是为什么我们去计划b-tls终止代理,在我们的情况下,它就像一个魅力,当我们没有控制服务器环境。
iis解决方案
在我们的例子中,需要客户端身份验证的web服务是在microsoft iis上运行的。如前所述,“不幸的是,我们的tls库不支持重新协商(我们也不打算添加它,尽管我们将添加相应的tls 1.3特性)。”(https://github.com/bcgit/bc-java/issues/593). 在阅读了iis文档和一些测试之后,我们成功地以一种可以使用bc tls lib建立tls会话的方式配置了环境:
第一步:
使用默认设置创建iis站点
使用“最佳实践”模板运行iiscrypto:



第二步:
启用sslalwaysnegoclientcert
将以下文本保存到名为“enable\u ssl\u renegotiate.js”的文件中

var vdirObj=GetObject("IIS://localhost/W3svc/1");
// replace 1 on this line with the number of the web site you wish to configure
WScript.Echo("Value of SSLAlwaysNegoClientCert Before: " + vdirObj.SSLAlwaysNegoClientCert);
vdirObj.Put("SSLAlwaysNegoClientCert", true);
vdirObj.SetInfo();
WScript.Echo("Value of SSLAlwaysNegoClientCert After: " + vdirObj.SSLAlwaysNegoClientCert);

从提升的/administrator命令提示符运行以下命令:

cscript.exe enable_ssl_renegotiate.js

我在bouncycastle github上发布了相同的答案-#847

相关问题