我所在的团队正在尝试使用证书将Java J2SE应用程序连接到安全的企业Web服务站点。没有任何团队成员具有为此类连接创建证书和编码的经验。
我们准备并提交了CSR,并从Web服务站点获得了.p7b证书。 .p7b包含两个证书:一个是由Web服务站点发布的,另一个是由公司所有者自己的CA颁发的Web服务站点。两者都出现在下面的密钥库列表中。密钥库在自定义SSLContext中引用,Java代码使用该SSLContext创建Apache HttpClient而没有错误。
当Java代码尝试执行HttpGet时,Web服务站点拒绝SSLHandshake并终止与错误的连接:
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
在握手调试跟踪中,在握手的步骤13中,是消息:
ServerHelloDone
Warning: no suitable certificate found - continuing without client authentication
Certificate chain
Empty
Keytool将密钥库的内容列为:(公司身份编辑)
Keystore type: PKCS12
Keystore provider: SUN
Your keystore contains 1 entry
Alias name: server
Creation date: Mar 28, 2019
Entry type: PrivateKeyEntry
Certificate chain length: 2
Certificate[1]:
Owner: ...
Issuer: ...
Serial number: ...
Valid from: Mon Mar 11 19:00:00 CDT 2019 until: Wed Mar 11 18:59:59 CDT 2020
Certificate fingerprints:
SHA1: ...
SHA256: ...
Signature algorithm name: SHA1withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3
Extensions:
#1: ObjectId: 2.16.840.1.113733.1.6.9 Criticality=false
0000: 01 01 FF ...
#2: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
CA:false
PathLen: undefined
]
#3: ObjectId: 2.5.29.31 Criticality=false
CRLDistributionPoints [
[DistributionPoint:
[URIName: http://onsite-crl.pki.digicert.com/ATTServicesIncApplicationCertificates/LatestCRL.crl]
]]
#4: ObjectId: 2.5.29.15 Criticality=false
KeyUsage [
DigitalSignature
Key_Encipherment
]
#5: ObjectId: 2.16.840.1.113730.1.1 Criticality=false
NetscapeCertType [
SSL client
]
Certificate[2]:
Owner: ...
Issuer: ...
Serial number: ...
Valid from: Wed Feb 23 18:00:00 CST 2011 until: Tue Feb 23 17:59:59 CST 2021
Certificate fingerprints:
SHA1: ...
SHA256: ...
Signature algorithm name: SHA1withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3
Extensions:
#1: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: 97 20 99 C2 73 2A 45 EB E0 02 7F 47 DA 7B AB 7C . ..s*E....G....
0010: EB 1F AF 6E ...n
]
]
#2: ObjectId: 2.5.29.19 Criticality=true
BasicConstraints:[
CA:true
PathLen:0
]
#3: ObjectId: 2.5.29.31 Criticality=false
CRLDistributionPoints [
[DistributionPoint:
[URIName: http://onsitecrl.verisign.com/offlineca/ATTServicesIncATTServicesIncRootCA.crl]
]]
#4: ObjectId: 2.5.29.15 Criticality=true
KeyUsage [
Key_CertSign
Crl_Sign
]
#5: ObjectId: 2.5.29.17 Criticality=false
SubjectAlternativeName [
CN=VeriSignMPKI-2-51
]
#6: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 25 64 37 69 DB DC 57 99 43 80 79 29 90 6C B8 13 %d7i..W.C.y).l..
0010: 58 EE B6 D0 X...
]
]
*******************************************
*******************************************
]
}
看来密钥库包含我们私钥的条目,但不包括客户端证书;仅列出来自Web服务站点的.p7b中的两个证书。
StackOverflow帖子位于:
why doesn't java send the client certificate during SSL handshake?
建议从密钥库导出客户端证书并编辑证书链。这并不能解决问题,显然是因为密钥库包含我们的私钥而不是我们签名的证书。
我没有标识为客户端证书的工件。 Oracle程序给出:
https://docs.oracle.com/cd/E19509-01/820-3503/ggezu/index.html
建议应该在准备原始CSR的过程中创建已签名的客户端证书(过程的第3步),但是我们似乎没有将该证书文件作为单独的工件。
我认为我们需要重新构建客户端证书并将其导入密钥库中证书链的适当位置。由于我们似乎没有在创建CSR时创建原始文件,是否可以从头开始重新创建客户端证书(Oracle过程的步骤3 - 5)并将其编辑回链中?有没有办法从原始CSR中提取或重新构建客户端证书?
任何问题,见解或建议非常感谢。谢谢。
看来密钥库包含我们私钥的条目,但不包括客户端证书;仅列出来自Web服务站点的.p7b中的两个证书。
您按keytool列出的PrivateKeyEntry确实包含客户端证书(BC,KU和NCT),以及可能是该客户端证书的颁发(父)证书的CA证书。 (如果您使用keytool将这些证书导入此密钥库,则CA证书肯定是颁发者,因为keytool会验证;如果您使用其他工具,则应强制执行相同的要求,但可能不会。)您将p7b描述为包含“second for由公司所有者自己的CA发布的Web服务站点“但是(1)如果是这种情况,keytool将不会将其作为同一链的一部分导入,并且(2)它没有意义,因为客户端不需要CA发布(即非自签名)服务器证书在其密钥库或信任库中,只有服务器CA在其信任库中的证书,并且作为单独的条目,不在客户端的PrivateKeyEntry中,即使它是共享文件。
根据您的描述,您将获得javax.net.debug=ssl
跟踪,因此请查看该跟踪中加载密钥库的部分并确保此条目已加载,并查看*** CertificateRequest
下的服务器Cert Authorities
以查看它所询问的CA for(紧接在*** ServerHelloDone
之前)并将(那些)与密钥库中链的实际CA(未编译)进行比较。由于您使用的是Apache HttpClient,如果您正在使用指定PrivateKeyStrategy的重载之一,请确保它正确选择别名。