websocket_handshake(State=#state{key=Key},
Req=#{pid := Pid, streamid := StreamID}, HandlerState, Env) ->
Challenge = base64:encode(crypto:hash(sha,
<< Key/binary, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" >>)),
Headers = cowboy_req:response_headers(#{
<<"connection">> => <<"Upgrade">>,
<<"upgrade">> => <<"websocket">>,
<<"sec-websocket-accept">> => Challenge
}, Req),
Pid ! {{Pid, StreamID}, {switch_protocol, Headers, ?MODULE, {State, HandlerState}}},
{ok, Req, Env}.
以上来自cowboy_websocket.erl 171行。
这段代码【258EAFA5-E914-47DA-95CA-C5AB0DC85B11】写死了。
很多人对此有疑问,为什么不随机生成呢?然后老外(母语是英文的)有人说RFC上这么说的。
然后我看了一眼RFC。https://tools.ietf.org/html/rfc6455
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 (seeSection 4 of [RFC4648]), to give the value "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=". This value would then be echoed in the |Sec-WebSocket-Accept| header field.
Google 翻译一下:
具体来说,如上例所示, Sec-WebSocket-Key |
头字段的值为“dGhlIHNhbXBsZSBub25jZQ ==”,服务器
将连接字符串“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”
形成字符串“dGhlIHNhbXBsZSBub25jZQ == 258EAFA5-E914-47DA-95CA-
C5AB0DC85B11“,服务器将采用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 | 标题字段。
人家只是举个例子。
注:这不禁让我想起了移动和联通的通讯加密算法An,人家出货的时候,告诉大家可以替换算法,但是没有人替换。
Cowboy的开发者也是醉了。