Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/scapy/layers/tls/crypto/md4.py: 36%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

56 statements  

1# SPDX-License-Identifier: WTFPL 

2# This file is part of Scapy 

3# See https://scapy.net/ for more information 

4# Copyright (C) 2019 James Seo <james@equiv.tech> (github.com/kangtastic). 

5 

6""" 

7MD4 implementation 

8 

9Modified from: 

10https://gist.github.com/kangtastic/c3349fc4f9d659ee362b12d7d8c639b6 

11""" 

12 

13import struct 

14 

15 

16class MD4: 

17 """ 

18 An implementation of the MD4 hash algorithm. 

19 

20 Modified to provide the same API as hashlib's. 

21 """ 

22 name = 'md4' 

23 block_size = 64 

24 width = 32 

25 mask = 0xFFFFFFFF 

26 

27 # Unlike, say, SHA-1, MD4 uses little-endian. Fascinating! 

28 h = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476] 

29 

30 def __init__(self, msg=b""): 

31 self.msg = msg 

32 

33 def update(self, msg): 

34 self.msg += msg 

35 

36 def digest(self): 

37 # Pre-processing: Total length is a multiple of 512 bits. 

38 ml = len(self.msg) * 8 

39 self.msg += b"\x80" 

40 self.msg += b"\x00" * (-(len(self.msg) + 8) % self.block_size) 

41 self.msg += struct.pack("<Q", ml) 

42 

43 # Process the message in successive 512-bit chunks. 

44 self._process([self.msg[i: i + self.block_size] 

45 for i in range(0, len(self.msg), self.block_size)]) 

46 

47 return struct.pack("<4L", *self.h) 

48 

49 def _process(self, chunks): 

50 for chunk in chunks: 

51 X, h = list(struct.unpack("<16I", chunk)), self.h.copy() 

52 

53 # Round 1. 

54 Xi = [3, 7, 11, 19] 

55 for n in range(16): 

56 i, j, k, l = map(lambda x: x % 4, range(-n, -n + 4)) 

57 K, S = n, Xi[n % 4] 

58 hn = h[i] + MD4.F(h[j], h[k], h[l]) + X[K] 

59 h[i] = MD4.lrot(hn & MD4.mask, S) 

60 

61 # Round 2. 

62 Xi = [3, 5, 9, 13] 

63 for n in range(16): 

64 i, j, k, l = map(lambda x: x % 4, range(-n, -n + 4)) 

65 K, S = n % 4 * 4 + n // 4, Xi[n % 4] 

66 hn = h[i] + MD4.G(h[j], h[k], h[l]) + X[K] + 0x5A827999 

67 h[i] = MD4.lrot(hn & MD4.mask, S) 

68 

69 # Round 3. 

70 Xi = [3, 9, 11, 15] 

71 Ki = [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15] 

72 for n in range(16): 

73 i, j, k, l = map(lambda x: x % 4, range(-n, -n + 4)) 

74 K, S = Ki[n], Xi[n % 4] 

75 hn = h[i] + MD4.H(h[j], h[k], h[l]) + X[K] + 0x6ED9EBA1 

76 h[i] = MD4.lrot(hn & MD4.mask, S) 

77 

78 self.h = [((v + n) & MD4.mask) for v, n in zip(self.h, h)] 

79 

80 @staticmethod 

81 def F(x, y, z): 

82 return (x & y) | (~x & z) 

83 

84 @staticmethod 

85 def G(x, y, z): 

86 return (x & y) | (x & z) | (y & z) 

87 

88 @staticmethod 

89 def H(x, y, z): 

90 return x ^ y ^ z 

91 

92 @staticmethod 

93 def lrot(value, n): 

94 lbits, rbits = (value << n) & MD4.mask, value >> (MD4.width - n) 

95 return lbits | rbits