java - (Java) 在 Mac OS X 上以编程方式访问 "System Roots"下的 SSL 证书

标签 java macos security x509certificate digital-certificate

我正在编写一个 Java 应用程序,它通过远程 Https 站点进行休息 Api 调用。远程站点由受信任的证书签名。它在 Windows 上运行良好,但是由于 SSL 证书问题,它在 OS X 上运行有问题。

我做了一些挖掘,发现原因与我如何在代码中使用 getInstance 调用初始化 KeyStore 对象有关。它只从“系统”钥匙串(keychain)中读取证书,而不是从“系统根”钥匙串(keychain)中读取证书。下面是从 keystore 中打印出所有证书的代码片段。

// In windows use "WINDOWS-ROOT"
KeyStore osTrustManager = KeyStore.getInstance("KeychainStore");
osTrustManager.load(null, null);

Enumeration<String> enumerator = osTrustManager.aliases();
while (enumerator.hasMoreElements()) {
    String alias = enumerator.nextElement();
    if (osTrustManager.isCertificateEntry(alias)) {
        m_logger.info(String.format("%s (certificate)\n", alias));
    }
}

如何更改代码以实现这一目标?感谢是否有人可以插话。

这是“系统根”下的证书样本
Screenshot from OS X

最佳答案

不知道有没有KeyStore这允许您访问 Mac OS X 系统根证书,但您可以尝试另一种方式。
在 Mac OS X 中,您可以使用 security 从任何钥匙串(keychain)获取证书列表。命令。
例如,此命令将为您提供有关安装在系统根钥匙串(keychain)中的不同证书的信息:

security find-certificate -a "/System/Library/Keychains/SystemRootCertificates.keychain"
此实用程序有两个标志,-p ,它将以 PEM 编码输出每个证书,以及 -a ,这允许我们按名称过滤结果 - 由于系统中安装了大量 CA,这很方便。
这个想法是使用 Java 中的这个实用程序。
不久前,我偶然发现了一个名为 clienteafirma 的库。设计用于处理数字签名。
这个库有一个名为 AppleScript 的类。 .这个类基本上是 Process 的包装。这允许我们运行任意命令。
以下代码使用该类和 security命令来获取所有颁发的证书,例如 VeriSign :
public static void main(String... args) {
  // Keychains that we can use
  final String KEYCHAIN_PATH = "/Library/Keychains/System.keychain";
  final String SYSTEM_KEYCHAIN_PATH = "/System/Library/Keychains/SystemRootCertificates.keychain";
  // Show me only certificates from VeriSign
  final String AUTHORITY = "VeriSign";
  final String OSX_SEC_COMMAND = "security find-certificate -a -p -c %AUTHORITY% %KEYCHAIN%";
  final String cmd = OSX_SEC_COMMAND.replace("%AUTHORITY%", AUTHORITY).replace("%KEYCHAIN%", SYSTEM_KEYCHAIN_PATH);
  System.out.println(cmd);
  System.out.println();

  final AppleScript script = new AppleScript(cmd);
  InputStream certificateStream = null;
  try {
    // Run script
    final String result = script.run();
    certificateStream = new ByteArrayInputStream(result.getBytes());
    // Process the output of the command
    final CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
    final Collection<X509Certificate> certificates = (Collection<X509Certificate>) certificateFactory.generateCertificates(certificateStream);
    // Use the certificates as you need
    for (X509Certificate certificate : certificates) {
      String alias = certificate.getSubjectX500Principal().getName();
      System.out.println("Certificate: " + alias);
    }
  } catch (Throwable t) {
    t.printStackTrace();
  } finally {
    if (certificateStream != null) {
      try {
        certificateStream.close();
      } catch (IOException io) {
        io.printStackTrace();
      }
    }
  }
}

关于java - (Java) 在 Mac OS X 上以编程方式访问 "System Roots"下的 SSL 证书,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46986355/

相关文章:

java - 为什么 new java.text.SimpleDateFormat ("EEEE").format(new java.util.Date(2015, 6, 9)) 返回错误的星期几?

java - int[] 数组的outputStream.write()

Java-TestNG : Why does my Assertion always passes when written within try-catch block

macos - NSSetUncaughtExceptionHandler 在 Mac 上不起作用

C 程序(在 OS X 中)- 文件是为存档构建的,不是被链接的体系结构 (x86_64)

macos - 如何增加 docker-machine 内存 Mac

javascript - 自动检测服务器端黑客攻击

java - 管理使用不同类创建的 Java CardLayout JPanel

c# - 阻止第三方程序集访问资源

sql-server - 如何保护 SQL Server 2005 数据库的安全?