JDBC+SSL:将 CA 证书、客户端证书和客户端捆绑到一个密钥库文件中

JDBC+SSL: Bundling a CA cert, client cert and client into a single keystore file

Google Cloud SQL 通过为您生成服务器 ca-cert.pemclient-cert.pemclient-key.pem 来支持 SSL 连接。我已经通过以下步骤让我的 Java 客户端连接到 Cloud SQL:

1) 将服务器 CA 证书导入到信任库文件中:

keytool -import -alias mysqlServerCACert -file ca-cert.pem -keystore truststore

2) 将客户端证书和客户端密钥捆绑到一个 pkcs12 文件中:

openssl pkcs12 -export -in client-cert.pem -inkey client-key.pem -out client.p12 -name clientalias -CAfile ca-cert.pem

3) 将 pkcs12 导入密钥库文件:

keytool -importkeystore -deststorepass keystore -destkeystore keystore -srckeystore client.p12 -srcstoretype PKCS12 -srcstorepass keystore -alias clientalias

4) 告诉 JVM 使用我的信任库和密钥库:

-Djavax.net.ssl.keyStore=/path/to/my/keystore \
-Djavax.net.ssl.keyStorePassword=keystore \
-Djavax.net.ssl.trustStore=/path/to/my/truststore \
-Djavax.net.ssl.trustStorePassword=truststore

这一切都有效,但不幸的是它排除了来自其他客户端库的出站 HTTPS 连接——在我的例子中,Firebase java 客户端库。问题是我的 -Djavax.net.ssl.trustStore 参数覆盖了与 JDK.

捆绑在一起的默认 cacerts 文件

我似乎有两个选择。一种不理想的选择是将我的服务器 CA 证书导入到 JDK 的 cacerts 文件中,在每台生产和开发机器上,使用 OS-specific 和 JDK-特定于版本的命令。这个选项对于实际的生产设置来说似乎很笨重。

另一种选择是将我的服务器 CA 证书和客户端证书捆绑到一个(本地)信任链中,然后 Java 将使用它来验证我的客户端密钥。从我读过的内容来看,我很确定这是可能的,但我不知道所需的咒语。

我的猜测是,我应该使用单个 openssl 命令创建一个包含我的服务器 CA 证书、客户端证书和客户端密钥的 pkcs12 包,顺序正确,然后使用 keytool将其导入新的密钥库。我会省略 -D.../trustStore JVM 参数,只指定密钥库参数。 Java 将为我的云 SQL 客户端密钥使用本地 CA 信任链,但会退回到全局 cacerts 文件进行所有其他 SSL 协商。

这可能吗?如果作为单个 pkcs12 不能直接实现,那么是否有一些其他步骤可以将它们全部放入单个密钥库中,绕过对信任库的需要?

将默认的 JRE cacerts 文件复制到新的信任库并将服务器证书添加到其中。用于所有客户。将此作为构建步骤并在每次升级 JRE 时重复,这样您就不会错过默认 cacerts.

中的证书更改

当然,如果服务器证书由公认的 CA 正确签名,则无需将其导入任何地方,或使用自定义信任库。如果它不是由公认的 CA 签署的,它应该是。