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

建立安全连接时,没有通用的密码套件

冯玮
2023-03-14
问题内容

我正在尝试在两个Java项目之间建立安全连接,但是却遇到了SSLHandshakeException(没有通用密码套件)的问题。这是在两侧创建套接字的方法:

客户:

private SSLSocket getSocketConnection() throws SSLConnectionException {
    try {

        /* Load properties */
        String keystore = properties.getProperty("controller.keystore");
        String passphrase = properties.getProperty("controller.passphrase");
        String host = properties.getProperty("controller.host");
        int port = Integer.parseInt(properties
                .getProperty("controller.port"));

        /* Create keystore */
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(new FileInputStream(keystore), passphrase.toCharArray());

        /* Get factory for the given keystore */
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(keyStore);
        SSLContext ctx = SSLContext.getInstance("SSL");
        ctx.init(null, tmf.getTrustManagers(), null);
        SSLSocketFactory factory = ctx.getSocketFactory();

        return (SSLSocket) factory.createSocket(host, port);
    } catch (Exception e) {
        throw new SSLConnectionException(
                "Problem connecting with remote controller: "
                        + e.getMessage(), e.getCause());
    }
}

服务器:

private SSLServerSocket getServerSocket() throws SSLConnectionException {
    try {

        /* Load properties */
        Properties properties = getProperties("controller.properties");

        String keystore = properties.getProperty("controller.keystore");
        String passphrase = properties.getProperty("controller.passphrase");
        int port = Integer.parseInt(properties
                .getProperty("controller.port"));

        /* Create keystore */
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(new FileInputStream(keystore), passphrase.toCharArray());

        /* Get factory for the given keystore */
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(keyStore);
        SSLContext ctx = SSLContext.getInstance("SSL");
        ctx.init(null, tmf.getTrustManagers(), null);
        SSLServerSocketFactory factory = ctx.getServerSocketFactory();

        return (SSLServerSocket) factory.createServerSocket(port);
    } catch (Exception e) {
        throw new SSLConnectionException(
                "Problem starting auth server: "
                        + e.getMessage(), e.getCause());
    }
}

我有一个用keytool生成的RSA密钥。此代码从磁盘加载它。

我做错了什么?

更新: 我在此数组的两侧添加了对setEnabledCipherSuites的调用:

String enableThese[] =
{
    "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
    "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
    "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA"
};

我得到相同的结果。


问题答案:

在服务器端,你不能初始化密钥库/ keymanagers,只有信任/ trustmanagers: ctx.init(null, tmf.getTrustManagers(), null)

在服务器上,始终必须初始化密钥管理器以配置服务器证书。仅当您要使用客户端证书身份验证时,才需要初始化信任库。(有关密钥管理器和信任管理器之间的区别,此问题中有更多详细信息。)

没有配置任何密钥管理器,就没有基于RSA或DSA的证书,因此没有依赖于证书进行身份验证的密码套件(默认情况下所有启用的密码套件)都可用。因此,您在客户端和服务器之间不会获得相同的密码套件。

您需要这样的东西:

KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keystore, password.toCharArray()); // That's the key's password, if different.
// ...
ctx.init(kmf.getKeyManagers(), null, null);

从您的示例中还不清楚,但是您当然不应该在客户端(作为信任库)和服务器端(作为密钥库)使用相同的密钥库:私钥应该只为服务器所知,而不会不必位于客户的信任库中。

编辑:( 我将尝试以另一种方式重新解释,因为目前尚不清楚每个人。也许有帮助。)

以下代码SSLContext使用一null组密钥管理器(第一个参数)初始化:ctx.init(null, tmf.getTrustManagers(), null)。(没有默认的密钥管理器。)

密钥管理器是在运行代码的一侧管理 您的
(私有)密钥和证书的工具。在服务器上,密钥管理器负责处理服务器证书及其私钥。密钥管理器本身通常由“密钥库密钥库”初始化。Java中的“ keystore
”可以有多种含义。 密钥库 的含义之一是可以将密钥和证书(通常是文件)存储到其中的实体。这样的密钥库可用于初始化信任管理器1(在这种情况下,它称为
truststore )或密钥管理器(在这种情况下,它称为 密钥库)。 )。抱歉,不是我选择的名称,但这是调用系统属性的方式。


当服务器配置有空密钥管理器时,它将配置为不包含任何证书和关联的私钥。因此,它没有任何RSA或DSA证书。因此,无论它们是否已显式启用,它都将无法使用任何*_RSA_**_DSS_*密码套件(它们将因缺少证书而被自动禁用)。这有效地丢弃了默认情况下启用的任何密码套件(或无论如何显式启用的任何此类密码套件)。因此,“没有共同的密码套件”。

简而言之,需要SSLContext在服务器端配置一个证书及其私钥2。这是通过配置其密钥管理器来完成的。反过来,这通常是通过将密钥库与KeyManagerFactory(而不是TrustManagerFactory)一起使用来完成的。

1:信任管理器使用本地信任锚(例如,受信任的CA证书)来评估对 远程 方(即​​,信任客户端证书的服务器或信任服务器证书的客户端)的信任。

2:JSSE支持的某些密码套件不需要证书,但是它们是匿名密码套件(不安全)或Kerberos密码套件(需要完全不同地设置)。两者都是默认禁用的。



 类似资料:
  • 我试图在两个Java项目之间建立安全连接,但我得到了一个SSLHandshakeException(没有共同的密码套件)。这是在双方创建套接字的方法: 客户: 服务器: 我有一个使用keytool生成的RSA密钥。此代码从磁盘加载它。 我做错了什么? 更新:我用这个数组在两边添加了对setEnabledCipherSuites的a调用: 我得到同样的结果。

  • 问题内容: 我最近一直在将SSL套接字用于消息传递系统。 我终于开始使用CA颁发的证书。我将其导入到密钥库中,设置了密钥库属性,并启动了客户端,但是当我尝试发送数据时,我一直收到握手异常。 我启用了调试模式,发现这是由于造成的。有什么想法吗? 如果有帮助,它还说它忽略了TLSV1和TLSV1.1中的大约10个密码套件。 我还安装了无限强度加密策略。 客户代码 服务器代码 编辑: 我刚刚添加了密码,

  • 问题内容: 我使用此代码创建了到SQL Server的连接。 但是我得到了这个错误: com.microsoft.sqlserver.jdbc.SQLServerException:驱动程序无法使用安全套接字层(SSL)加密建立与SQL Server的安全连接。错误:“套接字已关闭”。ClientConnectionId:5975fad5-8f8d-496a-a2bb- bff3a8d1a755

  • 问题内容: 按照此处的说明进行操作,并重新创建了我以前错误创建的证书。就像我现在在服务器和客户端上看到的一样,情况发生了变化。 服务器是ClassFileServer.java,相应的客户端是SSLSocketClientWithClientAuth.java 有关使两端都能正常播放的任何提示,请注意,我使用的是localhost,因此我假设密码功能相同。 更新: 这是我用于生成文件的步骤,我可能

  • 我试图通过我的groovy代码连接到我公司的Microsoft sql。使用此代码: 这会导致错误: 39m:没有这样的属性:类的连接:31m[0;39m[31m39m(31m)[0;39m[31m39m(31m)[0;39m[31m39m(31m)[0;39m[31m39m(CreateOrg: 47)[0;39m[31m31m(39m)[0;TempTestCase1555589132729.

  • 我使用此代码创建了与 SQL Server 的连接。 但我有一个错误: 驱动程序无法使用安全套接字层(SSL)加密建立到sqlserver的安全连接。错误:“套接字关闭”。client connection id:5975 fad 5-8f8d-496 a-a2bb-BF F3 A8 D1 a 755 有人能帮我吗?预先感谢