我们需要使用AES加密进行客户端服务器通信,因此当我在SSLServetSocket上启用Cipher Suite TLS_DHE_RSA_WITH_AES_128_CBC_SHA(使用Java 6)并运行该程序时,我会遇到异常
没有可用的证书或密钥对应启用的SSL密码套件
我的问题是我们可以通过SSLSocket进行AES加密,还是需要常规套接字。如果我们不能使用它,任何人都可以请给我一个使用AES加密的客户端服务器通信的例子。
这是代码
public class AESServerSocketTest {
public static void main(String[] args) {
SSLServerSocket serverSocket;
try
{
SSLContext ctx = javax.net.ssl.SSLContext.getDefault();
serverSocket =(SSLServerSocket)ctx.getServerSocketFactory().createServerSocket(8181);
serverSocket.setEnabledCipherSuites(new String[]{"TLS_DHE_RSA_WITH_AES_128_CBC_SHA"});
SSLSocket in = (SSLSocket)serverSocket.accept();
}
catch (Exception e)
{
System.out.println("Exception " + e);
}
}
}
先谢谢
答案 0 :(得分:1)
匿名密码套件不执行任何身份验证。即使使用加密技术,您也可以通过加密频道与远程方通话,但您无法确定是谁,因此它可能是中间人(MITM)。 TLS 1.1 specification对匿名密码套件说了以下内容:
以下密码套件用于完全匿名 Diffie-Hellman通信,其中任何一方都未通过身份验证。 请注意,此模式容易受到中间人攻击,并且是 因此弃用。
简而言之,不要使用它们(除了测试之外),或者如果你真的确定不会有活跃的MITM。 (TLS 1.2规范的用法更加强烈。)
如果您想安全地使用TLS,您需要一种方法让客户验证身份的远程方。在绝大多数情况下,这是使用X.509证书完成的。特别是,对于TLS_DHE_RSA_WITH_AES_128_CBC_SHA
密码套件,您需要一个带有RSA公钥的证书(这解释了您收到的错误消息)。
您应该生成或请求证书(自签名或通过CA,可能是您自己的,具体取决于客户端的配置方式),以正确识别服务器。客户端不仅需要信任证书(显式或通过已建立的CA),而且其身份信息需要与客户端尝试连接的服务器名称相匹配。
从您的示例中,您不清楚是通过SSL / TLS实施HTTPS(例如)还是您自己的协议。 RFC 6125是此领域的最新规范,它统一了多种协议(例如HTTPS,LDAPS,IMAPS等)的实践。由于它是最近的RFC,很少有库明确地实现它(尽管它们可能在实践中实现,因为它整合了最佳实践)。有疑问,遵守RFC 2818, section 3.1(HTTP over TLS)关于此主题的指南通常是明智的:
如果存在类型为dNSName的subjectAltName扩展名,则必须 用作身份。否则,(最具体的)通用名称
必须使用证书的Subject字段中的字段。虽然 使用Common Name是现有的做法,它已被弃用 鼓励证书颁发机构改为使用dNSName。使用指定的匹配规则执行匹配 [RFC2459]。如果存在多个给定类型的标识 证书(例如,多个dNSName名称,任何一个匹配 该集合被认为是可接受的。)名称可能包含通配符 字符*,被认为匹配任何单个域名 组件或组件片段。例如, .a.com匹配foo.a.com但是 不是bar.foo.a.com。 f .com匹配foo.com但不匹配bar.com。
在某些情况下,URI被指定为IP地址而不是a 主机名。在这种情况下,iPAddress subjectAltName必须存在 在证书中,必须与URI中的IP完全匹配。
(RFC 6125 explicitly discourages the use of wildcard certificates。)
由于实际原因,证书中的IP地址并不理想(我认为很多商业CA都不会生成此类证书)。如果可以,请使用主题备用名称扩展名,如果不这样做,将主机名放在主题DN的CN=
RDN中就足够了。有关如何在this answer中使用SAN生成CSR /证书的说明。特别是,可以使用-ext
option of Java 7's keytool
(例如-ext san=dns:www.example.com
);请注意,Java 7的keytool生成的密钥库也应该可以在以前版本的JRE上使用。
此外,如果您没有除SSLContext.getDefault()
以外的任何其他代码(在这种情况下您也可以使用默认的SSLServerSocketFactory
),则需要指定密钥库:JRE不会没有默认值(与信任存储相对)。这可以使用javax.net.ssl.keyStore
(以及相关的系统属性)来完成。此答案中有更多内容(例如):https://stackoverflow.com/a/6341566/372643
答案 1 :(得分:0)
没有可用的证书或密钥对应于SSL密码套件 已启用
此错误表示:
您启用的密码套件不适合/接受私钥/证书(这很可能意味着例如短密钥长度)或您尚未配置任何证书。