diff options
| author | Alexander Karatarakis <alkarata@microsoft.com> | 2018-04-05 16:41:52 -0700 |
|---|---|---|
| committer | Alexander Karatarakis <alkarata@microsoft.com> | 2018-04-06 17:24:46 -0700 |
| commit | e71230855443a0b87c38e011531cfc6b9d6ffce5 (patch) | |
| tree | 7c018bd6113b458a7ebdf0da9c9229d3b3ecf245 | |
| parent | 870fa61e0132028f43c292b7fd7a7d7c6525a8d7 (diff) | |
| download | vcpkg-e71230855443a0b87c38e011531cfc6b9d6ffce5.tar.gz vcpkg-e71230855443a0b87c38e011531cfc6b9d6ffce5.zip | |
[vcpkg hash] Add string hashing (as opposed to file hashing)
| -rw-r--r-- | toolsrc/include/vcpkg/commands.h | 4 | ||||
| -rw-r--r-- | toolsrc/src/vcpkg/commands.hash.cpp | 57 |
2 files changed, 60 insertions, 1 deletions
diff --git a/toolsrc/include/vcpkg/commands.h b/toolsrc/include/vcpkg/commands.h index 65e7fdd14..d8d2abfa9 100644 --- a/toolsrc/include/vcpkg/commands.h +++ b/toolsrc/include/vcpkg/commands.h @@ -131,8 +131,10 @@ namespace vcpkg::Commands namespace Hash { + std::string get_string_hash(const std::string& s, const std::string& hash_type); + std::string get_file_hash(const fs::path& path, const std::string& hash_type); + void perform_and_exit(const VcpkgCmdArguments& args); - std::string get_file_hash(fs::path const& path, std::string const& hash_type); } namespace Fetch diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index 087f3e682..856b0e283 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -103,6 +103,42 @@ namespace vcpkg::Commands::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; + + 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); + } } #else @@ -128,6 +164,27 @@ namespace vcpkg::Commands::Hash cmd_line); return Strings::trim(std::string{ec_data.output}); } + + std::string get_string_hash(const std::string& s, const std::string& hash_type) + { + if (!Strings::case_insensitive_ascii_starts_with(hash_type, "SHA")) + { + Checks::exit_with_message( + VCPKG_LINE_INFO, "shasum only supports SHA hashes, but %s was provided", hash_type); + } + + const std::string digest_size = hash_type.substr(3, hash_type.length() - 3); + + const std::string cmd_line = Strings::format( + R"(echo -n "%s" | shasum -a %s | awk '{ print $1 }')", s, digest_size); + const auto ec_data = System::cmd_execute_and_capture_output(cmd_line); + Checks::check_exit(VCPKG_LINE_INFO, + ec_data.exit_code == 0, + "Failed to run:\n" + " %s", + cmd_line); + return Strings::trim(std::string{ec_data.output}); + } } #endif |
