예제 #1
0
 /// <summary>
 /// Creates a Signer with a clock and a parser. This is used for testing purposes.
 /// </summary>
 /// <param name="authenticationHeaderParser">
 /// the header parser
 /// </param>
 /// <param name="clock">
 /// the Clock from which to retrieve the current time
 /// </param>
 public Signer(AuthenticationHeaderParser authenticationHeaderParser, Clock clock)
 {
     this.authenticationHeaderParser = authenticationHeaderParser;
     this.clock = clock;
 }
        /// <summary>
        /// Verifies the request against a credential store.
        /// </summary>
        /// <param name="request">
        /// the request to verify.
        /// </param>
        /// <param name="credentialStore">
        /// the credential store used to verify the request.
        /// </param>
        /// <returns>
        /// true if the request validates. false for any other reason except a SigningException.
        /// </returns>
        public bool Verify(Request request, CredentialStore credentialStore)
        {
            DateTime now      = Clock.Now();
            string   strDate  = now.ToString(DateStampFormat);
            string   dateTime = request.GetHeader(XAmzDateHeader);

            if (dateTime == null)
            {
                return(false);
            }

            // Fail if the Authentication header is not found
            string actualAuthorization = request.GetHeader(AuthorizationHeader);

            if (string.IsNullOrEmpty(actualAuthorization))
            {
                return(false);
            }

            request.RemoveHeader(AuthorizationHeader);

            // Clear any header that isn't in the list of signed signedHeaders
            AuthenticationHeader authenticationHeader = AuthenticationHeaderParser.Parse(actualAuthorization);

            if (authenticationHeader == null)
            {
                return(false);
            }

            string[] signedHeaders = authenticationHeader.SignedHeaders.Split(';');

            RemoveUnsignedHeaders(request, signedHeaders);

            DateTime dateOfRequest;

            if (!DateTime.TryParseExact(dateTime, DateTimeFormat, null, DateTimeStyles.None, out dateOfRequest))
            {
                return(false);
            }

            TimeSpan timeSpan = now - dateOfRequest;

            if (Math.Abs(timeSpan.TotalMilliseconds) > TimeToleranceInMilliseconds)
            {
                return(false);
            }

            // The credential info should follow this pattern: KEYID/DATE
            string[] credentialInfo = authenticationHeader.Credential.Split('/');

            if (credentialInfo.GetLength(0) < 2)
            {
                return(false);
            }

            Credential credential;

            try
            {
                credential = credentialStore.Get(credentialInfo[0]);
            }
            catch (CredentialNotFoundException)
            {
                return(false);
            }

            byte[] timedKey         = Sign(strDate, credential.SecretKey);
            string canonicalRequest = GetCanonicalRequest(request);
            string stringToSign     = GetStringToSign(AlgorithmHeader, dateTime, EmptyScope, canonicalRequest);
            string signature        = BitConverter.ToString(Sign(stringToSign, timedKey)).Replace("-", "").ToLower();

            string computedAuthorization = GetAuthorizatioinHeader(request, credential, strDate, signature);

            return(computedAuthorization.Equals(actualAuthorization));
        }