ページ

2012年1月6日

RFCになったwebsocketのハンドシェイクの部分

@t2y に「You've been writing only about cat, recently. I feel you are over.」っていわれちゃいました。そんなことではいけないと思い、それから最新のwebsocketに対応してくれ、ってリクエストが来ているwebscoketのpython clientもバージョンアップすべく、RFCになったほうを読んでいます。大きな処理の流れは、昔のwebsocketと大きくは違わないので割愛します。

まず、サーバに接続してリクエストを投げます。クライアントからのリクエストはこんな感じです。今回はecho.websocket.orgに対してリクエストを投げています。

GET / HTTP/1.1
Host: echo.websocket.org
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: c6b8hTg4EeGb2gQMztV1/g==
Origin: http://echo.websocket.org
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13

websocketのサーバに接続するとき、Sec-WebSocket-KeyとHost, Origin以外のヘッダーはほぼ固定ですね。Sec-WebSocket-Keyだけがリクエストごと変更されます。まあ、同じでも問題ないんだけど。

Sec-WebSocket-Keyはuuidの16bitのバイト列をbase64エンコードしたもの、っていうことになっています。でも、サーバの実装は長さのチェックとかしていなさそうなので、何でもいいかも。

このリクエストに対してサーバは、
HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: Kxep+hNu9n51529fGidYu7a3wO0=
Server: Kaazing Gateway
Date: Fri, 06 Jan 2012 07:39:19 GMT

となります。echo.websocket.orgってKaazing Gateway使っているんですね。で、Sec-WebSocket-Acceptでちゃんとしたサーバかをチェックしていますが、以前にも書きましたが、これで何がセキュアになるのか、さっぱり分かりません。

Sec-WebSocket-Acceptは、Sec-WebSocket-Keyで送った文字列に258EAFA5-E914-47DA-95CA-C5AB0DC85B11をconcatして、shaでdigestしたもののbase64エンコードした値です。えっ?何言ってんだって?コードだと

s = sec_websocket_key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
digest = sha.sha(s).digest()
print base64.encodestring(digest).lower()

と言うことです。これでサーバからのレスポンスのSec-WebSocket-Acceptと、クライアントで計算した値が同じであればハンドシェークは成功です。まあ、厳密いえばUpgradeヘッダーとかその辺の値のバリデーションも必要なんですが・・・。

でも、大昔よりは幾分シンプルになりましたね。

次回は実際のデータ転送について。


0 件のコメント: