我想解析 TLS (1.1/2) 握手并确定 SNI 信息。
JDK8 为此提供了功能。但我想要一个更直接和兼容的版本:
我开发了这个块,但它不能可靠地工作(有些浏览器可以工作,有些不能):
def parseSNI(data: List[Int]): String = {
if (data.head != 0x16) {
println("Not TLS :-(")
return "none"
}
if (data(1) < 3 || (data(1) == 3 && data(2) < 1)) {
println("SSL < 3.1 so it's still not TLS")
return "none"
}
val restLength = data(3) + data(4)
val rest = data.slice(5, (4 + restLength))
var current = 0
var handshakeType = rest(0)
current += 1
// Check Handshake
if (handshakeType != 0x1) {
println("Not a ClientHello")
}
// Skip over another length
current += 3
// Skip over protocolversion
current += 2
// Skip over random number
current += 4 + 28
// Skip over session ID
val sessionIDLength = rest(current)
current += 1
current += sessionIDLength
val cipherSuiteLength = (rest(current) << 8) + rest(current + 1)
current += 2
current += cipherSuiteLength
val compressionMethodLength = (rest(current))
current += 1
current += compressionMethodLength
if (current > restLength) {
println("no extensions")
}
var currentPos = 0
// Skip over extensionsLength
current += 2
var hostname = ""
while (current < restLength && hostname == "") {
var extensionType = (rest(current) << 8) + rest(current + 1)
current += 2
var extensionDataLength = (rest(current) << 8) + rest(current + 1)
current += 2
if (extensionType == 0) {
// Skip over number of names as we're assuming there's just one
current += 2
var nameType = rest(current)
current += 1
if (nameType != 0) {
println("Not a hostname")
}
var nameLen = (rest(current) << 8) + rest(current + 1)
current += 2
hostname = rest.slice(current, current + nameLen).map(x => x.toChar).mkString
}
current += extensionDataLength
}
hostname
}
有人知道更好的方法吗?
谢谢!