From 94c29976d0020b48a5c565234b71f8f6abaf08be Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Wed, 10 Aug 2016 09:54:49 +0200 Subject: cmCryptoHash: Documentation comments --- Source/cmCryptoHash.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Source/cmCryptoHash.h b/Source/cmCryptoHash.h index 6aaaf93..84dea9b 100644 --- a/Source/cmCryptoHash.h +++ b/Source/cmCryptoHash.h @@ -16,12 +16,26 @@ #include +/** + * @brief Abstract base class for cryptographic hash generators + */ 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 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. + /// An empty string otherwise. std::string HashFile(const std::string& file); protected: -- cgit v0.12 From 74f0d4abcd8de84283858fe144772e688669e46a Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Wed, 10 Aug 2016 10:35:19 +0200 Subject: cmCryptoHash: New byte hash to string function --- Source/cmCryptoHash.cxx | 31 +++++++++++++++++++++++++++++++ Source/cmCryptoHash.h | 7 +++++++ 2 files changed, 38 insertions(+) diff --git a/Source/cmCryptoHash.cxx b/Source/cmCryptoHash.cxx index 8d60c1f..59b9abd 100644 --- a/Source/cmCryptoHash.cxx +++ b/Source/cmCryptoHash.cxx @@ -34,6 +34,37 @@ CM_AUTO_PTR cmCryptoHash::New(const char* algo) } } +bool cmCryptoHash::IntFromHexDigit(char input, char& output) +{ + if (input >= '0' && input <= '9') { + output = char(input - '0'); + return true; + } else if (input >= 'a' && input <= 'f') { + output = char(input - 'a' + 0xA); + return true; + } else if (input >= 'A' && input <= 'F') { + output = char(input - 'A' + 0xA); + return true; + } + return false; +} + +std::string cmCryptoHash::ByteHashToString( + const std::vector& hash) +{ + // Map from 4-bit index to hexadecimal representation. + static char const hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + + std::string res; + for (std::vector::const_iterator vit = hash.begin(); + vit != hash.end(); ++vit) { + res.push_back(hex[(*vit) >> 4]); + res.push_back(hex[(*vit) & 0xF]); + } + return res; +} + std::string cmCryptoHash::HashString(const std::string& input) { this->Initialize(); diff --git a/Source/cmCryptoHash.h b/Source/cmCryptoHash.h index 84dea9b..80ab269 100644 --- a/Source/cmCryptoHash.h +++ b/Source/cmCryptoHash.h @@ -29,6 +29,13 @@ public: /// @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 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); -- cgit v0.12 From f582dba6664e5ea814f3b33c71ae4d83db17b996 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Wed, 10 Aug 2016 11:08:15 +0200 Subject: cmCryptoHash: Return byte vector from internal Finalize method Some callers may want the raw byte vector instead of the hex character string. Convert the internal implementation to use this so that we can later add public APIs to get it. --- Source/cmCryptoHash.cxx | 20 ++++++++++---------- Source/cmCryptoHash.h | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Source/cmCryptoHash.cxx b/Source/cmCryptoHash.cxx index 59b9abd..8d96421 100644 --- a/Source/cmCryptoHash.cxx +++ b/Source/cmCryptoHash.cxx @@ -70,7 +70,7 @@ std::string cmCryptoHash::HashString(const std::string& input) this->Initialize(); this->Append(reinterpret_cast(input.c_str()), static_cast(input.size())); - return this->Finalize(); + return ByteHashToString(this->Finalize()); } std::string cmCryptoHash::HashFile(const std::string& file) @@ -99,7 +99,7 @@ std::string cmCryptoHash::HashFile(const std::string& file) } } if (fin.eof()) { - return this->Finalize(); + return ByteHashToString(this->Finalize()); } return ""; } @@ -124,11 +124,11 @@ void cmCryptoHashMD5::Append(unsigned char const* buf, int sz) cmsysMD5_Append(this->MD5, buf, sz); } -std::string cmCryptoHashMD5::Finalize() +std::vector cmCryptoHashMD5::Finalize() { - char md5out[32]; - cmsysMD5_FinalizeHex(this->MD5, md5out); - return std::string(md5out, 32); + std::vector hash(16, 0); + cmsysMD5_Finalize(this->MD5, &hash[0]); + return hash; } #define cmCryptoHash_SHA_CLASS_IMPL(SHA) \ @@ -142,11 +142,11 @@ std::string cmCryptoHashMD5::Finalize() { \ SHA##_Update(this->SHA, buf, sz); \ } \ - std::string cmCryptoHash##SHA::Finalize() \ + std::vector cmCryptoHash##SHA::Finalize() \ { \ - char out[SHA##_DIGEST_STRING_LENGTH]; \ - SHA##_End(this->SHA, out); \ - return std::string(out, SHA##_DIGEST_STRING_LENGTH - 1); \ + std::vector hash(SHA##_DIGEST_LENGTH, 0); \ + SHA##_Final(&hash[0], this->SHA); \ + return hash; \ } cmCryptoHash_SHA_CLASS_IMPL(SHA1) cmCryptoHash_SHA_CLASS_IMPL(SHA224) diff --git a/Source/cmCryptoHash.h b/Source/cmCryptoHash.h index 80ab269..ab50e82 100644 --- a/Source/cmCryptoHash.h +++ b/Source/cmCryptoHash.h @@ -48,7 +48,7 @@ public: protected: virtual void Initialize() = 0; virtual void Append(unsigned char const*, int) = 0; - virtual std::string Finalize() = 0; + virtual std::vector Finalize() = 0; }; class cmCryptoHashMD5 : public cmCryptoHash @@ -62,7 +62,7 @@ public: protected: void Initialize() CM_OVERRIDE; void Append(unsigned char const* buf, int sz) CM_OVERRIDE; - std::string Finalize() CM_OVERRIDE; + std::vector Finalize() CM_OVERRIDE; }; #define cmCryptoHash_SHA_CLASS_DECL(SHA) \ @@ -77,7 +77,7 @@ protected: protected: \ virtual void Initialize(); \ virtual void Append(unsigned char const* buf, int sz); \ - virtual std::string Finalize(); \ + virtual std::vector Finalize(); \ } cmCryptoHash_SHA_CLASS_DECL(SHA1); -- cgit v0.12 From 3a5f609cbb4ae63fca1eb87918767a4296d16e5f Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Wed, 10 Aug 2016 11:30:06 +0200 Subject: cmCryptoHash: New ByteHash methods that return a byte vector --- Source/cmCryptoHash.cxx | 66 ++++++++++++++++++++++++++++++------------------- Source/cmCryptoHash.h | 15 +++++++++++ 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/Source/cmCryptoHash.cxx b/Source/cmCryptoHash.cxx index 8d96421..9bd07a3 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::string cmCryptoHash::HashFile(const std::string& file) +std::vector cmCryptoHash::ByteHashFile(const std::string& file) { cmsys::ifstream fin(file.c_str(), std::ios::in | std::ios::binary); - if (!fin) { - return ""; + 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(); +} - this->Initialize(); +std::string cmCryptoHash::HashString(const std::string& input) +{ + return ByteHashToString(this->ByteHashString(input)); +} - // 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 ""; +std::string cmCryptoHash::HashFile(const std::string& file) +{ + return ByteHashToString(this->ByteHashFile(file)); } cmCryptoHashMD5::cmCryptoHashMD5() diff --git a/Source/cmCryptoHash.h b/Source/cmCryptoHash.h index ab50e82..4e92b06 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. -- cgit v0.12