![Openssl 生成无效的 websocket 安全代码](https://linux22.com/image/79794/Openssl%20%E7%94%9F%E6%88%90%E6%97%A0%E6%95%88%E7%9A%84%20websocket%20%E5%AE%89%E5%85%A8%E4%BB%A3%E7%A0%81.png)
我需要在 GAWK 上编写 websocket 服务器。服务器必须通过以下算法(来自 RFC)处理用户的 Sec-WebSocket-Key:
- 连接键与
258EAFA5-E914-47DA-95CA-C5AB0DC85B11
- 取二进制形式的 sha-1(应有 20 个符号)
- 从二进制形式中获取 base64
我正在尝试使用 openssl 但生成的代码不正确:
$ openssl sha1 -binary <<< 'a0+ZvgYqsMFHRerif0go8g==258EAFA5-E914-47DA-95CA-C5AB0DC85B11' | openssl base64
mYryklMdRrrLwrMQDeKEzOVMMWk=
同时,以下 PHP 代码会生成有效的输出:
$key = "a0+ZvgYqsMFHRerif0go8g==";
$hash = $key.'258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
$hash = sha1($hash,true);
$hash = base64_encode($hash);
echo($hash);
tswGtNOxrRhDmC04XQaDigMeaJA=
我究竟做错了什么?
答案1
这里的字符串构造<<<…
提供给定的字符串加一个换行符作为命令的输入。所以openssl sha1 -binary <<< 'a0+ZvgYqsMFHRerif0go8g==258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
相当于
printf '%s\n' 'a0+ZvgYqsMFHRerif0go8g==258EAFA5-E914-47DA-95CA-C5AB0DC85B11' | openssl sha1 -binary
但您的规范说“Concat key with 258EAFA5-E914-47DA-95CA-C5AB0DC85B11”,而不是“Concat[enate] key with 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 and a newline”。所以你需要
printf '%s' 'a0+ZvgYqsMFHRerif0go8g==258EAFA5-E914-47DA-95CA-C5AB0DC85B11' | openssl sha1 -binary
这确实产生了tswGtNOxrRhDmC04XQaDigMeaJA=
.
echo -n …
等价于printf %s …
,除了有些 shell 不支持echo -n
或扩展 中的反斜杠转义echo …
,而printf %s …
具有标准行为(始终按字面打印参数)。