|
|
@@ -34,7 +34,39 @@ CM_AUTO_PTR<cmCryptoHash> cmCryptoHash::New(const char* algo)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-std::string cmCryptoHash::HashString(const std::string& input)
|
|
|
+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<unsigned char>& 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<unsigned char>::const_iterator vit = hash.begin();
|
|
|
+ vit != hash.end(); ++vit) {
|
|
|
+ res.push_back(hex[(*vit) >> 4]);
|
|
|
+ res.push_back(hex[(*vit) & 0xF]);
|
|
|
+ }
|
|
|
+ return res;
|
|
|
+}
|
|
|
+
|
|
|
+std::vector<unsigned char> cmCryptoHash::ByteHashString(
|
|
|
+ const std::string& input)
|
|
|
{
|
|
|
this->Initialize();
|
|
|
this->Append(reinterpret_cast<unsigned char const*>(input.c_str()),
|
|
|
@@ -42,35 +74,48 @@ std::string cmCryptoHash::HashString(const std::string& input)
|
|
|
return this->Finalize();
|
|
|
}
|
|
|
|
|
|
-std::string cmCryptoHash::HashFile(const std::string& file)
|
|
|
+std::vector<unsigned char> 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<char*>(buffer);
|
|
|
+ unsigned char const* buffer_uc =
|
|
|
+ reinterpret_cast<unsigned char const*>(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<int>(fin.gcount())) {
|
|
|
+ this->Append(buffer_uc, gcount);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (fin.eof()) {
|
|
|
+ // Success
|
|
|
+ return this->Finalize();
|
|
|
+ }
|
|
|
+ // Finalize anyway
|
|
|
+ this->Finalize();
|
|
|
}
|
|
|
+ // Return without success
|
|
|
+ return std::vector<unsigned char>();
|
|
|
+}
|
|
|
|
|
|
- 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<char*>(buffer);
|
|
|
- unsigned char const* buffer_uc =
|
|
|
- reinterpret_cast<unsigned char const*>(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<int>(fin.gcount())) {
|
|
|
- this->Append(buffer_uc, gcount);
|
|
|
- }
|
|
|
- }
|
|
|
- if (fin.eof()) {
|
|
|
- return this->Finalize();
|
|
|
- }
|
|
|
- return "";
|
|
|
+std::string cmCryptoHash::HashFile(const std::string& file)
|
|
|
+{
|
|
|
+ return ByteHashToString(this->ByteHashFile(file));
|
|
|
}
|
|
|
|
|
|
cmCryptoHashMD5::cmCryptoHashMD5()
|
|
|
@@ -93,11 +138,11 @@ void cmCryptoHashMD5::Append(unsigned char const* buf, int sz)
|
|
|
cmsysMD5_Append(this->MD5, buf, sz);
|
|
|
}
|
|
|
|
|
|
-std::string cmCryptoHashMD5::Finalize()
|
|
|
+std::vector<unsigned char> cmCryptoHashMD5::Finalize()
|
|
|
{
|
|
|
- char md5out[32];
|
|
|
- cmsysMD5_FinalizeHex(this->MD5, md5out);
|
|
|
- return std::string(md5out, 32);
|
|
|
+ std::vector<unsigned char> hash(16, 0);
|
|
|
+ cmsysMD5_Finalize(this->MD5, &hash[0]);
|
|
|
+ return hash;
|
|
|
}
|
|
|
|
|
|
#define cmCryptoHash_SHA_CLASS_IMPL(SHA) \
|
|
|
@@ -111,11 +156,11 @@ std::string cmCryptoHashMD5::Finalize()
|
|
|
{ \
|
|
|
SHA##_Update(this->SHA, buf, sz); \
|
|
|
} \
|
|
|
- std::string cmCryptoHash##SHA::Finalize() \
|
|
|
+ std::vector<unsigned char> 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<unsigned char> hash(SHA##_DIGEST_LENGTH, 0); \
|
|
|
+ SHA##_Final(&hash[0], this->SHA); \
|
|
|
+ return hash; \
|
|
|
}
|
|
|
|
|
|
cmCryptoHash_SHA_CLASS_IMPL(SHA1) cmCryptoHash_SHA_CLASS_IMPL(SHA224)
|