"""Demonstrates implementation of SHA1 Hash function in a Python class and gives utilitiesto 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"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 thatreturned by the hashlib librarySHA1 hash or SHA1 sum of a string is a crytpographic function which means it is easyto calculate forwards but extemely difficult to calculate backwards. What this meansis, you can easily calculate the hash of a string, but it is extremely difficult toknow the original string if you have its hash. This property is useful to communicatesecurely, send encrypted messages and is very useful in payment systems, blockchainand cryptocurrency etc.The Algorithm as described in the reference:First we start with a message. The message is padded and the length of the messageis added to the end. It is then split into blocks of 512 bits or 64 bytes. The blocksare then processed one at a time. Each block must be expanded and compressed.The value after each compression is added to a 160bit buffer called the current hashstate. After the last block is processed the current hash state is returned asthe final hash.Reference: https://deadhacker.com/2006/02/21/sha-1-illustrated/"""import argparseimport structimport hashlib #hashlib is only used inside the Test classimport unittestclass SHA1Hash:"""Class to contain the entire pipeline for SHA1 Hashing Algorithm"""def __init__(self, data):"""Inititates the variables data and h. h is a list of 5 8-digit Hexadecimalnumbers corresponding to (1732584193, 4023233417, 2562383102, 271733878, 3285377520)respectively. We will start with this as a message digest. 0x is how you writeHexadecimal numbers in Python"""self.data = dataself.h = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]@staticmethoddef rotate(n, b):"""Static method to be used inside other methods. Left rotates n by b."""return ((n << b) | (n >> (32 - b))) & 0xffffffffdef padding(self):"""Pads the input message with zeros so that padded_data has 64 bytes or 512 bits"""padding = b'\x80' + b'\x00'*(63 - (len(self.data) + 8) % 64)padded_data = self.data + padding + struct.pack('>Q', 8 * len(self.data))return padded_datadef split_blocks(self):"""Returns a list of bytestrings each of length 64"""return [self.padded_data[i:i+64] for i in range(0, len(self.padded_data), 64)]# @staticmethoddef expand_block(self, block):"""Takes a bytestring-block of length 64, unpacks it to a list of integers and returns alist of 80 integers pafter some bit operations"""w = list(struct.unpack('>16L', block)) + [0] * 64for i in range(16, 80):w[i] = self.rotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1)return wdef final_hash(self):"""Calls all the other methods to process the input. Pads the data, then splits intoblocks and then does a series of operations for each block (including expansion).For each block, the variable h that was initialized is copied to a,b,c,d,eand these 5 variables a,b,c,d,e undergo several changes. After all the blocks areprocessed, these 5 variables are pairwise added to h ie a to h[0], b to h[1] and so on.This h becomes our final hash which is returned."""self.padded_data = self.padding()self.blocks = self.split_blocks()for block in self.blocks:expanded_block = self.expand_block(block)a, b, c, d, e = self.hfor i in range(0, 80):if 0 <= i < 20:f = (b & c) | ((~b) & d)k = 0x5A827999elif 20 <= i < 40:f = b ^ c ^ dk = 0x6ED9EBA1elif 40 <= i < 60:f = (b & c) | (b & d) | (c & d)k = 0x8F1BBCDCelif 60 <= i < 80:f = b ^ c ^ dk = 0xCA62C1D6a, b, c, d, e = self.rotate(a, 5) + f + e + k + expanded_block[i] & 0xffffffff,\a, self.rotate(b, 30), c, dself.h = self.h[0] + a & 0xffffffff,\self.h[1] + b & 0xffffffff,\self.h[2] + c & 0xffffffff,\self.h[3] + d & 0xffffffff,\self.h[4] + e & 0xffffffffreturn '%08x%08x%08x%08x%08x' %tuple(self.h)class SHA1HashTest(unittest.TestCase):"""Test class for the SHA1Hash class. Inherits the TestCase class from unittest"""def testMatchHashes(self):msg = bytes('Test String', 'utf-8')self.assertEqual(SHA1Hash(msg).final_hash(), hashlib.sha1(msg).hexdigest())def main():"""Provides option 'string' or 'file' to take input and prints the calculated SHA1 hash.unittest.main() has been commented because we probably dont want to runthe test each time."""# unittest.main()parser = argparse.ArgumentParser(description='Process some strings or files')parser.add_argument('--string', dest='input_string',default='Hello World!! Welcome to Cryptography',help='Hash the string')parser.add_argument('--file', dest='input_file', help='Hash contents of a file')args = parser.parse_args()input_string = args.input_string#In any case hash input should be a bytestringif args.input_file:with open(args.input_file, 'rb') as f:hash_input = f.read()else:hash_input = bytes(input_string, 'utf-8')print(SHA1Hash(hash_input).final_hash())if __name__ == '__main__':main()
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。