LCOV - code coverage report
Current view: top level - util - sha1.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 97.8 % 90 88
Test Date: 2026-11-10 10:38:07 Functions: 100.0 % 8 8

            Line data    Source code
       1              : #ifndef THINGER_UTIL_SHA1_HPP
       2              : #define THINGER_UTIL_SHA1_HPP
       3              : 
       4              : #include <string>
       5              : #include <cstring>
       6              : #include <cstdint>
       7              : 
       8              : namespace thinger::util {
       9              : 
      10              : class sha1 {
      11              : private:
      12              :     static constexpr uint32_t K[] = {
      13              :         0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6
      14              :     };
      15              : 
      16              :     uint32_t H[5];
      17              :     unsigned char buffer[64];
      18              :     uint64_t count;
      19              :     
      20      1727488 :     static uint32_t rotate_left(uint32_t value, size_t count) {
      21      1727488 :         return (value << count) | (value >> (32 - count));
      22              :     }
      23              : 
      24         7712 :     void process_block() {
      25              :         uint32_t W[80];
      26              :         
      27              :         // Copy block to W[0..15]
      28       131104 :         for (int i = 0; i < 16; i++) {
      29       123392 :             W[i] = (buffer[i * 4] << 24) | 
      30       123392 :                    (buffer[i * 4 + 1] << 16) | 
      31       123392 :                    (buffer[i * 4 + 2] << 8) | 
      32       123392 :                    (buffer[i * 4 + 3]);
      33              :         }
      34              :         
      35              :         // Extend W[16..79]
      36       501280 :         for (int i = 16; i < 80; i++) {
      37       493568 :             W[i] = rotate_left(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
      38              :         }
      39              :         
      40         7712 :         uint32_t A = H[0];
      41         7712 :         uint32_t B = H[1];
      42         7712 :         uint32_t C = H[2];
      43         7712 :         uint32_t D = H[3];
      44         7712 :         uint32_t E = H[4];
      45              :         
      46              :         // Main loop
      47       624672 :         for (int i = 0; i < 80; i++) {
      48              :             uint32_t f, k;
      49       616960 :             if (i < 20) {
      50       154240 :                 f = (B & C) | ((~B) & D);
      51       154240 :                 k = K[0];
      52       462720 :             } else if (i < 40) {
      53       154240 :                 f = B ^ C ^ D;
      54       154240 :                 k = K[1];
      55       308480 :             } else if (i < 60) {
      56       154240 :                 f = (B & C) | (B & D) | (C & D);
      57       154240 :                 k = K[2];
      58              :             } else {
      59       154240 :                 f = B ^ C ^ D;
      60       154240 :                 k = K[3];
      61              :             }
      62              :             
      63       616960 :             uint32_t temp = rotate_left(A, 5) + f + E + k + W[i];
      64       616960 :             E = D;
      65       616960 :             D = C;
      66       616960 :             C = rotate_left(B, 30);
      67       616960 :             B = A;
      68       616960 :             A = temp;
      69              :         }
      70              :         
      71         7712 :         H[0] += A;
      72         7712 :         H[1] += B;
      73         7712 :         H[2] += C;
      74         7712 :         H[3] += D;
      75         7712 :         H[4] += E;
      76         7712 :     }
      77              : 
      78              : public:
      79         3856 :     sha1() {
      80         3856 :         reset();
      81         3856 :     }
      82              : 
      83         3856 :     void reset() {
      84         3856 :         H[0] = 0x67452301;
      85         3856 :         H[1] = 0xEFCDAB89;
      86         3856 :         H[2] = 0x98BADCFE;
      87         3856 :         H[3] = 0x10325476;
      88         3856 :         H[4] = 0xC3D2E1F0;
      89         3856 :         count = 0;
      90         3856 :         memset(buffer, 0, sizeof(buffer));
      91         3856 :     }
      92              : 
      93         3856 :     void update(const unsigned char* data, size_t len) {
      94         7712 :         while (len > 0) {
      95         3856 :             size_t buffer_pos = count % 64;
      96         3856 :             size_t to_copy = std::min(len, 64 - buffer_pos);
      97              :             
      98         3856 :             memcpy(buffer + buffer_pos, data, to_copy);
      99         3856 :             count += to_copy;
     100         3856 :             data += to_copy;
     101         3856 :             len -= to_copy;
     102              :             
     103         3856 :             if ((count % 64) == 0) {
     104            0 :                 process_block();
     105              :             }
     106              :         }
     107         3856 :     }
     108              : 
     109         3856 :     void update(const std::string& str) {
     110         3856 :         update(reinterpret_cast<const unsigned char*>(str.c_str()), str.length());
     111         3856 :     }
     112              : 
     113         3856 :     std::string finalize() {
     114              :         // Padding
     115         3856 :         size_t buffer_pos = count % 64;
     116         3856 :         buffer[buffer_pos++] = 0x80;
     117              :         
     118         3856 :         if (buffer_pos > 56) {
     119         3856 :             memset(buffer + buffer_pos, 0, 64 - buffer_pos);
     120         3856 :             process_block();
     121         3856 :             buffer_pos = 0;
     122              :         }
     123              :         
     124         3856 :         memset(buffer + buffer_pos, 0, 56 - buffer_pos);
     125              :         
     126              :         // Append length in bits
     127         3856 :         uint64_t bit_count = count * 8;
     128        34704 :         for (int i = 0; i < 8; i++) {
     129        30848 :             buffer[56 + i] = (bit_count >> ((7 - i) * 8)) & 0xFF;
     130              :         }
     131              :         
     132         3856 :         process_block();
     133              :         
     134              :         // Convert hash to string
     135         3856 :         std::string result;
     136         3856 :         result.reserve(20);
     137        23136 :         for (int i = 0; i < 5; i++) {
     138        19280 :             result += static_cast<char>((H[i] >> 24) & 0xFF);
     139        19280 :             result += static_cast<char>((H[i] >> 16) & 0xFF);
     140        19280 :             result += static_cast<char>((H[i] >> 8) & 0xFF);
     141        19280 :             result += static_cast<char>(H[i] & 0xFF);
     142              :         }
     143              :         
     144         3856 :         return result;
     145            0 :     }
     146              : 
     147         3856 :     static std::string hash(const std::string& input) {
     148         3856 :         sha1 hasher;
     149         3856 :         hasher.update(input);
     150         7712 :         return hasher.finalize();
     151              :     }
     152              : };
     153              : 
     154              : } // namespace thinger::util
     155              : 
     156              : #endif // THINGER_UTIL_SHA1_HPP
        

Generated by: LCOV version 2.0-1