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); }
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."); }
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)); } }
/// <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)); }
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); }