web-dev-qa-db-ja.com

WebsocketプロトコルでのSec-Websocket-Keyの正確な定義

ヘッダーフィールドの正確な定義は何だろうと思っていますSec-Websocket-Keyです。

このフィールドは、WebSocket接続に使用されます。クライアントはサーバーにHTMLからWebsocketにアップグレードするように要求します。リクエストは次のようになります。

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

Sec-WebSocket-Keyフィールドは次のように定義されます [RFC6455]

| Sec-WebSocket-Key |ヘッダーフィールドは、WebSocketオープニングハンドシェイクで使用されます。パーツを提供するためにクライアントからサーバーに送信されます
サーバーが受信したことを証明するためにサーバーが使用する情報
有効なWebSocketオープニングハンドシェイク。これにより、サーバーがWebSocket以外のクライアント(HTTPなど)からの接続を受け入れないようにすることができます。
clients)は、疑いを持たないWebSocketサーバーにデータを送信するために悪用されています。

| Sec-WebSocket-Key |ヘッダーフィールドは、HTTPリクエストに複数回出現してはなりません(MUSTNOT)。

また、 [RFC6455]

このヘッダーフィールドの場合、サーバーは値を取得する必要があります(現在のとおり)
ヘッダーフィールド内。たとえば、base64でエンコードされた[RFC4648]バージョンから先頭と末尾の空白を差し引いたもの)、これを
グローバル一意識別子(GUID、[RFC4122]) "258EAFA5-E914-47DA-
文字列形式の95CA-C5AB0DC85B11 "。
WebSocketプロトコルを理解しないネットワークエンドポイント。 A
SHA-1ハッシュ(160ビット)[FIPS.180-3]、base64エンコード(のセクション4を参照)
[RFC4648])、この連結のうち、サーバーの
ハンドシェーク。具体的には、上記の例のように、| Sec-WebSocket-Key |ヘッダーフィールドの値が "dGhlIHNhbXBsZSBub25jZQ =="の場合、サーバーは文字列 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"を連結して文字列 "dGhlIHNhbXBsZSBub25jZQ == 258EAFA5-E914-47DA-95CA-95CA-95CA-95CA-5CAB-95CA-95CA-95CA-95CA-95CA-95CA-95CA-95CA-95CA-95CA-95CAB11サーバーはこのSHA-1ハッシュを取得し、値0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x90 0xf6 0x46 0x06 0xcf 0x38 0x59 0x45 0xb2 0xbe 0xc4 0xeaを提供します。次に、この値はbase64でエンコードされ([RFC4648]のセクション4を参照)、値を指定します
"s3pPLMBiTxaQ9kYGzzhZRbK + xOo ="。この値はエコーされます
| Sec-WebSocket-Accept |ヘッダーフィールド。

このフィールドの目的を完全に理解しました。しかし、どのように正確に生成されるかについての情報は見つかりません

おそらくそれは、ランダムな長さとランダムな文字セットを持つランダムな文字列ではありません。

1
thesys

Sec-WebSocket-Keyは、長さが16バイトの完全にランダムな文字列で、許容範囲はASCII値32〜127です。

空の文字列から始めます。次に、ASCII範囲32〜127の範囲内にある文字を生成する限り、この文字列に追加します。

16 ASCII文字に達したら、停止し、結果の文字列をbase64でエンコードします。

1
chuacw

RFC6455「WebSocketプロトコル」のセクション4.1(18ページのポイント7)に従って、Sec-WebSocket-Keyヘッダーの値はランダムに選択された16バイトのナンスでなければなりません(10進値0〜255を意味する任意の値はそれぞれに問題ありません)同じポイントで提供されたサンプルノートから推測できるように、バイトの)base64エンコード。

   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=="

@chuacwで示されるように、ASCII印刷可能文字+ DELである必要がある値に制限がないことを意味します

例として、Linux上のCでフィールドを生成するには:

#include <sys/random.h>
...
u8 bytes[16];
getentropy(bytes, 16);
return(base64(bytes));
1
Emil