Get a List of Trusted Certificates in Java – 在Java中获取受信任的证书列表

最后修改: 2020年 9月 29日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this quick tutorial, we’ll learn how to read a list of trusted certificates in Java through quick and practical examples.

在这个快速教程中,我们将通过快速实用的例子来学习如何在Java中读取可信证书的列表。

2. Loading the KeyStore

2.加载KeyStore

Java stores the trusted certificates in a special file named cacerts that lives inside our Java installation folder.

Java将受信任的证书存储在一个名为cacerts的特殊文件中,该文件位于我们的Java安装文件夹中。

Let’s start by reading this file and loading it into the KeyStore:

让我们从读取这个文件开始,把它加载到KeyStore

private KeyStore loadKeyStore() {
    String relativeCacertsPath = "/lib/security/cacerts".replace("/", File.separator);
    String filename = System.getProperty("java.home") + relativeCacertsPath;
    FileInputStream is = new FileInputStream(filename);

    KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
    String password = "changeit";
    keystore.load(is, password.toCharArray());

    return keystore;
}

The default password for this KeyStore is “changeit”, but it could be different if it was previously changed in our system.

这个KeyStore的默认密码是“changeit”,但如果它以前在我们的系统中被改变过,它可能是不同的。

Once loaded, the KeyStore will hold our trusted certificates, and next, we’ll see how to read them.

一旦加载,KeyStore将保存我们的可信证书,接下来,我们将看到如何读取它们。

3. Reading Certificates From a Specified KeyStore

3.从指定的KeyStore读取证书

We’re going to use the PKIXParameters class, which takes a KeyStore as a constructor parameter:

我们将使用PKIXParameters类,它需要一个KeyStore作为构造函数参数。

@Test
public void whenLoadingCacertsKeyStore_thenCertificatesArePresent() {
    KeyStore keyStore = loadKeyStore();
    PKIXParameters params = new PKIXParameters(keyStore);

    Set<TrustAnchor> trustAnchors = params.getTrustAnchors();
    List<Certificate> certificates = trustAnchors.stream()
      .map(TrustAnchor::getTrustedCert)
      .collect(Collectors.toList());

    assertFalse(certificates.isEmpty());
}

The PKIXParameters class is usually used for validating a certificate, but in our example, we simply used it to exact the certificates from our KeyStore.

PKIXParameters类通常用于验证证书,但在我们的例子中,我们只是用它来精确我们的KeyStore中的证书。

When creating an instance of PKIXParametrs, it builds a list of TrustAnchor that will contain the trusted certificates present in our KeyStore.

在创建PKIXParametrs的实例时,它建立了一个TrustAnchor的列表,其中将包含我们KeyStore中存在的受信任的证书。

A TrustAnchor instance simply represents a trusted certificate.

一个TrustAnchor实例只是代表一个受信任的证书。

4. Reading Certificates From Default KeyStore

4.从默认的KeyStore读取证书

We can also get a list of the trusted certificates present in our system by using the TrustManagerFactory class and initializing it without a KeyStore, which will use the default KeyStore.

我们也可以通过使用TrustManagerFactory类并在没有KeyStore的情况下对其进行初始化来获得我们系统中存在的受信任证书的列表,这将使用默认的KeyStore

If we don’t provide a KeyStore explicitly, the same one from the previous chapter will be used by default:

如果我们没有明确地提供一个KeyStore,默认情况下将使用前一章中的那个。

@Test
public void whenLoadingDefaultKeyStore_thenCertificatesArePresent() {
    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    trustManagerFactory.init((KeyStore) null);

    List<TrustManager> trustManagers = Arrays.asList(trustManagerFactory.getTrustManagers());
    List<X509Certificate> certificates = trustManagers.stream()
      .filter(X509TrustManager.class::isInstance)
      .map(X509TrustManager.class::cast)
      .map(trustManager -> Arrays.asList(trustManager.getAcceptedIssuers()))
      .flatMap(Collection::stream)
      .collect(Collectors.toList());

    assertFalse(certificates.isEmpty());
}

In the above example, we’ve used X509TrustManager, which is a specialized TrustManager used to authenticate the remote part of an SSL connection.

在上面的例子中,我们使用了X509TrustManager,它是一个专门的TrustManager,用于认证SSL连接的远程部分

Note that this behavior may depend on the specific JDK implementation, as the specification doesn’t define what should happen in case the init() KeyStore parameter is null.

请注意,这种行为可能取决于具体的 JDK 实现,因为规范没有定义在init()KeyStore参数为null时应该如何处理。

5. Certificate Aliases

5.证书别名

A certificate alias is simply a String that uniquely identifies a certificate.

证书别名是一个简单的字符串,可以唯一地识别一个证书。

Among the default certificates imported by Java, there’s also a well-known certificate issued by GoDaddy, a public Internet domain registrar, which we’ll use in our tests:

在Java导入的默认证书中,还有一个由公共互联网域名注册商GoDaddy颁发的知名证书,我们将在测试中使用它:

String GODADDY_CA_ALIAS = "godaddyrootg2ca [jdk]";

Let’s see how we can read all certificate aliases present in our KeyStore:

让我们看看如何读取存在于我们KeyStore中的所有证书别名。

@Test
public void whenLoadingKeyStore_thenGoDaddyCALabelIsPresent() {
    KeyStore keyStore = loadKeyStore();

    Enumeration<String> aliasEnumeration = keyStore.aliases();
    List<String> aliases = Collections.list(aliasEnumeration);
    assertTrue(aliases.contains(GODADDY_CA_ALIAS));
}

In the next example, we’ll see how we can retrieve a certificate by its alias:

在下一个例子中,我们将看到如何通过别名检索一个证书。

@Test
public void whenLoadingKeyStore_thenGoDaddyCertificateIsPresent() {
    KeyStore keyStore = loadKeyStore();

    Certificate goDaddyCertificate = keyStore.getCertificate(GODADDY_CA_ALIAS);
    assertNotNull(goDaddyCertificate);
}

6. Conclusion

6.结语

In this quick article, we’ve looked at different ways of listing trusted certificates in Java through quick and practical examples.

在这篇快速文章中,我们通过快速而实用的例子,了解了在Java中列出可信证书的不同方法。

As always, code snippets can be found over on GitHub.

像往常一样,代码片段可以在GitHub上找到over