CamelJettyWebSocketServer,致命错误:42:空证书链

2022-01-19 00:00:00 ssl java apache-camel

我尝试在自定义骆驼端点中建立相互验证的连接.我尝试进行测试.当我将 ClientAuthentication.REQUIRE 设置为 NONE 时,会建立 TLS 连接,一切正常.不过,我想对连接进行相互身份验证.当我将标志设置为 REQUIRE 时,我得到(启用完整调试输出):

I try to set up a mutually authenticated connection in a custom camel endpoint. I try to run a test. When I set ClientAuthentication.REQUIRE to NONE, a TLS connection is established and all is fine. I would like to have mutual authentication on connections, though. When i set the flag to REQUIRE, I get (with enabled full debug output):

CamelJettyWebSocketServer-40,致命错误:42:空证书链javax.net.ssl.SSLHandshakeException:空证书链

CamelJettyWebSocketServer-40, fatal error: 42: null cert chain javax.net.ssl.SSLHandshakeException: null cert chain

让我困惑的是:当我不激活客户端身份验证时,客户端和服务器端都建立了 Web 套接字连接并进行单向身份验证.那么证书和信任链似乎没问题?

What puzzles me: When i do not activate client authentication, both client and server side set up a web socket connection and do unidirectional authentication. So the certificates and trust chains seem to be fine?

我的证书链是这样设置的:Root CA -> Sub CA -> Client &服务器证书.因此,包含 RootCA 和 SubCA 证书的信任库在服务器端和客户端都是相同的,只有密钥库不同.

My cert chain is set up like this: Root CA -> Sub CA -> Client & Server Cert. So the truststore, containing RootCA and SubCA certs are identical on both server and client side, only the keystore differs.

这是日志的最后一部分(原始数据被剥离):

This is the last part of the log (raw data stripped):

* ServerHello, TLSv1.2 RandomCookie: GMT: 1478504471 bytes = ...192、99、62} 密码套件:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384压缩方法:0 扩展 renegotiation_info,重新协商的连接:* %% 已初始化:[会话 2,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384]** TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 [读取] MD5 和 SHA1 哈希:len = 81 0000:...
.*** 证书链链 [0] = [ [ 版本:V3 主题:CN=dptmt idl Server, OU=dptmt, O=company, L=Muenchen, ST=Bayern, C=DE签名算法:SHA256withRSA,OID = 1.2.840.113549.1.1.11

* ServerHello, TLSv1.2 RandomCookie: GMT: 1478504471 bytes = ... 192, 99, 62} Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 Compression Method: 0 Extension renegotiation_info, renegotiated_connection: * %% Initialized: [Session-2, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384] ** TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 [read] MD5 and SHA1 hashes: len = 81 0000: ...
. *** Certificate chain chain [0] = [ [ Version: V3 Subject: CN=dptmt idl Server, OU=dptmt, O=company, L=Muenchen, ST=Bayern, C=DE Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11

密钥:Sun RSA 公钥,2048 位模数:...公共指数:65537 有效性:[来自:10 月 25 日星期二 11:50:28 CEST2016年,To: Thu Oct 25 11:50:28 CEST 2018] Issuer: CN=idl SubCA 2016, O=company, C=DE SerialNumber: [01]

Key: Sun RSA public key, 2048 bits modulus: ... public exponent: 65537 Validity: [From: Tue Oct 25 11:50:28 CEST 2016, To: Thu Oct 25 11:50:28 CEST 2018] Issuer: CN=idl SubCA 2016, O=company, C=DE SerialNumber: [ 01]

证书扩展:8 1:ObjectId:1.3.6.1.5.5.7.1.1Criticality=false AuthorityInfoAccess [ [ accessMethod: cklmsuers访问位置:URIName:http://downloads.dptmt.company.de/rootcacert2016.cert ] ]

Certificate Extensions: 8 1: ObjectId: 1.3.6.1.5.5.7.1.1 Criticality=false AuthorityInfoAccess [ [ accessMethod: cklmsuers accessLocation: URIName: http://downloads.dptmt.company.de/rootcacert2016.cert ] ]

[2]: ObjectId: 2.5.29.35 Criticality=false AuthorityKeyIdentifier [密钥标识符 [ 0000: F3 85 C5 44 9F 10 A7 BE AF 8E 6C 54 73 07 31CB ...D......lTs.1.0010:FB 4F 73 81
.Os.] ]

[2]: ObjectId: 2.5.29.35 Criticality=false AuthorityKeyIdentifier [ KeyIdentifier [ 0000: F3 85 C5 44 9F 10 A7 BE AF 8E 6C 54 73 07 31 CB ...D......lTs.1. 0010: FB 4F 73 81
.Os. ] ]

[3]:ObjectId:2.5.29.19 Criticality=false 基本约束:[
CA:false PathLen: 未定义]

[3]: ObjectId: 2.5.29.19 Criticality=false BasicConstraints:[
CA:false PathLen: undefined ]

[4]:ObjectId:2.5.29.31 Criticality=false CRLDistributionPoints [
[分发点:[URIName:http://crl.dptmt.company.de/idl.crl]]]

[4]: ObjectId: 2.5.29.31 Criticality=false CRLDistributionPoints [
[DistributionPoint: [URIName: http://crl.dptmt.company.de/idl.crl] ]]

[5]:ObjectId:2.5.29.37 Criticality=false ExtendedKeyUsages [
clientAuth serverAuth ]

[5]: ObjectId: 2.5.29.37 Criticality=false ExtendedKeyUsages [
clientAuth serverAuth ]

[6]:ObjectId:2.5.29.15 Criticality=false KeyUsage [
数字签名密钥_加密]

[6]: ObjectId: 2.5.29.15 Criticality=false KeyUsage [
DigitalSignature Key_Encipherment ]

[7]:ObjectId:2.5.29.17 Criticality=false SubjectAlternativeName [
DNSName:本地主机 DNSName:127.0.0.1 DNSName:idlconnector.dptmt.company.de]

[7]: ObjectId: 2.5.29.17 Criticality=false SubjectAlternativeName [
DNSName: localhost DNSName: 127.0.0.1 DNSName: idlconnector.dptmt.company.de ]

[8]:ObjectId:2.5.29.14 关键性=false SubjectKeyIdentifier [密钥标识符 [ 0000: C8 39 51 89 74 35 FF AB 07 38 12 79 C0 AA 8C17 .9Q.t5...8.y.... 0010: 22 D3 81 34
"..4 ] ]

[8]: ObjectId: 2.5.29.14 Criticality=false SubjectKeyIdentifier [ KeyIdentifier [ 0000: C8 39 51 89 74 35 FF AB 07 38 12 79 C0 AA 8C 17 .9Q.t5...8.y.... 0010: 22 D3 81 34
"..4 ] ]

] 算法:[SHA256withRSA]...

] Algorithm: [SHA256withRSA]...

]*** 找到可信证书:[ [版本:V3 主题:CN=idl SubCA 2016,O=company,C=DE 签名算法:SHA256withRSA,OID= 1.2.840.113549.1.1.11

] *** Found trusted certificate: [ [ Version: V3 Subject: CN=idl SubCA 2016, O=company, C=DE Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11

密钥:Sun RSA 公钥,2048 位模数:...公共指数:65537 有效性:[来自:10 月 25 日星期二 11:49:47 CEST2016年,To: Wed Oct 23 11:49:47 CEST 2024] Issuer: CN=idl Root CA 2016, O=company, C=DE SerialNumber: [01]

Key: Sun RSA public key, 2048 bits modulus: ... public exponent: 65537 Validity: [From: Tue Oct 25 11:49:47 CEST 2016, To: Wed Oct 23 11:49:47 CEST 2024] Issuer: CN=idl Root CA 2016, O=company, C=DE SerialNumber: [ 01]

证书扩展:6 1:ObjectId:1.3.6.1.5.5.7.1.1Criticality=false AuthorityInfoAccess [ [ accessMethod: cklmsuers访问位置:URIName:http://downloads.dptmt.company.de/rootcacert2016.cert ] ]

Certificate Extensions: 6 1: ObjectId: 1.3.6.1.5.5.7.1.1 Criticality=false AuthorityInfoAccess [ [ accessMethod: cklmsuers accessLocation: URIName: http://downloads.dptmt.company.de/rootcacert2016.cert ] ]

[2]: ObjectId: 2.5.29.35 Criticality=false AuthorityKeyIdentifier [密钥标识符 [ 0000: 7B 98 1D B2 FF 81 B4 DB D8 C2 5F 1D 88 8A AD1A ...._..... 0010:52 2D 60 2C
R-`, ] ]

[2]: ObjectId: 2.5.29.35 Criticality=false AuthorityKeyIdentifier [ KeyIdentifier [ 0000: 7B 98 1D B2 FF 81 B4 DB D8 C2 5F 1D 88 8A AD 1A .........._..... 0010: 52 2D 60 2C
R-`, ] ]

[3]:ObjectId:2.5.29.19 临界=true BasicConstraints:[CA:truePathLen:2147483647]

[3]: ObjectId: 2.5.29.19 Criticality=true BasicConstraints:[ CA:true PathLen:2147483647 ]

[4]:ObjectId:2.5.29.31 Criticality=false CRLDistributionPoints [
[分发点:[URIName:http://crl.dptmt.company.de/idl.crl]]]

[4]: ObjectId: 2.5.29.31 Criticality=false CRLDistributionPoints [
[DistributionPoint: [URIName: http://crl.dptmt.company.de/idl.crl] ]]

[5]:ObjectId:2.5.29.15 Criticality=false KeyUsage [
DigitalSignature Key_CertSign Crl_Sign ]

[5]: ObjectId: 2.5.29.15 Criticality=false KeyUsage [
DigitalSignature Key_CertSign Crl_Sign ]

[6]:ObjectId:2.5.29.14 关键性 = 假 SubjectKeyIdentifier [密钥标识符 [ 0000: F3 85 C5 44 9F 10 A7 BE AF 8E 6C 54 73 07 31CB ...D......lTs.1.0010:FB 4F 73 81
.Os.] ]

[6]: ObjectId: 2.5.29.14 Criticality=false SubjectKeyIdentifier [ KeyIdentifier [ 0000: F3 85 C5 44 9F 10 A7 BE AF 8E 6C 54 73 07 31 CB ...D......lTs.1. 0010: FB 4F 73 81
.Os. ] ]

] 算法:[SHA256withRSA] 签名:...

] Algorithm: [SHA256withRSA] Signature: ...

] [读取] MD5 和 SHA1 哈希:len = 1156 0000: 0B ...
F..T* ECDH ServerKeyExchange 签名算法 SHA512withRSA 服务器密钥:Sun EC 公钥,256 位公共 x 坐标:28847400382242897438936230468661390225193273270317541849731947641016598202380公共 y 坐标:44672647556933576846980891280419719564112470643460642037901420136126664747387参数:secp256r1 [NIST P-256, X9.62 prime256v1](1.2.840.10045.3.1.7) [读取] MD5 和 SHA1 哈希:len = 333 0000: ... CertificateRequest 证书类型:RSA、DSS、ECDSA 支持的签名算法:SHA512withECDSA、SHA512withRSA、SHA384withECDSA、SHA3​​84withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA,SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA,SHA1withRSA、SHA1withDSA 证书颁发机构:[阅读] MD5 和SHA1 哈希:... ServerHelloDone [读取] MD5 和 SHA1 哈希:len = 4 0000: 0E 00 00 00 .... 警告:不适合找到证书 - 在没有客户端身份验证的情况下继续* 证书链

] [read] MD5 and SHA1 hashes: len = 1156 0000: 0B ...
F..T * ECDH ServerKeyExchange Signature Algorithm SHA512withRSA Server key: Sun EC public key, 256 bits public x coord: 28847400382242897438936230468661390225193273270317541849731947641016598202380 public y coord: 44672647556933576846980891280419719564112470643460642037901420136126664747387 parameters: secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7) [read] MD5 and SHA1 hashes: len = 333 0000: ... CertificateRequest Cert Types: RSA, DSS, ECDSA Supported Signature Algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA Cert Authorities: [read] MD5 and SHA1 hashes: ... ServerHelloDone [read] MD5 and SHA1 hashes: len = 4 0000: 0E 00 00 00 .... Warning: no suitable certificate found - continuing without client authentication * Certificate chain

* ECDHClientKeyExchange ECDH 公共值:{ ... 完成 verify_data: { 99, 243, 110, 215, 154, 6, 238, 190, 185, 65, 205, 89 } [write] MD5 和 SHA1 哈希:len = 16 0000: 14 00 00 0C 63 F3 6E D7 9A 06 EE BE B9 41 CD 59 ....c.n......A.Y 之前填充的明文加密:len = 96 0000:...
LC 08:41:11.655[CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0]调试 org.eclipse.jetty.io.SelectorManager - 选择器循环被唤醒从选择,1/1 选择 08:41:11.655[CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0]调试 org.eclipse.jetty.io.SelectChannelEndPoint - 主要兴趣更新 1 -> 0SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,Open,in,out,R,-,177/30000,SslConnection}{io=1,kio=0,kro=1}08:41:11.655[CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0]调试 org.eclipse.jetty.io.SelectChannelEndPoint - 本地兴趣更新 1 -> 0 为SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,Open,in,out,R,-,177/30000,SslConnection}{io=0,kio=0,kro=1}08:41:11.655[CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0]调试 org.eclipse.jetty.io.SelectorManager - 排队更改org.eclipse.jetty.io.SelectChannelEndPoint$1@431394e9 08:41:11.655[CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0]调试 org.eclipse.jetty.io.AbstractConnection -FILL_INTERESTED-->填充SslConnection@3c4546fe{NEED_UNWRAP,eio=-1/-1,di=-1} ->HttpConnection@80ef4f3[FILL_INTERESTED,DecryptedEndPoint@4f49498{/127.0.0.1:37052<->9292,Open,in,out,R,-,178/30000,HttpConnection}->SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,Open,in,out,-,-,177/30000,SslConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=START,0 of0},g=HttpGenerator{s=START},c=HttpChannelOverHttp@40d049f5{r=0,c=false,a=IDLE,uri=}]08:41:11.655[CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0]调试 org.eclipse.jetty.io.ssl.SslConnection - onFillable enterDecryptedEndPoint@4f49498{/127.0.0.1:37052<->9292,Open,in,out,R,-,178/30000,HttpConnection}->SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,Open,输入,输出,-,-,177/30000,SslConnection}{io=0,kio=0,kro=1}08:41:11.655[CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0]调试 org.eclipse.jetty.io.AbstractConnection -FILL_INTERESTED-->填充HttpConnection@80ef4f3[FILLING,DecryptedEndPoint@4f49498{/127.0.0.1:37052<->9292,Open,in,out,-,-,178/30000,HttpConnection}->SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,Open,in,out,-,-,177/30000,SslConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=START,0 of0},g=HttpGenerator{s=START},c=HttpChannelOverHttp@40d049f5{r=0,c=false,a=IDLE,uri=}]08:41:11.655[CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0]调试 org.eclipse.jetty.io.ssl.SslConnection - onFillable 退出DecryptedEndPoint@4f49498{/127.0.0.1:37052<->9292,Open,in,out,-,-,178/30000,HttpConnection}->SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,Open,输入,输出,-,-,177/30000,SslConnection}{io=0,kio=0,kro=1}08:41:11.656[CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0]调试 org.eclipse.jetty.io.AbstractConnection - FILLING-->IDLESslConnection@3c4546fe{NEED_UNWRAP,eio=-1/-1,di=-1} ->HttpConnection@80ef4f3[FILLING,DecryptedEndPoint@4f49498{/127.0.0.1:37052<->9292,Open,in,out,-,-,178/30000,HttpConnection}->SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,Open,in,out,-,-,177/30000,SslConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=START,0 of0},g=HttpGenerator{s=START},c=HttpChannelOverHttp@40d049f5{r=0,c=false,a=IDLE,uri=}]08:41:11.656[CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0]调试 org.eclipse.jetty.io.SelectorManager - 运行更改org.eclipse.jetty.io.SelectChannelEndPoint$1@431394e9 08:41:11.656[CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0]调试 org.eclipse.jetty.io.SelectorManager - 选择器循环等待选择 08:41:11.656 [CamelJettyWebSocketServer-40] 调试org.eclipse.jetty.server.HttpConnection -HttpConnection@80ef4f3[FILLING,DecryptedEndPoint@4f49498{/127.0.0.1:37052<->9292,Open,in,out,-,-,178/30000,HttpConnection}->SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,Open,in,out,-,-,177/30000,SslConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=START,0 of0},g=HttpGenerator{s=START},c=HttpChannelOverHttp@40d049f5{r=0,c=false,a=IDLE,uri=}]onFillable HttpChannelState@772152e{s=IDLE i=true a=null} 08:41:11.656[CamelJettyWebSocketServer-40] 调试org.eclipse.jetty.io.ssl.SslConnection -SslConnection@3c4546fe{NEED_UNWRAP,eio=-1/-1,di=-1} ->HttpConnection@80ef4f3[FILLING,DecryptedEndPoint@4f49498{/127.0.0.1:37052<->9292,Open,in,out,-,-,179/30000,HttpConnection}->SelectChannelEndPoint@37823e21{/127.0.0.1:37052<;->9292,Open,in,out,-,-,178/30000,SslConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=START,0 of0},g=HttpGenerator{s=START},c=HttpChannelOverHttp@40d049f5{r=0,c=false,a=IDLE,uri=}]填入 08:41:11.656 [CamelJettyWebSocketServer-40] DEBUGorg.eclipse.jetty.io.ChannelEndPoint - 填充 82SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,Open,in,out,-,-,178/30000,SslConnection}{io=0,kio=0,kro=1}[原始写入]:长度 = 6 0000:14 03 03 00 01 01
...... [原始写入]:长度 = 101 0000:......08:41:11.656 [CamelJettyWebSocketServer-40] 调试org.eclipse.jetty.io.ssl.SslConnection -SslConnection@3c4546fe{NEED_UNWRAP,eio=82/-1,di=-1} ->HttpConnection@80ef4f3[FILLING,DecryptedEndPoint@4f49498{/127.0.0.1:37052<->9292,Open,in,out,-,-,179/30000,HttpConnection}->SelectChannelEndPoint@37823e21{/127.0.0.1:37052<;->9292,Open,in,out,-,-,0/30000,SslConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=START,0的0},g=HttpGenerator{s=START},c=HttpChannelOverHttp@40d049f5{r=0,c=false,a=IDLE,uri=}]填充 82 个加密字节 E5 28 74 84 36 9F 56 D8 11 0C 38.f..L.(t.6.V...8 0060: 38 2C AC 97 6C
[原始读取]:长度 = 58,..l 0000: ...CamelJettyWebSocketServer-40,阅读:TLSv1.2 握手,长度 = 7708:41:11.666 [CamelJettyWebSocketServer-40] 调试org.eclipse.jetty.io.ssl.SslConnection -SslConnection@3c4546fe{NEED_TASK,eio=0/-1,di=-1} ->HttpConnection@80ef4f3[FILLING,DecryptedEndPoint@4f49498{/127.0.0.1:37052<->9292,Open,in,out,-,-,189/30000,HttpConnection}->SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,打开,输入,输出,-,-,10/30000,SslConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=START,0的0},g=HttpGenerator{s=START},c=HttpChannelOverHttp@40d049f5{r=0,c=false,a=IDLE,uri=}]展开状态 = OK HandshakeStatus = NEED_TASK bytesConsumed = 82bytesProduced = 0* 证书链*** CamelJettyWebSocketServer-40,致命错误:42:空证书链 javax.net.ssl.SSLHandshakeException:空证书链 %% 无效:[会话 1,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384]

* ECDHClientKeyExchange ECDH Public value: { ... Finished verify_data: { 99, 243, 110, 215, 154, 6, 238, 190, 185, 65, 205, 89 } [write] MD5 and SHA1 hashes: len = 16 0000: 14 00 00 0C 63 F3 6E D7 9A 06 EE BE B9 41 CD 59 ....c.n......A.Y Padded plaintext before ENCRYPTION: len = 96 0000: ...
LC 08:41:11.655 [CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0] DEBUG org.eclipse.jetty.io.SelectorManager - Selector loop woken up from select, 1/1 selected 08:41:11.655 [CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0] DEBUG org.eclipse.jetty.io.SelectChannelEndPoint - Key interests updated 1 -> 0 on SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,Open,in,out,R,-,177/30000,SslConnection}{io=1,kio=0,kro=1} 08:41:11.655 [CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0] DEBUG org.eclipse.jetty.io.SelectChannelEndPoint - Local interests updating 1 -> 0 for SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,Open,in,out,R,-,177/30000,SslConnection}{io=0,kio=0,kro=1} 08:41:11.655 [CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0] DEBUG org.eclipse.jetty.io.SelectorManager - Queued change org.eclipse.jetty.io.SelectChannelEndPoint$1@431394e9 08:41:11.655 [CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0] DEBUG org.eclipse.jetty.io.AbstractConnection - FILL_INTERESTED-->FILLING SslConnection@3c4546fe{NEED_UNWRAP,eio=-1/-1,di=-1} -> HttpConnection@80ef4f3[FILL_INTERESTED,DecryptedEndPoint@4f49498{/127.0.0.1:37052<->9292,Open,in,out,R,-,178/30000,HttpConnection}->SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,Open,in,out,-,-,177/30000,SslConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=START,0 of 0},g=HttpGenerator{s=START},c=HttpChannelOverHttp@40d049f5{r=0,c=false,a=IDLE,uri=}] 08:41:11.655 [CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0] DEBUG org.eclipse.jetty.io.ssl.SslConnection - onFillable enter DecryptedEndPoint@4f49498{/127.0.0.1:37052<->9292,Open,in,out,R,-,178/30000,HttpConnection}->SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,Open,in,out,-,-,177/30000,SslConnection}{io=0,kio=0,kro=1} 08:41:11.655 [CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0] DEBUG org.eclipse.jetty.io.AbstractConnection - FILL_INTERESTED-->FILLING HttpConnection@80ef4f3[FILLING,DecryptedEndPoint@4f49498{/127.0.0.1:37052<->9292,Open,in,out,-,-,178/30000,HttpConnection}->SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,Open,in,out,-,-,177/30000,SslConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=START,0 of 0},g=HttpGenerator{s=START},c=HttpChannelOverHttp@40d049f5{r=0,c=false,a=IDLE,uri=}] 08:41:11.655 [CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0] DEBUG org.eclipse.jetty.io.ssl.SslConnection - onFillable exit DecryptedEndPoint@4f49498{/127.0.0.1:37052<->9292,Open,in,out,-,-,178/30000,HttpConnection}->SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,Open,in,out,-,-,177/30000,SslConnection}{io=0,kio=0,kro=1} 08:41:11.656 [CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0] DEBUG org.eclipse.jetty.io.AbstractConnection - FILLING-->IDLE SslConnection@3c4546fe{NEED_UNWRAP,eio=-1/-1,di=-1} -> HttpConnection@80ef4f3[FILLING,DecryptedEndPoint@4f49498{/127.0.0.1:37052<->9292,Open,in,out,-,-,178/30000,HttpConnection}->SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,Open,in,out,-,-,177/30000,SslConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=START,0 of 0},g=HttpGenerator{s=START},c=HttpChannelOverHttp@40d049f5{r=0,c=false,a=IDLE,uri=}] 08:41:11.656 [CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0] DEBUG org.eclipse.jetty.io.SelectorManager - Running change org.eclipse.jetty.io.SelectChannelEndPoint$1@431394e9 08:41:11.656 [CamelJettyWebSocketServer-31-selector-ServerConnectorManager@3fcdcf/0] DEBUG org.eclipse.jetty.io.SelectorManager - Selector loop waiting on select 08:41:11.656 [CamelJettyWebSocketServer-40] DEBUG org.eclipse.jetty.server.HttpConnection - HttpConnection@80ef4f3[FILLING,DecryptedEndPoint@4f49498{/127.0.0.1:37052<->9292,Open,in,out,-,-,178/30000,HttpConnection}->SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,Open,in,out,-,-,177/30000,SslConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=START,0 of 0},g=HttpGenerator{s=START},c=HttpChannelOverHttp@40d049f5{r=0,c=false,a=IDLE,uri=}] onFillable HttpChannelState@772152e{s=IDLE i=true a=null} 08:41:11.656 [CamelJettyWebSocketServer-40] DEBUG org.eclipse.jetty.io.ssl.SslConnection - SslConnection@3c4546fe{NEED_UNWRAP,eio=-1/-1,di=-1} -> HttpConnection@80ef4f3[FILLING,DecryptedEndPoint@4f49498{/127.0.0.1:37052<->9292,Open,in,out,-,-,179/30000,HttpConnection}->SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,Open,in,out,-,-,178/30000,SslConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=START,0 of 0},g=HttpGenerator{s=START},c=HttpChannelOverHttp@40d049f5{r=0,c=false,a=IDLE,uri=}] fill enter 08:41:11.656 [CamelJettyWebSocketServer-40] DEBUG org.eclipse.jetty.io.ChannelEndPoint - filled 82 SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,Open,in,out,-,-,178/30000,SslConnection}{io=0,kio=0,kro=1} [Raw write]: length = 6 0000: 14 03 03 00 01 01
...... [Raw write]: length = 101 0000: ... 08:41:11.656 [CamelJettyWebSocketServer-40] DEBUG org.eclipse.jetty.io.ssl.SslConnection - SslConnection@3c4546fe{NEED_UNWRAP,eio=82/-1,di=-1} -> HttpConnection@80ef4f3[FILLING,DecryptedEndPoint@4f49498{/127.0.0.1:37052<->9292,Open,in,out,-,-,179/30000,HttpConnection}->SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,Open,in,out,-,-,0/30000,SslConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=START,0 of 0},g=HttpGenerator{s=START},c=HttpChannelOverHttp@40d049f5{r=0,c=false,a=IDLE,uri=}] filled 82 encrypted bytes E5 28 74 84 36 9F 56 D8 11 0C 38 .f..L.(t.6.V...8 0060: 38 2C AC 97 6C
[Raw read]: length = 5 8,..l 0000: ... CamelJettyWebSocketServer-40, READ: TLSv1.2 Handshake, length = 77 08:41:11.666 [CamelJettyWebSocketServer-40] DEBUG org.eclipse.jetty.io.ssl.SslConnection - SslConnection@3c4546fe{NEED_TASK,eio=0/-1,di=-1} -> HttpConnection@80ef4f3[FILLING,DecryptedEndPoint@4f49498{/127.0.0.1:37052<->9292,Open,in,out,-,-,189/30000,HttpConnection}->SelectChannelEndPoint@37823e21{/127.0.0.1:37052<->9292,Open,in,out,-,-,10/30000,SslConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=START,0 of 0},g=HttpGenerator{s=START},c=HttpChannelOverHttp@40d049f5{r=0,c=false,a=IDLE,uri=}] unwrap Status = OK HandshakeStatus = NEED_TASK bytesConsumed = 82 bytesProduced = 0 * Certificate chain *** CamelJettyWebSocketServer-40, fatal error: 42: null cert chain javax.net.ssl.SSLHandshakeException: null cert chain %% Invalidated: [Session-1, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384]

启用 SSL 调试的完整日志(包含 RAW 数据)可在此处找到:完整日志

The full log (containing RAW data) with enabled SSL debug can be found here: Full Log

我的测试在这里定义:

public void startTestServer() throws Exception {
    // start a simple websocket echo service
    server = new Server(PORT);
    Connector connector = new ServerConnector(server);
    server.addConnector(connector);

    ServletContextHandler ctx = new ServletContextHandler();
    ctx.setContextPath("/");
    ctx.addServlet(TestServletFactory.class.getName(), "/*");

    server.setHandler(ctx);

    server.start();
    assertTrue(server.isStarted());      
}

public void stopTestServer() throws Exception {
    server.stop();
    server.destroy();
}

@Override
public void setUp() throws Exception {

    ClassLoader classLoader = getClass().getClassLoader();
    URL trustStoreURL = classLoader.getResource("jsse/client-truststore.jks");
    System.setProperty("javax.net.ssl.trustStore", trustStoreURL.getFile());
    System.setProperty("javax.net.ssl.trustStorePassword", "password");
    startTestServer();
    super.setUp();
}

@Override
public void tearDown() throws Exception {
    super.tearDown();
    stopTestServer();
}

@Test
public void testTwoRoutes() throws Exception {
    MockEndpoint mock = getMockEndpoint("mock:result");
    mock.expectedBodiesReceived(TEST_MESSAGE);

    template.sendBody("direct:input", TEST_MESSAGE);

    mock.assertIsSatisfied();
}

private static SSLContextParameters defineClientSSLContextClientParameters() {

    KeyStoreParameters ksp = new KeyStoreParameters();
    ksp.setResource(Thread.currentThread().getContextClassLoader().getResource("jsse/client-keystore.jks").toString());
    ksp.setPassword(PWD);

    KeyManagersParameters kmp = new KeyManagersParameters();
    kmp.setKeyPassword(PWD);
    kmp.setKeyStore(ksp);

    KeyStoreParameters tsp = new KeyStoreParameters();
    tsp.setResource(Thread.currentThread().getContextClassLoader().getResource("jsse/client-truststore.jks").toString());

    tsp.setPassword(PWD);

    TrustManagersParameters tmp = new TrustManagersParameters();
    tmp.setKeyStore(tsp);

    SSLContextServerParameters scsp = new SSLContextServerParameters();
    scsp.setClientAuthentication(ClientAuthentication.REQUIRE.name());
    //scsp.setClientAuthentication(ClientAuthentication.NONE.name());

    SSLContextParameters sslContextParameters = new SSLContextParameters();
    sslContextParameters.setKeyManagers(kmp);
    sslContextParameters.setTrustManagers(tmp);
    sslContextParameters.setServerParameters(scsp);


    return sslContextParameters;
}

private static SSLContextParameters defineServerSSLContextParameters() {
    KeyStoreParameters ksp = new KeyStoreParameters();
    ksp.setResource(Thread.currentThread().getContextClassLoader().getResource("jsse/server-keystore.jks").toString());
    ksp.setPassword(PWD);

    KeyManagersParameters kmp = new KeyManagersParameters();
    kmp.setKeyPassword(PWD);
    kmp.setKeyStore(ksp);

    KeyStoreParameters tsp = new KeyStoreParameters();
    tsp.setResource(Thread.currentThread().getContextClassLoader().getResource("jsse/server-truststore.jks").toString());
    tsp.setPassword(PWD);

    TrustManagersParameters tmp = new TrustManagersParameters();
    tmp.setKeyStore(tsp);

    SSLContextServerParameters scsp = new SSLContextServerParameters();
    scsp.setClientAuthentication(ClientAuthentication.REQUIRE.name());
    //scsp.setClientAuthentication(ClientAuthentication.NONE.name());

    SSLContextParameters sslContextParameters = new SSLContextParameters();
    sslContextParameters.setKeyManagers(kmp);
    sslContextParameters.setTrustManagers(tmp);
    sslContextParameters.setServerParameters(scsp);


   return sslContextParameters;
}

@Override
protected RouteBuilder[] createRouteBuilders() throws Exception {
    RouteBuilder[] rbs = new RouteBuilder[2];

    // A consumer
    rbs[0] = new RouteBuilder() {
        public void configure() {

            // Needed to configure TLS on the client side
            WsComponent wsComponent = (WsComponent) context.getComponent("someclient");
            wsComponent.setSslContextParameters(defineClientSSLContextClientParameters());

            from("direct:input").routeId("foo")
                .log(">>> Message from direct to WebSocket Client : ${body}")
                .to("someclient://localhost:9292/echo")
                .log(">>> Message from WebSocket Client to server: ${body}");
            }
    };

    // A provider
    rbs[1] = new RouteBuilder() {
        public void configure() {

                // Needed to configure TLS on the server side
                WebsocketComponent websocketComponent = (WebsocketComponent) context.getComponent("someserver");
                websocketComponent.setSslContextParameters(defineServerSSLContextParameters());

                // This route is set to use TLS, referring to the parameters set above
                from("someserver:localhost:9292/echo")
                .log(">>> Message from WebSocket Server to mock: ${body}")
                .to("mock:result");
        }
    };
    return rbs;
}

你能帮我弄清楚发生了什么吗?

Can you help me get an idea of what is going on?

推荐答案

答案迟了,还是让我试试吧:

Late answer but still, let me try:

你写道:

当我将 ClientAuthentication.REQUIRE 设置为 NONE 时,会建立 TLS 连接,一切正常"

和:

令我困惑的是:当我没有激活客户端身份验证时,客户端和服务器端都建立了 Web 套接字连接"

在我看来这里没有问题,这是预期的行为,不是吗?如果您不要求客户端进行身份验证,那么您就有了连接.

In my opinion there's no problem here, it's expected behaviour isn't it? If you don't require the client to authenticate, then you have a connection.

如果您确实要求客户端进行身份验证并且客户端没有发送正确的证书链,那么您会收到 fatal error: 42: null cert链在服务器端.

If you do require the client to authenticate and the client doesn't send the correct certificate chain then you get a fatal error: 42: null cert chain on the server side.

您可以使用 openssl 进行测试,但首先在服务器端使用 -Djavax.net.debug=all 启用 SSL 调试,然后执行:

You can test this with openssl, but enable SSL debuging first on the server side with -Djavax.net.debug=all, then do:

openssl s_client -connect localhost:443 -CAfile cacert.pem -cert clientcert.pem -key clientkey.pem -state -tls1_2

您应该在 openssl 输出的末尾看到 Verify return code: 0 (ok).

You should see Verify return code: 0 (ok) at the end of the openssl output.

在服务器端,将该部分服务器日志复制到 srv-side-openssl-client-log.txt(例如).

On the server side, copy that part of the server log into srv-side-openssl-client-log.txt (for example).

现在测试与您的 Java 客户端的连接并将该服务器日志复制到 srv-side-java-client-log.txt.

Now test the connection with your Java client and copy that server log into srv-side-java-client-log.txt.

比较两者,看看有什么不同.您的 srv-side-java-client-log.txt 可能缺少一大块十六进制代码,因为它不发送证书链.

Compare the two and see what is different. Your srv-side-java-client-log.txt probably is missing a huge block of hex codes because it doesn't send the certificate chain.

相关文章