当前位置: 首页 > 面试题库 >

Java SSL连接,以编程方式将服务器证书添加到密钥库

柴意智
2023-03-14
问题内容

我正在将SSL客户端连接到我的SSL服务器。当客户端由于根密钥不存在而无法验证证书时,我需要选择将该证书添加到代码中的本地密钥存储中并继续。有一些示例始终接受所有证书,但是我希望用户验证证书并将其添加到本地密钥存储中,而无需离开应用程序。

SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("localhost", 23467);
try{
    sslsocket.startHandshake();
} catch (IOException e) {
    //here I want to get the peer's certificate, conditionally add to local key store, then reauthenticate successfully
}

关于自定义SocketFactory,TrustManager,SSLContext等的内容很多,我不太了解它们如何组合在一起,或者这将是我实现目标的最短路径。


问题答案:

您可以使用X509TrustManager来实现。

使用以下方法获取SSLContext

SSLContext ctx = SSLContext.getInstance("TLS");

然后X509TrustManager使用SSLContext#init用您的自定义对其进行初始化。SecureRandom和KeyManager
[]可以为null。后者仅在您执行客户端身份验证时有用,如果在您的情况下仅服务器需要身份验证而无需设置它。

从此SSLContext中,使用SSLContext#getSocketFactory获取SSLSocketFactory
并按计划进行。

关于X509TrustManager的实现,它可能看起来像这样:

TrustManager tm = new X509TrustManager() {
    public void checkClientTrusted(X509Certificate[] chain,
                    String authType)
                    throws CertificateException {
        //do nothing, you're the client
    }

    public X509Certificate[] getAcceptedIssuers() {
        //also only relevant for servers
    }

    public void checkServerTrusted(X509Certificate[] chain,
                    String authType)
                    throws CertificateException {
        /* chain[chain.length -1] is the candidate for the
         * root certificate. 
         * Look it up to see whether it's in your list.
         * If not, ask the user for permission to add it.
         * If not granted, reject.
         * Validate the chain using CertPathValidator and 
         * your list of trusted roots.
         */
    }
};

编辑:

Ryan是正确的,我忘了解释如何将新根添加到现有根中。假设您当前的受信任根的KeyStore来自cacerts(JDK随附的“
Java默认信任存储”,位于jre / lib / security下)。我假设您使用KeyStore#load(InputStream,char
[])加载了该密钥库(采用JKS格式)。

KeyStore ks = KeyStore.getInstance("JKS");
FileInputStream in = new FileInputStream("<path to cacerts"");
ks.load(in, "changeit".toCharArray);

cacerts如果尚未更改,默认密码为“ changeit”。

然后,您可以使用KeyStore#setEntry添加其他受信任的根。您可以省略ProtectionParameter(即null),KeyStore.Entry将是一个TrustedCertificateEntry,它将新的根作为其构造函数参数

KeyStore.Entry newEntry = new KeyStore.TrustedCertificateEntry(newRoot);
ks.setEntry("someAlias", newEntry, null);

如果您想在某个时候持久保存更改后的信任库,可以使用KeyStore#store(OutputStream,char
[]来实现。



 类似资料:
  • 我遵循了以下教程。因此,我在服务器初始化中添加了服务器.crt 和服务器.key 然后我尝试向Postman发送请求。为此,我向Postman添加了证书: 但是当我发送请求时,我收到此错误 - SSL错误:无法验证第一个证书。我知道我可以禁用SSL验证,但似乎应该有一个选项可以在不禁用它的情况下执行此操作。你能帮帮我吗

  • 问题内容: 如何从类路径中将.p12证书导入到Java密钥库中?首先,我使用了InstallCert https://code.google.com/p/java- use- examples/source/browse/trunk/src/com/aw/ad/util/InstallCert.java 进行了一些更改,以便获得服务器证书将被导入到Java安装目录中的密钥库中。这工作正常,但现在我

  • 我收到SSL握手异常错误:PKIX“路径不链接”(此处描述)。我通过使用 openssl 导入证书链来修复它: < code > OpenSSL s _ client-主机www.envmgr.com-端口443-显示证书 并将其安装到我的JDK的密钥库中: 这很有效。万岁。问题是我们将把我们的应用程序放在像rackspace或AWS这样的云服务器上,我认为我们很有可能无法修改JVM的密钥库来添加

  • 问题内容: 我的文件带有证书链-certificate.cer: 我需要将此证书链添加到密钥库。 我做的事: 结果,我在密钥库中只有1个证书。 但是应该有3. 什么地方可能出问题? 解决方案: CA向我发送了PKCS#7格式的证书。 我将它们存储在certificate.p7b文件中,然后通过以下命令将它们成功添加到密钥库中: 问题答案: 从keytool管理员中-如果以PKCS#7格式输入,它将

  • HTTP POST https://fcm.googleapis.com/fcm/send headers: 授权密钥=12345678900987654321 内容类型应用程序/JSON FCM管理或API是否提供了执行服务器密钥生成的方法?

  • 使用spring boot和jetty,我希望能够将我的应用程序配置为侦听其他端口,这些端口在运行时以编程方式添加(删除?)。 我试过的: 我遵循了本教程,它允许我在多个端口上侦听。这很好地工作,但不幸的是只在启动时工作。 我已经尝试了a类到服务中,这样我就可以添加连接器-我得到了错误 建筑gradle(依赖项 不确定从这里尝试什么。。。