From 3a5f609cbb4ae63fca1eb87918767a4296d16e5f Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Wed, 10 Aug 2016 11:30:06 +0200 Subject: [PATCH] cmCryptoHash: New ByteHash methods that return a byte vector --- Source/cmCryptoHash.cxx | 72 ++++++++++++++++++++++++----------------- Source/cmCryptoHash.h | 15 +++++++++ 2 files changed, 58 insertions(+), 29 deletions(-) diff --git a/Source/cmCryptoHash.cxx b/Source/cmCryptoHash.cxx index 8d9642115..9bd07a3b0 100644 --- a/Source/cmCryptoHash.cxx +++ b/Source/cmCryptoHash.cxx @@ -65,43 +65,57 @@ std::string cmCryptoHash::ByteHashToString( return res; } -std::string cmCryptoHash::HashString(const std::string& input) +std::vector cmCryptoHash::ByteHashString( + const std::string& input) { this->Initialize(); this->Append(reinterpret_cast(input.c_str()), static_cast(input.size())); - return ByteHashToString(this->Finalize()); + return this->Finalize(); +} + +std::vector cmCryptoHash::ByteHashFile(const std::string& file) +{ + cmsys::ifstream fin(file.c_str(), std::ios::in | std::ios::binary); + if (fin) { + this->Initialize(); + { + // Should be efficient enough on most system: + cm_sha2_uint64_t buffer[512]; + char* buffer_c = reinterpret_cast(buffer); + unsigned char const* buffer_uc = + reinterpret_cast(buffer); + // This copy loop is very sensitive on certain platforms with + // slightly broken stream libraries (like HPUX). Normally, it is + // incorrect to not check the error condition on the fin.read() + // before using the data, but the fin.gcount() will be zero if an + // error occurred. Therefore, the loop should be safe everywhere. + while (fin) { + fin.read(buffer_c, sizeof(buffer)); + if (int gcount = static_cast(fin.gcount())) { + this->Append(buffer_uc, gcount); + } + } + } + if (fin.eof()) { + // Success + return this->Finalize(); + } + // Finalize anyway + this->Finalize(); + } + // Return without success + return std::vector(); +} + +std::string cmCryptoHash::HashString(const std::string& input) +{ + return ByteHashToString(this->ByteHashString(input)); } std::string cmCryptoHash::HashFile(const std::string& file) { - cmsys::ifstream fin(file.c_str(), std::ios::in | std::ios::binary); - if (!fin) { - return ""; - } - - this->Initialize(); - - // Should be efficient enough on most system: - cm_sha2_uint64_t buffer[512]; - char* buffer_c = reinterpret_cast(buffer); - unsigned char const* buffer_uc = - reinterpret_cast(buffer); - // This copy loop is very sensitive on certain platforms with - // slightly broken stream libraries (like HPUX). Normally, it is - // incorrect to not check the error condition on the fin.read() - // before using the data, but the fin.gcount() will be zero if an - // error occurred. Therefore, the loop should be safe everywhere. - while (fin) { - fin.read(buffer_c, sizeof(buffer)); - if (int gcount = static_cast(fin.gcount())) { - this->Append(buffer_uc, gcount); - } - } - if (fin.eof()) { - return ByteHashToString(this->Finalize()); - } - return ""; + return ByteHashToString(this->ByteHashFile(file)); } cmCryptoHashMD5::cmCryptoHashMD5() diff --git a/Source/cmCryptoHash.h b/Source/cmCryptoHash.h index ab50e8231..4e92b063e 100644 --- a/Source/cmCryptoHash.h +++ b/Source/cmCryptoHash.h @@ -23,22 +23,37 @@ class cmCryptoHash { public: virtual ~cmCryptoHash() {} + /// @brief Returns a new hash generator of the requested type /// @arg algo Hash type name. Supported hash types are /// MD5, SHA1, SHA224, SHA256, SHA384, SHA512 /// @return A valid auto pointer if algo is supported or /// an invalid/NULL pointer otherwise static CM_AUTO_PTR New(const char* algo); + /// @brief Converts a hex character to its binary value (4 bits) /// @arg input Hex character [0-9a-fA-F]. /// @arg output Binary value of the input character (4 bits) /// @return True if input was a valid hex character static bool IntFromHexDigit(char input, char& output); + /// @brief Converts a byte hash to a sequence of hex character pairs static std::string ByteHashToString(const std::vector& hash); + + /// @brief Calculates a binary hash from string input data + /// @return Binary hash vector + std::vector ByteHashString(const std::string& input); + + /// @brief Calculates a binary hash from file content + /// @see ByteHashString() + /// @return Non empty binary hash vector if the file was read successfully. + /// An empty vector otherwise. + std::vector ByteHashFile(const std::string& file); + /// @brief Calculates a hash string from string input data /// @return Sequence of hex characters pairs for each byte of the binary hash std::string HashString(const std::string& input); + /// @brief Calculates a hash string from file content /// @see HashString() /// @return Non empty hash string if the file was read successfully.