Question

I'm wondering what the exact definition of the header-field Sec-Websocket-Key is.

The field is used for Websocket connections. The client asks the server to upgrade from HTML to Websocket. The request can look like this:

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13

The Sec-WebSocket-Key field is defined as follows [RFC6455]:

The |Sec-WebSocket-Key| header field is used in the WebSocket opening handshake. It is sent from the client to the server to provide part
of the information used by the server to prove that it received a
valid WebSocket opening handshake. This helps ensure that the server does not accept connections from non-WebSocket clients (e.g., HTTP
clients) that are being abused to send data to unsuspecting WebSocket servers.

The |Sec-WebSocket-Key| header field MUST NOT appear more than once in an HTTP request.

And also in [RFC6455]:

For this header field, the server has to take the value (as present
in the header field, e.g., the base64-encoded [RFC4648] version minus any leading and trailing whitespace) and concatenate this with the
Globally Unique Identifier (GUID, [RFC4122]) "258EAFA5-E914-47DA-
95CA-C5AB0DC85B11" in string form, which is unlikely to be used by
network endpoints that do not understand the WebSocket Protocol. A
SHA-1 hash (160 bits) [FIPS.180-3], base64-encoded (see Section 4 of
[RFC4648]), of this concatenation is then returned in the server's
handshake. Concretely, if as in the example above, the |Sec-WebSocket-Key| header field had the value "dGhlIHNhbXBsZSBub25jZQ==", the server would concatenate the string "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" to form the string "dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA- C5AB0DC85B11". The server would then take the SHA-1 hash of this, giving the value 0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x90 0xf6 0x46 0x06 0xcf 0x38 0x59 0x45 0xb2 0xbe 0xc4 0xea. This value is then base64-encoded (see Section 4 of [RFC4648]), to give the value
"s3pPLMBiTxaQ9kYGzzhZRbK+xOo=". This value would then be echoed in
the |Sec-WebSocket-Accept| header field.

I've completly understood the purpose of this field. However, I can not find any information on how exactly it is generated.

Probably it is not just a random string with random length and a random charset.

Was it helpful?

Solution

The Sec-WebSocket-Key is a completely random string with a length of 16 bytes, and has an allowable range of ASCII value 32 to 127.

You start with an empty string. Then as long as you generate a character that is within the ASCII range 32 to 127, you add to this string.

Once you reached 16 ASCII characters, stop, and base64 encode the resultant string.

OTHER TIPS

As per RFC6455 "The WebSocket Protocol", section 4.1 (page 18, point 7), the value of Sec-WebSocket-Key header MUST be a randomly selected 16 byte nonce (of any value meaning decimal values 0 to 255 are okay for each of the bytes, as can be inferred from the provided example note in the same point) base64-encoded.

   7.   The request MUST include a header field with the name
        |Sec-WebSocket-Key|.  The value of this header field MUST be a
        nonce consisting of a randomly selected 16-byte value that has
        been base64-encoded (see Section 4 of [RFC4648]).  The nonce
        MUST be selected randomly for each connection.

        NOTE: As an example, if the randomly selected value was the
        sequence of bytes 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09
        0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10, the value of the header
        field would be "AQIDBAUGBwgJCgsMDQ4PEC=="

Meaning there is no limitation on the values having to be ASCII printable characters+DEL at all as indicated by @chuacw

As an example, to generate the field in C on Linux:

#include <sys/random.h>
...
u8 bytes[16];
getentropy(bytes, 16);
return(base64(bytes));
Licensed under: CC-BY-SA with attribution
scroll top