diff options
| author | Alexander Karatarakis <alkarata@microsoft.com> | 2018-04-05 17:03:45 -0700 |
|---|---|---|
| committer | Alexander Karatarakis <alkarata@microsoft.com> | 2018-04-06 17:24:46 -0700 |
| commit | c1257f988a49b167cd9d94a0931806c6e465700a (patch) | |
| tree | 591741e69ae5781394a3e0ae2ffa507cd3a615de /toolsrc/src | |
| parent | e71230855443a0b87c38e011531cfc6b9d6ffce5 (diff) | |
| download | vcpkg-c1257f988a49b167cd9d94a0931806c6e465700a.tar.gz vcpkg-c1257f988a49b167cd9d94a0931806c6e465700a.zip | |
[vcpkg hash] Refactor to reduce code duplication
Diffstat (limited to 'toolsrc/src')
| -rw-r--r-- | toolsrc/src/vcpkg/commands.hash.cpp | 149 |
1 files changed, 78 insertions, 71 deletions
diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index 856b0e283..c0130f12f 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -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); } }; - } - 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)) + struct BCryptHasher { - 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); - } - - std::string get_string_hash(const std::string& s, const std::string& hash_type) - { - BCryptAlgorithmHandle algorithm_handle; + 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; + } - 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"); + 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); + } - 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; + 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); + } - BCryptHashHandle 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"); + } - 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"); + 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"); + } - 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::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); + } - std::unique_ptr<unsigned char[]> hash_buffer = std::make_unique<UCHAR[]>(length_in_bytes); + BCryptAlgorithmHandle algorithm_handle; + ULONG 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"); + std::string get_file_hash(const fs::path& path, const std::string& hash_type) + { + return BCryptHasher{hash_type}.hash_file(path); + } - return to_hex(hash_buffer.get(), length_in_bytes); + std::string get_string_hash(const std::string& s, const std::string& hash_type) + { + return BCryptHasher{hash_type}.hash_string(s); } } |
