Example #1
0
        /// <summary>
        /// Computes and returns the canonical request
        /// </summary>
        /// <param name="headersToSign">Request headers that are to be included in the signature</param>
        /// <param name="serviceEndPoint">The endpoint to the service being called</param>
        /// <param name="queryString">The query parameters for the request</param>
        /// <param name="headers">The full request headers</param>
        /// <param name="requestBody">The body of the request</param>
        /// <param name="binaryRequestBodyHash">The hash of the binary request body if present.</param>
        /// <param name="httpMethod">The http method used for the request</param>
        /// <returns>Canonicalised request as a string</returns>
        private static string GetCanonicalRequest(List <string> headersToSign,
                                                  Uri serviceEndPoint,
                                                  string queryString,
                                                  IDictionary <string, string> headers,
                                                  string requestBody,
                                                  string binaryRequestBodyHash,
                                                  string httpMethod)
        {
            StringBuilder canonicalRequest = new StringBuilder();

            canonicalRequest.AppendFormat("{0}\n", httpMethod);
            canonicalRequest.AppendFormat("{0}\n", GetCanonicalizedResourcePath(serviceEndPoint));
            canonicalRequest.AppendFormat("{0}\n", queryString);


            canonicalRequest.AppendFormat("{0}\n", GetCanonicalizedHeaders(headersToSign, headers));
            canonicalRequest.AppendFormat("{0}\n", GetSignedHeaders(headersToSign));

            if (binaryRequestBodyHash != null)
            {
                canonicalRequest.Append(binaryRequestBodyHash);
            }
            else
            {
                byte[] payloadHashBytes = CanonicalizationHash.ComputeHash(Encoding.UTF8.GetBytes(requestBody));
                canonicalRequest.Append(AWSSDKUtils.ToHex(payloadHashBytes, true));
            }

            return(canonicalRequest.ToString());
        }
        /// <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="clientConfig">The configuration that specifies which hashing algorithm to use</param>
        /// <param name="request">The request to have the signature compute for</param>
        /// <param name="secureKey">The AWS secret key stored in a secure string</param>
        /// <exception cref="Amazon.Runtime.SignatureException">If any problems are encountered while signing the request</exception>
        public override void Sign(IRequest request, ClientConfig clientConfig, string awsAccessKeyId, string awsSecretAccessKey, SecureString secureKey)
        {
            // clean up request from previous execution
            request.Headers.Remove("Authorization");

            string signingAlgorithm = SigningAlgorithm.HmacSHA256.ToString().ToUpper();

            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("{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 stringToSign = new StringBuilder();

            stringToSign.AppendFormat("{0}-{1}\n{2}\n{3}\n", SCHEME, ALGORITHM, dateTime, scope);

            byte[] canonicalRequestHashBytes = CanonicalizationHash.ComputeHash(Encoding.UTF8.GetBytes(canonicalRequest));
            stringToSign.Append(AWSSDKUtils.ToHex(canonicalRequestHashBytes, true));

            KeyedHashAlgorithm kha = KeyedHashAlgorithm.Create(signingAlgorithm);

            kha.Key = ComposeSigningKey(signingAlgorithm, awsSecretAccessKey, secureKey, region, dateStamp, service);
            byte[] signature = kha.ComputeHash(Encoding.UTF8.GetBytes(stringToSign.ToString()));

            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();
        }
Example #3
0
        /// <summary>
        /// Calculates the AWS4 signature using the supplied request parameters and AWS account credentials.
        /// </summary>
        /// <param name="headers">Request headers</param>
        /// <param name="parameters">Request AWS Query parameters to be included in the signature</param>
        /// <param name="serviceURL">Service endpoint URL</param>
        /// <param name="authenticationServiceName">
        /// The short-form name of the target service for inclusion in the signature; only needed if this
        /// cannot be determined by parsing the endpoint.
        /// </param>
        /// <param name="authenticationRegion">
        /// Region name for inclusion in the signature; only needed if this  cannot be determined by parsing
        /// the endpoint.
        /// </param>
        /// <param name="httpMethod">The HTTP method used to make the request.</param>
        /// <param name="credentials">User credentials</param>
        /// <returns>The signature string to be added as header 'Authorization' on the eventual request</returns>
        /// <exception cref="Amazon.Runtime.SignatureException">If any problems are encountered while signing the request</exception>
        public static string CalculateSignature(IDictionary <string, string> headers,
                                                IDictionary <string, string> parameters,
                                                string serviceURL,
                                                string httpMethod,
                                                string authenticationServiceName,
                                                string authenticationRegion,
                                                ImmutableCredentials credentials)
        {
            string signingAlgorithm = SigningAlgorithm.HmacSHA256.ToString().ToUpper();

            DateTime dt        = DateTime.UtcNow;
            string   dateTime  = dt.ToString(AWSSDKUtils.ISO8601BasicDateTimeFormat, CultureInfo.InvariantCulture);
            string   dateStamp = dt.ToString("yyyyMMdd", CultureInfo.InvariantCulture);

            string region;

            if (!string.IsNullOrEmpty(authenticationRegion))
            {
                region = authenticationRegion;
            }
            else
            {
                region = AWSSDKUtils.DetermineRegion(serviceURL).ToLower();
            }
            string service = authenticationServiceName.Trim().ToLower();

            headers.Add("Host", new Uri(serviceURL).Host);
            headers.Add("X-Amz-Date", dateTime);

            string scope = string.Format("{0}/{1}/{2}/{3}", dateStamp, region, service, TERMINATOR);

            List <string> headersToSign    = GetHeadersForSigning(headers);
            string        canonicalRequest = GetCanonicalRequest(headersToSign,
                                                                 new Uri(serviceURL),
                                                                 "",
                                                                 headers,
                                                                 AWSSDKUtils.GetParametersAsString(parameters),
                                                                 null, // No support for binary request body yet here.
                                                                 httpMethod);

            StringBuilder stringToSign = new StringBuilder();

            stringToSign.AppendFormat("{0}-{1}\n{2}\n{3}\n", SCHEME, ALGORITHM, dateTime, scope);

            byte[] canonicalRequestHashBytes = CanonicalizationHash.ComputeHash(Encoding.UTF8.GetBytes(canonicalRequest));
            stringToSign.Append(AWSSDKUtils.ToHex(canonicalRequestHashBytes, true));

            KeyedHashAlgorithm kha = KeyedHashAlgorithm.Create(signingAlgorithm);

            kha.Key = ComposeSigningKey(signingAlgorithm, credentials.ClearSecretKey, credentials.SecureSecretKey, region, dateStamp, service);
            byte[] signature = kha.ComputeHash(Encoding.UTF8.GetBytes(stringToSign.ToString()));

            StringBuilder authorizationHeader = new StringBuilder();

            authorizationHeader.AppendFormat("{0}-{1} ", SCHEME, ALGORITHM);
            authorizationHeader.AppendFormat("Credential={0}/{1}, ", credentials.AccessKey, scope);
            authorizationHeader.AppendFormat("SignedHeaders={0}, ", GetSignedHeaders(headersToSign));
            authorizationHeader.AppendFormat("Signature={0}", AWSSDKUtils.ToHex(signature, true));

            return(authorizationHeader.ToString());
        }
Example #4
0
        private void SignHttp(IRequest request, ClientConfig clientConfig, string awsAccessKeyId, string awsSecretAccessKey, SecureString secureKey)
        {
            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["Date"]       = date;
            request.Headers["X-Amz-Date"] = date;

            // 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["Host"] = hostHeader;

            byte[] bytesToSign;
            string stringToSign;

            if (isHttps)
            {
                request.Headers[NONCE_HEADER] = 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 = CanonicalizationHash.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));
            }

            string signature = ComputeHash(bytesToSign, awsSecretAccessKey, secureKey, 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[AUTHORIZATION_HEADER] = authorizationHeader;
        }