从这道题的问号数量我们可以看出,这是一种需要将几条知识连接在一起才能形成答案的情况。没有一个单独的部分是困难的,尽管有些(LiClipse)是晦涩的,有些(Java 的 keytool)在不容易找到的文档中得到了回答。
诊断
先解释一下。Eclipse 主要是 Java 语言代码,它运行在JRE(Java 运行时环境)上。“SSL”是指一种通信协议。后来它被重命名为“TLS”,但我将在这里使用“SSL”。事实证明,SSL 通信是由 JRE 处理的:“PKIX”是指一个工作组提出了 SSL 使用的证书系统,“ sun.security.provider
”表示Java SE 安全架构正在处理通信。
SSL 安全性的一部分是验证,当您要求连接到某个互联网站点(如“git.ffmpeg.org”)时,您确实到达了该站点,而不是冒名顶替者。“证书”是标识目的地名称的一小块数据,并通过颁发该证书的服务的数字签名证明该数据的正确性。如果您信任颁发者,并且证书上的签名有效,则您可以信任生成的证书所说的内容。发行服务本身有一个证书,由它自己的发行服务依次签名。证书以“信任链”链接到它们的发行者。一些证书和一些发行者锚定了链。这被称为“根证书”。
JRE 在 JRE 信任库中包含多个根证书的副本。它存储在 JRE 的 Java 主目录中的一个文件中,位于./lib/security/cacerts
)。JRE 还包括一个工具./bin/keytool
,用于在信任库中添加和删除证书。但是 JRE 并不包含所有重要的根证书。
该错误对话告诉我们的是,LiClipse 和 EGit 要求 JRE 的安全代码将证书连接到信任链中,从 git.ffmpeg.org 服务器的证书到 JRE 信任库中的某个证书。这失败了,因为信任库缺少必要的证书。解决方案是将 git.ffmpeg.org 的证书添加到本地 JRE Trust Store。JREkeytool
会让我们添加它。(如果您相信服务器根证书背后的人只有经过身份验证的好演员的证书,您可以添加来自以服务器证书结尾的信任链中的根证书。如果您的赌注很高,您可能应该获得一个比这篇博客文章更好的安全简报,在信任之前。)
所以,我们需要做的是:
- 获取目标服务器 git.ffmpeg.org 或该链的根证书的 SSL 证书
- 识别 LiClipse 使用的 JRE,以及其 Java 主目录的位置
- 了解如何在该 JRE 中使用 keytool
- 在该 JRE 中找到信任库
- 使用 keytool 将新的 SSL 证书添加到 LiClipse JRE 的信任库
- 测试更改是否有效
获取 SSL 证书
首先,我们获得目标服务器 git.ffmpeg.org 的 SSL 证书。或者,我们可以从服务器证书的信任链中获取根“证书颁发机构”(CA)证书。如果您获得了服务器的证书,您只需将该服务器标记为受信任的。如果您获得 CA 根证书,那么您可以使用任何具有该 CA 直接或间接颁发的证书的服务器,这可能是更多的服务器。但是,也许您并不信任每个 CA 所做的一切。做出这种权衡超出了这些说明的范围。
获取目标服务器的 SSL 证书的一种直接方法是通过OpenSSL命令行工具。
% openssl s_client -connect git.ffmpeg.org:443 </dev/null 2>/dev/null >cert.crt
(详情:openssl s_client
是一个 SSL/TLS 协议客户端的参考实现,它与服务器正确通信,有助于诊断。s_client 从标准输入读取 HTTP 命令,因此“ </dev/null
”符号使标准输入为空文件。“ 2>/dev/null
”符号丢弃任何输出到stderr,这样它就不会在常规输出中混淆。-connect选项的参数是主机名,':',端口名。端口443是https协议的标准端口。来源:超级用户回答。)
这会将目标服务器的证书存储在文件中cert.crt
。它的大小约为 2182 字节左右。它看起来像这样:
-----BEGIN CERTIFICATE-----
MIIGBDCCBOygAwIBAgISA/dw6A9zk496P+FouEc0W3OyMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
... [ 29 lines omitted ] ...
7U4xF6Csg3X76Xx35kIVO/JJOhoDbGIydD1Cya7dba9ZhNFa+KU1uiyu5AX+i4fd
bCXI4Ukqzwc=
-----END CERTIFICATE-----
或者,您可以使用 Firefox Web 浏览器(v 57 左右)下载目标服务器的证书。导航到https://git.ffmpeg.org。按照Mozilla 的说明查看该站点的证书。
- 单击位置栏左侧的“(i)”图标,然后单击右箭头,然后单击“安全”选项卡,然后单击“查看证书”按钮。出现证书查看器。
- 单击“详细信息”选项卡。
- 在顶部窗格“证书层次结构”中,单击服务器的底部条目或根的顶部条目。
- 然后单击“导出...”按钮。出现“文件保存”对话框,文件名以“.crt”结尾。
- 将包含证书的文件保存在可访问的地方。
在 Chrome 和 Safari 上,似乎无法下载证书本身,但您可以获得包含证书信息的文本文件,可读但不可重复使用。
根 CA 证书更难获得。-showcerts
选项将openssl s_client
打印出信任链。与文档的声明相反,这只是服务器发送的证书。服务器通常不会在其信任链的根部发送根 CA 证书。(请参阅 OpenSSL 问题s_client -showcerts man text misleading: "all certificate in the chain",#4933。)但是,此选项会打印出根 CA 证书上的名称。它是服务器发送的最终证书的颁发者。
% openssl s_client -connect git.ffmpeg.org:443 -showcerts </dev/null 2>/dev/null
CONNECTED(00000003)
---
Certificate chain
0 s:/CN=ffmpeg.org
i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
-----BEGIN CERTIFICATE-----
MIIGBDCCBOygAwIBAgISAzCih69KsBB6DxJc3koSpgrMMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
... [ 29 lines omitted ] ...
Gi010DGiJpnEM3LIcrsokySWppACKkBCcEW3dlAL/kX+8CQrtT+ns8OtAC2RYuMF
jGjs0Nphih0=
-----END CERTIFICATE-----
1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
i:/O=Digital Signature Trust Co./CN=DST Root CA X3
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
... [ 29 lines omitted ] ...
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----
---
根 CA 证书标识为:“ /O=Digital Signature Trust Co./CN=DST Root CA X3
”。
有几个地方可以查找根 CA 证书的集合。每个浏览器都包含一个它信任的证书集合,并且可以找到包含该集合的文件。但我找到的最简单的来源是 MacPorts 与 openssl 一起安装的证书。这些位于 OpenSSL 数据位置,该位置是编译成 OpenSSL 的目录。查找名为cert.pem的文件和名为cert/的目录。(有关 更多信息,请参阅 Paul Heinlein 的OpenSSL 识别哪些证书颁发机构? )。在我的计算机上,它看起来像:
% openssl version -d OPENSSLDIR: "/opt/local/etc/openssl"
要列出 OpenSSL 信任的所有证书文件的路径,可以使用此命令。(来源:我对如何列出受 OpenSSL 信任的证书的回答?在 StackOverflow 上。)
% find -H `openssl version -d | sed -E 's/OPENSSLDIR: "([^"]*)"/\1/'`/(cert.pem|certs) \
-type f -exec ls -l {} \+
lrwxr-xr-x 1 root admin 40 29 Nov 02:05 /opt/local/etc/openssl/cert.pem -> /opt/local/share/curl/curl-ca-bundle.crt
(如果你想对证书文件做一些不同的事情,你可以使用不同的命令代替ls -l {}
上面的“”。)所以,这表明我的 OpenSSL 安装重用curl-ca-bundle.crt
了工具“cUrl”。)查看那个文件,我看到它用我在服务器证书的 /CN 字段中看到的相同名称标记每个证书。此命令使用grep查找并打印该证书。您可以省略 -text 选项以在开头省略文本版本:
% find -H `openssl version -d | sed -E 's/OPENSSLDIR: "([^"]*)"/\1/'`/(cert.pem|certs) \
-type f -exec grep -B 1 -A 19 'DST Root CA X3' {} \+ | openssl x509 -text
Certificate:
... [ 4 lines omitted ] ...
Signature Algorithm: sha1WithRSAEncryption
Issuer: O=Digital Signature Trust Co., CN=DST Root CA X3
Validity
Not Before: Sep 30 21:12:19 2000 GMT
Not After : Sep 30 14:01:15 2021 GMT
Subject: O=Digital Signature Trust Co., CN=DST Root CA X3
Subject Public Key Info:
... [ 45 lines omitted ] ...
-----BEGIN CERTIFICATE-----
MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
... [ 11 lines omitted ] ...
JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
-----END CERTIFICATE-----
--BEGIN CERTIFICATE--
从“ ”行到“ ”行的证书文本--END CERTIFICATE--
是您可以选择安装在 LiClipse 中的根 CA 证书。要将那部分放入文件中,请-text
从上述命令中删除选项,并将结果通过管道传输到名称如“ DST Root CA X3.crt
”的文件中。
识别 LiClipse JRE
证书安装在LiClipse 使用的Java 运行时环境 (JRE)中。下一个任务是识别此 JRE 及其Java 主目录的位置。
幸运的是,LiClipse(Mac 版)是否包含它自己的 JRE 副本?在 Stack Overflow 上得到了回答。是的,Mac 版 LiClipse确实包含自己的 JRE。Java 主目录位于./jre/Contents/Home
应用程序包中。该./bin
子目录具有可执行文件,如主java可执行文件。
% cd /Applications/LiClipse\ 4.0.0/LiClipse.app/jre/Contents/Home
% ls -F
COPYRIGHT THIRDPARTYLICENSEREADME.txt man/
LICENSE Welcome.html release
README bin/
THIRDPARTYLICENSEREADME-JAVAFX.txt* lib/
% bin/java -version
java version "1.8.0_77"
Java(TM) SE Runtime Environment (build 1.8.0_77-b03)
Java HotSpot(TM) 64-Bit Server VM (build 25.77-b03, mixed mode)
LiClipse JRE 的密钥工具
Java JRE 包含一个命令行实用程序keytool,用于管理该 JRE 的密钥。该实用程序位于./bin/keytool
JRE 内。您可以通过阅读keytool 文档了解更多信息。您还可以使用它的-help
选项运行 keytool,并阅读 keytool 手册页(使用“ man -M man/
”获取 JRE 的手册页,而不是系统的。)而且,虽然许多关于 keytool 的网页会假设 Windows 并显示“keytool.exe” ,在 Mac 上您当然不使用“.exe”扩展名。
% cd /Applications/LiClipse\ 4.0.0/LiClipse.app/jre/Contents/Home
% man -M man/ keytool
... [man page omitted] ...
% bin/keytool -help
Key and Certificate Management Tool
... [20 lines omitted] ...
Use "keytool -command_name -help" for usage of command_name
这个 keytool 是我们用来将密钥添加到 Trust Store 的工具。
LiClipse JRE 的信任库
JRE 将在不同位置查找密钥。默认值为~/.keystore
,与当前用户相关联的位置,该用户的所有 JRE 都可以查阅该位置。默认情况下,此位置没有任何内容。回退位置位于 JRE 的 Java 主目录下,一个文件./lib/security/cacerts
.
这些位置是关于 Java 安全体系结构的更大故事的一部分,我不会在这里讨论。您可以通过阅读 keytool 文档的术语部分和Java Cryptography Architecture (JCA) Reference Guide开始学习它。您将看到与“信任库”相关的术语“密钥库”。有时这些术语可以互换使用。出于我们的目的,“信任商店”是正确的术语。
权宜之计是修改 JRE 的本地信任库。路径在上面。keytool 文档的cacerts部分告诉我们它的初始密码是“ changeit
”。对于 LiClipse JRE,这可能仍然是它的密码。
将新的根证书添加到 LiClipse JRE 的信任库
剩下的就是把这些碎片放在一起。使用 keytool 将新的服务器 SSL 证书或根 CA 证书添加到 LiClipse JRE 的信任库。
% cd /Applications/LiClipse\ 4.0.0/LiClipse.app/jre/Contents/Home
% bin/keytool -import -alias FFmpeg.org -file cert.crt -keystore lib/security/cacerts -storepass changeit
Owner: CN=ffmpeg.org
Issuer: CN=Let's Encrypt Authority X3, O=Let's Encrypt, C=US
Serial number: 3f770e80f73938f7a3fe168b847345b73b2
Valid from: Tue Oct 31 23:22:03 PDT 2017 until: Mon Jan 29 22:22:03 PST 2018
Certificate fingerprints:
MD5: 61:57:B5:6B:56:08:B9:ED:E8:EC:EC:85:A9:CA:1A:F4
SHA1: 75:1B:86:CD:1E:34:7C:13:2F:49:E2:6D:73:A0:4F:05:09:11:7B:72
SHA256: EB:FA:E4:3F:CB:22:31:9F:97:7B:FA:E4:79:D6:90:7F:E0:20:3E:DA:E8:6F:C3:F0:38:55:F7:C0:1E:0D:6A:33
Signature algorithm name: SHA256withRSA
Version: 3
....
Trust this certificate? [no]: yes
Certificate was added to keystore
通过阅读手册页可以清楚地了解keytool调用。总结:-import
命令 keytool 添加证书,-alias
为存储中的证书提供标题,-file
提供从中读取证书的文件-keystore
的路径,提供密钥库的路径(没有它,~/.keystore
将使用默认值) ,并-storepass
给出该密钥库的密码。您可以添加-noprompt
减少工具评论的选项,以及-trustcacerts
停止有关信任证书的问题的选项,但对于这样的用途,我喜欢进行交叉检查。
如果您愿意,相同的调用将导入根 CA 证书。
测试
接下来,我们测试更改是否有效。再次尝试在 LiClipse 下使用 EGit 从 ffmpeg.org 执行“git pull”。这一次,没有出现错误对话框。这表明 JRE 的安全代码连接信任链中的证书,从 git.ffmpeg.org 服务器的证书到 JRE 信任库中的某些证书。(如果您在 JRE 信任库中安装了服务器的证书,那么这是一个 1 证书链。)
笔记
这是如何将 SSL 证书添加到 LiClipse 以允许 EGit 访问 git repo的浓缩,这是我写的一篇关于该主题的博客文章。