/// <summary> /// Calculates response value. /// </summary> /// <param name="userName">User name.</param> /// <param name="password">User password.</param> /// <returns>Returns calculated rsponse value.</returns> public string CalculateResponse(string userName, string password) { /* * MD5 * A1 = username-value ":" realm-value ":" passwd * * MD5-sess * A1 = md5(username-value ":" realm-value ":" passwd) ":" nonce-value ":" cnonce-value * * qop not peresent or auth * A2 = Method ":" digest-uri-value * * qop auth-int * A2 = Method ":" digest-uri-value ":" md5h(entity-body) * * qop present * response = md5h(md5h(A1) ":" nonce-value ":" nc-value ":" cnonce-value ":" qop-value ":" md5h(A2)) * * qop not present * response = md5h(md5h(A1) ":" nonce-value ":" md5h(A2)) * */ string a1 = ""; string a2 = ""; // Create A1 if (Algorithm == "" || Algorithm.ToLower() == "md5") { a1 = userName + ":" + Realm + ":" + password; } else if (Algorithm.ToLower() == "md5-sess") { a1 = Core.ComputeMd5(userName + ":" + Realm + ":" + password, false) + ":" + Nonce + ":" + CNonce; } else { throw new ArgumentException("Invalid Algorithm value '" + Algorithm + "' !"); } // Create A2 if (Qop == "" || Qop.ToLower() == "auth") { a2 = m_Method.ToUpper() + ":" + Uri; } else { throw new ArgumentException("Invalid qop value '" + Qop + "' !"); } // Calculate response value. // qop present if (!string.IsNullOrEmpty(Qop)) { return (Core.ComputeMd5( Core.ComputeMd5(a1, true) + ":" + Nonce + ":" + NonceCount.ToString("x8") + ":" + CNonce + ":" + Qop + ":" + Core.ComputeMd5(a2, true), true)); } // qop not present else { return (Core.ComputeMd5( Core.ComputeMd5(a1, true) + ":" + Nonce + ":" + Core.ComputeMd5(a2, true), true)); } }
// HEX( KD ( HEX(H(A1)), // { // nonce-value, ":" nc-value, ":", // cnonce-value, ":", qop-value, ":", HEX(H(A2)) })) // // If authzid is specified, then A1 is // // A1 = { H( { username-value, ":", realm-value, ":", passwd } ), // ":", nonce-value, ":", cnonce-value, ":", authzid-value } // // If authzid is not specified, then A1 is // // A1 = { H( { username-value, ":", realm-value, ":", passwd } ), // ":", nonce-value, ":", cnonce-value } // // where // // passwd = *OCTET public void GenerateResponse() { byte[] H1; byte[] H2; byte[] H3; //byte[] temp; string A1; string A2; string A3; string p1; string p2; var sb = new StringBuilder(); sb.Append(Username); sb.Append(":"); sb.Append(Realm); sb.Append(":"); sb.Append(Password); #if !CF H1 = new MD5CryptoServiceProvider().ComputeHash(Encoding.UTF8.GetBytes(sb.ToString())); #else //H1 = Encoding.Default.GetBytes(util.Hash.MD5Hash(sb.ToString())); H1 = util.Hash.MD5Hash(Encoding.UTF8.GetBytes(sb.ToString())); #endif sb.Remove(0, sb.Length); sb.Append(":"); sb.Append(Nonce); sb.Append(":"); sb.Append(Cnonce); if (Authzid != null) { sb.Append(":"); sb.Append(Authzid); } A1 = sb.ToString(); // sb.Remove(0, sb.Length); // sb.Append(Encoding.Default.GetChars(H1)); // //sb.Append(Encoding.ASCII.GetChars(H1)); // // sb.Append(A1); var bA1 = Encoding.ASCII.GetBytes(A1); var bH1A1 = new byte[H1.Length + bA1.Length]; //Array.Copy(H1, bH1A1, H1.Length); Array.Copy(H1, 0, bH1A1, 0, H1.Length); Array.Copy(bA1, 0, bH1A1, H1.Length, bA1.Length); #if !CF H1 = new MD5CryptoServiceProvider().ComputeHash(bH1A1); //Console.WriteLine(util.Hash.HexToString(H1)); #else //H1 = Encoding.Default.GetBytes(util.Hash.MD5Hash(sb.ToString())); //H1 =util.Hash.MD5Hash(Encoding.Default.GetBytes(sb.ToString())); H1 = util.Hash.MD5Hash(bH1A1); #endif sb.Remove(0, sb.Length); sb.Append("AUTHENTICATE:"); sb.Append(DigestUri); if (Qop.CompareTo("auth") != 0) { sb.Append(":00000000000000000000000000000000"); } A2 = sb.ToString(); H2 = Encoding.ASCII.GetBytes(A2); #if !CF H2 = new MD5CryptoServiceProvider().ComputeHash(H2); #else //H2 = Encoding.Default.GetBytes(util.Hash.MD5Hash(H2)); H2 = util.Hash.MD5Hash(H2); #endif // create p1 and p2 as the hex representation of H1 and H2 p1 = Hash.HexToString(H1).ToLower(); p2 = Hash.HexToString(H2).ToLower(); sb.Remove(0, sb.Length); sb.Append(p1); sb.Append(":"); sb.Append(Nonce); sb.Append(":"); sb.Append(Nc); sb.Append(":"); sb.Append(Cnonce); sb.Append(":"); sb.Append(Qop); sb.Append(":"); sb.Append(p2); A3 = sb.ToString(); #if !CF H3 = new MD5CryptoServiceProvider().ComputeHash(Encoding.ASCII.GetBytes(A3)); #else //H3 = Encoding.Default.GetBytes(util.Hash.MD5Hash(A3)); H3 = util.Hash.MD5Hash(Encoding.ASCII.GetBytes(A3)); #endif Response = Hash.HexToString(H3).ToLower(); }
/// <summary> /// Calculates 'rspauth' value. /// </summary> /// <param name="userName">User name.</param> /// <param name="password">Password.</param> /// <returns>Returns 'rspauth' value.</returns> public string CalculateRspAuth(string userName, string password) { /* RFC 2617 3.2.3. * The optional response digest in the "response-auth" directive * supports mutual authentication -- the server proves that it knows the * user's secret, and with qop=auth-int also provides limited integrity * protection of the response. The "response-digest" value is calculated * as for the "request-digest" in the Authorization header, except that * if "qop=auth" or is not specified in the Authorization header for the * request, A2 is * * A2 = ":" digest-uri-value * * and if "qop=auth-int", then A2 is * * A2 = ":" digest-uri-value ":" H(entity-body) * * where "digest-uri-value" is the value of the "uri" directive on the * Authorization header in the request. The "cnonce-value" and "nc- * value" MUST be the ones for the client request to which this message * is the response. The "response-auth", "cnonce", and "nonce-count" * directives MUST BE present if "qop=auth" or "qop=auth-int" is * specified. */ string a1 = ""; string a2 = ""; // Create A1 if (Algorithm == "" || Algorithm.ToLower() == "md5") { a1 = userName + ":" + Realm + ":" + password; } else if (Algorithm.ToLower() == "md5-sess") { a1 = Core.ComputeMd5(userName + ":" + Realm + ":" + password, false) + ":" + Nonce + ":" + CNonce; } else { throw new ArgumentException("Invalid Algorithm value '" + Algorithm + "' !"); } // Create A2 if (Qop == "" || Qop.ToLower() == "auth") { a2 = ":" + Uri; } else { throw new ArgumentException("Invalid qop value '" + Qop + "' !"); } // Calculate response value. // qop present if (!string.IsNullOrEmpty(Qop)) { return (Core.ComputeMd5( Core.ComputeMd5(a1, true) + ":" + Nonce + ":" + NonceCount.ToString("x8") + ":" + CNonce + ":" + Qop + ":" + Core.ComputeMd5(a2, true), true)); } // qop not present else { return (Core.ComputeMd5( Core.ComputeMd5(a1, true) + ":" + Nonce + ":" + Core.ComputeMd5(a2, true), true)); } }