确定Java

时间:2016-09-07 15:32:15

标签: java ssl handshake diffie-hellman

我想与服务器建立HTTPS连接,如果我正在使用的话 非短暂的DH密钥交换,我想知道什么参数 是为了那个连接。实际上,我真的不在乎它是不是 短暂与否。

我正在寻找的是能够建立连接然后发出警告 如果连接使用“弱”DH参数。这是我的事吗 可以在连接时检查?或者是DH参数的集合(或者更多 具体而言,由这些参数定义的那些参数的长度 密码套件本身?

例如,Qualys社区主题有一个插图 SSLLabs认为“弱”的密码套件(好吧,每个人都认为 他们很弱......他们只是有一个抱怨他们的公共工具): https://community.qualys.com/thread/14821

他们特别提到例如TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 这是密码套件0x9f并提及DH参数。是那些 参数的参数被烘焙到密码套件中(意思是它们是 总是 1024位)或者这是服务器的配置 那些密码套件因特定的DH参数选择而变弱?

在任何一种情况下,我都希望能够从中嗅到这些信息 如果可能的话连接。有谁知道这是否可以做到, 怎么样?

我已经编写了一些代码来尝试获取有关握手的信息,但是我一直在为我希望包含此数据的对象获取null

SSLSocketFactory sf = ...;
Socket sock = new Socket();
sock.connect(address, timeout);

SSLSocket socket = (SSLSocket)sf.createSocket(sock, host, port, true);
socket.startHandshake();
SSLSession sess = socket.getHandshakeSession();

我希望sess此时会包含一些有关握手的有趣信息,但它是nullstartHandshake的javadoc表示它将在握手完成时通知事件侦听器。所以我尝试了这个:

SSLSocketFactory sf = ...;
Socket sock = new Socket();
sock.connect(address, timeout);

SSLSocket socket = (SSLSocket)sf.createSocket(sock, host, port, true);
socket.startHandshake();
// SSLSession sess = socket.getHandshakeSession();
SSLSession sess = socket.getSession(); // This forces the handshake to complete
sess = socket.getHandshakeSession();

...但此时sess仍为null。 “真正的”SSLSession确实存在,并提供有关连接的信息,但“握手会话”似乎总是null

所以我尝试写一个HandshakeCompletedListener,我确实得到了一个SSLSession,但它似乎与SSLSocket已经得到的相同,所以“握手”会议似乎没有用。

如何从SSLSession获取这些参数?

2 个答案:

答案 0 :(得分:1)

  

这些参数是'参数烘焙到密码套件中(意味着它们总是1024位),或者这是服务器的配置,由于特定的DH参数选择,使得这些密码套件变弱?

不,这是协议的配置参数 。 Java的默认值为1024位,但可以使用系统属性jdk.tls.ephemeralDHKeySize为JSSE(Java TLS实现)更改全局。最好在启动期间使用Java VM的-D选项设置它。

对于静态DH密钥对(用于身份验证),您必须查看DH证书。但我不认为你会找到任何人,每个人都使用RSA进行身份验证。

  

在任何一种情况下,如果可能的话,我希望能够从连接中嗅出该信息。有谁知道这是否可以做到,以及如何做到?

好吧,对于嗅探这样的工具,比如WireShark就足够了。毫无疑问,你可以解析TLS连接中的DH参数之类的东西(当然,如果它们首先使用的话)。

您还可以使用-Djavax.net.debug

调试连接

对于Java应用程序/库,您可以查找密码套件,然后,如果它包含DHE_,则查找上述系统属性(请记住其默认值)。

Java JSSE API并未考虑深度数据包检查。它(字面上)是服务器和客户端应用程序的面向服务的实现。虽然你当然可以使用OpenJDK代码本身(它是GPL' ed,对吗?)你最好使用单独的实现,可能还有更宽松的许可。

对于嗅探器,我宁愿使用C / C ++(或至少是C / C ++前端)而不是Java。

答案 1 :(得分:0)

对于大多数密码算法,长度由名称cypher名称确定,如此处How to get the actual block cipher key size for Java SSL connection _in code_?所述。 我建议通过仅选择您想要支持的密码来禁用这些密码,而不是在人们使用不安全的密码时警告他们。您可以在jvm级别或SSLSocket上执行此操作,例如

String pickedCipher[] ={"TLS_RSA_WITH_AES_128_CBC_SHA"}; 
socket.setEnabledCipherSuites(pickedCipher);

您也可以设置所需的密钥大小,请参阅此处 https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#customizing_dh_keys

您可以在https://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html

中查看Java安全性中使用的默认值和类

如果您感到好奇并希望更详细地研究这一点,我建议您打开ssl日志记录,如此处所述。