예제 #1
0
        public string Compose(EscherConfig config, string key, DateTime dateTime, string[] headersToSign, string stringToSign, string secret)
        {
            Array.Sort(headersToSign, StringComparer.Ordinal);

            return(String.Join(" ", new[]
            {
                config.AlgorithmPrefix + "-HMAC-" + config.HashAlgorithm.ToUpper(),
                string.Format("Credential={0}/{1}/{2},", key, dateTime.ToEscherShortDate(), config.CredentialScope),
                string.Format("SignedHeaders={0},", String.Join(";", headersToSign.Select(h => h.ToLower()))),
                "Signature=" + SignatureCalculator.Sign(stringToSign, secret, dateTime, config)
            }));
        }
예제 #2
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);
        }