我有一个自定义的CAroot.crt(由我生成),并且我所有的客户证书都与此CAroot.crt签名。我有一个TrustStore.jks,其中仅放置了客户端证书,而不放置CAroot.crt,因为我希望可以随时从我的信任库中删除客户端。
当我尝试启动我的应用程序时,我得到了以下信息:
*** Certificate chain
<Empty>
***
main, fatal error: 42: null cert chain
这是我的trustStore.jks:
Keystore type: jks
Keystore provider: SUN
Your keystore contains 1 entry
Alias name: localhost
Creation date: Nov 23, 2019
Entry type: trustedCertEntry
Owner: CN=localhost, OU=IT, O=QUEROBUY, L=SAO CAETANO DO SUL, ST=SAO PAULO, C=BR
Issuer: CN=localhost, OU=IT, O=LANHELLAS XYZ, L=SAO CAETANO DO SUL, ST=SAO PAULO, C=BR
Serial number: 5416c04e360f9d50323c52d8a5b04be2969c9b86
Valid from: Sat Nov 23 16:39:54 BRT 2019 until: Tue Apr 06 16:39:54 BRT 2021
Certificate fingerprints:
MD5: 8F:29:1C:1F:05:89:0B:E6:A0:57:84:FE:B0:78:68:2D
SHA1: 95:C8:EA:0E:C8:7C:4E:99:E4:73:85:49:57:D6:BB:88:AF:52:52:12
SHA256: 7E:ED:19:AF:02:DB:CC:88:98:D0:10:4E:39:67:AA:4D:3F:70:DA:76:03:1B:CB:41:06:DC:3B:51:38:16:78:5F
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 1
*******************************************
*******************************************
如果我在我的trustStore.jks中添加“ CARoot.crt”,则一切正常,但是我失去了使某些特定客户端证书无效的机会。想象一下,我有10个客户端,每个客户端都有由“ CARoot.crt”分配的您自己的证书(.crt),但是由于某种原因,客户端001应该立即失效,我只是从服务器中的trustStore.jks中删除您的公钥,而无需我应该等待证书的到期日期。
答案 0 :(得分:1)
TrustStore.jks是java如何确定它是否信任证书的方式。它本质上是根证书的密钥库文件。如果要避免“不信任邮件”,则必须将根证书添加到此存储中。
在您的方案中,由于您使用该根颁发了10个客户端证书,因此从您的信任或密钥库中删除client_certificate.crt不会对它不信任。因为根据设计,java正在查看TrustStore并查找根证书,因此仍然信任client_certificate.crt。您将需要重新设计CA。
在部署任何类型的PKI基础结构时,您还需要设置CRL和/或OCSP服务器。这是用于吊销证书的两种协议。
我还建议您不要直接从根目录颁发“最终用户证书”。最好从根目录颁发中间证书,然后使用middle_certificate.crt颁发实际的服务器或客户端证书。 由于某种原因,请参见此处:https://security.stackexchange.com/questions/128779/why-is-it-more-secure-to-use-intermediate-ca-certificates#128800
这是使用OpenSSL部署您自己的CA的简便方法。它将向您展示如何设置根服务器,中间服务器和吊销服务器。 https://jamielinux.com/docs/openssl-certificate-authority/
答案 1 :(得分:1)
为什么::如果您稍稍看一下调试日志,则会看到CertificateRequest
消息,该消息(除其他事项外)指定了服务器要求的Cert [ificate]授权;参见rfc5246。 Java将其定义为信任库中证书的主题名称,因为通常希望信任库中的证书是CA证书(通常是CA root 证书,因为预定义证书是这样)。尽管有例外,但大多数客户端软件都遵循此说明。因此,如果您的信任库包含类似
Subject=Client1 Issuer=MyCA
Subject=Client2 Issuer=MyCA
Subject=Client3 Issuer=MyCA
然后您的服务器将请求Client1 Client2 Client3
中的任何一个颁发的证书,但不是 MyCA
中的一个。如果客户实际上只有一个证书,并且是 for ,例如Client2
是由 MyCA
发行的-并非由任何Clientn
发行的-大多数客户端软件都认为该证书无法用于该服务器/握手。
PKI方式。不能在证书到期之前使证书无效。通常,PKI专门设计用于处理此类情况,通常称为撤销。证书可以在到期之前被吊销的原因有很多,其中包括:有关用于SSL / TLS的特定PKI方案(以及Java的其他用途,例如代码签名),即PKIX(或有效等效的X.509),请参见rfc5280 5.3.1以及第5节的其余部分对于证书吊销列表(CRL),是较旧的传统吊销方式;对于在线证书状态协议(OCSP),是rfc6960,是较新的方式。
对于“真实”(公共)PKI,这通常是可行的。 Java实现了PKIX吊销检查,但是对于SSL / TLS(JSSE),它默认禁用;您必须设置sysprop com.sun.net.ssl.checkRevocation
才能使用它。您可能还需要为CRL设置com.sun.security.enableCRLDP
,而AFAICT始终需要为OCSP设置 security 属性(不是sysprop)ocsp.enable
。参见例如:
Check X509 certificate revocation status in Spring-Security before authenticating
Checking a X509 Certificate Revocation
Java SSL Certificate Revocation Checking
但是运行CRL分发点和/或OCSP响应程序,以使它们在需要时是正确的和-这可以是随时的-并非易事;这是真正的CA收取费用(或获得补贴)的事情之一。为您自己的个人CA进行此操作可能会从痛苦到实际上不可能实现,但是如果您愿意,请对CA更加具体。
您的情况在原则上更简单;您只有一个CA并进行操作,因此您知道何时发生撤销。您可以在服务器发生更改时向服务器轻松提供CRL。但是AFAICS内置代码无法使用该信息,因此您必须使用允许编写自己的TrustManager的钩子来代替内置代码,并对其进行修改以使用带有以下内容的验证器:使用CRL的CertStore。这可能也是相当多的工作,但是只有一次。
解决方法。您可以通过修改服务器或客户端来继续使用单独信任叶证书的方法,而不用PKI术语“正确”地进行操作。
您可以更改服务器中的(X509)TrustManager钩子以照常验证证书,但是可以覆盖getAcceptedIssuers
以返回不同的(并针对您的情况而定)“请求的” CA列表,从而导致JSSE发送一个使客户端使用其正确证书的CertificateRequest。
根据客户端的不同,您可能可以更改它们以忽略“请求的” CA,并始终发送其证书-服务器的默认TrustManager会验证它们是否在信任库中(或 CA是)。对于OpenSSL,这很容易。 OpenSSL已经忽略了请求的CA列表,仅发送配置的内容。对于Java,您可以钩住客户端KeyManager并覆盖chooseClientAliases
方法,以不像通常那样检查所需的颁发者列表。对于其他客户,请添加到您的Q或询问新客户。