2

我想解析 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

  }

有人知道更好的方法吗?

谢谢!

4

0 回答 0