private HmacSigningResult SignRequest(SigningContext ctx)
        {
            var result = new HmacSigningResult();

            if (ctx.Header.ContainsKey(HeaderKeys.HostHeader))
            {
                ctx.Header.Remove(HeaderKeys.HostHeader);
            }
            var hostHeader = ctx.Endpoint.Host;

            if (!ctx.Endpoint.IsDefaultPort)
            {
                hostHeader += ":" + ctx.Endpoint.Port;
            }
            ctx.Header.Add(HeaderKeys.HostHeader, hostHeader);
            result.Headers.Add(HeaderKeys.HostHeader, ctx.Header[HeaderKeys.HostHeader]);

            var signedAt         = InitializeHeaders(result);
            var credentialString = BuildCredentialString(signedAt);
            var bodyHash         = SetRequestBodyHash(ctx.Body);

            var sortedHeaders            = SortAndPruneHeaders(ctx.Header);
            var canonicalizedHeaderNames = CanonicalizeHeaderNames(sortedHeaders);

            var parametersToCanonicalize = GetParametersToCanonicalize(ctx.Query);
            var canonicalQueryParams     = CanonicalizeQueryParameters(parametersToCanonicalize);

            var canonicalRequest =
                CanonicalizeRequest(ctx.Endpoint, ctx.Method, sortedHeaders, canonicalQueryParams, bodyHash);

            var signature = ComputeSignature(ctx.Key, signedAt, credentialString, canonicalRequest);

            result.Signature = signature;
            var authorizationHeader = new StringBuilder();

            authorizationHeader.Append(Constants.FeiniuBus1AlgorithmTag);
            authorizationHeader.AppendFormat(" {0}={1}/{2},", Constants.Credential, ctx.Identifier, credentialString);
            authorizationHeader.AppendFormat("{0}={1},", Constants.SignedHeaders, canonicalizedHeaderNames);
            authorizationHeader.AppendFormat("{0}={1}", Constants.Signature, signature);
            result.Headers.Add(HeaderKeys.AuthorizationHeader, authorizationHeader.ToString());

            return(result);
        }
 public HmacSigningResult Sign(SigningContext ctx)
 {
     return(SignRequest(ctx));
 }