From a8b5c748c2cc162fcb69b86b4deeae3a66965c05 Mon Sep 17 00:00:00 2001 From: QuantumNovice Date: Tue, 6 Aug 2019 00:35:30 +0500 Subject: [PATCH 1/3] Added pytests to sha1.py --- 16L' | 0 Q' | 0 hashes/sha1.py | 10 ++++++++-- 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 16L' create mode 100644 Q' diff --git a/16L' b/16L' new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Q' b/Q' new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/hashes/sha1.py b/hashes/sha1.py index 4c78ad3a89e5..511ea6363733 100644 --- a/hashes/sha1.py +++ b/hashes/sha1.py @@ -2,7 +2,7 @@ Demonstrates implementation of SHA1 Hash function in a Python class and gives utilities to find hash of string or hash of text from a file. Usage: python sha1.py --string "Hello World!!" - pyhton sha1.py --file "hello_world.txt" + python sha1.py --file "hello_world.txt" When run without any arguments, it prints the hash of the string "Hello World!! Welcome to Cryptography" Also contains a Test class to verify that the generated Hash is same as that returned by the hashlib library @@ -32,6 +32,8 @@ class SHA1Hash: """ Class to contain the entire pipeline for SHA1 Hashing Algorithm + >>> SHA1Hash(bytes('Allan', 'utf-8')).final_hash() + '872af2d8ac3d8695387e7c804bf0e02c18df9e6e' """ def __init__(self, data): """ @@ -47,6 +49,8 @@ def __init__(self, data): def rotate(n, b): """ Static method to be used inside other methods. Left rotates n by b. + >>> SHA1Hash('').rotate(12,2) + 48 """ return ((n << b) | (n >> (32 - b))) & 0xffffffff @@ -68,7 +72,7 @@ def split_blocks(self): def expand_block(self, block): """ Takes a bytestring-block of length 64, unpacks it to a list of integers and returns a - list of 80 integers pafter some bit operations + list of 80 integers after some bit operations """ w = list(struct.unpack('>16L', block)) + [0] * 64 for i in range(16, 80): @@ -146,3 +150,5 @@ def main(): if __name__ == '__main__': main() + import doctest + doctest.testmod() \ No newline at end of file From 802bb76fb98e2e2cc27ad337e2f644e429309e3f Mon Sep 17 00:00:00 2001 From: QuantumNovice Date: Tue, 6 Aug 2019 11:16:27 +0500 Subject: [PATCH 2/3] tweaking md5 --- hashes/md5.py | 287 +++++++++++++++++++++++++++----------------------- 1 file changed, 154 insertions(+), 133 deletions(-) diff --git a/hashes/md5.py b/hashes/md5.py index d3f15510874e..feb3b10eb031 100644 --- a/hashes/md5.py +++ b/hashes/md5.py @@ -1,155 +1,176 @@ from __future__ import print_function import math + def rearrange(bitString32): - """[summary] - Regroups the given binary string. - - Arguments: - bitString32 {[string]} -- [32 bit binary] - - Raises: - ValueError -- [if the given string not are 32 bit binary string] - - Returns: - [string] -- [32 bit binary string] - """ - - if len(bitString32) != 32: - raise ValueError("Need length 32") - newString = "" - for i in [3,2,1,0]: - newString += bitString32[8*i:8*i+8] - return newString + """[summary] + Regroups the given binary string. + + Arguments: + bitString32 {[string]} -- [32 bit binary] + + Raises: + ValueError -- [if the given string not are 32 bit binary string] + + Returns: + [string] -- [32 bit binary string] + >>> rearrange('1234567890abcdfghijklmnopqrstuvw') + 'pqrstuvwhijklmno90abcdfg12345678' + """ + + if len(bitString32) != 32: + raise ValueError("Need length 32") + newString = "" + for i in [3, 2,1,0]: + newString += bitString32[8*i:8*i+8] + return newString + def reformatHex(i): - """[summary] - Converts the given integer into 8-digit hex number. + """[summary] + Converts the given integer into 8-digit hex number. - Arguments: - i {[int]} -- [integer] - """ + Arguments: + i {[int]} -- [integer] + >>> reformatHex(666) + '9a020000' + """ + + hexrep = format(i, '08x') + thing = "" + for i in [3, 2,1,0]: + thing += hexrep[2*i:2*i+2] + return thing - hexrep = format(i,'08x') - thing = "" - for i in [3,2,1,0]: - thing += hexrep[2*i:2*i+2] - return thing def pad(bitString): - """[summary] - Fills up the binary string to a 512 bit binary string - - Arguments: - bitString {[string]} -- [binary string] - - Returns: - [string] -- [binary string] - """ - - startLength = len(bitString) - bitString += '1' - while len(bitString) % 512 != 448: - bitString += '0' - lastPart = format(startLength,'064b') - bitString += rearrange(lastPart[32:]) + rearrange(lastPart[:32]) - return bitString + """[summary] + Fills up the binary string to a 512 bit binary string + + Arguments: + bitString {[string]} -- [binary string] + + Returns: + [string] -- [binary string] + """ + startLength = len(bitString) + bitString += '1' + while len(bitString) % 512 != 448: + bitString += '0' + lastPart = format(startLength, '064b') + bitString += rearrange(lastPart[32:]) + rearrange(lastPart[:32]) + return bitString + def getBlock(bitString): - """[summary] - Iterator: - Returns by each call a list of length 16 with the 32 bit - integer blocks. - - Arguments: - bitString {[string]} -- [binary string >= 512] - """ - - currPos = 0 - while currPos < len(bitString): - currPart = bitString[currPos:currPos+512] - mySplits = [] - for i in range(16): - mySplits.append(int(rearrange(currPart[32*i:32*i+32]),2)) - yield mySplits - currPos += 512 + """[summary] + Iterator: + Returns by each call a list of length 16 with the 32 bit + integer blocks. -def not32(i): - i_str = format(i,'032b') - new_str = '' - for c in i_str: - new_str += '1' if c=='0' else '0' - return int(new_str,2) + Arguments: + bitString {[string]} -- [binary string >= 512] + """ -def sum32(a,b): - return (a + b) % 2**32 + currPos = 0 + while currPos < len(bitString): + currPart = bitString[currPos:currPos+512] + mySplits = [] + for i in range(16): + mySplits.append(int(rearrange(currPart[32*i:32*i+32]), 2)) + yield mySplits + currPos += 512 + + +def not32(i): + ''' + >>> not32(34) + 4294967261 + ''' + i_str = format(i, '032b') + new_str = '' + for c in i_str: + new_str += '1' if c == '0' else '0' + return int(new_str, 2) + +def sum32(a, b): + ''' + + ''' + return (a + b) % 2**32 + +def leftrot32(i, s): + return (i << s) ^ (i >> (32-s)) -def leftrot32(i,s): - return (i << s) ^ (i >> (32-s)) def md5me(testString): - """[summary] - Returns a 32-bit hash code of the string 'testString' - - Arguments: - testString {[string]} -- [message] - """ - - bs ='' - for i in testString: - bs += format(ord(i),'08b') - bs = pad(bs) - - tvals = [int(2**32 * abs(math.sin(i+1))) for i in range(64)] - - a0 = 0x67452301 - b0 = 0xefcdab89 - c0 = 0x98badcfe - d0 = 0x10325476 - - s = [7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, \ - 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, \ - 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, \ - 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 ] - - for m in getBlock(bs): - A = a0 - B = b0 - C = c0 - D = d0 - for i in range(64): - if i <= 15: - #f = (B & C) | (not32(B) & D) - f = D ^ (B & (C ^ D)) - g = i - elif i<= 31: - #f = (D & B) | (not32(D) & C) - f = C ^ (D & (B ^ C)) - g = (5*i+1) % 16 - elif i <= 47: - f = B ^ C ^ D - g = (3*i+5) % 16 - else: - f = C ^ (B | not32(D)) - g = (7*i) % 16 - dtemp = D - D = C - C = B - B = sum32(B,leftrot32((A + f + tvals[i] + m[g]) % 2**32, s[i])) - A = dtemp - a0 = sum32(a0, A) - b0 = sum32(b0, B) - c0 = sum32(c0, C) - d0 = sum32(d0, D) - - digest = reformatHex(a0) + reformatHex(b0) + reformatHex(c0) + reformatHex(d0) - return digest + """[summary] + Returns a 32-bit hash code of the string 'testString' + + Arguments: + testString {[string]} -- [message] + """ + + bs = '' + for i in testString: + bs += format(ord(i), '08b') + bs = pad(bs) + + tvals = [int(2**32 * abs(math.sin(i+1))) for i in range(64)] + + a0 = 0x67452301 + b0 = 0xefcdab89 + c0 = 0x98badcfe + d0 = 0x10325476 + + s = [7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, + 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, \ + 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, \ + 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 ] + + for m in getBlock(bs): + A = a0 + B = b0 + C = c0 + D = d0 + for i in range(64): + if i <= 15: + #f = (B & C) | (not32(B) & D) + f = D ^ (B & (C ^ D)) + g = i + elif i <= 31: + #f = (D & B) | (not32(D) & C) + f = C ^ (D & (B ^ C)) + g = (5*i+1) % 16 + elif i <= 47: + f = B ^ C ^ D + g = (3*i+5) % 16 + else: + f = C ^ (B | not32(D)) + g = (7*i) % 16 + dtemp = D + D = C + C = B + B = sum32(B, leftrot32((A + f + tvals[i] + m[g]) % 2**32, s[i])) + A = dtemp + a0 = sum32(a0, A) + b0 = sum32(b0, B) + c0 = sum32(c0, C) + d0 = sum32(d0, D) + + digest = reformatHex(a0) + reformatHex(b0) + \ + reformatHex(c0) + reformatHex(d0) + return digest + def test(): - assert md5me("") == "d41d8cd98f00b204e9800998ecf8427e" - assert md5me("The quick brown fox jumps over the lazy dog") == "9e107d9d372bb6826bd81d3542a419d6" - print("Success.") + assert md5me("") == "d41d8cd98f00b204e9800998ecf8427e" + assert md5me( + "The quick brown fox jumps over the lazy dog") == "9e107d9d372bb6826bd81d3542a419d6" + print("Success.") if __name__ == "__main__": - test() + test() + import doctest + doctest.testmod() From 900ccd1bac7107f6829e0d7cebae73df2425a1a0 Mon Sep 17 00:00:00 2001 From: QuantumNovice Date: Tue, 6 Aug 2019 12:03:35 +0500 Subject: [PATCH 3/3] Added Pytests to hashes/md5.py --- hashes/md5.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hashes/md5.py b/hashes/md5.py index feb3b10eb031..7891f2077986 100644 --- a/hashes/md5.py +++ b/hashes/md5.py @@ -14,9 +14,9 @@ def rearrange(bitString32): Returns: [string] -- [32 bit binary string] - >>> rearrange('1234567890abcdfghijklmnopqrstuvw') - 'pqrstuvwhijklmno90abcdfg12345678' - """ + >>> rearrange('1234567890abcdfghijklmnopqrstuvw') + 'pqrstuvwhijklmno90abcdfg12345678' + """ if len(bitString32) != 32: raise ValueError("Need length 32")