docs: def get_nt_challenge_response(self, lm_challenge_response, server_certificate_hash):
          """
          [MS-NLMP] v28.0 2016-07-14
  
          3.3.1 - NTLM v1 Authentication
          3.3.2 - NTLM v2 Authentication
  
          This method returns the NtChallengeResponse key based on the ntlm_compatibility chosen
          and the target_info supplied by the CHALLENGE_MESSAGE. It is quite different from what
          is set in the document as it combines the NTLMv1, NTLM2 and NTLMv2 methods into one
          and calls separate methods based on the ntlm_compatibility value chosen.
  
          :param lm_challenge_response: The LmChallengeResponse calculated beforeand, used to get the key_exchange_key value
          :param server_certificate_hash: The SHA256 hash of the server certificate (DER encoded) NTLM is authenticated to.
                                          Used in Channel Binding Tokens if present, default value is None. See
                                          AuthenticateMessage in messages.py for more details
          :return response: (NtChallengeResponse) - The NT response to the server challenge. Computed by the client
          :return session_base_key: (SessionBaseKey) - A session key calculated from the user password challenge
          :return target_info: (AV_PAIR) - The AV_PAIR structure used in the nt_challenge calculations
          """
          if self._negotiate_flags & NegotiateFlags.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY and self._ntlm_compatibility < 3:
              # The compatibility level is less than 3 which means it doesn't support NTLMv2 but we want extended security so use NTLM2 which is different from NTLMv2
              # [MS-NLMP] - 3.3.1 NTLMv1 Authentication
              response, session_base_key = ComputeResponse._get_NTLM2_response(self._password, self._server_challenge, self._client_challenge)
              key_exchange_key = compkeys._get_exchange_key_ntlm_v1(self._negotiate_flags, session_base_key,
                                                                    self._server_challenge, lm_challenge_response,
                                                                    comphash._lmowfv1(self._password))
              target_info = None
  
          elif 0 <= self._ntlm_compatibility < 3:
              response, session_base_key = ComputeResponse._get_NTLMv1_response(self._password, self._server_challenge)
              key_exchange_key = compkeys._get_exchange_key_ntlm_v1(self._negotiate_flags, session_base_key,
                                                                    self._server_challenge, lm_challenge_response,
                                                                    comphash._lmowfv1(self._password))
              target_info = None
          else:
              if self._server_target_info is None:
                  target_info = TargetInfo()
              else:
                  target_info = self._server_target_info
  
              if target_info[TargetInfo.MSV_AV_TIMESTAMP] is None:
                  timestamp = get_windows_timestamp()
              else:
                  timestamp = target_info[TargetInfo.MSV_AV_TIMESTAMP][1]
  
                  # [MS-NLMP] If the CHALLENGE_MESSAGE TargetInfo field has an MsvAvTimestamp present, the client SHOULD provide a MIC
                  target_info[TargetInfo.MSV_AV_FLAGS] = struct.pack("<L", AvFlags.MIC_PROVIDED)
  
              if server_certificate_hash != None:
                  channel_bindings_hash = ComputeResponse._get_channel_bindings_value(server_certificate_hash)
                  target_info[TargetInfo.MSV_AV_CHANNEL_BINDINGS] = channel_bindings_hash
  
              response, session_base_key = ComputeResponse._get_NTLMv2_response(self._user_name, self._password, self._domain_name,
                                                   self._server_challenge, self._client_challenge, timestamp, target_info)
  
              key_exchange_key = compkeys._get_exchange_key_ntlm_v2(session_base_key)
  
          return response, key_exchange_key, target_info