diff options
author | unril <unril@yandex-team.ru> | 2022-02-10 16:46:05 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:46:05 +0300 |
commit | 3b241dd57cf58f20bbbd63fa6a0a758dbec09b68 (patch) | |
tree | 1a2c5ffcf89eb53ecd79dbc9bc0a195c27404d0c /contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSigner.cpp | |
parent | 11ae9eca250d0188b7962459cbc6706719e7dca9 (diff) | |
download | ydb-3b241dd57cf58f20bbbd63fa6a0a758dbec09b68.tar.gz |
Restoring authorship annotation for <unril@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSigner.cpp')
-rw-r--r-- | contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSigner.cpp | 568 |
1 files changed, 284 insertions, 284 deletions
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSigner.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSigner.cpp index f6a0d5da71..de4826fa5b 100644 --- a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSigner.cpp +++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/auth/AWSAuthSigner.cpp @@ -17,14 +17,14 @@ #include <aws/core/utils/memory/AWSMemory.h> #include <aws/core/utils/crypto/Sha256.h> #include <aws/core/utils/crypto/Sha256HMAC.h> -#include <aws/core/utils/stream/PreallocatedStreamBuf.h> -#include <aws/core/utils/event/EventMessage.h> -#include <aws/core/utils/event/EventHeader.h> +#include <aws/core/utils/stream/PreallocatedStreamBuf.h> +#include <aws/core/utils/event/EventMessage.h> +#include <aws/core/utils/event/EventHeader.h> #include <cstdio> #include <iomanip> #include <math.h> -#include <cstring> +#include <cstring> using namespace Aws; using namespace Aws::Client; @@ -35,8 +35,8 @@ using namespace Aws::Utils::Logging; static const char* EQ = "="; static const char* AWS_HMAC_SHA256 = "AWS4-HMAC-SHA256"; -static const char* EVENT_STREAM_CONTENT_SHA256 = "STREAMING-AWS4-HMAC-SHA256-EVENTS"; -static const char* EVENT_STREAM_PAYLOAD = "AWS4-HMAC-SHA256-PAYLOAD"; +static const char* EVENT_STREAM_CONTENT_SHA256 = "STREAMING-AWS4-HMAC-SHA256-EVENTS"; +static const char* EVENT_STREAM_PAYLOAD = "AWS4-HMAC-SHA256-PAYLOAD"; static const char* AWS4_REQUEST = "aws4_request"; static const char* SIGNED_HEADERS = "SignedHeaders"; static const char* CREDENTIAL = "Credential"; @@ -46,25 +46,25 @@ static const char* X_AMZ_ALGORITHM = "X-Amz-Algorithm"; static const char* X_AMZ_CREDENTIAL = "X-Amz-Credential"; static const char* UNSIGNED_PAYLOAD = "UNSIGNED-PAYLOAD"; static const char* X_AMZ_SIGNATURE = "X-Amz-Signature"; -static const char* X_AMZN_TRACE_ID = "x-amzn-trace-id"; -static const char* X_AMZ_CONTENT_SHA256 = "x-amz-content-sha256"; -static const char* USER_AGENT = "user-agent"; +static const char* X_AMZN_TRACE_ID = "x-amzn-trace-id"; +static const char* X_AMZ_CONTENT_SHA256 = "x-amz-content-sha256"; +static const char* USER_AGENT = "user-agent"; static const char* SIGNING_KEY = "AWS4"; static const char* SIMPLE_DATE_FORMAT_STR = "%Y%m%d"; static const char* EMPTY_STRING_SHA256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; -static const char v4LogTag[] = "AWSAuthV4Signer"; -static const char v4StreamingLogTag[] = "AWSAuthEventStreamV4Signer"; +static const char v4LogTag[] = "AWSAuthV4Signer"; +static const char v4StreamingLogTag[] = "AWSAuthEventStreamV4Signer"; namespace Aws { namespace Auth { - const char SIGNATURE[] = "Signature"; + const char SIGNATURE[] = "Signature"; const char SIGV4_SIGNER[] = "SignatureV4"; - const char EVENTSTREAM_SIGV4_SIGNER[] = "EventStreamSignatureV4"; - const char EVENTSTREAM_SIGNATURE_HEADER[] = ":chunk-signature"; - const char EVENTSTREAM_DATE_HEADER[] = ":date"; + const char EVENTSTREAM_SIGV4_SIGNER[] = "EventStreamSignatureV4"; + const char EVENTSTREAM_SIGNATURE_HEADER[] = ":chunk-signature"; + const char EVENTSTREAM_DATE_HEADER[] = ":date"; const char NULL_SIGNER[] = "NullSigner"; } } @@ -152,7 +152,7 @@ AWSAuthV4Signer::AWSAuthV4Signer(const std::shared_ptr<Auth::AWSCredentialsProvi m_region(region), m_hash(Aws::MakeUnique<Aws::Utils::Crypto::Sha256>(v4LogTag)), m_HMAC(Aws::MakeUnique<Aws::Utils::Crypto::Sha256HMAC>(v4LogTag)), - m_unsignedHeaders({USER_AGENT, X_AMZN_TRACE_ID}), + m_unsignedHeaders({USER_AGENT, X_AMZN_TRACE_ID}), m_payloadSigningPolicy(signingPolicy), m_urlEscapePath(urlEscapePath) { @@ -203,7 +203,7 @@ bool AWSAuthV4Signer::SignRequest(Aws::Http::HttpRequest& request, const char* r if(signBody || request.GetUri().GetScheme() != Http::Scheme::HTTPS) { - payloadHash = ComputePayloadHash(request); + payloadHash = ComputePayloadHash(request); if (payloadHash.empty()) { return false; @@ -217,7 +217,7 @@ bool AWSAuthV4Signer::SignRequest(Aws::Http::HttpRequest& request, const char* r if(m_includeSha256HashHeader) { - request.SetHeaderValue(X_AMZ_CONTENT_SHA256, payloadHash); + request.SetHeaderValue(X_AMZ_CONTENT_SHA256, payloadHash); } //calculate date header to use in internal signature (this also goes into date header). @@ -245,7 +245,7 @@ bool AWSAuthV4Signer::SignRequest(Aws::Http::HttpRequest& request, const char* r //remove that last semi-colon if (!signedHeadersValue.empty()) { - signedHeadersValue.pop_back(); + signedHeadersValue.pop_back(); } AWS_LOGSTREAM_DEBUG(v4LogTag, "Signed Headers value:" << signedHeadersValue); @@ -375,11 +375,11 @@ bool AWSAuthV4Signer::PresignRequest(Aws::Http::HttpRequest& request, const char canonicalRequestString.append(signedHeadersValue); canonicalRequestString.append(NEWLINE); if (ServiceRequireUnsignedPayload(signingServiceName)) - { + { canonicalRequestString.append(UNSIGNED_PAYLOAD); - } - else - { + } + else + { canonicalRequestString.append(EMPTY_STRING_SHA256); } AWS_LOGSTREAM_DEBUG(v4LogTag, "Canonical Request String: " << canonicalRequestString); @@ -438,7 +438,7 @@ Aws::String AWSAuthV4Signer::GenerateSignature(const Aws::String& stringToSign, { AWS_LOGSTREAM_ERROR(v4LogTag, "Unable to hmac (sha256) final string"); AWS_LOGSTREAM_DEBUG(v4LogTag, "The final string is: \"" << stringToSign << "\""); - return {}; + return {}; } //now we finally sign our request string with our hex encoded derived hash. @@ -470,7 +470,7 @@ Aws::String AWSAuthV4Signer::ComputePayloadHash(Aws::Http::HttpRequest& request) if (!hashResult.IsSuccess()) { AWS_LOGSTREAM_ERROR(v4LogTag, "Unable to hash (sha256) request body"); - return {}; + return {}; } auto sha256Digest = hashResult.GetResult(); @@ -532,275 +532,275 @@ Aws::Utils::ByteBuffer AWSAuthV4Signer::ComputeHash(const Aws::String& secretKey } return hashResult.GetResult(); } - -AWSAuthEventStreamV4Signer::AWSAuthEventStreamV4Signer(const std::shared_ptr<Auth::AWSCredentialsProvider>& - credentialsProvider, const char* serviceName, const Aws::String& region) : - m_serviceName(serviceName), - m_region(region), - m_credentialsProvider(credentialsProvider) -{ - - m_unsignedHeaders.emplace_back(X_AMZN_TRACE_ID); - m_unsignedHeaders.emplace_back(USER_AGENT_HEADER); -} - + +AWSAuthEventStreamV4Signer::AWSAuthEventStreamV4Signer(const std::shared_ptr<Auth::AWSCredentialsProvider>& + credentialsProvider, const char* serviceName, const Aws::String& region) : + m_serviceName(serviceName), + m_region(region), + m_credentialsProvider(credentialsProvider) +{ + + m_unsignedHeaders.emplace_back(X_AMZN_TRACE_ID); + m_unsignedHeaders.emplace_back(USER_AGENT_HEADER); +} + bool AWSAuthEventStreamV4Signer::SignRequest(Aws::Http::HttpRequest& request, const char* region, const char* serviceName, bool /* signBody */) const -{ - AWSCredentials credentials = m_credentialsProvider->GetAWSCredentials(); - - //don't sign anonymous requests - if (credentials.GetAWSAccessKeyId().empty() || credentials.GetAWSSecretKey().empty()) - { - return true; - } - - if (!credentials.GetSessionToken().empty()) - { - request.SetAwsSessionToken(credentials.GetSessionToken()); - } - - request.SetHeaderValue(X_AMZ_CONTENT_SHA256, EVENT_STREAM_CONTENT_SHA256); - - //calculate date header to use in internal signature (this also goes into date header). - DateTime now = GetSigningTimestamp(); +{ + AWSCredentials credentials = m_credentialsProvider->GetAWSCredentials(); + + //don't sign anonymous requests + if (credentials.GetAWSAccessKeyId().empty() || credentials.GetAWSSecretKey().empty()) + { + return true; + } + + if (!credentials.GetSessionToken().empty()) + { + request.SetAwsSessionToken(credentials.GetSessionToken()); + } + + request.SetHeaderValue(X_AMZ_CONTENT_SHA256, EVENT_STREAM_CONTENT_SHA256); + + //calculate date header to use in internal signature (this also goes into date header). + DateTime now = GetSigningTimestamp(); Aws::String dateHeaderValue = now.ToGmtString(DateFormat::ISO_8601_BASIC); - request.SetHeaderValue(AWS_DATE_HEADER, dateHeaderValue); - - Aws::StringStream headersStream; - Aws::StringStream signedHeadersStream; - - for (const auto& header : CanonicalizeHeaders(request.GetHeaders())) - { - if(ShouldSignHeader(header.first)) - { - headersStream << header.first.c_str() << ":" << header.second.c_str() << NEWLINE; - signedHeadersStream << header.first.c_str() << ";"; - } - } - - Aws::String canonicalHeadersString = headersStream.str(); - AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Canonical Header String: " << canonicalHeadersString); - - //calculate signed headers parameter - Aws::String signedHeadersValue = signedHeadersStream.str(); - //remove that last semi-colon - if (!signedHeadersValue.empty()) - { - signedHeadersValue.pop_back(); - } - - AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Signed Headers value:" << signedHeadersValue); - - //generate generalized canonicalized request string. - Aws::String canonicalRequestString = CanonicalizeRequestSigningString(request, true/* m_urlEscapePath */); - - //append v4 stuff to the canonical request string. - canonicalRequestString.append(canonicalHeadersString); - canonicalRequestString.append(NEWLINE); - canonicalRequestString.append(signedHeadersValue); - canonicalRequestString.append(NEWLINE); - canonicalRequestString.append(EVENT_STREAM_CONTENT_SHA256); - - AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Canonical Request String: " << canonicalRequestString); - - //now compute sha256 on that request string - auto hashResult = m_hash.Calculate(canonicalRequestString); - if (!hashResult.IsSuccess()) - { - AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to hash (sha256) request string"); - AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "The request string is: \"" << canonicalRequestString << "\""); - return false; - } - - auto sha256Digest = hashResult.GetResult(); + request.SetHeaderValue(AWS_DATE_HEADER, dateHeaderValue); + + Aws::StringStream headersStream; + Aws::StringStream signedHeadersStream; + + for (const auto& header : CanonicalizeHeaders(request.GetHeaders())) + { + if(ShouldSignHeader(header.first)) + { + headersStream << header.first.c_str() << ":" << header.second.c_str() << NEWLINE; + signedHeadersStream << header.first.c_str() << ";"; + } + } + + Aws::String canonicalHeadersString = headersStream.str(); + AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Canonical Header String: " << canonicalHeadersString); + + //calculate signed headers parameter + Aws::String signedHeadersValue = signedHeadersStream.str(); + //remove that last semi-colon + if (!signedHeadersValue.empty()) + { + signedHeadersValue.pop_back(); + } + + AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Signed Headers value:" << signedHeadersValue); + + //generate generalized canonicalized request string. + Aws::String canonicalRequestString = CanonicalizeRequestSigningString(request, true/* m_urlEscapePath */); + + //append v4 stuff to the canonical request string. + canonicalRequestString.append(canonicalHeadersString); + canonicalRequestString.append(NEWLINE); + canonicalRequestString.append(signedHeadersValue); + canonicalRequestString.append(NEWLINE); + canonicalRequestString.append(EVENT_STREAM_CONTENT_SHA256); + + AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Canonical Request String: " << canonicalRequestString); + + //now compute sha256 on that request string + auto hashResult = m_hash.Calculate(canonicalRequestString); + if (!hashResult.IsSuccess()) + { + AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to hash (sha256) request string"); + AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "The request string is: \"" << canonicalRequestString << "\""); + return false; + } + + auto sha256Digest = hashResult.GetResult(); Aws::String canonicalRequestHash = HashingUtils::HexEncode(sha256Digest); - Aws::String simpleDate = now.ToGmtString(SIMPLE_DATE_FORMAT_STR); - + Aws::String simpleDate = now.ToGmtString(SIMPLE_DATE_FORMAT_STR); + Aws::String signingRegion = region ? region : m_region; Aws::String signingServiceName = serviceName ? serviceName : m_serviceName; Aws::String stringToSign = GenerateStringToSign(dateHeaderValue, simpleDate, canonicalRequestHash, signingRegion, signingServiceName); auto finalSignature = GenerateSignature(credentials, stringToSign, simpleDate, signingRegion, signingServiceName); - - Aws::StringStream ss; - ss << AWS_HMAC_SHA256 << " " << CREDENTIAL << EQ << credentials.GetAWSAccessKeyId() << "/" << simpleDate + + Aws::StringStream ss; + ss << AWS_HMAC_SHA256 << " " << CREDENTIAL << EQ << credentials.GetAWSAccessKeyId() << "/" << simpleDate << "/" << signingRegion << "/" << signingServiceName << "/" << AWS4_REQUEST << ", " << SIGNED_HEADERS << EQ - << signedHeadersValue << ", " << SIGNATURE << EQ << HashingUtils::HexEncode(finalSignature); - - auto awsAuthString = ss.str(); - AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Signing request with: " << awsAuthString); - request.SetAwsAuthorization(awsAuthString); - request.SetSigningAccessKey(credentials.GetAWSAccessKeyId()); + << signedHeadersValue << ", " << SIGNATURE << EQ << HashingUtils::HexEncode(finalSignature); + + auto awsAuthString = ss.str(); + AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Signing request with: " << awsAuthString); + request.SetAwsAuthorization(awsAuthString); + request.SetSigningAccessKey(credentials.GetAWSAccessKeyId()); request.SetSigningRegion(signingRegion); - return true; -} - -// this works regardless if the current machine is Big/Little Endian -static void WriteBigEndian(Aws::String& str, uint64_t n) -{ - int shift = 56; - while(shift >= 0) - { - str.push_back((n >> shift) & 0xFF); - shift -= 8; - } -} - -bool AWSAuthEventStreamV4Signer::SignEventMessage(Event::Message& message, Aws::String& priorSignature) const -{ - using Event::EventHeaderValue; - - Aws::StringStream stringToSign; - stringToSign << EVENT_STREAM_PAYLOAD << NEWLINE; - const DateTime now = GetSigningTimestamp(); - const auto simpleDate = now.ToGmtString(SIMPLE_DATE_FORMAT_STR); + return true; +} + +// this works regardless if the current machine is Big/Little Endian +static void WriteBigEndian(Aws::String& str, uint64_t n) +{ + int shift = 56; + while(shift >= 0) + { + str.push_back((n >> shift) & 0xFF); + shift -= 8; + } +} + +bool AWSAuthEventStreamV4Signer::SignEventMessage(Event::Message& message, Aws::String& priorSignature) const +{ + using Event::EventHeaderValue; + + Aws::StringStream stringToSign; + stringToSign << EVENT_STREAM_PAYLOAD << NEWLINE; + const DateTime now = GetSigningTimestamp(); + const auto simpleDate = now.ToGmtString(SIMPLE_DATE_FORMAT_STR); stringToSign << now.ToGmtString(DateFormat::ISO_8601_BASIC) << NEWLINE - << simpleDate << "/" << m_region << "/" - << m_serviceName << "/aws4_request" << NEWLINE << priorSignature << NEWLINE; - - - Aws::String nonSignatureHeaders; - nonSignatureHeaders.push_back(char(sizeof(EVENTSTREAM_DATE_HEADER) - 1)); // length of the string - nonSignatureHeaders += EVENTSTREAM_DATE_HEADER; - nonSignatureHeaders.push_back(static_cast<char>(EventHeaderValue::EventHeaderType::TIMESTAMP)); // type of the value - WriteBigEndian(nonSignatureHeaders, static_cast<uint64_t>(now.Millis())); // the value of the timestamp in big-endian - - auto hashOutcome = m_hash.Calculate(nonSignatureHeaders); - if (!hashOutcome.IsSuccess()) - { - AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to hash (sha256) non-signature headers."); - return false; - } - - const auto nonSignatureHeadersHash = hashOutcome.GetResult(); - stringToSign << HashingUtils::HexEncode(nonSignatureHeadersHash) << NEWLINE; - - if (message.GetEventPayload().empty()) - { - AWS_LOGSTREAM_WARN(v4StreamingLogTag, "Attempting to sign an empty message (no payload and no headers). " - "It is unlikely that this is the intended behavior."); - } - else - { - // use a preallocatedStreamBuf to avoid making a copy. - // The Hashing API requires either Aws::String or IStream as input. - // TODO: the hashing API should be accept 'unsigned char*' as input. - Utils::Stream::PreallocatedStreamBuf streamBuf(message.GetEventPayload().data(), message.GetEventPayload().size()); - Aws::IOStream payload(&streamBuf); - hashOutcome = m_hash.Calculate(payload); - - if (!hashOutcome.IsSuccess()) - { - AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to hash (sha256) non-signature headers."); - return false; - } - const auto payloadHash = hashOutcome.GetResult(); - stringToSign << HashingUtils::HexEncode(payloadHash); - AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Payload hash - " << HashingUtils::HexEncode(payloadHash)); - } - + << simpleDate << "/" << m_region << "/" + << m_serviceName << "/aws4_request" << NEWLINE << priorSignature << NEWLINE; + + + Aws::String nonSignatureHeaders; + nonSignatureHeaders.push_back(char(sizeof(EVENTSTREAM_DATE_HEADER) - 1)); // length of the string + nonSignatureHeaders += EVENTSTREAM_DATE_HEADER; + nonSignatureHeaders.push_back(static_cast<char>(EventHeaderValue::EventHeaderType::TIMESTAMP)); // type of the value + WriteBigEndian(nonSignatureHeaders, static_cast<uint64_t>(now.Millis())); // the value of the timestamp in big-endian + + auto hashOutcome = m_hash.Calculate(nonSignatureHeaders); + if (!hashOutcome.IsSuccess()) + { + AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to hash (sha256) non-signature headers."); + return false; + } + + const auto nonSignatureHeadersHash = hashOutcome.GetResult(); + stringToSign << HashingUtils::HexEncode(nonSignatureHeadersHash) << NEWLINE; + + if (message.GetEventPayload().empty()) + { + AWS_LOGSTREAM_WARN(v4StreamingLogTag, "Attempting to sign an empty message (no payload and no headers). " + "It is unlikely that this is the intended behavior."); + } + else + { + // use a preallocatedStreamBuf to avoid making a copy. + // The Hashing API requires either Aws::String or IStream as input. + // TODO: the hashing API should be accept 'unsigned char*' as input. + Utils::Stream::PreallocatedStreamBuf streamBuf(message.GetEventPayload().data(), message.GetEventPayload().size()); + Aws::IOStream payload(&streamBuf); + hashOutcome = m_hash.Calculate(payload); + + if (!hashOutcome.IsSuccess()) + { + AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to hash (sha256) non-signature headers."); + return false; + } + const auto payloadHash = hashOutcome.GetResult(); + stringToSign << HashingUtils::HexEncode(payloadHash); + AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Payload hash - " << HashingUtils::HexEncode(payloadHash)); + } + Utils::ByteBuffer finalSignatureDigest = GenerateSignature(m_credentialsProvider->GetAWSCredentials(), stringToSign.str(), simpleDate, m_region, m_serviceName); - const auto finalSignature = HashingUtils::HexEncode(finalSignatureDigest); - AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Final computed signing hash: " << finalSignature); - priorSignature = finalSignature; - - message.InsertEventHeader(EVENTSTREAM_DATE_HEADER, EventHeaderValue(now.Millis(), EventHeaderValue::EventHeaderType::TIMESTAMP)); - message.InsertEventHeader(EVENTSTREAM_SIGNATURE_HEADER, std::move(finalSignatureDigest)); - - AWS_LOGSTREAM_INFO(v4StreamingLogTag, "Event chunk final signature - " << finalSignature); - return true; -} - -bool AWSAuthEventStreamV4Signer::ShouldSignHeader(const Aws::String& header) const -{ - return std::find(m_unsignedHeaders.cbegin(), m_unsignedHeaders.cend(), Aws::Utils::StringUtils::ToLower(header.c_str())) == m_unsignedHeaders.cend(); -} - -Utils::ByteBuffer AWSAuthEventStreamV4Signer::GenerateSignature(const AWSCredentials& credentials, const Aws::String& stringToSign, + const auto finalSignature = HashingUtils::HexEncode(finalSignatureDigest); + AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Final computed signing hash: " << finalSignature); + priorSignature = finalSignature; + + message.InsertEventHeader(EVENTSTREAM_DATE_HEADER, EventHeaderValue(now.Millis(), EventHeaderValue::EventHeaderType::TIMESTAMP)); + message.InsertEventHeader(EVENTSTREAM_SIGNATURE_HEADER, std::move(finalSignatureDigest)); + + AWS_LOGSTREAM_INFO(v4StreamingLogTag, "Event chunk final signature - " << finalSignature); + return true; +} + +bool AWSAuthEventStreamV4Signer::ShouldSignHeader(const Aws::String& header) const +{ + return std::find(m_unsignedHeaders.cbegin(), m_unsignedHeaders.cend(), Aws::Utils::StringUtils::ToLower(header.c_str())) == m_unsignedHeaders.cend(); +} + +Utils::ByteBuffer AWSAuthEventStreamV4Signer::GenerateSignature(const AWSCredentials& credentials, const Aws::String& stringToSign, const Aws::String& simpleDate, const Aws::String& region, const Aws::String& serviceName) const -{ - Utils::Threading::ReaderLockGuard guard(m_derivedKeyLock); - const auto& secretKey = credentials.GetAWSSecretKey(); - if (secretKey != m_currentSecretKey || simpleDate != m_currentDateStr) - { - guard.UpgradeToWriterLock(); - // double-checked lock to prevent updating twice - if (m_currentDateStr != simpleDate || m_currentSecretKey != secretKey) - { - m_currentSecretKey = secretKey; - m_currentDateStr = simpleDate; +{ + Utils::Threading::ReaderLockGuard guard(m_derivedKeyLock); + const auto& secretKey = credentials.GetAWSSecretKey(); + if (secretKey != m_currentSecretKey || simpleDate != m_currentDateStr) + { + guard.UpgradeToWriterLock(); + // double-checked lock to prevent updating twice + if (m_currentDateStr != simpleDate || m_currentSecretKey != secretKey) + { + m_currentSecretKey = secretKey; + m_currentDateStr = simpleDate; m_derivedKey = ComputeHash(m_currentSecretKey, m_currentDateStr, region, serviceName); - } - - } - return GenerateSignature(stringToSign, m_derivedKey); -} - -Utils::ByteBuffer AWSAuthEventStreamV4Signer::GenerateSignature(const Aws::String& stringToSign, const ByteBuffer& key) const -{ - AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Final String to sign: " << stringToSign); - - Aws::StringStream ss; - - auto hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)stringToSign.c_str(), stringToSign.length()), key); - if (!hashResult.IsSuccess()) - { - AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Unable to hmac (sha256) final string"); - AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "The final string is: \"" << stringToSign << "\""); - return {}; - } - - return hashResult.GetResult(); -} - -Aws::String AWSAuthEventStreamV4Signer::GenerateStringToSign(const Aws::String& dateValue, const Aws::String& simpleDate, - const Aws::String& canonicalRequestHash, const Aws::String& region, const Aws::String& serviceName) const -{ - //generate the actual string we will use in signing the final request. - Aws::StringStream ss; - - ss << AWS_HMAC_SHA256 << NEWLINE << dateValue << NEWLINE << simpleDate << "/" << region << "/" - << serviceName << "/" << AWS4_REQUEST << NEWLINE << canonicalRequestHash; - - return ss.str(); -} - -Aws::Utils::ByteBuffer AWSAuthEventStreamV4Signer::ComputeHash(const Aws::String& secretKey, - const Aws::String& simpleDate, const Aws::String& region, const Aws::String& serviceName) const -{ - Aws::String signingKey(SIGNING_KEY); - signingKey.append(secretKey); - auto hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)simpleDate.c_str(), simpleDate.length()), - ByteBuffer((unsigned char*)signingKey.c_str(), signingKey.length())); - - if (!hashResult.IsSuccess()) - { - AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to HMAC (SHA256) date string \"" << simpleDate << "\""); - return {}; - } - - auto kDate = hashResult.GetResult(); - hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)region.c_str(), region.length()), kDate); - if (!hashResult.IsSuccess()) - { - AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to HMAC (SHA256) region string \"" << region << "\""); - return {}; - } - - auto kRegion = hashResult.GetResult(); - hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)serviceName.c_str(), serviceName.length()), kRegion); - if (!hashResult.IsSuccess()) - { - AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to HMAC (SHA256) service string \"" << m_serviceName << "\""); - return {}; - } - - auto kService = hashResult.GetResult(); - hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)AWS4_REQUEST, strlen(AWS4_REQUEST)), kService); - if (!hashResult.IsSuccess()) - { - AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Unable to HMAC (SHA256) request string"); - AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "The request string is: \"" << AWS4_REQUEST << "\""); - return {}; - } - return hashResult.GetResult(); -} + } + + } + return GenerateSignature(stringToSign, m_derivedKey); +} + +Utils::ByteBuffer AWSAuthEventStreamV4Signer::GenerateSignature(const Aws::String& stringToSign, const ByteBuffer& key) const +{ + AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Final String to sign: " << stringToSign); + + Aws::StringStream ss; + + auto hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)stringToSign.c_str(), stringToSign.length()), key); + if (!hashResult.IsSuccess()) + { + AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Unable to hmac (sha256) final string"); + AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "The final string is: \"" << stringToSign << "\""); + return {}; + } + + return hashResult.GetResult(); +} + +Aws::String AWSAuthEventStreamV4Signer::GenerateStringToSign(const Aws::String& dateValue, const Aws::String& simpleDate, + const Aws::String& canonicalRequestHash, const Aws::String& region, const Aws::String& serviceName) const +{ + //generate the actual string we will use in signing the final request. + Aws::StringStream ss; + + ss << AWS_HMAC_SHA256 << NEWLINE << dateValue << NEWLINE << simpleDate << "/" << region << "/" + << serviceName << "/" << AWS4_REQUEST << NEWLINE << canonicalRequestHash; + + return ss.str(); +} + +Aws::Utils::ByteBuffer AWSAuthEventStreamV4Signer::ComputeHash(const Aws::String& secretKey, + const Aws::String& simpleDate, const Aws::String& region, const Aws::String& serviceName) const +{ + Aws::String signingKey(SIGNING_KEY); + signingKey.append(secretKey); + auto hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)simpleDate.c_str(), simpleDate.length()), + ByteBuffer((unsigned char*)signingKey.c_str(), signingKey.length())); + + if (!hashResult.IsSuccess()) + { + AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to HMAC (SHA256) date string \"" << simpleDate << "\""); + return {}; + } + + auto kDate = hashResult.GetResult(); + hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)region.c_str(), region.length()), kDate); + if (!hashResult.IsSuccess()) + { + AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to HMAC (SHA256) region string \"" << region << "\""); + return {}; + } + + auto kRegion = hashResult.GetResult(); + hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)serviceName.c_str(), serviceName.length()), kRegion); + if (!hashResult.IsSuccess()) + { + AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to HMAC (SHA256) service string \"" << m_serviceName << "\""); + return {}; + } + + auto kService = hashResult.GetResult(); + hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)AWS4_REQUEST, strlen(AWS4_REQUEST)), kService); + if (!hashResult.IsSuccess()) + { + AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Unable to HMAC (SHA256) request string"); + AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "The request string is: \"" << AWS4_REQUEST << "\""); + return {}; + } + return hashResult.GetResult(); +} |