Coverage for /root/GitHubProjects/impacket/impacket/crypto.py : 69%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# Impacket - Collection of Python classes for working with network protocols.
2#
3# SECUREAUTH LABS. Copyright (C) 2018 SecureAuth Corporation. All rights reserved.
4#
5# This software is provided under a slightly modified version
6# of the Apache Software License. See the accompanying LICENSE file
7# for more information.
8#
9# Description:
10# RFC 4493 implementation (https://www.ietf.org/rfc/rfc4493.txt)
11# RFC 4615 implementation (https://www.ietf.org/rfc/rfc4615.txt)
12#
13# NIST SP 800-108 Section 5.1, with PRF HMAC-SHA256 implementation
14# (https://tools.ietf.org/html/draft-irtf-cfrg-kdf-uses-00#ref-SP800-108)
15#
16# [MS-LSAD] Section 5.1.2
17# [MS-SAMR] Section 2.2.11.1.1
18#
19# Author:
20# Alberto Solino (@agsolino)
21#
23from __future__ import division
24from __future__ import print_function
25from impacket import LOG
26try:
27 from Cryptodome.Cipher import DES, AES
28except Exception:
29 LOG.error("Warning: You don't have any crypto installed. You need pycryptodomex")
30 LOG.error("See https://pypi.org/project/pycryptodomex/")
31from struct import pack, unpack
32from impacket.structure import Structure
33import hmac, hashlib
34from six import b
36def Generate_Subkey(K):
38# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
39# + Algorithm Generate_Subkey +
40# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
41# + +
42# + Input : K (128-bit key) +
43# + Output : K1 (128-bit first subkey) +
44# + K2 (128-bit second subkey) +
45# +-------------------------------------------------------------------+
46# + +
47# + Constants: const_Zero is 0x00000000000000000000000000000000 +
48# + const_Rb is 0x00000000000000000000000000000087 +
49# + Variables: L for output of AES-128 applied to 0^128 +
50# + +
51# + Step 1. L := AES-128(K, const_Zero); +
52# + Step 2. if MSB(L) is equal to 0 +
53# + then K1 := L << 1; +
54# + else K1 := (L << 1) XOR const_Rb; +
55# + Step 3. if MSB(K1) is equal to 0 +
56# + then K2 := K1 << 1; +
57# + else K2 := (K1 << 1) XOR const_Rb; +
58# + Step 4. return K1, K2; +
59# + +
60# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
62 AES_128 = AES.new(K, AES.MODE_ECB)
64 L = AES_128.encrypt(bytes(bytearray(16)))
66 LHigh = unpack('>Q',L[:8])[0]
67 LLow = unpack('>Q',L[8:])[0]
69 K1High = ((LHigh << 1) | ( LLow >> 63 )) & 0xFFFFFFFFFFFFFFFF
70 K1Low = (LLow << 1) & 0xFFFFFFFFFFFFFFFF
72 if (LHigh >> 63):
73 K1Low ^= 0x87
75 K2High = ((K1High << 1) | (K1Low >> 63)) & 0xFFFFFFFFFFFFFFFF
76 K2Low = ((K1Low << 1)) & 0xFFFFFFFFFFFFFFFF
78 if (K1High >> 63):
79 K2Low ^= 0x87
81 K1 = bytearray(pack('>QQ', K1High, K1Low))
82 K2 = bytearray(pack('>QQ', K2High, K2Low))
84 return K1, K2
86def XOR_128(N1,N2):
88 J = bytearray()
89 for i in range(len(N1)):
90 #J.append(indexbytes(N1,i) ^ indexbytes(N2,i))
91 J.append(N1[i] ^ N2[i])
92 return J
94def PAD(N):
95 padLen = 16-len(N)
96 return N + b'\x80' + b'\x00'*(padLen-1)
98def AES_CMAC(K, M, length):
100# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
101# + Algorithm AES-CMAC +
102# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
103# + +
104# + Input : K ( 128-bit key ) +
105# + : M ( message to be authenticated ) +
106# + : len ( length of the message in octets ) +
107# + Output : T ( message authentication code ) +
108# + +
109# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
110# + Constants: const_Zero is 0x00000000000000000000000000000000 +
111# + const_Bsize is 16 +
112# + +
113# + Variables: K1, K2 for 128-bit subkeys +
114# + M_i is the i-th block (i=1..ceil(len/const_Bsize)) +
115# + M_last is the last block xor-ed with K1 or K2 +
116# + n for number of blocks to be processed +
117# + r for number of octets of last block +
118# + flag for denoting if last block is complete or not +
119# + +
120# + Step 1. (K1,K2) := Generate_Subkey(K); +
121# + Step 2. n := ceil(len/const_Bsize); +
122# + Step 3. if n = 0 +
123# + then +
124# + n := 1; +
125# + flag := false; +
126# + else +
127# + if len mod const_Bsize is 0 +
128# + then flag := true; +
129# + else flag := false; +
130# + +
131# + Step 4. if flag is true +
132# + then M_last := M_n XOR K1; +
133# + else M_last := padding(M_n) XOR K2; +
134# + Step 5. X := const_Zero; +
135# + Step 6. for i := 1 to n-1 do +
136# + begin +
137# + Y := X XOR M_i; +
138# + X := AES-128(K,Y); +
139# + end +
140# + Y := M_last XOR X; +
141# + T := AES-128(K,Y); +
142# + Step 7. return T; +
143# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
145 const_Bsize = 16
146 const_Zero = bytearray(16)
148 AES_128= AES.new(K, AES.MODE_ECB)
149 M = bytearray(M[:length])
150 K1, K2 = Generate_Subkey(K)
151 n = len(M)//const_Bsize
153 if n == 0:
154 n = 1
155 flag = False
156 else:
157 if (length % const_Bsize) == 0:
158 flag = True
159 else:
160 n += 1
161 flag = False
163 M_n = M[(n-1)*const_Bsize:]
164 if flag is True:
165 M_last = XOR_128(M_n,K1)
166 else:
167 M_last = XOR_128(PAD(M_n),K2)
169 X = const_Zero
170 for i in range(n-1):
171 M_i = M[(i)*const_Bsize:][:16]
172 Y = XOR_128(X, M_i)
173 X = bytearray(AES_128.encrypt(bytes(Y)))
174 Y = XOR_128(M_last, X)
175 T = AES_128.encrypt(bytes(Y))
177 return T
179def AES_CMAC_PRF_128(VK, M, VKlen, Mlen):
180# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
181# + AES-CMAC-PRF-128 +
182# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
183# + +
184# + Input : VK (Variable-length key) +
185# + : M (Message, i.e., the input data of the PRF) +
186# + : VKlen (length of VK in octets) +
187# + : len (length of M in octets) +
188# + Output : PRV (128-bit Pseudo-Random Variable) +
189# + +
190# +-------------------------------------------------------------------+
191# + Variable: K (128-bit key for AES-CMAC) +
192# + +
193# + Step 1. If VKlen is equal to 16 +
194# + Step 1a. then +
195# + K := VK; +
196# + Step 1b. else +
197# + K := AES-CMAC(0^128, VK, VKlen); +
198# + Step 2. PRV := AES-CMAC(K, M, len); +
199# + return PRV; +
200# + +
201# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
202 if VKlen == 16:
203 K = VK
204 else:
205 K = AES_CMAC(bytes(bytearray(16)), VK, VKlen)
207 PRV = AES_CMAC(K, M, Mlen)
209 return PRV
211def KDF_CounterMode(KI, Label, Context, L):
212# Implements NIST SP 800-108 Section 5.1, with PRF HMAC-SHA256
213# https://tools.ietf.org/html/draft-irtf-cfrg-kdf-uses-00#ref-SP800-108
214# Fixed values:
215# 1. h - The length of the output of the PRF in bits, and
216# 2. r - The length of the binary representation of the counter i.
217# Input: KI, Label, Context, and L.
218# Process:
219# 1. n := [L/h]
220# 2. If n > 2r-1, then indicate an error and stop.
221# 3. result(0):= empty .
222# 4. For i = 1 to n, do
223# a. K(i) := PRF (KI, [i]2 || Label || 0x00 || Context || [L]2)
224# b. result(i) := result(i-1) || K(i).
225# 5. Return: KO := the leftmost L bits of result(n).
226 h = 256
227 r = 32
229 n = L // h
231 if n == 0: 231 ↛ 234line 231 didn't jump to line 234, because the condition on line 231 was never false
232 n = 1
234 if n > (pow(2,r)-1): 234 ↛ 235line 234 didn't jump to line 235, because the condition on line 234 was never true
235 raise Exception("Error computing KDF_CounterMode")
237 result = b''
238 K = b''
240 for i in range(1,n+1):
241 input = pack('>L', i) + Label + b'\x00' + Context + pack('>L',L)
242 K = hmac.new(KI, input, hashlib.sha256).digest()
243 result = result + K
245 return result[:(L//8)]
247# [MS-LSAD] Section 5.1.2 / 5.1.3
248class LSA_SECRET_XP(Structure):
249 structure = (
250 ('Length','<L=0'),
251 ('Version','<L=0'),
252 ('_Secret','_-Secret', 'self["Length"]'),
253 ('Secret', ':'),
254 )
257def transformKey(InputKey):
258 # Section 5.1.3
259 OutputKey = []
260 OutputKey.append( chr(ord(InputKey[0:1]) >> 0x01) )
261 OutputKey.append( chr(((ord(InputKey[0:1])&0x01)<<6) | (ord(InputKey[1:2])>>2)) )
262 OutputKey.append( chr(((ord(InputKey[1:2])&0x03)<<5) | (ord(InputKey[2:3])>>3)) )
263 OutputKey.append( chr(((ord(InputKey[2:3])&0x07)<<4) | (ord(InputKey[3:4])>>4)) )
264 OutputKey.append( chr(((ord(InputKey[3:4])&0x0F)<<3) | (ord(InputKey[4:5])>>5)) )
265 OutputKey.append( chr(((ord(InputKey[4:5])&0x1F)<<2) | (ord(InputKey[5:6])>>6)) )
266 OutputKey.append( chr(((ord(InputKey[5:6])&0x3F)<<1) | (ord(InputKey[6:7])>>7)) )
267 OutputKey.append( chr(ord(InputKey[6:7]) & 0x7F) )
269 for i in range(8):
270 OutputKey[i] = chr((ord(OutputKey[i]) << 1) & 0xfe)
272 return b("".join(OutputKey))
274def decryptSecret(key, value):
275 # [MS-LSAD] Section 5.1.2
276 plainText = b''
277 key0 = key
278 for i in range(0, len(value), 8):
279 cipherText = value[:8]
280 tmpStrKey = key0[:7]
281 tmpKey = transformKey(tmpStrKey)
282 Crypt1 = DES.new(tmpKey, DES.MODE_ECB)
283 plainText += Crypt1.decrypt(cipherText)
284 key0 = key0[7:]
285 value = value[8:]
286 # AdvanceKey
287 if len(key0) < 7:
288 key0 = key[len(key0):]
290 secret = LSA_SECRET_XP(plainText)
291 return (secret['Secret'])
293def encryptSecret(key, value):
294 # [MS-LSAD] Section 5.1.2
295 cipherText = b''
296 key0 = key
297 value0 = pack('<LL', len(value), 1) + value
298 for i in range(0, len(value0), 8):
299 if len(value0) < 8:
300 value0 = value0 + b'\x00'*(8-len(value0))
301 plainText = value0[:8]
302 tmpStrKey = key0[:7]
303 print(type(tmpStrKey))
304 print(tmpStrKey)
305 tmpKey = transformKey(tmpStrKey)
306 Crypt1 = DES.new(tmpKey, DES.MODE_ECB)
307 cipherText += Crypt1.encrypt(plainText)
308 key0 = key0[7:]
309 value0 = value0[8:]
310 # AdvanceKey
311 if len(key0) < 7:
312 key0 = key[len(key0):]
314 return cipherText
316def SamDecryptNTLMHash(encryptedHash, key):
317 # [MS-SAMR] Section 2.2.11.1.1
318 Block1 = encryptedHash[:8]
319 Block2 = encryptedHash[8:]
321 Key1 = key[:7]
322 Key1 = transformKey(Key1)
323 Key2 = key[7:14]
324 Key2 = transformKey(Key2)
326 Crypt1 = DES.new(Key1, DES.MODE_ECB)
327 Crypt2 = DES.new(Key2, DES.MODE_ECB)
329 plain1 = Crypt1.decrypt(Block1)
330 plain2 = Crypt2.decrypt(Block2)
332 return plain1 + plain2
334def SamEncryptNTLMHash(encryptedHash, key):
335 # [MS-SAMR] Section 2.2.11.1.1
336 Block1 = encryptedHash[:8]
337 Block2 = encryptedHash[8:]
339 Key1 = key[:7]
340 Key1 = transformKey(Key1)
341 Key2 = key[7:14]
342 Key2 = transformKey(Key2)
344 Crypt1 = DES.new(Key1, DES.MODE_ECB)
345 Crypt2 = DES.new(Key2, DES.MODE_ECB)
347 plain1 = Crypt1.encrypt(Block1)
348 plain2 = Crypt2.encrypt(Block2)
350 return plain1 + plain2