-->

没有共同的密码套件而建立安全连接(No cipher suites in common while

2019-07-21 14:16发布

我试图建立两个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());
    }
}

我有密钥工具生成的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"
};

我得到同样的结果。

Answer 1:

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

在服务器,初始化的的KeyManager总是需要配置服务器证书。 初始化的信任,当你想使用客户证书认证才是必需的。 (有更多的细节这个问题进行的KeyManager和的TrustManager之间的差异。)

如果没有配置的任何的KeyManager,没有可用的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);

这不是从你的例子清楚,但你不应该,当然使用客户端在同一个密钥库(作为信任库)和服务器端(如密钥库):私钥只应知道的服务器,并没有按“T需要在客户端的信任库中。


编辑:(。我会尝试用不同的方式来重新解释,因为它不是坦途也许它可能会帮助)

下面的代码初始化所述SSLContextnull键管理者阵列(第一自变量): ctx.init(null, tmf.getTrustManagers(), null) 。 (没有默认的密钥管理器。)

密钥管理器就是管理你的 (私人)密钥和证书,在何处运行代码的一面。 在服务器上,密钥管理器是什么是负责处理服务器证书和私钥。 密钥管理器本身通常是由“密钥库密钥库”初始化。 “ 密钥库 ”在Java中可以有多个含义。 一的密钥库的含义是在其中密钥和证书可被存储,通常是文件的实体。 这样的密钥库可以被用于初始化一个信任管理器1(在这种情况下,它被称为信任 )或密钥管理器(在这种情况下,它被称为密钥库 )。 对不起,不是我的选择的名字,但是这是系统属性的调用方式。

当服务器配置了一个空的密钥管理器,它配置没有任何证书和相关的私钥。 因此,它没有任何RSA或DSA证书。 因此,将无法使用任何的*_RSA_**_DSS_*密码套件,是否已得到明确允许或没有(他们将被自动缺少证书禁止他们使用)。 这有效地丢弃在默认情况下(或明确启用反正任何这样的加密套件)启用的任何密码套件。 因此,有“无密码套件中常见的”。

总之,一个SSLContext需要用证书及其私钥2被配置在服务器端。 这可以通过配置其密钥管理器来完成。 反过来,这通常是通过使用密钥库与实现KeyManagerFactory (不是TrustManagerFactory )。

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

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



文章来源: No cipher suites in common while establishing a secure connection
标签: java ssl rsa jsse