/** * @file SHA1.h * @brief Inline SHA-1 implementation (public domain). * * Used exclusively for the WebSocket HTTP upgrade handshake * (Sec-WebSocket-Accept computation per RFC 6455). * No external dependencies. */ #ifndef STREAMHUB_SHA1_H_ #define STREAMHUB_SHA1_H_ #include "CompilerTypes.h" #include namespace StreamHub { using MARTe::uint8; using MARTe::uint32; using MARTe::uint64; /** * @brief Compute SHA-1 hash of @p data (len bytes) into @p digest (20 bytes). */ inline void SHA1(const uint8 *data, uint32 len, uint8 digest[20]) { uint32 h0 = 0x67452301u; uint32 h1 = 0xEFCDAB89u; uint32 h2 = 0x98BADCFEu; uint32 h3 = 0x10325476u; uint32 h4 = 0xC3D2E1F0u; /* ---- pre-process: append bit '1', zeros, 64-bit BE length ----------- */ uint8 msg[128]; memset(msg, 0, sizeof(msg)); uint32 msgLen = len; if (len < 56u) { memcpy(msg, data, len); msg[len] = 0x80u; /* 8-byte big-endian bit count at bytes 56-63 */ uint64 bitLen = static_cast(len) * 8u; for (int i = 7; i >= 0; i--) { msg[56 + i] = static_cast(bitLen & 0xFFu); bitLen >>= 8; } msgLen = 64u; } else { /* two-block path for inputs up to 55+64=119 bytes — sufficient for WS keys */ memcpy(msg, data, len); msg[len] = 0x80u; uint64 bitLen = static_cast(len) * 8u; for (int i = 7; i >= 0; i--) { msg[120 + i] = static_cast(bitLen & 0xFFu); bitLen >>= 8; } msgLen = 128u; } /* ---- process each 64-byte block -------------------------------------- */ for (uint32 blk = 0u; blk < msgLen; blk += 64u) { uint32 w[80]; const uint8 *b = msg + blk; uint32 i; for (i = 0u; i < 16u; i++) { w[i] = (static_cast(b[i*4u + 0u]) << 24u) | (static_cast(b[i*4u + 1u]) << 16u) | (static_cast(b[i*4u + 2u]) << 8u) | (static_cast(b[i*4u + 3u])); } for (i = 16u; i < 80u; i++) { uint32 v = w[i-3u] ^ w[i-8u] ^ w[i-14u] ^ w[i-16u]; w[i] = (v << 1u) | (v >> 31u); } uint32 a = h0, bv = h1, c = h2, d = h3, e = h4; for (i = 0u; i < 80u; i++) { uint32 f, k; if (i < 20u) { f = (bv & c) | ((~bv) & d); k = 0x5A827999u; } else if (i < 40u) { f = bv ^ c ^ d; k = 0x6ED9EBA1u; } else if (i < 60u) { f = (bv & c) | (bv & d) | (c & d); k = 0x8F1BBCDCu; } else { f = bv ^ c ^ d; k = 0xCA62C1D6u; } uint32 tmp = ((a << 5u) | (a >> 27u)) + f + e + k + w[i]; e = d; d = c; c = (bv << 30u) | (bv >> 2u); bv = a; a = tmp; } h0 += a; h1 += bv; h2 += c; h3 += d; h4 += e; } /* ---- produce big-endian digest --------------------------------------- */ digest[ 0] = static_cast(h0 >> 24u); digest[ 1] = static_cast(h0 >> 16u); digest[ 2] = static_cast(h0 >> 8u); digest[ 3] = static_cast(h0); digest[ 4] = static_cast(h1 >> 24u); digest[ 5] = static_cast(h1 >> 16u); digest[ 6] = static_cast(h1 >> 8u); digest[ 7] = static_cast(h1); digest[ 8] = static_cast(h2 >> 24u); digest[ 9] = static_cast(h2 >> 16u); digest[10] = static_cast(h2 >> 8u); digest[11] = static_cast(h2); digest[12] = static_cast(h3 >> 24u); digest[13] = static_cast(h3 >> 16u); digest[14] = static_cast(h3 >> 8u); digest[15] = static_cast(h3); digest[16] = static_cast(h4 >> 24u); digest[17] = static_cast(h4 >> 16u); digest[18] = static_cast(h4 >> 8u); digest[19] = static_cast(h4); } } /* namespace StreamHub */ #endif /* STREAMHUB_SHA1_H_ */