diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/HashingUtils.cpp | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/HashingUtils.cpp')
-rw-r--r-- | contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/HashingUtils.cpp | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/HashingUtils.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/HashingUtils.cpp new file mode 100644 index 0000000000..147bddf33e --- /dev/null +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/utils/HashingUtils.cpp @@ -0,0 +1,236 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include <aws/core/utils/logging/LogMacros.h> +#include <aws/core/utils/HashingUtils.h> +#include <aws/core/utils/StringUtils.h> +#include <aws/core/utils/base64/Base64.h> +#include <aws/core/utils/crypto/Sha256.h> +#include <aws/core/utils/crypto/Sha256HMAC.h> +#include <aws/core/utils/crypto/MD5.h> +#include <aws/core/utils/Outcome.h> +#include <aws/core/utils/memory/stl/AWSStringStream.h> +#include <aws/core/utils/memory/stl/AWSList.h> + +#include <iomanip> + +using namespace Aws::Utils; +using namespace Aws::Utils::Base64; +using namespace Aws::Utils::Crypto; + +// internal buffers are fixed-size arrays, so this is harmless memory-management wise +static Aws::Utils::Base64::Base64 s_base64; + +// Aws Glacier Tree Hash calculates hash value for each 1MB data +const static size_t TREE_HASH_ONE_MB = 1024 * 1024; + +Aws::String HashingUtils::Base64Encode(const ByteBuffer& message) +{ + return s_base64.Encode(message); +} + +ByteBuffer HashingUtils::Base64Decode(const Aws::String& encodedMessage) +{ + return s_base64.Decode(encodedMessage); +} + +ByteBuffer HashingUtils::CalculateSHA256HMAC(const ByteBuffer& toSign, const ByteBuffer& secret) +{ + Sha256HMAC hash; + return hash.Calculate(toSign, secret).GetResult(); +} + +ByteBuffer HashingUtils::CalculateSHA256(const Aws::String& str) +{ + Sha256 hash; + return hash.Calculate(str).GetResult(); +} + +ByteBuffer HashingUtils::CalculateSHA256(Aws::IOStream& stream) +{ + Sha256 hash; + return hash.Calculate(stream).GetResult(); +} + +/** + * This function is only used by HashingUtils::CalculateSHA256TreeHash() in this cpp file + * It's a helper function be used to compute the TreeHash defined at: + * http://docs.aws.amazon.com/amazonglacier/latest/dev/checksum-calculations.html + */ +static ByteBuffer TreeHashFinalCompute(Aws::List<ByteBuffer>& input) +{ + Sha256 hash; + assert(input.size() != 0); + + // O(n) time complexity of merging (n + n/2 + n/4 + n/8 +...+ 1) + while (input.size() > 1) + { + auto iter = input.begin(); + // if only one element left, just left it there + while (std::next(iter) != input.end()) + { + // if >= two elements + Aws::String str(reinterpret_cast<char*>(iter->GetUnderlyingData()), iter->GetLength()); + // list erase returns iterator of next element next to the erased element or end() if erased the last one + // list insert inserts element before pos, here we erase two elements, and insert a new element + iter = input.erase(iter); + str.append(reinterpret_cast<char*>(iter->GetUnderlyingData()), iter->GetLength()); + iter = input.erase(iter); + input.insert(iter, hash.Calculate(str).GetResult()); + + if (iter == input.end()) break; + } // while process to the last element + } // while the list has only one element left + + return *(input.begin()); +} + +ByteBuffer HashingUtils::CalculateSHA256TreeHash(const Aws::String& str) +{ + Sha256 hash; + if (str.size() == 0) + { + return hash.Calculate(str).GetResult(); + } + + Aws::List<ByteBuffer> input; + size_t pos = 0; + while (pos < str.size()) + { + input.push_back(hash.Calculate(Aws::String(str, pos, TREE_HASH_ONE_MB)).GetResult()); + pos += TREE_HASH_ONE_MB; + } + + return TreeHashFinalCompute(input); +} + +ByteBuffer HashingUtils::CalculateSHA256TreeHash(Aws::IOStream& stream) +{ + Sha256 hash; + Aws::List<ByteBuffer> input; + auto currentPos = stream.tellg(); + if (currentPos == std::ios::pos_type(-1)) + { + currentPos = 0; + stream.clear(); + } + stream.seekg(0, stream.beg); + Array<char> streamBuffer(TREE_HASH_ONE_MB); + while (stream.good()) + { + stream.read(streamBuffer.GetUnderlyingData(), TREE_HASH_ONE_MB); + auto bytesRead = stream.gcount(); + if (bytesRead > 0) + { + input.push_back(hash.Calculate(Aws::String(reinterpret_cast<char*>(streamBuffer.GetUnderlyingData()), static_cast<size_t>(bytesRead))).GetResult()); + } + } + stream.clear(); + stream.seekg(currentPos, stream.beg); + + if (input.size() == 0) + { + return hash.Calculate("").GetResult(); + } + return TreeHashFinalCompute(input); +} + +Aws::String HashingUtils::HexEncode(const ByteBuffer& message) +{ + Aws::String encoded; + encoded.reserve(2 * message.GetLength()); + + for (unsigned i = 0; i < message.GetLength(); ++i) + { + encoded.push_back("0123456789abcdef"[message[i] >> 4]); + encoded.push_back("0123456789abcdef"[message[i] & 0x0f]); + } + + return encoded; +} + +ByteBuffer HashingUtils::HexDecode(const Aws::String& str) +{ + //number of characters should be even + assert(str.length() % 2 == 0); + assert(str.length() >= 2); + + if(str.length() < 2 || str.length() % 2 != 0) + { + return ByteBuffer(); + } + + size_t strLength = str.length(); + size_t readIndex = 0; + + if(str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) + { + strLength -= 2; + readIndex = 2; + } + + ByteBuffer hexBuffer(strLength / 2); + size_t bufferIndex = 0; + + for (size_t i = readIndex; i < str.length(); i += 2) + { + if(!StringUtils::IsAlnum(str[i]) || !StringUtils::IsAlnum(str[i + 1])) + { + //contains non-hex characters + assert(0); + } + + char firstChar = str[i]; + uint8_t distance = firstChar - '0'; + + if(isalpha(firstChar)) + { + firstChar = static_cast<char>(toupper(firstChar)); + distance = firstChar - 'A' + 10; + } + + unsigned char val = distance * 16; + + char secondChar = str[i + 1]; + distance = secondChar - '0'; + + if(isalpha(secondChar)) + { + secondChar = static_cast<char>(toupper(secondChar)); + distance = secondChar - 'A' + 10; + } + + val += distance; + hexBuffer[bufferIndex++] = val; + } + + return hexBuffer; +} + +ByteBuffer HashingUtils::CalculateMD5(const Aws::String& str) +{ + MD5 hash; + return hash.Calculate(str).GetResult(); +} + +ByteBuffer HashingUtils::CalculateMD5(Aws::IOStream& stream) +{ + MD5 hash; + return hash.Calculate(stream).GetResult(); +} + +int HashingUtils::HashString(const char* strToHash) +{ + if (!strToHash) + return 0; + + unsigned hash = 0; + while (char charValue = *strToHash++) + { + hash = charValue + 31 * hash; + } + + return hash; +} |