aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Karatarakis <alkarata@microsoft.com>2018-04-05 16:41:52 -0700
committerAlexander Karatarakis <alkarata@microsoft.com>2018-04-06 17:24:46 -0700
commite71230855443a0b87c38e011531cfc6b9d6ffce5 (patch)
tree7c018bd6113b458a7ebdf0da9c9229d3b3ecf245
parent870fa61e0132028f43c292b7fd7a7d7c6525a8d7 (diff)
downloadvcpkg-e71230855443a0b87c38e011531cfc6b9d6ffce5.tar.gz
vcpkg-e71230855443a0b87c38e011531cfc6b9d6ffce5.zip
[vcpkg hash] Add string hashing (as opposed to file hashing)
-rw-r--r--toolsrc/include/vcpkg/commands.h4
-rw-r--r--toolsrc/src/vcpkg/commands.hash.cpp57
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