public void ComposeTest(SigningTestFixture signingTestFixture) { var stringToSignComposer = new StringToSignComposer(); var stringToSign = stringToSignComposer.Compose( signingTestFixture.expected.canonicalizedRequest, signingTestFixture.config.DateTime, signingTestFixture.config.ToEscherConfig() ); Assert.AreEqual(signingTestFixture.expected.stringToSign, stringToSign, "stringToSign does not work"); }
public TRequest SignRequest <TRequest>(TRequest request, string key, string secret, string[] headersToSign, DateTime currentTime) where TRequest : IEscherRequest { currentTime = currentTime.ToUniversalTime(); AddMandatoryHeaders(request, currentTime); headersToSign = AddMandatoryHeadersToSign(headersToSign); var canonicalizedRequest = new RequestCanonicalizer().Canonicalize(request, headersToSign, Config); var stringToSign = new StringToSignComposer().Compose(canonicalizedRequest, currentTime, Config); var authHeader = new AuthHeaderComposer().Compose(Config, key, currentTime, headersToSign, stringToSign, secret); request.Headers.Add(new Header(Config.AuthHeaderName, authHeader)); return(request); }
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); }