def generateChallengeResponseV1(password, server_challenge, has_extended_security=False, client_challenge=None): """ Generate a NTLMv1 response @param password: User password string @param server_challange: A 8-byte challenge string sent from the server @param has_extended_security: A boolean value indicating whether NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY flag is enabled in the NTLM negFlag @param client_challenge: A 8-byte string representing client challenge. If None, it will be generated randomly if needed by the response generation @return: a tuple of ( NT challenge response string, LM challenge response string ) References: =========== - http://ubiqx.org/cifs/SMB.html (2.8.3.3 and 2.8.3.4) - [MS-NLMP]: 3.3.1 """ _password = (password.upper() + '\0' * 14)[:14] d1 = des(expandDesKey(_password[:7])) d2 = des(expandDesKey(_password[7:])) lm_response_key = d1.encrypt("KGS!@#$%") + d2.encrypt( "KGS!@#$%" ) # LM password hash. In [MS-NLMP], this is the result of LMOWFv1 function d = MD4() d.update(password.encode('UTF-16LE')) nt_response_key = d.digest( ) # In [MS-NLMP], this is the result of NTOWFv1 function if has_extended_security: if not client_challenge: client_challenge = '' for i in range(0, 8): client_challenge += chr(random.getrandbits(8)) assert len(client_challenge) == 8 lm_challenge_response = client_challenge + '\0' * 16 nt_challenge_response = DESL( nt_response_key, MD5(server_challenge + client_challenge).digest()[0:8]) else: nt_challenge_response = DESL( nt_response_key, server_challenge) # The result after DESL is the NT response lm_challenge_response = DESL( lm_response_key, server_challenge) # The result after DESL is the LM response d = MD4() d.update(nt_response_key) session_key = d.digest() return nt_challenge_response, lm_challenge_response, session_key
def generateChallengeResponseV2(password, user, server_challenge, server_info, domain='', client_challenge=None): client_timestamp = '\0' * 8 if not client_challenge: client_challenge = '' for i in range(0, 8): client_challenge += chr(random.getrandbits(8)) assert len(client_challenge) == 8 d = MD4() d.update(password.encode('UTF-16LE')) ntlm_hash = d.digest() # The NT password hash response_key = hmac.new(ntlm_hash, ( user.upper() + domain ).encode('UTF-16LE')).digest( ) # The NTLMv2 password hash. In [MS-NLMP], this is the result of NTOWFv2 and LMOWFv2 functions temp = '\x01\x01' + '\0' * 6 + client_timestamp + client_challenge + '\0' * 4 + server_info ntproofstr = hmac.new(response_key, server_challenge + temp).digest() nt_challenge_response = ntproofstr + temp lm_challenge_response = hmac.new( response_key, server_challenge + client_challenge).digest() + client_challenge session_key = hmac.new(response_key, ntproofstr).digest() return nt_challenge_response, lm_challenge_response, session_key