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

Generated by: LCOV version 2.0-1