116 lines
4.0 KiB
C++
116 lines
4.0 KiB
C++
/**
|
|
* @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 <string.h>
|
|
|
|
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<uint64>(len) * 8u;
|
|
for (int i = 7; i >= 0; i--) {
|
|
msg[56 + i] = static_cast<uint8>(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<uint64>(len) * 8u;
|
|
for (int i = 7; i >= 0; i--) {
|
|
msg[120 + i] = static_cast<uint8>(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<uint32>(b[i*4u + 0u]) << 24u) |
|
|
(static_cast<uint32>(b[i*4u + 1u]) << 16u) |
|
|
(static_cast<uint32>(b[i*4u + 2u]) << 8u) |
|
|
(static_cast<uint32>(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<uint8>(h0 >> 24u); digest[ 1] = static_cast<uint8>(h0 >> 16u);
|
|
digest[ 2] = static_cast<uint8>(h0 >> 8u); digest[ 3] = static_cast<uint8>(h0);
|
|
digest[ 4] = static_cast<uint8>(h1 >> 24u); digest[ 5] = static_cast<uint8>(h1 >> 16u);
|
|
digest[ 6] = static_cast<uint8>(h1 >> 8u); digest[ 7] = static_cast<uint8>(h1);
|
|
digest[ 8] = static_cast<uint8>(h2 >> 24u); digest[ 9] = static_cast<uint8>(h2 >> 16u);
|
|
digest[10] = static_cast<uint8>(h2 >> 8u); digest[11] = static_cast<uint8>(h2);
|
|
digest[12] = static_cast<uint8>(h3 >> 24u); digest[13] = static_cast<uint8>(h3 >> 16u);
|
|
digest[14] = static_cast<uint8>(h3 >> 8u); digest[15] = static_cast<uint8>(h3);
|
|
digest[16] = static_cast<uint8>(h4 >> 24u); digest[17] = static_cast<uint8>(h4 >> 16u);
|
|
digest[18] = static_cast<uint8>(h4 >> 8u); digest[19] = static_cast<uint8>(h4);
|
|
}
|
|
|
|
} /* namespace StreamHub */
|
|
|
|
#endif /* STREAMHUB_SHA1_H_ */
|