根据Sec-WebSocket-Key计算Sec-WebSocket-Accept

cpp 复制代码
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>

#pragma warning(disable:4996)

#define GET_UINT32_BE(n,b,i)                            \
{                                                       \
    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
        | ( (uint32_t) (b)[(i) + 3]       );            \
}

#define PUT_UINT32_BE(n,b,i)                            \
{                                                       \
    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
}

#define BASE64_SIZE_T_MAX   ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
#define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL               -0x002A  /**< Output buffer too small. */

typedef struct {
    uint32_t total[2];          /*!< The number of Bytes processed.  */
    uint32_t state[5];          /*!< The intermediate digest state.  */
    unsigned char buffer[64];   /*!< The data block being processed. */
} tagSHA1_context_t;

tagSHA1_context_t sha1_ctx;

unsigned char Con_secWsKey[60];
//unsigned char SecWsKey[24] = "kMgvb6KivsYVl2EHinJHZg==";
unsigned char SecWsKey[32] = "dGhlIHNhbXBsZSBub25jZQ==";
unsigned char Output[32];
unsigned char SecWsAccept[32];
int realLen;

void ws_concat(unsigned char *con_sec_ws_key, unsigned char *sec_ws_key)
{
    const unsigned char salt[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
    strcpy((char *)con_sec_ws_key, (char *)sec_ws_key);
    strcpy((char *)con_sec_ws_key + 24, (char *)salt);
}

void sha1_init(void)
{
    memset((void *)&sha1_ctx, 0, sizeof(sha1_ctx));
}

void sha1_start(void)
{
    sha1_ctx.total[0] = 0;
    sha1_ctx.total[1] = 0;
    sha1_ctx.state[0] = 0x67452301;
    sha1_ctx.state[1] = 0xEFCDAB89;
    sha1_ctx.state[2] = 0x98BADCFE;
    sha1_ctx.state[3] = 0x10325476;
    sha1_ctx.state[4] = 0xC3D2E1F0;
}

int sha1_process(tagSHA1_context_t *ctx, unsigned char data[64])
{
    uint32_t temp, W[16], A, B, C, D, E;

    assert(ctx != NULL);
    assert((unsigned char*)data != NULL);

    GET_UINT32_BE(W[0], data, 0);
    GET_UINT32_BE(W[1], data, 4);
    GET_UINT32_BE(W[2], data, 8);
    GET_UINT32_BE(W[3], data, 12);
    GET_UINT32_BE(W[4], data, 16);
    GET_UINT32_BE(W[5], data, 20);
    GET_UINT32_BE(W[6], data, 24);
    GET_UINT32_BE(W[7], data, 28);
    GET_UINT32_BE(W[8], data, 32);
    GET_UINT32_BE(W[9], data, 36);
    GET_UINT32_BE(W[10], data, 40);
    GET_UINT32_BE(W[11], data, 44);
    GET_UINT32_BE(W[12], data, 48);
    GET_UINT32_BE(W[13], data, 52);
    GET_UINT32_BE(W[14], data, 56);
    GET_UINT32_BE(W[15], data, 60);

#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))

#define R(t)                                                    \
    (                                                           \
        temp = W[( (t) -  3 ) & 0x0F] ^ W[( (t) - 8 ) & 0x0F] ^ \
               W[( (t) - 14 ) & 0x0F] ^ W[  (t)       & 0x0F],  \
        ( W[(t) & 0x0F] = S(temp,1) )                           \
    )

#define P(a,b,c,d,e,x)                                          \
    do                                                          \
    {                                                           \
        (e) += S((a),5) + F((b),(c),(d)) + K + (x);             \
        (b) = S((b),30);                                        \
    } while( 0 )

    A = ctx->state[0];
    B = ctx->state[1];
    C = ctx->state[2];
    D = ctx->state[3];
    E = ctx->state[4];

#define F(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
#define K 0x5A827999

    P(A, B, C, D, E, W[0]);
    P(E, A, B, C, D, W[1]);
    P(D, E, A, B, C, W[2]);
    P(C, D, E, A, B, W[3]);
    P(B, C, D, E, A, W[4]);
    P(A, B, C, D, E, W[5]);
    P(E, A, B, C, D, W[6]);
    P(D, E, A, B, C, W[7]);
    P(C, D, E, A, B, W[8]);
    P(B, C, D, E, A, W[9]);
    P(A, B, C, D, E, W[10]);
    P(E, A, B, C, D, W[11]);
    P(D, E, A, B, C, W[12]);
    P(C, D, E, A, B, W[13]);
    P(B, C, D, E, A, W[14]);
    P(A, B, C, D, E, W[15]);
    P(E, A, B, C, D, R(16));
    P(D, E, A, B, C, R(17));
    P(C, D, E, A, B, R(18));
    P(B, C, D, E, A, R(19));

#undef K
#undef F

#define F(x,y,z) ((x) ^ (y) ^ (z))
#define K 0x6ED9EBA1

    P(A, B, C, D, E, R(20));
    P(E, A, B, C, D, R(21));
    P(D, E, A, B, C, R(22));
    P(C, D, E, A, B, R(23));
    P(B, C, D, E, A, R(24));
    P(A, B, C, D, E, R(25));
    P(E, A, B, C, D, R(26));
    P(D, E, A, B, C, R(27));
    P(C, D, E, A, B, R(28));
    P(B, C, D, E, A, R(29));
    P(A, B, C, D, E, R(30));
    P(E, A, B, C, D, R(31));
    P(D, E, A, B, C, R(32));
    P(C, D, E, A, B, R(33));
    P(B, C, D, E, A, R(34));
    P(A, B, C, D, E, R(35));
    P(E, A, B, C, D, R(36));
    P(D, E, A, B, C, R(37));
    P(C, D, E, A, B, R(38));
    P(B, C, D, E, A, R(39));

#undef K
#undef F

#define F(x,y,z) (((x) & (y)) | ((z) & ((x) | (y))))
#define K 0x8F1BBCDC

    P(A, B, C, D, E, R(40));
    P(E, A, B, C, D, R(41));
    P(D, E, A, B, C, R(42));
    P(C, D, E, A, B, R(43));
    P(B, C, D, E, A, R(44));
    P(A, B, C, D, E, R(45));
    P(E, A, B, C, D, R(46));
    P(D, E, A, B, C, R(47));
    P(C, D, E, A, B, R(48));
    P(B, C, D, E, A, R(49));
    P(A, B, C, D, E, R(50));
    P(E, A, B, C, D, R(51));
    P(D, E, A, B, C, R(52));
    P(C, D, E, A, B, R(53));
    P(B, C, D, E, A, R(54));
    P(A, B, C, D, E, R(55));
    P(E, A, B, C, D, R(56));
    P(D, E, A, B, C, R(57));
    P(C, D, E, A, B, R(58));
    P(B, C, D, E, A, R(59));

#undef K
#undef F

#define F(x,y,z) ((x) ^ (y) ^ (z))
#define K 0xCA62C1D6

    P(A, B, C, D, E, R(60));
    P(E, A, B, C, D, R(61));
    P(D, E, A, B, C, R(62));
    P(C, D, E, A, B, R(63));
    P(B, C, D, E, A, R(64));
    P(A, B, C, D, E, R(65));
    P(E, A, B, C, D, R(66));
    P(D, E, A, B, C, R(67));
    P(C, D, E, A, B, R(68));
    P(B, C, D, E, A, R(69));
    P(A, B, C, D, E, R(70));
    P(E, A, B, C, D, R(71));
    P(D, E, A, B, C, R(72));
    P(C, D, E, A, B, R(73));
    P(B, C, D, E, A, R(74));
    P(A, B, C, D, E, R(75));
    P(E, A, B, C, D, R(76));
    P(D, E, A, B, C, R(77));
    P(C, D, E, A, B, R(78));
    P(B, C, D, E, A, R(79));

#undef K
#undef F

    ctx->state[0] += A;
    ctx->state[1] += B;
    ctx->state[2] += C;
    ctx->state[3] += D;
    ctx->state[4] += E;

    return(0);
}


int sha1_update(tagSHA1_context_t *ctx, unsigned char *input, size_t ilen)
{
    int ret;
    size_t fill = 0;
    uint32_t left = 0;

    assert(ctx != NULL);
    assert(ilen == 0 || input != NULL);

    if (ilen == 0) {
        return 0;
    }

    left = ctx->total[0] & 0x3F;
    fill = 64 - left;

    ctx->total[0] += (uint32_t)ilen;
    ctx->total[0] &= 0xFFFFFFFF;

    if (ctx->total[0] < (uint32_t)ilen) {
        ctx->total[1]++;
    }

    if (left && ilen >= fill) {
        memcpy((void*)(ctx->buffer + left), input, fill);

        if ((ret = sha1_process(ctx, ctx->buffer)) != 0) {
            return ret;
        }

        input += fill;
        ilen -= fill;
        left = 0;
    }

    while (ilen >= 64) {
        if ((ret = sha1_process(ctx, input)) != 0) {
            return ret;
        }
        input += 64;
        ilen -= 64;
    }

    if (ilen > 0) {
        memcpy((void*)(ctx->buffer + left), input, ilen);
    }

    return 0;
}

int sha1_finish(tagSHA1_context_t* ctx, unsigned char output[20])
{
    int ret = 0;
    uint32_t used = 0;
    uint32_t high = 0;
    uint32_t low = 0;

    assert(ctx != NULL);
    assert((unsigned char*)output != NULL);

    used = ctx->total[0] & 0x3F;

    ctx->buffer[used++] = 0x80;

    if (used <= 56) {
        /* Enough room for padding + length in current block */
        memset(ctx->buffer + used, 0, 56 - used);
    } else {
        /* We'll need an extra block */
        memset(ctx->buffer + used, 0, 64 - used);

        if ((ret = sha1_process(ctx, ctx->buffer)) != 0) {
            return ret;
        }

        memset(ctx->buffer, 0, 56);
    }

    /*
     * Add message length
     */
    high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
    low  = (ctx->total[0] << 3 );

    PUT_UINT32_BE(high, ctx->buffer, 56);
    PUT_UINT32_BE(low, ctx->buffer, 60);

    if ((ret = sha1_process(ctx, ctx->buffer)) != 0) {
        return ret;
    }

    /*
     * Output final state
     */
    PUT_UINT32_BE(ctx->state[0], output, 0);
    PUT_UINT32_BE(ctx->state[1], output, 4);
    PUT_UINT32_BE(ctx->state[2], output, 8);
    PUT_UINT32_BE(ctx->state[3], output, 12);
    PUT_UINT32_BE(ctx->state[4], output, 16);

    return 0;
}

void sha1_free(void)
{
    memset(&sha1_ctx, 0, sizeof(sha1_ctx));
}

const unsigned char base64_enc_map[64] =
{
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
    'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
    'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
    'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
    'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
    'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
    '8', '9', '+', '/'
};

int base64_encode(unsigned char *dst, size_t dlen, size_t *olen, unsigned char *src, size_t slen)
{
    size_t i = 0;
    size_t n = 0;
    int C1 = 0;
    int C2 = 0;
    int C3 = 0;
    unsigned char *p = NULL;

    if (slen == 0) {
        *olen = 0;
        return(0);
    }

    n = slen / 3 + (slen % 3 != 0);

    if (n > (BASE64_SIZE_T_MAX - 1) / 4) {
        *olen = BASE64_SIZE_T_MAX;
        return(MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL);
    }

    n *= 4;

    if ((dlen < n + 1) || (NULL == dst)) {
        *olen = n + 1;
        return(MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL);
    }

    n = (slen / 3) * 3;

    for (i = 0, p = dst; i < n; i += 3) {
        C1 = *src++;
        C2 = *src++;
        C3 = *src++;

        *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
        *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
        *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
        *p++ = base64_enc_map[C3 & 0x3F];
    }

    if (i < slen) {
        C1 = *src++;
        C2 = ((i + 1) < slen) ? *src++ : 0;

        *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
        *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];

        if ((i + 1) < slen)
            *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
        else *p++ = '=';

        *p++ = '=';
    }

    *olen = p - dst;
    *p = 0;

    return 0;
}

void calc_sha1(void)
{
    sha1_init();
    sha1_start();
    sha1_update(&sha1_ctx, Con_secWsKey, 60);
    sha1_finish(&sha1_ctx, Output);         // Output: c417b4a47e13bfbd5f68d7cfc5a30c9644abb895
#if 1
    printf("Output:");
    for (uint8_t i = 0; i < 20; i++) {
        printf("%02x", Output[i]);
    }
    printf("\n");
#endif
    sha1_free();
    base64_encode(SecWsAccept, sizeof(SecWsAccept), &realLen, Output, 20);
#if 1
    printf("realLen: %d\n", realLen);
#endif
}
int main(void)
{
    ws_concat(Con_secWsKey, SecWsKey);
#if 1
    puts(Con_secWsKey);
#endif
    calc_sha1();
    puts(SecWsAccept);

    return 0;
}

运行结果:

dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11

Output:b37a4f2cc0624f1690f64606cf385945b2bec4ea

realLen: 28
s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

相关推荐
Kaede62 小时前
深入探索 WebSocket:构建实时应用的核心技术
网络·websocket·网络协议
if时光重来2 小时前
springboot项目使用websocket功能,使用了nginx反向代理后连接失败问题解决
spring boot·websocket·nginx
网络安全大学堂3 小时前
【网络安全入门基础教程】网络安全零基础学习方向及需要掌握的技能
网络·学习·安全·web安全·网络安全·黑客
wanhengidc3 小时前
云手机将要面临的挑战有哪些?
运维·网络·安全·游戏·智能手机
岚天start3 小时前
网络计算工具ipcalc详解
linux·运维·网络·网关·广播地址·掩码·ipcalc
三毛20046 小时前
玳瑁的嵌入式日记D33-0904(协议头)
网络
乘乘凉6 小时前
简陋的RPC
服务器·网络·rpc
大有数据可视化6 小时前
安全与效率兼得:工业控制系统如何借力数字孪生实现双赢?
网络·数字孪生·工业空盒子
Linux运维技术栈6 小时前
Cloudflare安全规则实用指南:从路径拦截到IP限制的10个经典范例
网络·tcp/ip·安全