public static async Task <string> GetDigestTokenForCredential(NetworkCredential credential, HttpRequestMessage request, DigestResponse digestResponse)
        {
            StringBuilder sb = StringBuilderCache.Acquire();

            // It is mandatory for servers to implement sha-256 per RFC 7616
            // Keep MD5 for backward compatibility.
            string algorithm;

            if (digestResponse.Parameters.TryGetValue(Algorithm, out algorithm))
            {
                if (algorithm != Sha256 && algorithm != Md5 && algorithm != Sha256Sess && algorithm != MD5Sess)
                {
                    return(null);
                }
            }
            else
            {
                algorithm = Md5;
            }

            // Check if nonce is there in challenge
            string nonce;

            if (!digestResponse.Parameters.TryGetValue(Nonce, out nonce))
            {
                return(null);
            }

            // opaque token may or may not exist
            string opaque;

            digestResponse.Parameters.TryGetValue(Opaque, out opaque);

            string realm;

            if (!digestResponse.Parameters.TryGetValue(Realm, out realm))
            {
                return(null);
            }

            // Add username
            string userhash;

            if (digestResponse.Parameters.TryGetValue(UserHash, out userhash) && userhash == "true")
            {
                sb.AppendKeyValue(Username, ComputeHash(credential.UserName + ":" + realm, algorithm));
                sb.AppendKeyValue(UserHash, userhash, includeQuotes: false);
            }
            else
            {
                string usernameStar;
                if (HeaderUtilities.IsInputEncoded5987(credential.UserName, out usernameStar))
                {
                    sb.AppendKeyValue(UsernameStar, usernameStar, includeQuotes: false);
                }
                else
                {
                    sb.AppendKeyValue(Username, credential.UserName);
                }
            }

            // Add realm
            if (realm != string.Empty)
            {
                sb.AppendKeyValue(Realm, realm);
            }

            // Add nonce
            sb.AppendKeyValue(Nonce, nonce);

            // Add uri
            sb.AppendKeyValue(Uri, request.RequestUri.PathAndQuery);

            // Set qop, default is auth
            string qop = Auth;

            if (digestResponse.Parameters.ContainsKey(Qop))
            {
                // Check if auth-int present in qop string
                int index1 = digestResponse.Parameters[Qop].IndexOf(AuthInt);
                if (index1 != -1)
                {
                    // Get index of auth if present in qop string
                    int index2 = digestResponse.Parameters[Qop].IndexOf(Auth);

                    // If index2 < index1, auth option is available
                    // If index2 == index1, check if auth option available later in string after auth-int.
                    if (index2 == index1)
                    {
                        index2 = digestResponse.Parameters[Qop].IndexOf(Auth, index1 + AuthInt.Length);
                        if (index2 == -1)
                        {
                            qop = AuthInt;
                        }
                    }
                }
            }

            // Set cnonce
            string cnonce = GetRandomAlphaNumericString();

            // Calculate response
            string a1 = credential.UserName + ":" + realm + ":" + credential.Password;

            if (algorithm == Sha256Sess || algorithm == MD5Sess)
            {
                algorithm = algorithm == Sha256Sess ? Sha256 : Md5;
                a1        = ComputeHash(a1, algorithm) + ":" + nonce + ":" + cnonce;
            }

            string a2 = request.Method.Method + ":" + request.RequestUri.PathAndQuery;

            if (qop == AuthInt)
            {
                string content = request.Content == null ? string.Empty : await request.Content.ReadAsStringAsync().ConfigureAwait(false);

                a2 = a2 + ":" + ComputeHash(content, algorithm);
            }

            string response = ComputeHash(ComputeHash(a1, algorithm) + ":" +
                                          nonce + ":" +
                                          DigestResponse.NonceCount + ":" +
                                          cnonce + ":" +
                                          qop + ":" +
                                          ComputeHash(a2, algorithm), algorithm);

            // Add response
            sb.AppendKeyValue(Response, response);

            // Add algorithm
            sb.AppendKeyValue(Algorithm, algorithm, includeQuotes: false);

            // Add opaque
            if (opaque != null)
            {
                sb.AppendKeyValue(Opaque, opaque);
            }

            // Add qop
            sb.AppendKeyValue(Qop, qop, includeQuotes: false);

            // Add nc
            sb.AppendKeyValue(NC, DigestResponse.NonceCount, includeQuotes: false);

            // Add cnonce
            sb.AppendKeyValue(CNonce, cnonce, includeComma: false);

            return(StringBuilderCache.GetStringAndRelease(sb));
        }