在建立安全连接时,没有共同的密码套件

编程入门 行业动态 更新时间:2024-10-24 00:20:59
本文介绍了在建立安全连接时,没有共同的密码套件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

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

I'm trying to establish a secure connection between two Java projects but I'm getting a SSLHandshakeException (no cipher suites in common). This are the methods to create sockets in both sides:

客户端:

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密钥。此代码从磁盘加载。

I have a RSA key generated with keytool. This code load it from disk.

我做错了什么?

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

UPDATE: I added the a call to setEnabledCipherSuites in both sides with this array:

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" };

我得到相同的结果。

推荐答案

在服务器端,您没有初始化密钥库/密钥管理器,只有信任库/信任管理器: ctx.init(null,tmf.getTrustManagers(),null )。

On the server side, you're not initialising the keystore/keymanagers, only the truststore/trustmanagers: ctx.init(null, tmf.getTrustManagers(), null).

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

On the server, initialising the keymanager is always necessary to configure the server certificate. Initialising the truststore is only necessary when you want to use client-certificate authentication. (There are more details in this question for the difference between keymanager and trustmanager.)

如果没有配置任何keymanager,则没有可用的基于RSA或DSA的证书,因此没有依赖证书进行身份验证的密码套件(默认情况下启用的所有密码套件)都可用。因此,客户端和服务器之间没有共同的密码套件。

Without any keymanager configured, there is no RSA or DSA based certificate available, so no cipher suite that rely on a certificate for authentication (all the ones enabled by default are) are available. Hence, you get no cipher suites in common between the client and the server.

你需要这样的东西:

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);

从您的示例中不清楚,但您当然不应该在客户端上使用相同的密钥库(作为信任库)和服务器端(作为密钥库):私钥应该只为服务器所知,而不需要在客户端的信任存储中。

It's not clear from your example, but you shouldn't of course use the same keystore on the client (as a truststore) and on the server side (as a keystore): the private key should only be known to the server, and doesn't need to be in the client's trust store.

编辑:(我会尝试以不同的方式重新解释,因为每个人都不清楚。也许是可能有帮助。)

(I'll try to re-explain in a different way, since it wasn't clear for everyone. Perhaps it might help.)

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

The following code initialises the SSLContext with a null array of key managers (the first argument): ctx.init(null, tmf.getTrustManagers(), null). (There is no default key manager.)

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

The key manager is what manages your (private) keys and certificates, on the side where the code is running. On the server, the key manager is what's responsible for handling the server certificate and its private key. The key manager is itself usually initialised by the "keystore keystore". "keystore" in Java can have multiple meanings. One of the meaning of keystore is the entity into which keys and certificates can be stored, typically a file. Such a keystore can be used to initialise a trust manager1 (in which case it's referred to as the truststore) or a key manager (in which case it's referred to as a keystore). Sorry, not my choice of names, but that's the way the system properties are called.

当服务器配置了空密钥管理器时,它配置没有任何证书和相关的私钥。因此,它没有任何RSA或DSA证书。因此,它无法使用任何 * _ RSA _ * 或 * _ DSS _ * 密码套件,它们是否已明确启用(由于缺少与它们一起使用的证书,它们将被自动禁用)。这有效地丢弃了默认启用的任何密码套件(或者任何明确启用的任何此类密码套件)。因此,没有共同的密码套件。

When the server is configured with a null key manager, it is configured without any certificate and associated private key. Therefore, it doesn't have any RSA or DSA certificate. Therefore, it won't be able to use any of the *_RSA_* or *_DSS_* cipher suites, whether they've been explicitly enabled or not (they will be disabled automatically by lack of certificate to use with them). This effectively discards any cipher suite enabled by default (or any such cipher suite enabled explicitly anyway). Hence, there is "no cipher suite in common".

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

In short, an SSLContext on the server side needs to be configured with a certificate and its private key2. This is done by configuring its key manager. In turn, this is often done by using a keystore with a KeyManagerFactory (not a TrustManagerFactory).

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

1: The trust manager uses local trust anchors (e.g. trusted CA certificates) to evaluate trust in a remote party (i.e. a server trusting a client certificate or a client trusting a server certificate).

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

更多推荐

在建立安全连接时,没有共同的密码套件

本文发布于:2023-10-30 23:50:03,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1544370.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:套件   密码

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!