[vcpkg hash] Add string hashing (as opposed to file hashing)

This commit is contained in:
Alexander Karatarakis 2018-04-05 16:41:52 -07:00
parent 870fa61e01
commit e712308554
2 changed files with 60 additions and 1 deletions

View File

@ -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

View File

@ -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