private async Task <bool> IsMd5Valid(HttpRequestMessage requestMessage)
        {
            var hashHeader = requestMessage.Content.Headers.ContentMD5;

            //Console.WriteLine("Content-MD5:"+Convert.ToBase64String(hashHeader));
            if (requestMessage.Content == null)
            {
                return(hashHeader == null || hashHeader.Length == 0);
            }
            var headerMd5Bytes = requestMessage.Content.Headers.ContentMD5;
            var bytesContent   = await requestMessage.Content.ReadAsByteArrayAsync();

            var contentMd5Bytes = MD5Helper.ComputeHash(bytesContent);

            if (!headerMd5Bytes.SequenceEqual(contentMd5Bytes))
            {
                //md5二次判断是为了兼容Java语言生成的MD5值,下面的代码用于比较java生成的Md5与C#进行比对。
                //对于C# 直接比较MD5的md5 byte[]即可,无需比较C# md5的Bit形式
                var headerMd5 = Convert.ToBase64String(headerMd5Bytes);//这个用于还原在java中放入Content-MD5中的String
                var md5       = BitConverter.ToString(contentMd5Bytes).Replace("-", "");
                // mLogger.Debug(string.Format("Md5 Compare(header and server calculate):\r\n{0}\r\n{1}",headerMd5,md5));
                //  Log.D(string.Format("Md5 Compare(header and server calculate):\r\n{0}\r\n{1}", headerMd5, md5));
                return(string.Compare(md5, headerMd5, true) == 0);//不区分大小写进行比较
            }
            return(true);

            //var hash = await MD5Helper.ComputeHash(requestMessage.Content);
            //return hash.SequenceEqual(hashHeader);
        }
Beispiel #2
0
        public void MD5_Basic_uppercase()
        {
            string input          = "MD5 test ABC _ 123 $%^";
            string outputExpected = "13D3CD6193EDDBB721D0D19513BE210F";

            string outputFunction = MD5Helper.ComputeHash(input, true);

            Assert.AreEqual(outputExpected, outputFunction, "MD5 hash should be as expected.");
        }
Beispiel #3
0
        public void MD5_Basic_lowercase()
        {
            string input          = "MD5 test ABC _ 123 $%^";
            string outputExpected = "13d3cd6193eddbb721d0d19513be210f";

            string outputFunction = MD5Helper.ComputeHash(input, false);

            Assert.AreEqual(outputExpected, outputFunction, "MD5 hash should be as expected.");
        }
        private static byte[] ComputeHash(byte[] content, string algorithm)
        {
            switch (algorithm.ToUpper())
            {
            case "MD5":
                return(MD5Helper.ComputeHash(content));

            case "SHA256":
                return(SHA256Helper.ComputeHash(content));

            case "SHA384":
                return(SHA384Helper.ComputeHash(content));

            case "SHA512":
                return(SHA512Helper.ComputeHash(content));

            default:
                return(SHA1Helper.ComputeHash(content));
            }
        }
Beispiel #5
0
        /// <summary>
        /// Validates the request message content header, <c>ContentMD5</c>, matches a newly calculated MD5 hash of the content.
        /// </summary>
        /// <param name="requestMessage">The request message to have its content validated.</param>
        /// <returns><c>true</c> if the MD5 hash of the request content matches the <c>ContentMD5</c> content header; <c>false</c> otherwise.</returns>
        private async Task <bool> IsMd5Valid(HttpRequestMessage requestMessage)
        {
            var content          = requestMessage.Content;
            var contentMD5Header = requestMessage.Content?.Headers?.ContentMD5;

            // Validate that if there is no content then the there is also no ContentMD5 header (i.e. message body wasn't removed).
            if (content == null || content.Headers.ContentLength == 0)
            {
                return((contentMD5Header == null) || (contentMD5Header.Length == 0));
            }

            // Validate that if there is content then there is also a ContentMD5 header (i.e. contentMD5 header wasn't removed or left out).
            else if ((content.Headers.ContentLength > 0) && ((contentMD5Header == null) || (contentMD5Header.Length == 0)))
            {
                return(false);
            }

            // Validate the ContentMD5 header matches our calculated hash.
            var hash = await MD5Helper.ComputeHash(content);

            return(hash.SequenceEqual(contentMD5Header));
        }
Beispiel #6
0
        protected override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            string reqSignature          = "";
            HttpResponseMessage response = null;

            // Get digital signature if available.
            if (request.Headers?.Authorization != null && request.Headers?.Authorization.Scheme == HmacApiAuthConfiguration.AuthenticationScheme)
            {
                reqSignature = request.Headers.Authorization.Parameter;
            }
            else
            {
                // We should just return here if there is no signature.
                return(request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Unauthorized request : Missing or invalid signature"));
            }

            // TODO : Check to see if signature is currently in cache. If so return now.

            // TODO : Cache signature in memory for the validity period (5 mins) to ensure no request gets replayed.

            try
            {
                // Call the base authentication handler.
                response = await base.SendAsync(request, cancellationToken);
            }
            catch (Exception exception)
            {
                // Catch any authentication error messages and provide custom error message response.
                response = request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Error authenticating");
                var respMsg = new StringBuilder();
                respMsg.AppendLine("Error authenticating...");

                respMsg.AppendLine("StatusCode            : " + response.StatusCode);
                respMsg.AppendLine("ReasonPhrase          : " + response.ReasonPhrase);
                respMsg.AppendLine("WwwAuthenticate       : " + response.Headers.WwwAuthenticate.FirstOrDefault().ToString());
                respMsg.AppendLine("RequestDate           : " + request.Headers.Date.GetValueOrDefault().UtcDateTime.ToString(CultureInfo.InvariantCulture));
                respMsg.AppendLine("ServerDate            : " + (DateTimeOffset.Now));

                respMsg.AppendLine();

                respMsg.AppendLine("ExceptionMessage      : " + exception.Message);
                respMsg.AppendLine("ExceptionSource       : " + exception.Source);
                respMsg.AppendLine("ExceptionInnerMessage : " + exception.InnerException?.Message);
                respMsg.AppendLine("ExceptionStackTrace   : " + exception.StackTrace);
                response.Content = new StringContent(respMsg.ToString());
            }

            // Catch any authentication failure message and provide custom error message response.
            if (response != null && response.StatusCode == HttpStatusCode.Unauthorized)
            {
                var serverDate = DateTimeOffset.Now;
                var respMsg    = new StringBuilder();

                respMsg.AppendLine("Authentication failed");

                respMsg.AppendLine();

                respMsg.AppendLine("Basic Details\n");

                respMsg.AppendLine("URL              : " + request.RequestUri.AbsoluteUri.ToLower());
                respMsg.AppendLine("StatusCode       : " + response.StatusCode);
                respMsg.AppendLine("ReasonPhrase     : " + response.ReasonPhrase);
                //respMsg.AppendLine("WwwAuthenticate  : " + response.Headers.WwwAuthenticate.FirstOrDefault().ToString());
                respMsg.AppendLine("RequestDate      : " + request.Headers.Date.GetValueOrDefault().ToString("r"));
                respMsg.AppendLine("ServerDate       : " + serverDate.ToString("r"));
                respMsg.AppendLine("DateDifference   : " + (serverDate - request.Headers.Date.GetValueOrDefault()));

                respMsg.AppendLine();

                string username = "";
                if (request.Headers.Contains(HmacApiAuthConfiguration.UsernameHeader))
                {
                    username = request.Headers.GetValues(HmacApiAuthConfiguration.UsernameHeader).First();
                }
                string signature = "";
                if (request.Headers.Authorization != null && request.Headers.Authorization.Scheme == HmacApiAuthConfiguration.AuthenticationScheme)
                {
                    signature = request.Headers.Authorization.Parameter;
                }
                string md5           = "";
                string serverMd5     = "";
                long?  contentLength = 0;
                if (request.Content != null)
                {
                    contentLength = request.Content.Headers.ContentLength;
                    serverMd5     = Convert.ToBase64String(await MD5Helper.ComputeHash(request.Content)) == "1B2M2Y8AsgTpgAmY7PhCfg==" ? "" : Convert.ToBase64String(await MD5Helper.ComputeHash(request.Content));
                    if (request.Content.Headers.ContentMD5 != null && request.Content.Headers.ContentMD5.Length > 0)
                    {
                        md5 = Convert.ToBase64String(request.Content.Headers.ContentMD5);
                    }
                }
                bool   validRequest    = IsRequestValid(request);
                string msgSigRep       = _representBuilder.BuildRequestRepresentation(request);
                string serverSignature = _sigCalc.Signature(_secretRepo.GetSecretForUser(username), msgSigRep);

                respMsg.AppendLine("Auth Details\n");

                respMsg.AppendLine("RequestValid     : " + validRequest.ToString());
                respMsg.AppendLine("Username         : "******"ApiKey           : " + _secretRepo.GetSecretForUser(username));
                respMsg.AppendLine("Signature        : " + signature);
                respMsg.AppendLine("ServerSignature  : " + serverSignature);

                respMsg.AppendLine();

                respMsg.AppendLine("Content Details\n");

                respMsg.AppendLine("ContentMd5       : " + md5);
                respMsg.AppendLine("ServerContentMd5 : " + serverMd5);
                respMsg.AppendLine("CannonicalRep    :\n" + msgSigRep);

                respMsg.AppendLine("ContentLength    : " + contentLength);
                respMsg.AppendLine("ContentType      : " + request.Content.Headers.ContentType);
                respMsg.AppendLine("ContentMediaType : " + request.Content.Headers.ContentType.MediaType.ToLower());
                respMsg.AppendLine("Content          : \"" + await request.Content.ReadAsStringAsync() + "\"");

                response.Content = new StringContent(respMsg.ToString());
            }

            return(response);
        }