Base64 encoding for Sec-WebSocket-Accept value

Some time ago, I started experimenting with WebSockets using Node.js, taking care of the backend. It worked fine, but now, when I return the protocol, it has been updated, and I can not get it to work fine.

In particular, the problem is the Sec-WebSocket-Accept header. It seems that I am doing something wrong in the calculation, although I can not understand what it can be. As far as I can tell, I follow the instructions on Wikipedia to the point.

Here is my code:

 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); 

Connection example:

 // 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 

Looking more at this, I tried to reproduce the computed hash on a wiki, and it fails.

 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= 

As you can see, the SHA1 hash is correct, but the base64 encoding is not. Looking at this answer , it seems that I will do everything right. I tried the same process in PHP and I get the same result, so I clearly say "Doing It Wrong".

I am running Node.js v0.6.8.

Getting closer

Experimenting with more familiar PHP to me, and based on the behavior of printf in the shell, I came up with this working snippet:

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

Then I tried to reproduce this in JavaScript, but to no avail.

 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= 
+6
source share
2 answers

Sometimes reading a guide really helps.

hash.digest ([encoding])

Computes the digest of all transferred data to be hashed. The encoding can be "hex", "binary" or " base64 ".

(Emphasize mine.)

Thus, the problem was solved by changing the code to:

 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); 

"It's time to feel stupid. (Again.)

+4
source

use http://pajhome.org.uk/crypt/md5/sha1.html and code

 b64pad = "="; var b64hash = b64_sha1(secWsKey + magicString); console.log(b64hash); 
0
source

Source: https://habr.com/ru/post/906772/


All Articles