【问题标题】:Extract Server Certificates提取服务器证书
【发布时间】:2013-10-18 07:29:42
【问题描述】:

我需要帮助以获取适当的代码以获取服务器证书 - 有效和无效,由 CA 签名和自签名。任何链接和参考将不胜感激。

我有一个 UNIX 命令,它给了我想要的东西,但我想要使用 Java 的相同输出。 UNIX中的命令是这样的-

echo -n | openssl s_client -connect www.gmail.com:443 -showcerts | \
  sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /tmp/$SERVERNAME.cert

这会返回 gmail 上的(不知道加密的)证书链。我希望我的程序提供完全相同的信息。打印整个证书链。

【问题讨论】:

  • 通过“完全相同的信息”,您的意思是Java应用程序实际上应该在shell中执行相同的命令并显示输出?
  • 没有。不要从 java 运行 Unix 命令。但是,要获得与 Unix 命令相同编码的证书。

标签: java ssl openssl certificate


【解决方案1】:

这可以通过以下步骤完成:

  • 使用信任任何东西的TrustManager 初始化SSLContext(这个用例是使用这种信任管理器的极少数原因之一)。仅当您怀疑远程证书不受信任时才这样做。
  • 从中获取SSLSocketFactory
  • 从此工厂创建一个SSLSocket,使用您要连接的主机名。如果您使用主机名(而不是 InetAddress),这将在 Java 7 上启用 SNI,因此这相当于使用 -servername 作为 openssl 命令的附加选项。
  • 开始握手(例如使用startHandhsake()
  • 从此SSLSocket 获取SSLSession
  • 对于getPeerCertificates() 中的每个Certificate
    • 使用getEncoded() 获取其编码值(如byte[]
    • 将其转换为 PEM,或者:
      • 使用 BouncyCastle 的 PEMWriter
      • 使用 Base 64 编码器(例如 Apache Commons),添加 BEGIN/END 分隔符并每隔 64 个字符用新行分割字符串。

【讨论】:

  • 使用下面的代码。 Base64 字符串与我使用 Unix 命令收到的输出几乎相同。当我在两者之间进行比较时,我注意到只有两个字符不匹配。原始字符串 '+' 中的字符在我的 java 输出中以 '-' 的形式出现。 '/' 以 '_' 的形式出现。除了这两个,其他都完美。在此处粘贴代码: for(int i=0; i
  • 不要使用...URLSafeString,使用普通的base 64编码器即可。
  • 错误的 Base64 函数。 Base64.encodeBase64String(certBytes) 返回正确的证书。现在可以了。非常感谢布鲁诺。
  • 现在,我在浏览器中打开了 gmail.com。去'查看证书'。每个级别的导出证书(根、中级和 *.com)。它们被保存为 .crt 文件(根和中间)。单击打开根 .crt 文件并转到详细信息选项卡 - 复制到文件。下一步。选择“Base-64 编码的 X.509 (.CER)”。该文件的内容和我的 java 文件打印的字符串对于根证书是不同的。它们对于中间证书是相同的。从java中获取的根证书,保存到.cer文件中,打开后与浏览器中提取的证书相比有差异。
  • 据我了解,它只是重要的中间证书。根证书可能因信任源而异,即,对于浏览器,它是 firefox cert bundle,而对于我的代码,它是 java cert bundle。这似乎是差异根证书背后的原因。
【解决方案2】:

我过去遇到过同样的挑战,并在我的库中提供了此选项,您可以在此处查看:GitHub - SSLKickstart - Kickstart 我认为在此处分享它可能会对其他开发人员有所帮助。

用法

Map<String, List<Certificate>> certificates = CertificateUtils.getCertificate(
            "https://github.com/", 
            "https://stackoverflow.com/", 
            "https://reddit.com/",
            "https://youtube.com/");
            
// or get the server certificates as pem format
Map<String, List<String>> certificatesAsPem = CertificateUtils.getCertificateAsPem(
            "https://github.com/", 
            "https://stackoverflow.com/", 
            "https://reddit.com/",
            "https://youtube.com/");

使用 maven 安装库

<dependency>
    <groupId>io.github.hakky54</groupId>
    <artifactId>sslcontext-kickstart</artifactId>
    <version>6.7.0</version>
</dependency>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-04
    • 1970-01-01
    • 2012-03-24
    • 2020-08-22
    • 2020-12-03
    • 1970-01-01
    • 2014-05-01
    相关资源
    最近更新 更多