internal TSIP_Header CreateHeaderAuthorization(TSIP_Request request)
        {
            if (request == null)
            {
                TSK_Debug.Error("Invalid parameter");
                return(null);
            }

            String response, nc = null, uristring;

            if (String.IsNullOrEmpty(uristring = TSIP_Uri.ToString(request.Uri, true, false)))
            {
                TSK_Debug.Error("Failed to parse URI: {0}", request.Uri);
                return(null);
            }

            /* We compute the nc here because @ref tsip_challenge_get_response function will increment it's value. */
            if (mNc > 0)
            {
                nc = THTTP_Auth.GetNonceString(mNc).ToString();
            }
            /* entity_body ==> request-content */
            response = GetResponse(request.Method, uristring, request.Content);

            if (mProxy)
            {
                // FIXME
                TSK_Debug.Error("Proxy-Authorization header not supported yet");
            }
            else
            {
                TSIP_HeaderAuthorization header = new TSIP_HeaderAuthorization();
                header.UserName  = ChallengeUserName;
                header.Scheme    = mScheme;
                header.Realm     = mRealm;
                header.Nonce     = mNonce;
                header.Qop       = mQop;
                header.Algorithm = String.IsNullOrEmpty(mAlgorithm) ? "MD5" : mAlgorithm;
                header.Cnonce    = mNc > 0 ? mCnonce : null;
                header.Uri       = uristring;
                header.Nc        = mNc > 0 ? nc : null;
                header.Response  = response;

                return(header);
            }

            return(null);
        }
        internal String GetResponse(String method, String uristring, byte[] entity_body)
        {
            String response = String.Empty;

            if (IsDigest)
            {
                String ha1 = null, ha2;
                String nc = String.Empty;

                /* ===
                 *              Calculate HA1 = MD5(A1) = M5(username:realm:secret)
                 *              In case of AKAv1-MD5 and AKAv2-MD5 the secret must be computed as per RFC 3310 + 3GPP TS 206/7/8/9.
                 *              The resulting AKA RES parameter is treated as a "password"/"secret" when calculating the response directive of RFC 2617.
                 */
                if (IsAKAv1 || IsAKAv2)
                {
                    TSK_Debug.Error("AKAv1 and AKAv2 are not supported yet");
                    return(null);
                }
                else
                {
                    ha1 = THTTP_Auth.GetDigestHA1(ChallengeUserName, mRealm, ChallengePassword);
                }

                /* ===
                 *              HA2
                 */
                ha2 = THTTP_Auth.GetDigestHA2(method, uristring, entity_body, mQop);

                /* RESPONSE */
                if (mNc > 0)
                {
                    nc = THTTP_Auth.GetNonceString(mNc).ToString();
                }
                response = THTTP_Auth.GetDigestResponse(ha1, mNonce, mNc, mCnonce, mQop, ha2);

                if (!String.IsNullOrEmpty(mQop))
                {
                    ++mNc;
                }
            }

            return(response);
        }