1 #ifndef UTIL_HASH_HASH_H
2 #define UTIL_HASH_HASH_H
20 bool endsWith(
const std::string& str,
const std::string& suffix) {
21 if (str.size() < suffix.size())
return false;
22 return std::equal(suffix.rbegin(), suffix.rend(), str.rbegin());
27 std::ifstream file(filePath);
29 std::cerr <<
"Cannot open file: " << filePath << std::endl;
33 std::ostringstream preprocessed;
35 bool inBlockComment =
false;
37 while (std::getline(file, line)) {
40 size_t endBlock = line.find(
"*/");
41 if (endBlock != std::string::npos) {
42 line = line.substr(endBlock + 2);
43 inBlockComment =
false;
50 size_t lineComment = line.find(
"//");
51 if (lineComment != std::string::npos) {
52 line = line.substr(0, lineComment);
56 size_t startBlock = line.find(
"/*");
57 if (startBlock != std::string::npos) {
58 size_t endBlock = line.find(
"*/", startBlock + 2);
59 if (endBlock != std::string::npos) {
60 line.erase(startBlock, endBlock - startBlock + 2);
62 line.erase(startBlock);
63 inBlockComment =
true;
68 std::regex extraSpace(
"\\s+");
69 line = std::regex_replace(line, extraSpace,
" ");
73 preprocessed << line <<
"\n";
77 return preprocessed.str();
85 void update(
const uint8_t* data,
size_t length) {
86 for (
size_t i = 0; i < length; ++i) {
96 void update(
const std::string& data) {
97 update(
reinterpret_cast<const uint8_t*
>(data.c_str()), data.size());
100 std::string
final() {
106 std::ostringstream result;
107 for (
int i = 0; i < 32; ++i) {
108 result << std::hex << std::setw(2) << std::setfill(
'0') << (int)
hash[i];
117 state_ = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
118 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
127 const std::array<uint32_t, 64>
k_ = {
128 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
129 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01,
130 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
131 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
132 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152,
133 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
134 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
135 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
136 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
137 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08,
138 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f,
139 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
140 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
143 static void toBytes(uint8_t* output,
const std::array<uint32_t, 8>& input,
size_t size) {
144 for (
size_t i = 0; i < size; ++i) {
145 output[i * 4 + 0] = (input[i] >> 24) & 0xff;
146 output[i * 4 + 1] = (input[i] >> 16) & 0xff;
147 output[i * 4 + 2] = (input[i] >> 8) & 0xff;
148 output[i * 4 + 3] = (input[i] >> 0) & 0xff;
152 static uint32_t
rotr(uint32_t x, uint32_t n) {
153 return (x >> n) | (x << (32 - n));
156 static uint32_t
choose(uint32_t e, uint32_t f, uint32_t g) {
157 return (e & f) ^ (~e & g);
160 static uint32_t
majority(uint32_t a, uint32_t b, uint32_t c) {
161 return (a & b) ^ (a & c) ^ (b & c);
164 static uint32_t
sig0(uint32_t x) {
165 return rotr(x, 7) ^
rotr(x, 18) ^ (x >> 3);
168 static uint32_t
sig1(uint32_t x) {
169 return rotr(x, 17) ^
rotr(x, 19) ^ (x >> 10);
173 std::array<uint32_t, 64> m;
174 std::array<uint32_t, 8> v =
state_;
176 for (
size_t i = 0, j = 0; i < 16; ++i, j += 4) {
180 for (
size_t i = 16; i < 64; ++i) {
181 m[i] =
sig1(m[i - 2]) + m[i - 7] +
sig0(m[i - 15]) + m[i - 16];
184 for (
size_t i = 0; i < 64; ++i) {
185 uint32_t temp1 = v[7] +
choose(v[4], v[5], v[6]) +
rotr(v[4], 6) +
k_[i] + m[i];
186 uint32_t temp2 =
majority(v[0], v[1], v[2]) +
rotr(v[0], 2);
194 v[0] = temp1 + temp2;
197 for (
size_t i = 0; i < 8; ++i) {
216 std::fill(std::begin(
data_), std::end(
data_), 0);
234 if (preprocessed.empty()) {
239 sha256.
update(preprocessed);
240 return sha256.
final();
244 void processDirectory(
const std::string& directory, std::vector<std::string>& sortedFiles) {
245 for (
const auto& entry : std::filesystem::recursive_directory_iterator(directory)) {
246 if (entry.is_regular_file()) {
247 std::string filePath = entry.path().string();
249 sortedFiles.push_back(filePath);
255 std::sort(sortedFiles.begin(), sortedFiles.end());
259 std::vector<std::string> sortedFiles;
261 std::cout <<
"Scanning directory: " << srcDirectory << std::endl;
266 for (
const auto& filePath : sortedFiles) {
267 std::cout <<
"Processing file: " << filePath << std::endl;
272 std::cout <<
"\nFinal Hash (SHA256 of all preprocessed content): " << sha256.
final() << std::endl;