Gistrec icon

Git hash generator

Gistrec | PRO | 04/22/21 10:46:11 AM UTC (Edited) | 0 ⭐ | 1163 👁️ | Never ⏰ | []
C++ |

3.65 KB

|

None

|

0 👍

/

0 👎

# Сначала нужно сохранить данные о коммите в файл:
# (printf "commit %s\0" $(git cat-file commit HEAD | wc -c); git cat-file commit HEAD) >> file.txt
#
# Дальше нужно указать с какого байта начинаем декрементить счетчик.
# Пока что это место нахожу с момощью ручек в дебаг режиме.
#include <iostream>
#include <fstream>
#include <cassert>
#include <vector>
 
#include <openssl/sha.h>
#include <iomanip>
#include <algorithm>
#include <cmath>
 
#include <chrono>
 
 
std::vector<unsigned char> read(const std::string & path) {
    std::ifstream input(path, std::ios::binary);
    assert(input.is_open());
 
    std::vector<unsigned char> result;
    while (!input.eof())
    {
        const auto ch = input.get();
        result.push_back(ch);
    }
    assert(result.size() > 1);
    result.pop_back();
 
    return result;
}
 
template <class ContainerT>
void update(ContainerT & buffer, size_t position) {
    if (buffer[position] < u'0')
    {
        buffer[position] = u'9';
        // Уменьшаем предыдищуй разряд и обновляем его
        buffer[position - 1] -= 1;
        update(buffer, position - 1);
    }
}
 
template <class ContainerT>
void decrease(ContainerT & buffer, size_t position) {
    buffer[position] -= 1;
    update(buffer, position);
}
 
template <class ContainerT>
std::string to_string(const ContainerT & buffer) {
    std::stringstream result;
    result << std::hex << std::setfill('0');
    for (const auto byte : buffer)
    {
        result << std::setw(2) << (int)byte;
    }
    return result.str();
}
 
template <class ContainerT>
ContainerT from_string(const std::string & string) {
    ContainerT result;
    for (auto i = 0U; i < string.size(); i += 2) {
        //! Note: С unsigned char не работает.
        unsigned int buffer;
 
        std::istringstream iss(string.substr(i, 2));
        iss >> std::hex >> buffer;
 
        result.push_back(buffer);
    }
    return result;
}
 
int main() {
    using ContainerT = std::vector<unsigned char>;
    ContainerT target = from_string<ContainerT>("aaaaaa");
    ContainerT buffer = read("/home/alex/CLionProjects/git-hash/file.txt");
    ContainerT result(SHA_DIGEST_LENGTH);
 
    size_t iterations = 0;
 
    const auto time_start = std::chrono::high_resolution_clock::now();
 
    while (!std::equal(target.begin(), target.end(), result.begin())) {
        iterations++;
 
        decrease(buffer, 99);
 
        SHA1(buffer.data(), buffer.size(), result.data());
 
        if (iterations % (2 << 17) == 0)
        {
            const auto ratio = static_cast<double>(iterations) / std::pow(16, target.size() * 2);
 
            const auto time_now = std::chrono::high_resolution_clock::now();
            const auto elapsed_in_sec = std::chrono::duration_cast<std::chrono::seconds>(time_now - time_start).count();
 
            const auto estimated = elapsed_in_sec / ratio;
 
            std::cout << std::dec << "[" << iterations << "] Compute " << round(ratio * 10000) / 100 << "%, ";
            std::cout << "Elapsed " << elapsed_in_sec << " sec, Estimated " << std::round(estimated) << " sec." << std::endl;
        }
    }
    const auto ratio = static_cast<double>(iterations) / std::pow(16, target.size() * 2);
 
    const auto time_now = std::chrono::high_resolution_clock::now();
    const auto elapsed_in_sec = std::chrono::duration_cast<std::chrono::seconds>(time_now - time_start).count();
 
    std::cout << std::dec << "[" << iterations << "] Compute " << ratio * 100 << "%, ";
    std::cout << "Elapsed " << elapsed_in_sec << " sec." << std::endl;
    std::cout << "Result hash: " << to_string(result) << std::endl;
 
    for (const auto symbol : buffer) {
        std::cout << symbol;
    }
    std::cout << std::endl;
 
    return 0;
}
 

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎