mirror of
https://github.com/microsoft/vcpkg.git
synced 2024-11-25 06:26:51 +08:00
[vcpkg hash] Refactor to reduce code duplication
This commit is contained in:
parent
e712308554
commit
c1257f988a
@ -18,7 +18,7 @@ namespace vcpkg::Commands::Hash
|
||||
{
|
||||
namespace
|
||||
{
|
||||
static std::string to_hex(const unsigned char* string, const size_t bytes)
|
||||
std::string to_hex(const unsigned char* string, const size_t bytes)
|
||||
{
|
||||
static constexpr char HEX_MAP[] = "0123456789abcdef";
|
||||
|
||||
@ -58,86 +58,93 @@ namespace vcpkg::Commands::Hash
|
||||
if (handle) BCryptDestroyHash(handle);
|
||||
}
|
||||
};
|
||||
|
||||
struct BCryptHasher
|
||||
{
|
||||
explicit BCryptHasher(const std::string& hash_type)
|
||||
{
|
||||
NTSTATUS error_code =
|
||||
BCryptOpenAlgorithmProvider(&this->algorithm_handle.handle,
|
||||
Strings::to_utf16(Strings::ascii_to_uppercase(hash_type)).c_str(),
|
||||
nullptr,
|
||||
0);
|
||||
Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to open the algorithm provider");
|
||||
|
||||
DWORD hash_buffer_bytes;
|
||||
DWORD cb_data;
|
||||
error_code = BCryptGetProperty(this->algorithm_handle.handle,
|
||||
BCRYPT_HASH_LENGTH,
|
||||
reinterpret_cast<PUCHAR>(&hash_buffer_bytes),
|
||||
sizeof(DWORD),
|
||||
&cb_data,
|
||||
0);
|
||||
Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to get hash length");
|
||||
this->length_in_bytes = hash_buffer_bytes;
|
||||
}
|
||||
|
||||
std::string hash_file(const fs::path& path) const
|
||||
{
|
||||
BCryptHashHandle hash_handle;
|
||||
this->initialize_hash_handle(hash_handle);
|
||||
|
||||
FILE* file = nullptr;
|
||||
const auto ec = _wfopen_s(&file, path.c_str(), L"rb");
|
||||
Checks::check_exit(VCPKG_LINE_INFO, ec == 0, "Failed to open file: %s", path.u8string());
|
||||
unsigned char buffer[4096];
|
||||
while (const auto actual_size = fread(buffer, 1, sizeof(buffer), file))
|
||||
{
|
||||
hash_data(hash_handle, buffer, actual_size);
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
return this->finalize_hash_handle(hash_handle);
|
||||
}
|
||||
|
||||
std::string hash_string(const std::string& s) const
|
||||
{
|
||||
BCryptHashHandle hash_handle;
|
||||
this->initialize_hash_handle(hash_handle);
|
||||
hash_data(hash_handle, reinterpret_cast<unsigned char*>(const_cast<char*>(s.c_str())), s.size());
|
||||
return this->finalize_hash_handle(hash_handle);
|
||||
}
|
||||
|
||||
private:
|
||||
void initialize_hash_handle(BCryptHashHandle& hash_handle) const
|
||||
{
|
||||
const NTSTATUS error_code =
|
||||
BCryptCreateHash(this->algorithm_handle.handle, &hash_handle.handle, nullptr, 0, nullptr, 0, 0);
|
||||
Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to initialize the hasher");
|
||||
}
|
||||
|
||||
void hash_data(BCryptHashHandle& hash_handle, unsigned char* buffer, const size_t& data_size) const
|
||||
{
|
||||
const NTSTATUS error_code =
|
||||
BCryptHashData(hash_handle.handle, buffer, static_cast<ULONG>(data_size), 0);
|
||||
Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to hash data");
|
||||
}
|
||||
|
||||
std::string finalize_hash_handle(const BCryptHashHandle& hash_handle) const
|
||||
{
|
||||
std::unique_ptr<unsigned char[]> hash_buffer = std::make_unique<UCHAR[]>(this->length_in_bytes);
|
||||
const NTSTATUS error_code =
|
||||
BCryptFinishHash(hash_handle.handle, hash_buffer.get(), this->length_in_bytes, 0);
|
||||
Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to finalize the hash");
|
||||
return to_hex(hash_buffer.get(), this->length_in_bytes);
|
||||
}
|
||||
|
||||
BCryptAlgorithmHandle algorithm_handle;
|
||||
ULONG length_in_bytes;
|
||||
};
|
||||
}
|
||||
|
||||
std::string get_file_hash(const fs::path& path, const std::string& hash_type)
|
||||
{
|
||||
BCryptAlgorithmHandle algorithm_handle;
|
||||
|
||||
NTSTATUS error_code = BCryptOpenAlgorithmProvider(
|
||||
&algorithm_handle.handle, Strings::to_utf16(Strings::ascii_to_uppercase(hash_type)).c_str(), nullptr, 0);
|
||||
Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to open the algorithm provider");
|
||||
|
||||
DWORD hash_buffer_bytes;
|
||||
DWORD cb_data;
|
||||
error_code = BCryptGetProperty(algorithm_handle.handle,
|
||||
BCRYPT_HASH_LENGTH,
|
||||
reinterpret_cast<PUCHAR>(&hash_buffer_bytes),
|
||||
sizeof(DWORD),
|
||||
&cb_data,
|
||||
0);
|
||||
Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to get hash length");
|
||||
const ULONG length_in_bytes = hash_buffer_bytes;
|
||||
|
||||
BCryptHashHandle hash_handle;
|
||||
|
||||
error_code = BCryptCreateHash(algorithm_handle.handle, &hash_handle.handle, nullptr, 0, nullptr, 0, 0);
|
||||
Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to initialize the hasher");
|
||||
|
||||
FILE* file = nullptr;
|
||||
const auto ec = _wfopen_s(&file, path.c_str(), L"rb");
|
||||
Checks::check_exit(VCPKG_LINE_INFO, ec == 0, "Failed to open file: %s", path.u8string());
|
||||
unsigned char buffer[4096];
|
||||
while (const auto actual_size = fread(buffer, 1, sizeof(buffer), file))
|
||||
{
|
||||
error_code = BCryptHashData(hash_handle.handle, buffer, static_cast<ULONG>(actual_size), 0);
|
||||
Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to hash data");
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
|
||||
std::unique_ptr<unsigned char[]> hash_buffer = std::make_unique<UCHAR[]>(length_in_bytes);
|
||||
|
||||
error_code = BCryptFinishHash(hash_handle.handle, hash_buffer.get(), length_in_bytes, 0);
|
||||
Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to finalize the hash");
|
||||
|
||||
return to_hex(hash_buffer.get(), length_in_bytes);
|
||||
return BCryptHasher{hash_type}.hash_file(path);
|
||||
}
|
||||
|
||||
std::string get_string_hash(const std::string& s, const std::string& hash_type)
|
||||
{
|
||||
BCryptAlgorithmHandle algorithm_handle;
|
||||
|
||||
NTSTATUS error_code = BCryptOpenAlgorithmProvider(
|
||||
&algorithm_handle.handle, Strings::to_utf16(Strings::ascii_to_uppercase(hash_type)).c_str(), nullptr, 0);
|
||||
Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to open the algorithm provider");
|
||||
|
||||
DWORD hash_buffer_bytes;
|
||||
DWORD cb_data;
|
||||
error_code = BCryptGetProperty(algorithm_handle.handle,
|
||||
BCRYPT_HASH_LENGTH,
|
||||
reinterpret_cast<PUCHAR>(&hash_buffer_bytes),
|
||||
sizeof(DWORD),
|
||||
&cb_data,
|
||||
0);
|
||||
Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to get hash length");
|
||||
const ULONG length_in_bytes = hash_buffer_bytes;
|
||||
|
||||
BCryptHashHandle hash_handle;
|
||||
|
||||
error_code = BCryptCreateHash(algorithm_handle.handle, &hash_handle.handle, nullptr, 0, nullptr, 0, 0);
|
||||
Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to initialize the hasher");
|
||||
|
||||
auto* const buffer = reinterpret_cast<unsigned char*>(const_cast<char*>(s.c_str()));
|
||||
error_code = BCryptHashData(hash_handle.handle, buffer, static_cast<ULONG>(s.size()), 0);
|
||||
Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to hash data");
|
||||
|
||||
std::unique_ptr<unsigned char[]> hash_buffer = std::make_unique<UCHAR[]>(length_in_bytes);
|
||||
|
||||
error_code = BCryptFinishHash(hash_handle.handle, hash_buffer.get(), length_in_bytes, 0);
|
||||
Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to finalize the hash");
|
||||
|
||||
return to_hex(hash_buffer.get(), length_in_bytes);
|
||||
return BCryptHasher{hash_type}.hash_string(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user