HashResult MD5CommonCryptoImpl::Calculate(Aws::IStream& stream)
            {
                CC_MD5_CTX md5;
                CC_MD5_Init(&md5);

                auto currentPos = stream.tellg();
                stream.seekg(0, stream.beg);

                char streamBuffer[Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE];
                while(stream.good())
                {
                    stream.read(streamBuffer, Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE);
                    auto bytesRead = stream.gcount();

                    if(bytesRead > 0)
                    {
                        CC_MD5_Update(&md5, streamBuffer, static_cast<CC_LONG>(bytesRead));
                    }
                }

                stream.clear();
                stream.seekg(currentPos, stream.beg);

                ByteBuffer hash(CC_MD5_DIGEST_LENGTH);
                CC_MD5_Final(hash.GetUnderlyingData(), &md5);

                return HashResult(std::move(hash));
            }
HashResult Sha256CommonCryptoImpl::Calculate(Aws::IStream& stream)
{
    CC_SHA256_CTX sha256;
    CC_SHA256_Init(&sha256);

    unsigned currentPos = stream.tellg();
    stream.seekg(0, stream.beg);

    char streamBuffer[Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE];
    while(stream.good())
    {
	    stream.read(streamBuffer, Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE);
	    auto bytesRead = stream.gcount();

	    if(bytesRead > 0)
	    {
	        CC_SHA256_Update(&sha256, streamBuffer, bytesRead);
	    }
    }

    stream.clear();
    stream.seekg(currentPos, stream.beg);

    ByteBuffer hash(CC_SHA256_DIGEST_LENGTH);
    CC_SHA256_Final(hash.GetUnderlyingData(), &sha256);

    return HashResult(std::move(hash));
}
            HashResult BCryptHashImpl::Calculate(Aws::IStream& stream)
            {
                if (!IsValid())
                {
                    return HashResult();
                }

                std::lock_guard<std::mutex> locker(m_algorithmMutex);

                auto startingPos = stream.tellg();

                bool success = HashStream(stream);
                if (success)
                {
                    stream.clear();
                }

                stream.seekg(startingPos, stream.beg);

                if (!success)
                {
                    return HashResult();
                }

                return HashResult(ByteBuffer(m_hashBuffer, m_hashBufferLength));
            }
            bool BCryptHashImpl::HashStream(Aws::IStream& stream)
            {
                BCryptHashContext context(m_algorithmHandle, m_hashObject, m_hashObjectLength);
                if (!context.IsValid())
                {
                    AWS_LOG_ERROR(logTag, "Error creating hash handle.");
                    return false;
                }

                char streamBuffer[Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE];
                NTSTATUS status = 0;
                stream.seekg(0, stream.beg);
                while (stream.good())
                {
                    stream.read(streamBuffer, Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE);
                    std::streamsize bytesRead = stream.gcount();
                    if (bytesRead > 0)
                    {
                        status = BCryptHashData(context.m_hashHandle, (PBYTE)streamBuffer, (ULONG)bytesRead, 0);
                        if (!NT_SUCCESS(status))
                        {
                            AWS_LOG_ERROR(logTag, "Error computing hash.");
                            return false;
                        }
                    }
                }

                if (!stream.eof())
                {
                    return false;
                }

                status = BCryptFinishHash(context.m_hashHandle, m_hashBuffer, m_hashBufferLength, 0);
                if (!NT_SUCCESS(status))
                {
                    AWS_LOG_ERROR(logTag, "Error obtaining computed hash");
                    return false;
                }

                return true;
            }