Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8254631 Better support ALPN byte wire values in SunJSSE
  3. JDK-8265351

Release Note: Improve Encoding of TLS Application-Layer Protocol Negotiation (ALPN) Values



    • Type: Sub-task
    • Status: Open
    • Priority: P4
    • Resolution: Unresolved
    • Affects Version/s: 8u301, 11.0.12-oracle
    • Fix Version/s: None
    • Component/s: security-libs
    • Labels:


      Certain TLS ALPN values couldn't be properly read or written by the SunJSSE provider. This is due to the choice of Strings as the API interface and the undocumented internal use of the UTF-8 Character Set which converts characters larger than U+00007F (7-bit ASCII) into multi-byte arrays that may not be expected by a peer.

      ALPN values are now represented using the network byte representation expected by the peer, which should require no modification for standard 7-bit ASCII-based character Strings.

      The ApplicationProtocol String values returned by the methods in the `javax.net.ssl.SSLSocket` and `javax.net.ssl.SSLEngine` classes are in the network byte representation sent by the peer.

      The bytes could be directly compared, or converted to its Unicode String format for comparison.

      For example:
      ` String networkString = sslEngine.getHandshakeApplicationProtocol();
          byte[] bytes = networkString.getBytes(StandardCharsets.ISO_8859_1);
          // Match using bytes:
          // "http/1.1" (7-bit ASCII values same in UTF-8)
          // MEETEI MAYEK LETTERS "HUK UN I" (Unicode 0xabcd->0xabcf)
          String HTTP1_1 = "http/1.1";
          byte[] HTTP1_1_BYTES = HTTP1_1.getBytes(StandardCharsets.UTF_8);

          byte[] HUK_UN_I_BYTES = new byte[] {
              (byte) 0xab, (byte) 0xcd,
              (byte) 0xab, (byte) 0xce,
              (byte) 0xab, (byte) 0xcf};

          if ((Arrays.compare(bytes, HTTP1_1_BYTES) == 0 )
                  || Arrays.compare(bytes, HUK_UN_I_BYTES) == 0) {
      Alternatively match using String.equals() if we know the ALPN value was encoded from a `String` using a certain character set, for example `UTF-8`. The ALPN value must first be properly decoded to a Unicode `String` before use.

           String unicodeString = new String(bytes, StandardCharsets.UTF_8);
           if (unicodeString.equals(HTTP1_1)
                  || unicodeString.equals("\uabcd\uabce\uabcf")) {

      String values used in the `javax.net.ssl.SSLParameters.setApplicationProtocols(String[] protocols)` method must be presented using the network byte representation expected by the peer. For example, if an ALPN String should be exchanged using UTF-8, the String should be converted to its byte[] representation and stored as a byte-oriented String.

      For example:
      // MEETEI MAYEK LETTERS HUK UN I (Unicode 0xabcd->0xabcf): 2 bytes
      byte[] bytes = "\uabcd\uabce\uabcf".getBytes(StandardCharsets.UTF_8);
      String HUK_UN_I = new String(bytes, StandardCharsets.ISO_8859_1);
      // 0x00-0xFF: 1 byte
      String rfc7301Grease8F = "\008F\008F";
      SSLParameters p = sslSocket.getSSLParameters();
      p.setApplicationProtocols(new String[] { "h2", "http/1.1", rfc7301Grease8F, HUK_UN_I});

      SunJSSE now encodes/decodes String characters as 8-bit ISO_8859_1/LATIN-1 characters. This means applications that used characters above U+000007F that were previously encoded using UTF-8 may need to either be modified to perform the UTF-8 conversion, or set the Java security property *`jdk.tls.alpnCharset`* to "UTF-8" revert the behavior.




            coffeys Sean Coffey
            coffeys Sean Coffey
            0 Vote for this issue
            2 Start watching this issue