nik*_*org 6 base64 websocket node.js
不久前,我开始尝试使用Node.js来处理后端的WebSockets.它工作正常,但现在当我返回协议已更新,我不能让它正常工作.
具体来说,问题是Sec-WebSocket-Accept标题.我在计算时似乎做错了什么,虽然我无法理解那可能是什么.据我所知,我正按照维基百科上的说明进行操作.
这是我的代码:
var magicString = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
var secWsKey = req.headers['sec-websocket-key'];
var hash = require('crypto')
.createHash('SHA1')
.update(secWsKey + magicString)
.digest('hex');
var b64hash = new Buffer(hash).toString('base64');
var handshake = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" +
"Upgrade: WebSocket\r\n" +
"Connection: Upgrade\r\n" +
"Sec-WebSocket-Accept: " + b64hash + "\r\n" +
"\r\n";
socket.write(handshake);
Run Code Online (Sandbox Code Playgroud)
示例连接:
// The incoming headers
{ upgrade: 'websocket',
connection: 'Upgrade',
host: 'localhost:8888',
origin: 'http://localhost:8888',
'sec-websocket-key': '4aRdFZG5uYrEUw8dsNLW6g==',
'sec-websocket-version': '13' }
// The outgoing handshake
HTTP/1.1 101 Switching Protocols
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Accept: YTYwZWRlMjQ4NWFhNzJiYmRjZTQ5ODI4NjUwMWNjNjE1YTM0MzZkNg==
// Result: Error during WebSocket handshake: Sec-WebSocket-Accept mismatch
Run Code Online (Sandbox Code Playgroud)
仔细研究一下,我尝试在wiki中复制计算出的哈希,但它失败了.
var hash = require('crypto')
.createHash('SHA1')
.update('x3JJHMbDL1EzLkh9GBhXDw==258EAFA5-E914-47DA-95CA-C5AB0DC85B11')
.digest('hex');
// Result : 1d29ab734b0c9585240069a6e4e3e91b61da1969
// Expected: 1d29ab734b0c9585240069a6e4e3e91b61da1969
var buf = new Buffer(hash).toString('base64');
// Result : MWQyOWFiNzM0YjBjOTU4NTI0MDA2OWE2ZTRlM2U5MWI2MWRhMTk2OQ==
// Expected: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Run Code Online (Sandbox Code Playgroud)
如您所见,SHA1哈希是正确的,但base64编码不是.看看这个答案,似乎我会做得对.我在PHP中尝试了相同的过程,我得到了相同的结果,所以显然我做错了.
我正在运行Node.js v0.6.8.
进一步尝试PHP,这对我来说比较熟悉,并且从printfshell 的行为中得出,我想出了这个工作片段:
$hash = sha1('x3JJHMbDL1EzLkh9GBhXDw==258EAFA5-E914-47DA-95CA-C5AB0DC85B11');
$hashdec = '';
for ($i = 0; $i < strlen($hash); $i += 2) {
$hashdec .= chr(hexdec(substr($hash, $i, 2)));
};
echo base64_encode($hashdec);
// Result : HSmrc0sMlYUkAGmm5OPpG2HaGWk=
// Expected: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Run Code Online (Sandbox Code Playgroud)
然后我尝试在JavaScript中复制它,但没有用.
var magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
var key = "4aRdFZG5uYrEUw8dsNLW6g==";
var magic_key = magic + key;
var hash = require('crypto').createHash('sha1').update(magic_key).digest('hex');
var buf = new Buffer(hash.length / 2);
for (var i = 0; i < hash.length; i += 2) {
var token = hash.substr(i, 2);
var int = parseInt(token.toString(16), 16);
var chr = String.fromCharCode(int);
buf.write(chr);
}
console.log(buf.toString('base64'));
// Result : w53dAAEAAADBIIAFAQAAAGGAtwA=
// Expected: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Run Code Online (Sandbox Code Playgroud)
有时阅读手册确实有帮助。
hash.digest([编码])
计算所有要散列的传递数据的摘要。编码可以是“十六进制”,“二进制”或“ base64 ”。
(强调我的。)
因此,通过将代码更改为解决了该问题:
var magicString = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
var secWsKey = req.headers['sec-websocket-key'];
var hash = require('crypto')
.createHash('SHA1')
.update(secWsKey + magicString)
.digest('base64'); // <- see that, silly.
var handshake = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" +
"Upgrade: WebSocket\r\n" +
"Connection: Upgrade\r\n" +
"Sec-WebSocket-Accept: " + hash + "\r\n" +
"\r\n";
socket.write(handshake);
Run Code Online (Sandbox Code Playgroud)
'是时候感到愚蠢了。(再次。)