Repository navigation
Expand file tree
/
Copy pathhash.cpp
More file actions
115 lines (73 loc) · 2.29 KB
/
Copy pathhash.cpp
File metadata and controls
115 lines (73 loc) · 2.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include "hash.h"
#include <Windows.h>
#include <bcrypt.h>
#include <array>
#include <fstream>
#include <iomanip>
#include <sstream>
#include <stdexcept>
#include <vector>
#pragma comment (lib, "bcrypt.lib")
namespace HashGuard
{
std::string CalculateSHA256(const std::filesystem::path& filePath)
{
BCRYPT_ALG_HANDLE algorithm = nullptr;
BCRYPT_HASH_HANDLE hash = nullptr;
auto cleanup = [&]()
{
if (hash)
BCryptDestroyHash(hash);
if (algorithm)
BCryptCloseAlgorithmProvider(algorithm, 0);
};
try
{
std::ifstream file(filePath, std::ios::binary);
if (!file)
throw std::runtime_error("cannot open file");
NTSTATUS status = BCryptOpenAlgorithmProvider(&algorithm, BCRYPT_SHA256_ALGORITHM, nullptr, 0);
if (!BCRYPT_SUCCESS(status))
throw std::runtime_error("cannot initialize SHA-256");
DWORD hashLength = 0;
DWORD resultLength = 0;
status = BCryptGetProperty(algorithm, BCRYPT_HASH_LENGTH, reinterpret_cast<PUCHAR>(&hashLength), sizeof(hashLength), &resultLength, 0);
if (!BCRYPT_SUCCESS(status))
throw std::runtime_error("cannot get hash length");
status = BCryptCreateHash(algorithm, &hash, nullptr, 0, nullptr, 0, 0);
if (!BCRYPT_SUCCESS(status))
throw std::runtime_error("cannot create hash");
std::array<char, 65536> buffer{};
while (file)
{
file.read(buffer.data(), buffer.size());
std::streamsize bytesRead = file.gcount();
if (bytesRead > 0)
{
status = BCryptHashData(hash, reinterpret_cast<PUCHAR>(buffer.data()), static_cast<ULONG>(bytesRead), 0);
if (!BCRYPT_SUCCESS(status))
throw std::runtime_error("hashing failed");
}
}
if (file.bad())
throw std::runtime_error("file read failed");
std::vector<UCHAR> hashBytes(hashLength);
status = BCryptFinishHash(hash, hashBytes.data(), hashLength, 0);
if (!BCRYPT_SUCCESS(status))
throw std::runtime_error("cannot finish hash");
std::ostringstream output;
output << std::hex<< std::setfill('0');
for (UCHAR byte : hashBytes)
{
output << std::setw(2) << static_cast<int>(byte);
}
cleanup();
return output.str();
}
catch (...)
{
cleanup();
throw;
}
}
}