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=