使用 libtomcrypt 计算 websocket Sec-WebSocket-Accept 值

标签 c websocket sha1 libtomcrypt

RFC6455 指定了根据 Sec-WebSocket-Key header 的值计算 Sec-WebSocket-Accept 响应 header 的方法。此方法基于 SHA-1 散列并对结果进行 Base64 编码。

如何使用 libtomcrypt 在纯 C 中实现此方法对于 SHA-1 和 Base64?

注意:这个问题故意不表现出任何努力,因为我自己立即回答了它。请参阅下面我的努力。

最佳答案

这是一个完整的可编译示例,仅使用 libtomcrypt,无需任何动态内存分配,并成功计算 RFC6455 中的引用示例:

//This file is licensed under CC0 1.0 Universal (public domain)
//Compile like this: gcc -o wsencodetest wsencodetest.c -ltomcrypt
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <ctype.h>
#include <tomcrypt.h>

#define SHA1_HASHSIZE 20

//Magic GUID as defined in RFC6455 section 1.3
static const char magicGUID[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

/**
 * Compute the value of the Sec-WebSocket-Accept response header
 * from the value of the Sec-WebSocket-Key header.
 * @param key The whitespace or NUL terminated Sec-WebSocket-Key value
 * @param out Where to store the base64-encoded output. Must provide 29 bytes of memory.
 * The 29 bytes starting at out contain the resulting value (plus a terminating NUL byte)
 */
void computeWebsocketSecAccept(const char* key, char* dst) {
    /**
     * Determine start & length of key minus leading/trailing whitespace
     * See RFC6455 section 1.3
     */
    //Skip leading whitespace
    while(isspace(*key)) {
        key++;
    }
    //Determine key size.
    size_t keySize = 0;
    while(!isspace(key[keySize]) && key[keySize] != 0) {
        keySize++;
    }
    //Compute SHA1 hash. See RFC6455 section 1.3
    char hashOut[SHA1_HASHSIZE];
    hash_state md;

    sha1_desc.init(&md);
    sha1_desc.process(&md, key, keySize);
    sha1_desc.process(&md, magicGUID, sizeof(magicGUID));
    sha1_desc.done(&md, hashOut);
    //Encode hash to output buffer
    size_t outlen = 29; //We know the output is 28 in size
    base64_encode(hashOut, SHA1_HASHSIZE, dst, &outlen);
}

/**
 * Usage example
 */
int main(int argc, char** argv) {
    //Whitespace needs to be removed according to RFC6455
    //Example from RFC6455
    const char* key = " dGhlIHNhbXBsZSBub25jZQ== ";
    char buf[29];
    //Perform computation
    computeWebsocketSecAccept(key, buf);
    //Should print s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
    printf("%s\n", buf);
}

关于使用 libtomcrypt 计算 websocket Sec-WebSocket-Accept 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29311791/

相关文章:

c - 在C中,数组中可以有字符串吗?如果没有,有没有解决方法

c - 输入无效用户时 getpwnam() 使程序崩溃

c - 迭代时内核哈希表崩溃

javascript - Websocket 的正确方法

javascript - 具有共享 session 和用户身份验证的 WebSockets 和 HTTP 安全性

Spring WebSocket超时设置

android - Google App Engine 教程,无法获取签名证书指纹(SHA1)

MySQL哈希列密码+脚本bash

C - atmega328p - 我不明白出了什么问题

c - RFC 3174 (SHA-1) 中指定的十六进制数的含义