Skip to content

Commit d21b4cf

Browse files
QuantumNoviceharshildarji
authored andcommitted
Added pytests to hashes/md5.py (TheAlgorithms#1100)
* Added pytests to sha1.py * tweaking md5 * Added Pytests to hashes/md5.py
1 parent 89acf5d commit d21b4cf

File tree

1 file changed

+154
-133
lines changed

1 file changed

+154
-133
lines changed

hashes/md5.py

+154-133
Original file line numberDiff line numberDiff line change
@@ -1,155 +1,176 @@
11
from __future__ import print_function
22
import math
33

4+
45
def rearrange(bitString32):
5-
"""[summary]
6-
Regroups the given binary string.
7-
8-
Arguments:
9-
bitString32 {[string]} -- [32 bit binary]
10-
11-
Raises:
12-
ValueError -- [if the given string not are 32 bit binary string]
13-
14-
Returns:
15-
[string] -- [32 bit binary string]
16-
"""
17-
18-
if len(bitString32) != 32:
19-
raise ValueError("Need length 32")
20-
newString = ""
21-
for i in [3,2,1,0]:
22-
newString += bitString32[8*i:8*i+8]
23-
return newString
6+
"""[summary]
7+
Regroups the given binary string.
8+
9+
Arguments:
10+
bitString32 {[string]} -- [32 bit binary]
11+
12+
Raises:
13+
ValueError -- [if the given string not are 32 bit binary string]
14+
15+
Returns:
16+
[string] -- [32 bit binary string]
17+
>>> rearrange('1234567890abcdfghijklmnopqrstuvw')
18+
'pqrstuvwhijklmno90abcdfg12345678'
19+
"""
20+
21+
if len(bitString32) != 32:
22+
raise ValueError("Need length 32")
23+
newString = ""
24+
for i in [3, 2,1,0]:
25+
newString += bitString32[8*i:8*i+8]
26+
return newString
27+
2428

2529
def reformatHex(i):
26-
"""[summary]
27-
Converts the given integer into 8-digit hex number.
30+
"""[summary]
31+
Converts the given integer into 8-digit hex number.
2832
29-
Arguments:
30-
i {[int]} -- [integer]
31-
"""
33+
Arguments:
34+
i {[int]} -- [integer]
35+
>>> reformatHex(666)
36+
'9a020000'
37+
"""
38+
39+
hexrep = format(i, '08x')
40+
thing = ""
41+
for i in [3, 2,1,0]:
42+
thing += hexrep[2*i:2*i+2]
43+
return thing
3244

33-
hexrep = format(i,'08x')
34-
thing = ""
35-
for i in [3,2,1,0]:
36-
thing += hexrep[2*i:2*i+2]
37-
return thing
3845

3946
def pad(bitString):
40-
"""[summary]
41-
Fills up the binary string to a 512 bit binary string
42-
43-
Arguments:
44-
bitString {[string]} -- [binary string]
45-
46-
Returns:
47-
[string] -- [binary string]
48-
"""
49-
50-
startLength = len(bitString)
51-
bitString += '1'
52-
while len(bitString) % 512 != 448:
53-
bitString += '0'
54-
lastPart = format(startLength,'064b')
55-
bitString += rearrange(lastPart[32:]) + rearrange(lastPart[:32])
56-
return bitString
47+
"""[summary]
48+
Fills up the binary string to a 512 bit binary string
49+
50+
Arguments:
51+
bitString {[string]} -- [binary string]
52+
53+
Returns:
54+
[string] -- [binary string]
55+
"""
56+
startLength = len(bitString)
57+
bitString += '1'
58+
while len(bitString) % 512 != 448:
59+
bitString += '0'
60+
lastPart = format(startLength, '064b')
61+
bitString += rearrange(lastPart[32:]) + rearrange(lastPart[:32])
62+
return bitString
63+
5764

5865
def getBlock(bitString):
59-
"""[summary]
60-
Iterator:
61-
Returns by each call a list of length 16 with the 32 bit
62-
integer blocks.
63-
64-
Arguments:
65-
bitString {[string]} -- [binary string >= 512]
66-
"""
67-
68-
currPos = 0
69-
while currPos < len(bitString):
70-
currPart = bitString[currPos:currPos+512]
71-
mySplits = []
72-
for i in range(16):
73-
mySplits.append(int(rearrange(currPart[32*i:32*i+32]),2))
74-
yield mySplits
75-
currPos += 512
66+
"""[summary]
67+
Iterator:
68+
Returns by each call a list of length 16 with the 32 bit
69+
integer blocks.
7670
77-
def not32(i):
78-
i_str = format(i,'032b')
79-
new_str = ''
80-
for c in i_str:
81-
new_str += '1' if c=='0' else '0'
82-
return int(new_str,2)
71+
Arguments:
72+
bitString {[string]} -- [binary string >= 512]
73+
"""
8374

84-
def sum32(a,b):
85-
return (a + b) % 2**32
75+
currPos = 0
76+
while currPos < len(bitString):
77+
currPart = bitString[currPos:currPos+512]
78+
mySplits = []
79+
for i in range(16):
80+
mySplits.append(int(rearrange(currPart[32*i:32*i+32]), 2))
81+
yield mySplits
82+
currPos += 512
83+
84+
85+
def not32(i):
86+
'''
87+
>>> not32(34)
88+
4294967261
89+
'''
90+
i_str = format(i, '032b')
91+
new_str = ''
92+
for c in i_str:
93+
new_str += '1' if c == '0' else '0'
94+
return int(new_str, 2)
95+
96+
def sum32(a, b):
97+
'''
98+
99+
'''
100+
return (a + b) % 2**32
101+
102+
def leftrot32(i, s):
103+
return (i << s) ^ (i >> (32-s))
86104

87-
def leftrot32(i,s):
88-
return (i << s) ^ (i >> (32-s))
89105

90106
def md5me(testString):
91-
"""[summary]
92-
Returns a 32-bit hash code of the string 'testString'
93-
94-
Arguments:
95-
testString {[string]} -- [message]
96-
"""
97-
98-
bs =''
99-
for i in testString:
100-
bs += format(ord(i),'08b')
101-
bs = pad(bs)
102-
103-
tvals = [int(2**32 * abs(math.sin(i+1))) for i in range(64)]
104-
105-
a0 = 0x67452301
106-
b0 = 0xefcdab89
107-
c0 = 0x98badcfe
108-
d0 = 0x10325476
109-
110-
s = [7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, \
111-
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, \
112-
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, \
113-
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 ]
114-
115-
for m in getBlock(bs):
116-
A = a0
117-
B = b0
118-
C = c0
119-
D = d0
120-
for i in range(64):
121-
if i <= 15:
122-
#f = (B & C) | (not32(B) & D)
123-
f = D ^ (B & (C ^ D))
124-
g = i
125-
elif i<= 31:
126-
#f = (D & B) | (not32(D) & C)
127-
f = C ^ (D & (B ^ C))
128-
g = (5*i+1) % 16
129-
elif i <= 47:
130-
f = B ^ C ^ D
131-
g = (3*i+5) % 16
132-
else:
133-
f = C ^ (B | not32(D))
134-
g = (7*i) % 16
135-
dtemp = D
136-
D = C
137-
C = B
138-
B = sum32(B,leftrot32((A + f + tvals[i] + m[g]) % 2**32, s[i]))
139-
A = dtemp
140-
a0 = sum32(a0, A)
141-
b0 = sum32(b0, B)
142-
c0 = sum32(c0, C)
143-
d0 = sum32(d0, D)
144-
145-
digest = reformatHex(a0) + reformatHex(b0) + reformatHex(c0) + reformatHex(d0)
146-
return digest
107+
"""[summary]
108+
Returns a 32-bit hash code of the string 'testString'
109+
110+
Arguments:
111+
testString {[string]} -- [message]
112+
"""
113+
114+
bs = ''
115+
for i in testString:
116+
bs += format(ord(i), '08b')
117+
bs = pad(bs)
118+
119+
tvals = [int(2**32 * abs(math.sin(i+1))) for i in range(64)]
120+
121+
a0 = 0x67452301
122+
b0 = 0xefcdab89
123+
c0 = 0x98badcfe
124+
d0 = 0x10325476
125+
126+
s = [7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
127+
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, \
128+
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, \
129+
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 ]
130+
131+
for m in getBlock(bs):
132+
A = a0
133+
B = b0
134+
C = c0
135+
D = d0
136+
for i in range(64):
137+
if i <= 15:
138+
#f = (B & C) | (not32(B) & D)
139+
f = D ^ (B & (C ^ D))
140+
g = i
141+
elif i <= 31:
142+
#f = (D & B) | (not32(D) & C)
143+
f = C ^ (D & (B ^ C))
144+
g = (5*i+1) % 16
145+
elif i <= 47:
146+
f = B ^ C ^ D
147+
g = (3*i+5) % 16
148+
else:
149+
f = C ^ (B | not32(D))
150+
g = (7*i) % 16
151+
dtemp = D
152+
D = C
153+
C = B
154+
B = sum32(B, leftrot32((A + f + tvals[i] + m[g]) % 2**32, s[i]))
155+
A = dtemp
156+
a0 = sum32(a0, A)
157+
b0 = sum32(b0, B)
158+
c0 = sum32(c0, C)
159+
d0 = sum32(d0, D)
160+
161+
digest = reformatHex(a0) + reformatHex(b0) + \
162+
reformatHex(c0) + reformatHex(d0)
163+
return digest
164+
147165

148166
def test():
149-
assert md5me("") == "d41d8cd98f00b204e9800998ecf8427e"
150-
assert md5me("The quick brown fox jumps over the lazy dog") == "9e107d9d372bb6826bd81d3542a419d6"
151-
print("Success.")
167+
assert md5me("") == "d41d8cd98f00b204e9800998ecf8427e"
168+
assert md5me(
169+
"The quick brown fox jumps over the lazy dog") == "9e107d9d372bb6826bd81d3542a419d6"
170+
print("Success.")
152171

153172

154173
if __name__ == "__main__":
155-
test()
174+
test()
175+
import doctest
176+
doctest.testmod()

0 commit comments

Comments
 (0)