1
+ # This library is free software: you can redistribute it and/or
2
+ # modify it under the terms of the GNU Lesser General Public
3
+ # License as published by the Free Software Foundation, either
4
+ # version 3 of the License, or (at your option) any later version.
5
+
6
+ # This library is distributed in the hope that it will be useful,
7
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
8
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9
+ # Lesser General Public License for more details.
10
+
11
+ # You should have received a copy of the GNU Lesser General Public
12
+ # License along with this library. If not, see <http://www.gnu.org/licenses/> or <http://www.gnu.org/licenses/lgpl.txt>.
13
+
14
+ import binascii
15
+ import hashlib
16
+ import hmac
17
+ from ntlm_auth import des
18
+ from ntlm_auth .constants import NegotiateFlags
19
+
20
+ def _get_exchange_key_ntlm_v1 (negotiate_flags , session_base_key , server_challenge , lm_challenge_response , lm_hash ):
21
+ """
22
+ [MS-NLMP] v28.0 2016-07-14
23
+
24
+ 4.3.5.1 KXKEY
25
+ Calculates the Key Exchange Key for NTLMv1 authentication. Used for signing and sealing messages
26
+
27
+ @param negotiate_flags:
28
+ @param session_base_key: A session key calculated from the user password challenge
29
+ @param server_challenge: A random 8-byte response generated by the server in the CHALLENGE_MESSAGE
30
+ @param lm_challenge_response: The LmChallengeResponse value computed in ComputeResponse
31
+ @param lm_hash: The LMOWF computed in Compute Response
32
+ @return key_exchange_key: The Key Exchange Key (KXKEY) used to sign and seal messages and compute the ExportedSessionKey
33
+ """
34
+ if negotiate_flags & NegotiateFlags .NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY :
35
+ key_exchange_key = hmac .new (session_base_key , server_challenge + lm_challenge_response [:8 ]).digest ()
36
+ elif negotiate_flags & NegotiateFlags .NTLMSSP_NEGOTIATE_LM_KEY :
37
+ des_handler = des .DES (lm_hash [:7 ])
38
+ first_des = des_handler .encrypt (lm_challenge_response [:8 ])
39
+ des_handler = des .DES (lm_hash [7 :8 ] + binascii .unhexlify ('bdbdbdbdbdbdbd' ))
40
+ second_des = des_handler .encrypt (lm_challenge_response [:8 ])
41
+
42
+ key_exchange_key = first_des + second_des
43
+ elif negotiate_flags & NegotiateFlags .NTLMSSP_REQUEST_NON_NT_SESSION_KEY :
44
+ key_exchange_key = lm_hash [:8 ] + b'\0 ' * 8
45
+ else :
46
+ key_exchange_key = session_base_key
47
+
48
+ return key_exchange_key
49
+
50
+ def _get_exchange_key_ntlm_v2 (session_base_key ):
51
+ """
52
+ [MS-NLMP] v28.0 2016-07-14
53
+
54
+ 4.3.5.1 KXKEY
55
+ Calculates the Key Exchange Key for NTLMv2 authentication. Used for signing and sealing messages.
56
+ According to docs, 'If NTLM v2 is used, KeyExchangeKey MUST be set to the given 128-bit SessionBaseKey
57
+
58
+ @param session_base_key: A session key calculated from the user password challenge
59
+ @return key_exchange_key: The Key Exchange Key (KXKEY) used to sign and seal messages
60
+ """
61
+ return session_base_key
62
+
63
+ def get_sign_key (exported_session_key , magic_constant ):
64
+ """
65
+ 3.4.5.2 SIGNKEY
66
+
67
+ @param exported_session_key: A 128-bit session key used to derive signing and sealing keys
68
+ @param magic_constant: A constant value set in the MS-NLMP documentation (constants.SignSealConstants)
69
+ @return sign_key: Key used to sign messages
70
+ """
71
+
72
+ sign_key = hashlib .md5 (exported_session_key + magic_constant ).digest ()
73
+
74
+ return sign_key
75
+
76
+ def get_seal_key (negotiate_flags , exported_session_key , magic_constant ):
77
+ """
78
+ 3.4.5.3. SEALKEY
79
+ Main method to use to calculate the seal_key used to seal (encrypt) messages. This will determine
80
+ the correct method below to use based on the compatibility flags set and should be called instead
81
+ of the others
82
+
83
+ @param exported_session_key: A 128-bit session key used to derive signing and sealing keys
84
+ @param negotiate_flags: The negotiate_flags structure sent by the server
85
+ @param magic_constant: A constant value set in the MS-NLMP documentation (constants.SignSealConstants)
86
+ @return seal_key: Key used to seal messages
87
+ """
88
+
89
+ if negotiate_flags & NegotiateFlags .NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY :
90
+ seal_key = _get_seal_key_ntlm2 (negotiate_flags , exported_session_key , magic_constant )
91
+ elif negotiate_flags & NegotiateFlags .NTLMSSP_NEGOTIATE_LM_KEY :
92
+ seal_key = _get_seal_key_ntlm1 (negotiate_flags , exported_session_key )
93
+ else :
94
+ seal_key = exported_session_key
95
+
96
+ return seal_key
97
+
98
+ def _get_seal_key_ntlm1 (negotiate_flags , exported_session_key ):
99
+ """
100
+ 3.4.5.3 SEALKEY
101
+ Calculates the seal_key used to seal (encrypt) messages. This for authentication where
102
+ NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY has not been negotiated. Will weaken the keys
103
+ if NTLMSSP_NEGOTIATE_56 is not negotiated it will default to the 40-bit key
104
+
105
+ @param negotiate_flags: The negotiate_flags structure sent by the server
106
+ @param exported_session_key: A 128-bit session key used to derive signing and sealing keys
107
+ @return seal_key: Key used to seal messages
108
+ """
109
+ if negotiate_flags & NegotiateFlags .NTLMSSP_NEGOTIATE_56 :
110
+ seal_key = exported_session_key [:7 ] + binascii .unhexlify ('a0' )
111
+ else :
112
+ seal_key = exported_session_key [:5 ] + binascii .unhexlify ('e538b0' )
113
+
114
+ return seal_key
115
+
116
+ def _get_seal_key_ntlm2 (negotiate_flags , exported_session_key , magic_constant ):
117
+ """
118
+ 3.4.5.3 SEALKEY
119
+ Calculates the seal_key used to seal (encrypt) messages. This for authentication where
120
+ NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY has been negotiated. Will weaken the keys
121
+ if NTLMSSP_NEGOTIATE_128 is not negotiated, will try NEGOTIATE_56 and then will default
122
+ to the 40-bit key
123
+
124
+ @param negotiate_flags: The negotiate_flags structure sent by the server
125
+ @param exported_session_key: A 128-bit session key used to derive signing and sealing keys
126
+ @param magic_constant: A constant value set in the MS-NLMP documentation (constants.SignSealConstants)
127
+ @return seal_key: Key used to seal messages
128
+ """
129
+ if negotiate_flags & NegotiateFlags .NTLMSSP_NEGOTIATE_128 :
130
+ seal_key = exported_session_key
131
+ elif negotiate_flags & NegotiateFlags .NTLMSSP_NEGOTIATE_56 :
132
+ seal_key = exported_session_key [:7 ]
133
+ else :
134
+ seal_key = exported_session_key [:5 ]
135
+
136
+ seal_key = hashlib .md5 (seal_key + magic_constant ).digest ()
137
+
138
+ return seal_key
0 commit comments