有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

使用SSLEngine(JSSE)与旧客户端进行java SSL握手

这是对“SSL Handshaking Using Self-Signed Certs and SSLEngine (JSSE)”的后续问题

我已经实现了一个NIO Web服务器,它可以在同一个端口上处理SSL和非SSL消息。为了区分SSL和非SSL消息,我检查入站请求的第一个字节,看它是否是SSL/TLS消息。例如:

byte a = read(buf);
if (totalBytesRead==1 && (a>19 && a<25)){
    parseTLS(buf);
}

在parseTLS()方法中,我实例化了一个SSLEngine,启动握手、包装/打开消息等。对于大多数现代网络浏览器(Firefox 10、IE 9、Safari 5等),一切似乎都很好

问题是,像IE 6这样的旧web浏览器和像Java的URLConnection类这样的库似乎以不同的方式启动SSL/TLS握手。例如,IE 6的前几个字节看起来像这样(十六进制值):

80 4F 01 03 00 ...

如果我将消息传递给SSLEngine,它似乎无法识别该消息并抛出异常

javax.net.ssl.SSLException: Unsupported record version Unknown-0.0

那么IE 6和Java的URLConnection类到底发送了什么呢?这是JSSE SSLEngine可以支持的有效SSL/TLS消息吗?我是否需要做一些预处理或与客户协商以发送不同的消息

提前谢谢

更新

多亏了Bruno和EJP以及一些进一步的调试,我对正在发生的事情有了更好的理解。正如布鲁诺正确指出的那样,IE6和Java 6客户端正在通过SSLv2 ClientHello发送数据。与我之前的一条评论相反,Java 1.6中的SSLEngine实际上可以打开SSLv2消息,并生成有效的响应以发送回客户端。我之前报告的SSLException是我这边的一个错误,与SSLEngine无关(我错误地认为客户端已经完成了数据发送,当SSLEngine希望打开更多数据时,我得到了一个空字节缓冲)


共 (1) 个答案

  1. # 1 楼答案

    这看起来像an SSLv2 Client Hello (see TLS specification)

    TLS 1.1 clients that support SSL Version 2.0 servers MUST send SSL Version 2.0 client hello messages [SSL2]. TLS servers SHOULD accept either client hello format if they wish to support SSL 2.0 clients on the same connection port. The only deviations from the Version 2.0 specification are the ability to specify a version with a value of three and the support for more ciphering types in the CipherSpec.

    • 80 4F是长度,高位必须设置为1(请参见^{} description
    • 01是消息类型(客户端Hello)
    • 03 00是受支持的最高版本(此处为SSLv3)

    自Java7以来,this is now disabled by default

    编辑:

    澄清一下,这不是真正的SSLv2客户机Hello,这是SSLv2格式的SSLv3客户机Hello。在这种情况下,服务器将使用(正确的)SSLv3服务器Hello(对应于03 00请求的版本号)进行回复。这同样适用于TLS 1.0、1.1和1.2,尽管这种格式的使用逐渐被弃用

    JSSE7SSLServerSocket仍然会理解这样的客户机Hello,并使用SSLv3/TLS1进行适当的回复。x服务器你好