Websocket 密钥散列

Posted

技术标签:

【中文标题】Websocket 密钥散列【英文标题】:Websocket key hashing 【发布时间】:2016-04-04 18:30:38 【问题描述】:

我有一个简单的函数来处理 C websocket 程序中 Sec-WebSocket-Key 值的解析和散列。我让整个程序正常工作,但发现我有一堆 char* 没有指向的静态位置。正如您可能已经猜到的那样,这会导致一些内存问题并且需要修复。为了解决这个问题,我制作了大小为 100 的 char 并将 char* 指向它们。现在我从函数中返回的值不正确。有人可以告诉我我做错了什么。据我了解,这应该有效。仅供参考,我是自学成才的,但我对 C 的理解仍然存在巨大差距。

char* sock_handle_hash(struct sock_data *sockdat, int dataCount)  
    char EncodeHashbuff[100];
    char key1buff[100];
    char key2buff[100];
    char key3buff[100];
    char *EncodeHash = EncodeHashbuff;
    char *key1 = key1buff;
    char *key2 = key2buff;
    char *key3 = key3buff;


    unsigned char hash[SHA_DIGEST_LENGTH]; // this sets the length to the predefigned length in the SHA standard
    char *testKey = "Sec-WebSocket-Key"; // this is the key for the key value pair of the hash
    char *additionalHashData = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; // the magic string used in websockets
    sockdat->buffer[dataCount] = '\0'; // null terminate the buffer
    key1 = strtok(sockdat->buffer, "\n"); // brake up the data by new lines
    key1 = strtok(NULL, "\n"); // skip the first line
    while (key2 != NULL)  //find the key to hash
        key2 = strtok(NULL, ":"); //brake data into the key value pairs
        key3 = strtok(NULL, "\n"); // go to next line
        if(strcmp(key2, testKey) == 0)  // if the correct key
            if( key3[(strlen(key3)-1)] =='\r')
                key3[(strlen(key3)-1)]='\0';
            
            key3++;
            char key4[200];
            strcpy(key4, key3); // copy the string to the final key
            strcat(key4, additionalHashData); // concat the magic websocket hash string
            SHA1(key4, strlen(key4), hash); //Hash SHA1 to the correct reply value
            EncodeHash = apssock_base64(hash, sizeof hash); // base 64 encode the value
            break; //Stop looping 
                           
       

    return EncodeHash; //success retrun the hashed value for the handshake

【问题讨论】:

什么是“大小为 100 的字符”?你的意思是char [100],即。 char 的数组?并查看How to Ask。 return EncodeHash; 也可以是return EncodeHashbuff;,它返回函数范围内即将到期的自动变量的地址。因此,当调用者使用返回的地址时,未定义的行为。 Read this answer仔细。 仅供参考,除非 EncodeHash = apssock_base64(hash, sizeof hash); 动态分配生成的 base64 编码,我们从发布的代码中不知道,否则该代码路径同样会遭受类似的命运。如果它执行 dyna-alloc,它可能工作(至少它不会调用上面提到的 UB)。 谢谢 WhozCraig。这是一个非常有用的链接。仍然在解决这个问题。 【参考方案1】:

正如 WhozCraig 所说,我指的是无法保证存在的东西。为了解决这个问题,我在该行中添加了一个静态:

static char EncodeHashbuff[100];

【讨论】:

仅供参考:此解决方案不是线程安全的,因为内存将在线程之间共享。如果您的服务器是多线程的,这将失败。考虑更改函数的原型以接受要写入的缓冲区(这样,调用函数可以在堆栈上正常创建char 数组)。即char* sock_handle_hash(struct sock_data *sockdat, int dataCount, char * EncodeHash) 有趣。您能否提供有关该主题的更多信息的良好链接?谢谢。 有一些关于静态变量和线程安全的解释here 和here。至于将数据写入现有的char缓冲区,您可以看到一些答案herehere或here。

以上是关于Websocket 密钥散列的主要内容,如果未能解决你的问题,请参考以下文章

C++ WebSocket 服务器实现(接受密钥不匹配)

使用 IAM API 密钥的 IBM Watson 语音转文本 WebSocket 授权

C# .NET Core websocket ssl 问题 - dh 密钥太小

HTML 5 -- C# Websocket 响应

Websockets - Sec-WebSocket-Accept 不匹配

客户端与服务器端使用webSocket进行交互,使用json解析数据