/// <summary> /// Determines the appropriate signer and signs the request. /// </summary> /// <param name="awsAccessKeyId">The AWS public key</param> /// <param name="awsSecretAccessKey">The AWS secret key used to sign the request in clear text</param> /// <param name="metrics">Request metrics</param> /// <param name="clientConfig">The configuration that specifies which hashing algorithm to use</param> /// <param name="request">The request to have the signature compute for</param> /// <exception cref="Amazon.Runtime.SignatureException">If any problems are encountered while signing the request</exception> public override void Sign(IRequest request, ClientConfig clientConfig, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey) { var aws4Signer = SelectSigner(clientConfig) as AWS4Signer; if (aws4Signer != null) aws4Signer.Sign(request, clientConfig, metrics, awsAccessKeyId, awsSecretAccessKey); else base.Sign(request, clientConfig, metrics, awsAccessKeyId, awsSecretAccessKey); }
/// <summary> /// Calculates and signs the specified request using the AWS4 signing protocol by using the /// AWS account credentials given in the method parameters. The resulting signature is added /// to the request headers as 'Authorization'. Parameters supplied in the request, either in /// the resource path as a query string or in the Parameters collection must not have been /// uri encoded. If they have, use the SignRequest method to obtain a signature. /// </summary> /// <param name="request"> /// The request to compute the signature for. Additional headers mandated by the AWS4 protocol /// ('host' and 'x-amz-date') will be added to the request before signing. /// </param> /// <param name="clientConfig"> /// Client configuration data encompassing the service call (notably authentication /// region, endpoint and service name). /// </param> /// <param name="metrics"> /// Metrics for the request /// </param> /// <param name="awsAccessKeyId"> /// The AWS public key for the account making the service call. /// </param> /// <param name="awsSecretAccessKey"> /// The AWS secret key for the account making the call, in clear text. /// </param> /// <exception cref="Amazon.Runtime.SignatureException"> /// If any problems are encountered while signing the request. /// </exception> public override void Sign(IRequest request, ClientConfig clientConfig, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey) { var signingResult = SignRequest(request, clientConfig, metrics, awsAccessKeyId, awsSecretAccessKey); request.Headers[HeaderKeys.AuthorizationHeader] = signingResult.ForAuthorizationHeader; }
public override UnmarshallerContext CreateContext(IWebResponseData response, bool readEntireResponse, Stream stream, RequestMetrics metrics) { if (response.IsHeaderPresent(HeaderKeys.XAmzId2Header)) metrics.AddProperty(Metric.AmzId2, response.GetHeaderValue(HeaderKeys.XAmzId2Header)); if (response.IsHeaderPresent(HeaderKeys.XAmzCloudFrontIdHeader)) metrics.AddProperty(Metric.AmzCfId, response.GetHeaderValue(HeaderKeys.XAmzCloudFrontIdHeader)); return base.CreateContext(response, readEntireResponse, stream, metrics); }
internal void SignRequest(IRequest request, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey) { request.Headers[HeaderKeys.XAmzDateHeader] = AWSSDKUtils.FormattedCurrentTimestampRFC822; var stringToSign = BuildStringToSign(request); metrics.AddProperty(Metric.StringToSign, stringToSign); var auth = CryptoUtilFactory.CryptoInstance.HMACSign(stringToSign, awsSecretAccessKey, SigningAlgorithm.HmacSHA1); var authorization = string.Concat("AWS ", awsAccessKeyId, ":", auth); request.Headers[HeaderKeys.AuthorizationHeader] = authorization; }
public override void Sign(IRequest request, ClientConfig clientConfig, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey) { request.Headers["x-amz-date"] = AWSSDKUtils.FormattedCurrentTimestampRFC822; string toSign = buildSigningString(request.HttpMethod, request.CanonicalResource, request.Parameters, request.Headers); metrics.AddProperty(Metric.StringToSign, toSign); string auth = CryptoUtilFactory.CryptoInstance.HMACSign(toSign, awsSecretAccessKey, SigningAlgorithm.HmacSHA1); string authorization = string.Concat("AWS ", awsAccessKeyId, ":", auth); request.Headers[S3QueryParameter.Authorization.ToString()] = authorization; }
/// <summary> /// Calculates and signs the specified request using the AWS4 signing protocol by using the /// AWS account credentials given in the method parameters. /// </summary> /// <param name="awsAccessKeyId">The AWS public key</param> /// <param name="awsSecretAccessKey">The AWS secret key used to sign the request in clear text</param> /// <param name="metrics">Request metrics</param> /// <param name="clientConfig">The configuration that specifies which hashing algorithm to use</param> /// <param name="request">The request to have the signature compute for</param> /// <exception cref="Amazon.Runtime.SignatureException">If any problems are encountered while signing the request</exception> public override void Sign(IRequest request, ClientConfig clientConfig, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey) { // clean up request from previous execution request.Headers.Remove("Authorization"); SigningAlgorithm signingAlgorithm = SigningAlgorithm.HmacSHA256; DateTime dt = DateTime.UtcNow; string dateTime = dt.ToString(AWSSDKUtils.ISO8601BasicDateTimeFormat, CultureInfo.InvariantCulture); string dateStamp = dt.ToString("yyyyMMdd", CultureInfo.InvariantCulture); string region = DetermineRegion(clientConfig); string service = DetermineService(clientConfig); if (!request.Headers.ContainsKey("Host")) { string hostHeader = request.Endpoint.Host; if (!request.Endpoint.IsDefaultPort) hostHeader += ":" + request.Endpoint.Port; request.Headers.Add("Host", hostHeader); } request.Headers["X-Amz-Date"] = dateTime; string scope = string.Format(CultureInfo.InvariantCulture, "{0}/{1}/{2}/{3}", dateStamp, region, service, TERMINATOR); List<string> headersToSign = GetHeadersForSigning(request.Headers); var queryString = request.UseQueryString ? AWSSDKUtils.GetParametersAsString(request.Parameters) : ""; string canonicalRequest = GetCanonicalRequest(headersToSign, new Uri(request.Endpoint, request.ResourcePath), queryString, request.Headers, request.UseQueryString ? "" : GetRequestPayload(request), request.ContentStreamHash, request.HttpMethod); StringBuilder stringToSignBuilder = new StringBuilder(); stringToSignBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}-{1}\n{2}\n{3}\n", SCHEME, ALGORITHM, dateTime, scope); byte[] canonicalRequestHashBytes = CryptoUtilFactory.CryptoInstance.ComputeSHA256Hash(Encoding.UTF8.GetBytes(canonicalRequest)); stringToSignBuilder.Append(AWSSDKUtils.ToHex(canonicalRequestHashBytes, true)); byte[] hashKey = ComposeSigningKey(signingAlgorithm, awsSecretAccessKey, region, dateStamp, service); string stringToSign = stringToSignBuilder.ToString(); metrics.AddProperty(Metric.StringToSign, stringToSign); byte[] signature = CryptoUtilFactory.CryptoInstance.HMACSignBinary(Encoding.UTF8.GetBytes(stringToSign), hashKey, SigningAlgorithm.HmacSHA256); StringBuilder authorizationHeader = new StringBuilder(); authorizationHeader.AppendFormat("{0}-{1} ", SCHEME, ALGORITHM); authorizationHeader.AppendFormat("Credential={0}/{1}, ", awsAccessKeyId, scope); authorizationHeader.AppendFormat("SignedHeaders={0}, ", GetSignedHeaders(headersToSign)); authorizationHeader.AppendFormat("Signature={0}", AWSSDKUtils.ToHex(signature, true)); request.Headers["Authorization"] = authorizationHeader.ToString(); }
/// <summary> /// Signs the specified request with the AWS3 signing protocol by using the /// AWS account credentials given in the method parameters. /// </summary> /// <param name="awsAccessKeyId">The AWS public key</param> /// <param name="awsSecretAccessKey">The AWS secret key used to sign the request in clear text</param> /// <param name="metrics">Request metrics</param> /// <param name="clientConfig">The configuration that specifies which hashing algorithm to use</param> /// <param name="request">The request to have the signature compute for</param> /// <exception cref="Amazon.Runtime.SignatureException">If any problems are encountered while signing the request</exception> public override void Sign(IRequest request, ClientConfig clientConfig, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey) { if (UseAws3Https) { SignHttps(request, clientConfig, metrics, awsAccessKeyId, awsSecretAccessKey); } else { SignHttp(request, metrics, awsAccessKeyId, awsSecretAccessKey); } }
public override void Sign(IRequest request, ClientConfig clientConfig, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey) { var aws4Signer = SelectSigner(clientConfig) as AWS4Signer; if (aws4Signer != null) { var signingResult = aws4Signer.SignRequest(request, clientConfig, metrics, awsAccessKeyId, awsSecretAccessKey); request.Headers[HeaderKeys.AuthorizationHeader] = signingResult.ForAuthorizationHeader; if (request.UseChunkEncoding) request.AWS4SignerResult = signingResult; } else SignRequest(request, metrics, awsAccessKeyId, awsSecretAccessKey); }
public override void Sign(IRequest request, ClientConfig clientConfig, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey) { if (String.IsNullOrEmpty(awsAccessKeyId)) { throw new ArgumentOutOfRangeException("awsAccessKeyId", "The AWS Access Key ID cannot be NULL or a Zero length string"); } string dateTime = AWSSDKUtils.GetFormattedTimestampRFC822(0); request.Headers.Add(HeaderKeys.XAmzDateHeader, dateTime); string signature = ComputeHash(dateTime, awsSecretAccessKey, SigningAlgorithm.HmacSHA1); request.Headers.Add(HeaderKeys.AuthorizationHeader, "AWS " + awsAccessKeyId + ":" + signature); }
/// <summary> /// Determines the appropriate signer and signs the request. /// </summary> /// <param name="awsAccessKeyId">The AWS public key</param> /// <param name="awsSecretAccessKey">The AWS secret key used to sign the request in clear text</param> /// <param name="metrics">Request metrics</param> /// <param name="clientConfig">The configuration that specifies which hashing algorithm to use</param> /// <param name="request">The request to have the signature compute for</param> /// <exception cref="Amazon.Runtime.SignatureException">If any problems are encountered while signing the request</exception> public override void Sign(IRequest request, ClientConfig clientConfig, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey) { var signer = SelectSigner(querySigner, _useSigV4, request, clientConfig); var useV4 = signer is AWS4Signer; if (useV4) { if (request.Parameters.ContainsKey("SecurityToken")) { var token = request.Parameters["SecurityToken"]; request.Parameters.Remove("SecurityToken"); request.Headers[HeaderKeys.XAmzSecurityTokenHeader] = token; } } signer.Sign(request, clientConfig, metrics, awsAccessKeyId, awsSecretAccessKey); }
/// <summary> /// Signs the specified request with the AWS3 signing protocol by using the /// AWS account credentials given in the method parameters. /// </summary> /// <param name="awsAccessKeyId">The AWS public key</param> /// <param name="awsSecretAccessKey">The AWS secret key used to sign the request in clear text</param> /// <param name="metrics">Request metrics</param> /// <param name="clientConfig">The configuration that specifies which hashing algorithm to use</param> /// <param name="request">The request to have the signature compute for</param> /// <exception cref="Amazon.Runtime.SignatureException">If any problems are encountered while signing the request</exception> public override void Sign(IRequest request, ClientConfig clientConfig, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey) { var signer = SelectSigner(request, clientConfig); var useV4 = signer is AWS4Signer; if (useV4) signer.Sign(request, clientConfig, metrics, awsAccessKeyId, awsSecretAccessKey); else { if (UseAws3Https) { SignHttps(request, clientConfig, metrics, awsAccessKeyId, awsSecretAccessKey); } else { SignHttp(request, metrics, awsAccessKeyId, awsSecretAccessKey); } } }
private static void SignHttps(IRequest request, ClientConfig clientConfig, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey) { string nonce = Guid.NewGuid().ToString(); string date = AWSSDKUtils.FormattedCurrentTimestampRFC822; string stringToSign; stringToSign = date + nonce; metrics.AddProperty(Metric.StringToSign, stringToSign); string signature = ComputeHash(stringToSign, awsSecretAccessKey, clientConfig.SignatureMethod); StringBuilder builder = new StringBuilder(); builder.Append(HTTPS_SCHEME).Append(" "); builder.Append("AWSAccessKeyId=" + awsAccessKeyId + ","); builder.Append("Algorithm=" + clientConfig.SignatureMethod.ToString() + ","); builder.Append("SignedHeaders=x-amz-date;x-amz-nonce,"); builder.Append("Signature=" + signature); request.Headers[HeaderKeys.XAmzAuthorizationHeader] = builder.ToString(); request.Headers[HeaderKeys.XAmzNonceHeader] = nonce; request.Headers[HeaderKeys.XAmzDateHeader] = date; }
internal TimingEvent(RequestMetrics metrics, Metric metric) { this.metrics = metrics; this.metric = metric; }
internal TimingEvent(RequestMetrics metrics, Metric metric) { this.metrics = metrics; this.metric = metric; }
public abstract void Sign(IRequest request, ClientConfig clientConfig, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey);
/// <summary> /// Calculates the AWS4 signature for a presigned url. /// </summary> /// <param name="request"> /// The request to compute the signature for. Additional headers mandated by the AWS4 protocol /// ('host' and 'x-amz-date') will be added to the request before signing. If the Expires parameter /// is present, it is renamed to 'X-Amz-Expires' before signing. /// </param> /// <param name="clientConfig"> /// Adding supporting data for the service call required by the signer (notably authentication /// region, endpoint and service name). /// </param> /// <param name="metrics"> /// Metrics for the request /// </param> /// <param name="awsAccessKeyId"> /// The AWS public key for the account making the service call. /// </param> /// <param name="awsSecretAccessKey"> /// The AWS secret key for the account making the call, in clear text /// </param> /// <param name="service"> /// The service to sign for /// </param> /// <param name="overrideSigningRegion"> /// The region to sign to, if null then the region the client is configured for will be used. /// </param> /// <exception cref="Amazon.Runtime.SignatureException"> /// If any problems are encountered while signing the request. /// </exception> /// <remarks> /// Parameters passed as part of the resource path should be uri-encoded prior to /// entry to the signer. Parameters passed in the request.Parameters collection should /// be not be encoded; encoding will be done for these parameters as part of the /// construction of the canonical request. /// </remarks> public static AWS4SigningResult SignRequest(IRequest request, ClientConfig clientConfig, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey, string service, string overrideSigningRegion) { // clean up any prior signature in the headers if resigning request.Headers.Remove(HeaderKeys.AuthorizationHeader); if (!request.Headers.ContainsKey(HeaderKeys.HostHeader)) { var hostHeader = request.Endpoint.Host; if (!request.Endpoint.IsDefaultPort) hostHeader += ":" + request.Endpoint.Port; request.Headers.Add(HeaderKeys.HostHeader, hostHeader); } var signedAt = AWSSDKUtils.CorrectedUtcNow; var region = overrideSigningRegion ?? DetermineSigningRegion(clientConfig, service, request.AlternateEndpoint, request); // AWS4 presigned urls got S3 are expected to contain a 'UNSIGNED-PAYLOAD' magic string // during signing (other services use the empty-body sha) if (request.Headers.ContainsKey(HeaderKeys.XAmzContentSha256Header)) request.Headers.Remove(HeaderKeys.XAmzContentSha256Header); var sortedHeaders = SortHeaders(request.Headers); var canonicalizedHeaderNames = CanonicalizeHeaderNames(sortedHeaders); var parametersToCanonicalize = GetParametersToCanonicalize(request); parametersToCanonicalize.Add(XAmzAlgorithm, AWS4AlgorithmTag); parametersToCanonicalize.Add(XAmzCredential, string.Format(CultureInfo.InvariantCulture, "{0}/{1}/{2}/{3}/{4}", awsAccessKeyId, FormatDateTime(signedAt, AWSSDKUtils.ISO8601BasicDateFormat), region, service, Terminator)); parametersToCanonicalize.Add(HeaderKeys.XAmzDateHeader, FormatDateTime(signedAt, AWSSDKUtils.ISO8601BasicDateTimeFormat)); parametersToCanonicalize.Add(HeaderKeys.XAmzSignedHeadersHeader, canonicalizedHeaderNames); var canonicalQueryParams = CanonicalizeQueryParameters(parametersToCanonicalize); var canonicalRequest = CanonicalizeRequest(request.ResourcePath, request.HttpMethod, sortedHeaders, canonicalQueryParams, service == "s3" ? UnsignedPayload : EmptyBodySha256); if (metrics != null) metrics.AddProperty(Metric.CanonicalRequest, canonicalRequest); return ComputeSignature(awsAccessKeyId, awsSecretAccessKey, region, signedAt, service, canonicalizedHeaderNames, canonicalRequest, metrics); }
/// <summary> /// Calculates the AWS4 signature for a presigned url. /// </summary> /// <param name="request"> /// The request to compute the signature for. Additional headers mandated by the AWS4 protocol /// ('host' and 'x-amz-date') will be added to the request before signing. If the Expires parameter /// is present, it is renamed to 'X-Amz-Expires' before signing. /// </param> /// <param name="clientConfig"> /// Adding supporting data for the service call required by the signer (notably authentication /// region, endpoint and service name). /// </param> /// <param name="metrics"> /// Metrics for the request /// </param> /// <param name="awsAccessKeyId"> /// The AWS public key for the account making the service call. /// </param> /// <param name="awsSecretAccessKey"> /// The AWS secret key for the account making the call, in clear text /// </param> /// <exception cref="Amazon.Runtime.SignatureException"> /// If any problems are encountered while signing the request. /// </exception> /// <remarks> /// Parameters passed as part of the resource path should be uri-encoded prior to /// entry to the signer. Parameters passed in the request.Parameters collection should /// be not be encoded; encoding will be done for these parameters as part of the /// construction of the canonical request. /// </remarks> public new AWS4SigningResult SignRequest(IRequest request, ClientConfig clientConfig, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey) { return SignRequest(request, clientConfig, metrics, awsAccessKeyId, awsSecretAccessKey, "s3", null); }
/// <summary> /// Calculates and signs the specified request using the AWS4 signing protocol by using the /// AWS account credentials given in the method parameters. The resulting signature is added /// to the request headers as 'Authorization'. /// </summary> /// <param name="request"> /// The request to compute the signature for. Additional headers mandated by the AWS4 protocol /// ('host' and 'x-amz-date') will be added to the request before signing. /// </param> /// <param name="clientConfig"> /// Adding supporting data for the service call required by the signer (notably authentication /// region, endpoint and service name). /// </param> /// <param name="metrics"> /// Metrics for the request /// </param> /// <param name="awsAccessKeyId"> /// The AWS public key for the account making the service call. /// </param> /// <param name="awsSecretAccessKey"> /// The AWS secret key for the account making the call, in clear text /// </param> /// <exception cref="Amazon.Runtime.SignatureException"> /// If any problems are encountered while signing the request. /// </exception> public override void Sign(IRequest request, ClientConfig clientConfig, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey) { throw new InvalidOperationException("PreSignedUrl signature computation is not supported by this method; use SignRequest instead."); }
/// <summary> /// Computes and returns an AWS4 signature for the specified canonicalized request /// </summary> /// <param name="awsAccessKey"></param> /// <param name="awsSecretAccessKey"></param> /// <param name="region"></param> /// <param name="signedAt"></param> /// <param name="service"></param> /// <param name="signedHeaders"></param> /// <param name="canonicalRequest"></param> /// <param name="metrics"></param> /// <returns></returns> public static AWS4SigningResult ComputeSignature(string awsAccessKey, string awsSecretAccessKey, string region, DateTime signedAt, string service, string signedHeaders, string canonicalRequest, RequestMetrics metrics) { var dateStamp = FormatDateTime(signedAt, AWSSDKUtils.ISO8601BasicDateFormat); var scope = string.Format(CultureInfo.InvariantCulture, "{0}/{1}/{2}/{3}", dateStamp, region, service, Terminator); var stringToSignBuilder = new StringBuilder(); stringToSignBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}-{1}\n{2}\n{3}\n", Scheme, Algorithm, FormatDateTime(signedAt, AWSSDKUtils.ISO8601BasicDateTimeFormat), scope); var canonicalRequestHashBytes = ComputeHash(canonicalRequest); stringToSignBuilder.Append(AWSSDKUtils.ToHex(canonicalRequestHashBytes, true)); if (metrics != null) metrics.AddProperty(Metric.StringToSign, stringToSignBuilder); var key = ComposeSigningKey(awsSecretAccessKey, region, dateStamp, service); var stringToSign = stringToSignBuilder.ToString(); var signature = ComputeKeyedHash(SignerAlgorithm, key, stringToSign); return new AWS4SigningResult(awsAccessKey, signedAt, signedHeaders, scope, key, signature); }
/// <summary> /// Calculates and signs the specified request using the AWS4 signing protocol by using the /// AWS account credentials given in the method parameters. /// </summary> /// <param name="request"> /// The request to compute the signature for. Additional headers mandated by the AWS4 protocol /// ('host' and 'x-amz-date') will be added to the request before signing. /// </param> /// <param name="clientConfig"> /// Client configuration data encompassing the service call (notably authentication /// region, endpoint and service name). /// </param> /// <param name="metrics"> /// Metrics for the request. /// </param> /// <param name="awsAccessKeyId"> /// The AWS public key for the account making the service call. /// </param> /// <param name="awsSecretAccessKey"> /// The AWS secret key for the account making the call, in clear text. /// </param> /// <exception cref="Amazon.Runtime.SignatureException"> /// If any problems are encountered while signing the request. /// </exception> /// <remarks> /// Parameters passed as part of the resource path should be uri-encoded prior to /// entry to the signer. Parameters passed in the request.Parameters collection should /// be not be encoded; encoding will be done for these parameters as part of the /// construction of the canonical request. /// </remarks> public AWS4SigningResult SignRequest(IRequest request, ClientConfig clientConfig, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey) { var signedAt = InitializeHeaders(request.Headers, request.Endpoint); var service = DetermineService(clientConfig); var region = DetermineSigningRegion(clientConfig, service, request.AlternateEndpoint, request); var parametersToCanonicalize = GetParametersToCanonicalize(request); var canonicalParameters = CanonicalizeQueryParameters(parametersToCanonicalize); var bodyHash = SetRequestBodyHash(request); var sortedHeaders = SortHeaders(request.Headers); var canonicalRequest = CanonicalizeRequest(request.ResourcePath, request.HttpMethod, sortedHeaders, canonicalParameters, bodyHash); if (metrics != null) metrics.AddProperty(Metric.CanonicalRequest, canonicalRequest); return ComputeSignature(awsAccessKeyId, awsSecretAccessKey, region, signedAt, service, CanonicalizeHeaderNames(sortedHeaders), canonicalRequest, metrics); }
private static void SignHttp(IRequest request, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey) { SigningAlgorithm algorithm = SigningAlgorithm.HmacSHA256; string nonce = Guid.NewGuid().ToString(); string date = AWSSDKUtils.FormattedCurrentTimestampRFC822; bool isHttps = IsHttpsRequest(request); // Temporarily disabling the AWS3 HTTPS signing scheme and only using AWS3 HTTP isHttps = false; request.Headers[HeaderKeys.DateHeader] = date; request.Headers[HeaderKeys.XAmzDateHeader] = date; // Clear out existing auth header (can be there if retry) request.Headers.Remove(HeaderKeys.XAmzAuthorizationHeader); // AWS3 HTTP requires that we sign the Host header // so we have to have it in the request by the time we sign. string hostHeader = request.Endpoint.Host; if (!request.Endpoint.IsDefaultPort) hostHeader += ":" + request.Endpoint.Port; request.Headers[HeaderKeys.HostHeader] = hostHeader; byte[] bytesToSign = null; string stringToSign; if (isHttps) { request.Headers[HeaderKeys.XAmzNonceHeader] = nonce; stringToSign = date + nonce; bytesToSign = Encoding.UTF8.GetBytes(stringToSign); } else { Uri url = request.Endpoint; if (!string.IsNullOrEmpty(request.ResourcePath)) url = new Uri(request.Endpoint, request.ResourcePath); stringToSign = request.HttpMethod + "\n" + GetCanonicalizedResourcePath(url) + "\n" + GetCanonicalizedQueryString(request.Parameters) + "\n" + GetCanonicalizedHeadersForStringToSign(request) + "\n" + GetRequestPayload(request); bytesToSign = CryptoUtilFactory.CryptoInstance.ComputeSHA256Hash(Encoding.UTF8.GetBytes(stringToSign)); } metrics.AddProperty(Metric.StringToSign, stringToSign); string signature = ComputeHash(bytesToSign, awsSecretAccessKey, algorithm); StringBuilder builder = new StringBuilder(); builder.Append(isHttps ? HTTPS_SCHEME : HTTP_SCHEME); builder.Append(" "); builder.Append("AWSAccessKeyId=" + awsAccessKeyId + ","); builder.Append("Algorithm=" + algorithm.ToString() + ","); if (!isHttps) { builder.Append(GetSignedHeadersComponent(request) + ","); } builder.Append("Signature=" + signature); string authorizationHeader = builder.ToString(); request.Headers[HeaderKeys.XAmzAuthorizationHeader] = authorizationHeader; }
/// <summary> /// Calculates the AWS4 signature for a presigned url. /// </summary> /// <param name="request"> /// The request to compute the signature for. Additional headers mandated by the AWS4 protocol /// ('host' and 'x-amz-date') will be added to the request before signing. If the Expires parameter /// is present, it is renamed to 'X-Amz-Expires' before signing. /// </param> /// <param name="clientConfig"> /// Adding supporting data for the service call required by the signer (notably authentication /// region, endpoint and service name). /// </param> /// <param name="metrics"> /// Metrics for the request /// </param> /// <param name="awsAccessKeyId"> /// The AWS public key for the account making the service call. /// </param> /// <param name="awsSecretAccessKey"> /// The AWS secret key for the account making the call, in clear text /// </param> /// <param name="service"> /// The service to sign for /// </param> /// <param name="overrideSigningRegion"> /// The region to sign to, if null then the region the client is configured for will be used. /// </param> /// <exception cref="Amazon.Runtime.SignatureException"> /// If any problems are encountered while signing the request. /// </exception> /// <remarks> /// Parameters passed as part of the resource path should be uri-encoded prior to /// entry to the signer. Parameters passed in the request.Parameters collection should /// be not be encoded; encoding will be done for these parameters as part of the /// construction of the canonical request. /// </remarks> public static AWS4SigningResult SignRequest(IRequest request, ClientConfig clientConfig, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey, string service, string overrideSigningRegion) { // clean up any prior signature in the headers if resigning request.Headers.Remove(AuthorizationHeader); if (!request.Headers.ContainsKey(HostHeader)) { var hostHeader = request.Endpoint.Host; if (!request.Endpoint.IsDefaultPort) hostHeader += ":" + request.Endpoint.Port; request.Headers.Add(HostHeader, hostHeader); } var signedAt = DateTime.UtcNow; var region = overrideSigningRegion == null ? DetermineSigningRegion(clientConfig, service) : overrideSigningRegion; // remove any hash supplied in headers in favor of the 'unsigned-payload' expected by AWS4 if (request.Headers.ContainsKey(XAmzContentSha256)) request.Headers.Remove(XAmzContentSha256); var sortedHeaders = SortHeaders(request.Headers); var canonicalizedHeaderNames = CanonicalizeHeaderNames(sortedHeaders); // add the auth parameters for canonicalization to a copy of the parameters so we don't // end up adding url encoded data to the url subsquently var copiedParameters = new Dictionary<string, string>(request.Parameters) { {XAmzAlgorithm, string.Format(CultureInfo.InvariantCulture, "{0}-{1}", Scheme, Algorithm)}, { XAmzCredential, string.Format(CultureInfo.InvariantCulture, "{0}/{1}/{2}/{3}/{4}", awsAccessKeyId, FormatDateTime(signedAt, AWSSDKUtils.ISO8601BasicDateFormat), region, service, Terminator) }, {XAmzDate, FormatDateTime(signedAt, AWSSDKUtils.ISO8601BasicDateTimeFormat)}, {XAmzSignedHeaders, canonicalizedHeaderNames} }; var canonicalQueryParams = CanonicalizeQueryParameters(copiedParameters); var canonicalRequest = CanonicalizeRequest(request.ResourcePath, request.HttpMethod, sortedHeaders, canonicalQueryParams, service == "s3" ? UnsignedPayload : EmptyBodySha256); if (metrics != null) metrics.AddProperty(Metric.CanonicalRequest, canonicalRequest); return ComputeSignature(awsAccessKeyId, awsSecretAccessKey, region, signedAt, service, canonicalizedHeaderNames, canonicalRequest, metrics); }
/// <summary> /// Calculates and signs the specified request using the AWS4 signing protocol by using the /// AWS account credentials given in the method parameters. /// </summary> /// <param name="request"> /// The request to compute the signature for. Additional headers mandated by the AWS4 protocol /// ('host' and 'x-amz-date') will be added to the request before signing. /// </param> /// <param name="clientConfig"> /// Client configuration data encompassing the service call (notably authentication /// region, endpoint and service name). /// </param> /// <param name="metrics"> /// Metrics for the request. /// </param> /// <param name="awsAccessKeyId"> /// The AWS public key for the account making the service call. /// </param> /// <param name="awsSecretAccessKey"> /// The AWS secret key for the account making the call, in clear text. /// </param> /// <exception cref="Amazon.Runtime.SignatureException"> /// If any problems are encountered while signing the request. /// </exception> /// <remarks> /// Parameters passed as part of the resource path should be uri-encoded prior to /// entry to the signer. Parameters passed in the request.Parameters collection should /// be not be encoded; encoding will be done for these parameters as part of the /// construction of the canonical request. /// </remarks> public AWS4SigningResult SignRequest(IRequest request, ClientConfig clientConfig, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey) { var signedAt = InitializeHeaders(request.Headers, request.Endpoint); var service = DetermineService(clientConfig); var region = DetermineSigningRegion(clientConfig, service); var resourcePathParamStart = -1; var resourcePath = string.Empty; // Extract the true resource path, less any query parameters or sub resource if (!string.IsNullOrEmpty(request.ResourcePath)) { resourcePathParamStart = request.ResourcePath.IndexOf('?'); resourcePath = resourcePathParamStart == -1 ? request.ResourcePath : request.ResourcePath.Substring(0, resourcePathParamStart); } // if UseQueryString is indicated and Parameters are present, canonicalize those (including uri encoding them) // otherwise if we spotted parameters in the resource path, canonicalize those instead (which should be encoded // already) var canonicalQueryParams = string.Empty; if (request.UseQueryString && request.Parameters.Count > 0) canonicalQueryParams = CanonicalizeQueryParameters(request.Parameters); else if (resourcePathParamStart != -1) canonicalQueryParams = CanonicalizeQueryParameters(request.ResourcePath.Substring(resourcePathParamStart + 1), false); var bodyHash = SetRequestBodyHash(request); var sortedHeaders = SortHeaders(request.Headers); var canonicalRequest = CanonicalizeRequest(resourcePath, request.HttpMethod, sortedHeaders, canonicalQueryParams, bodyHash); if (metrics != null) metrics.AddProperty(Metric.CanonicalRequest, canonicalRequest); return ComputeSignature(awsAccessKeyId, awsSecretAccessKey, region, signedAt, service, CanonicalizeHeaderNames(sortedHeaders), canonicalRequest, metrics); }