3

我需要一些帮助来确保我们的 PKI 基础设施是安全的。这是它的工作原理:

  • 我们有一个(自签名)CA 证书,我们的服务器可以完全控制它。
  • 所有客户端(用 Java 编写)都配置了一个仅包含此 CA 证书的信任库。
  • 在安装客户端期间,服务器会颁发一个由我们的 CA 证书签名的客户端证书(其客户端 ID 为 CN)。
  • 然后客户端能够相互连接,并且当建立连接时,通过验证客户端各自的证书来执行相互客户端身份验证。我们初始化处理客户端身份验证的 TrustManager,如下所示:

.

private TrustManager[] getClientCATrustManagers() throws NoSuchAlgorithmException, IOException, KeyStoreException, CertificateException {       
    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX");
    KeyStore trustStore = getClientCATrustStore();
    trustManagerFactory.init(trustStore);

    return trustManagerFactory.getTrustManagers();
}

getClientCATrustStore()返回仅包含我们的 CA 的信任库。

这引出了我的问题。我对链验证的理解是,只要链的根是可信的,并且链上的证书都没有过期,那么这个链就被认为是有效的。对此我担心的是,我看到了客户将能够使用自己的证书来颁发新证书的风险。这是一个潜在的风险,如果是,我该如何预防?我看到了两个潜在的解决方案:

  1. 我创建了自己的 TrustManager 来防止这种情况。是否有任何实现已经这样做了?
  2. 当客户端证书由服务器颁发时,我以某种方式指定不允许客户端证书颁发它自己的证书。这可能吗?如果可以,怎么做?
4

1 回答 1

4

如果根是受信任的,并且所有中间证书都存在且有效,那么您认为证书链是有效且受信任的是正确的。

而且您对客户自己签发另一个证书的潜在风险也是正确的。但是有一些方法可以减轻这种风险。

X509 证书(第 3 版)包含指示它们被允许做什么或不做什么的扩展。

例如,您可能会对 2 个特定部分感兴趣:

  • 基本约束

  • 密钥用法

基本约束标识证书是否为 CA,这意味着它只能用于验证证书签名,如果它被指定为 CA 本身。它还指定路径长度。这限制了该 CA 可以签署/颁发的 CA 中间证书的数量。这个路径长度的一个很好的解释是在这个 SO question中。听起来您希望 CA 证书上的路径长度为 0。

密钥用法指示允许此实体执行的操作。通常,CA 证书具有以下关键使用属性:证书签名、CRL 签名。而非 CA 或“最终实体”证书可以具有:数字签名、不可否认性、密钥加密、数据加密。

这些扩展都受RFC5280管辖。

这是重要的部分。为了使这些证书扩展具有任何意义,它们必须由使用它们的应用程序检查和强制执行。

您的客户端应用程序可以查看扩展并验证其他客户端证书的路径长度是否为 0(这意味着 CA 和客户端证书之间没有中间证书)。

于 2013-08-22T22:23:44.173 回答