Ejemplo n.º 1
0
        private static IEnumerable <string> CanonicalizeHeaders(IEscherRequest request, string[] headersToSign)
        {
            var headers = request.Headers
                          .Select(NormalizeHeader)
                          .Where(h => headersToSign.Contains(h.Name))
                          .OrderBy(h => h.Name)
                          .ToArray();

            var headersAsString = new List <string>();

            foreach (var header in headers)
            {
                var currentHeader = header;

                if (headersAsString.Any(h => h.Contains(currentHeader.Name + ":")))
                {
                    continue;
                }

                var headersWithSameName = headers.Where(h => h.Name == currentHeader.Name);

                headersAsString.Add(currentHeader.Name + ":" + String.Join(",", headersWithSameName.Select(h => h.Value)));
            }

            return(headersAsString);
        }
Ejemplo n.º 2
0
        public string Canonicalize(IEscherRequest request, string[] headersToSign, EscherConfig config)
        {
            headersToSign = headersToSign.Select(h => h.ToLower()).ToArray();

            return String.Join("\n", new[]
            {
                request.Method.ToUpper(),
                request.Uri.AbsolutePath,
                CanonicalizeQueryString(request.Uri),
            }.Concat(CanonicalizeHeaders(request, headersToSign)).Concat(new[]
            {
                null,
                String.Join(";", headersToSign.OrderBy(s => s)),
                HashHelper.Hash(request.Body, config.HashAlgorithm)
            }));
        }
Ejemplo n.º 3
0
        public string Canonicalize(IEscherRequest request, string[] headersToSign, EscherConfig config)
        {
            headersToSign = headersToSign.Select(h => h.ToLower()).ToArray();

            return(String.Join("\n", new[]
            {
                request.Method.ToUpper(),
                request.Uri.AbsolutePath,
                CanonicalizeQueryString(request.Uri),
            }.Concat(CanonicalizeHeaders(request, headersToSign)).Concat(new[]
            {
                null,
                String.Join(";", headersToSign.OrderBy(s => s)),
                HashHelper.Hash(request.Body, config.HashAlgorithm)
            })));
        }
Ejemplo n.º 4
0
        private void AddMandatoryHeaders(IEscherRequest request, DateTime currentTime)
        {
            var dateHeaderPresent = request.Headers.Any(header => String.Equals(header.Name, Config.DateHeaderName, StringComparison.CurrentCultureIgnoreCase));

            if (!dateHeaderPresent)
            {
                request.Headers.Add(new Header(Config.DateHeaderName, currentTime.ToEscherLongDate()));
            }

            var hostHeaderPresent = request.Headers.Any(header => String.Equals(header.Name, "host", StringComparison.CurrentCultureIgnoreCase));

            if (!hostHeaderPresent)
            {
                request.Headers.Add(new Header("host", request.Uri.Host + (request.Uri.IsDefaultPort ? "" : ":" + request.Uri.Port)));
            }
        }
Ejemplo n.º 5
0
        private static IEnumerable<string> CanonicalizeHeaders(IEscherRequest request, string[] headersToSign)
        {
            var headers = request.Headers
                .Select(NormalizeHeader)
                .Where(h => headersToSign.Contains(h.Name))
                .OrderBy(h => h.Name)
                .ToArray();

            var headersAsString = new List<string>();

            foreach (var header in headers)
            {
                var currentHeader = header;

                if (headersAsString.Any(h => h.Contains(currentHeader.Name + ":")))
                    continue;

                var headersWithSameName = headers.Where(h => h.Name == currentHeader.Name);

                headersAsString.Add(currentHeader.Name + ":" + String.Join(",", headersWithSameName.Select(h => h.Value)));
            }

            return headersAsString;
        }
Ejemplo n.º 6
0
        public string Authenticate(IEscherRequest request, IKeyDb keyDb, DateTime currentTime)
        {
            currentTime = currentTime.ToUniversalTime();

            var authHeader = request.Headers.FirstOrDefault(header => header.Name == Config.AuthHeaderName);

            if (authHeader == null)
            {
                throw new EscherAuthenticationException("The authorization header is missing");
            }

            var dateHeader = request.Headers.FirstOrDefault(header => header.Name == Config.DateHeaderName);

            if (dateHeader == null)
            {
                throw new EscherAuthenticationException("The date header is missing");
            }

            var hostHeader = request.Headers.FirstOrDefault(header => header.Name.ToLower() == "host");

            if (hostHeader == null)
            {
                throw new EscherAuthenticationException("The host header is missing");
            }

            var match = Regex.Match(authHeader.Value, "^([^\\-]+)-HMAC-(SHA[\\d]+) Credential=([^/]+)/([\\d]{8})/([^,]+), SignedHeaders=([^,]+), Signature=([a-z0-9]+)$");

            if (!match.Success)
            {
                throw new EscherAuthenticationException("Could not parse auth header");
            }

            var algorythmPrefix = match.Groups[1].Value;
            var hashAlgorythm   = match.Groups[2].Value;
            var apiKey          = match.Groups[3].Value;
            var shortDate       = match.Groups[4].Value;
            var credentialScope = match.Groups[5].Value;
            var signedHeaders   = match.Groups[6].Value.Split(';');
            var signature       = match.Groups[7].Value;

            DateTime requestTime;

            try
            {
                requestTime = DateTime.Parse(dateHeader.Value).ToUniversalTime();
            }
            catch (FormatException)
            {
                requestTime = DateTimeParser.FromEscherLongDate(dateHeader.Value);
            }
            if (requestTime.ToUniversalTime().Date != DateTimeParser.FromEscherShortDate(shortDate).Date)
            {
                throw new EscherAuthenticationException("The Authorization header's shortDate does not match with the request date");
            }
            if (Math.Abs((currentTime - requestTime).TotalSeconds) > Config.ClockSkew)
            {
                throw new EscherAuthenticationException("The request date is not within the accepted time range");
            }

            if (credentialScope != Config.CredentialScope)
            {
                throw new EscherAuthenticationException("The credential scope is invalid");
            }

            if (!signedHeaders.Contains(Config.DateHeaderName.ToLower()))
            {
                throw new EscherAuthenticationException("The date header is not signed");
            }

            if (!signedHeaders.Contains("host"))
            {
                throw new EscherAuthenticationException("The host header is not signed");
            }

            if (!new[] { "SHA256", "SHA512" }.Contains(hashAlgorythm.ToUpper()))
            {
                throw new EscherAuthenticationException("Only SHA256 and SHA512 hash algorithms are allowed");
            }

            var secret = keyDb[apiKey];

            if (secret == null)
            {
                throw new EscherAuthenticationException("Invalid Escher key");
            }

            var canonicalizedRequest = new RequestCanonicalizer().Canonicalize(request, signedHeaders, Config);
            var stringToSign         = new StringToSignComposer().Compose(canonicalizedRequest, requestTime, Config);
            var calculatedSignature  = SignatureCalculator.Sign(stringToSign, secret, requestTime, Config);

            if (calculatedSignature != signature)
            {
                throw new EscherAuthenticationException("The signatures do not match");
            }

            return(apiKey);
        }
Ejemplo n.º 7
0
 public string Authenticate(IEscherRequest request, IKeyDb keyDb)
 {
     return(Authenticate(request, keyDb, DateTime.Now));
 }