0% found this document useful (0 votes)
44 views4 pages

Implementing SHA-1 in Python

This document outlines an implementation of the SHA-1 hash algorithm in Python for educational purposes. It includes the class definition, methods for preprocessing messages, processing blocks, and calculating the final hash value, along with example usage. The implementation demonstrates both single and incremental hashing of messages.

Uploaded by

krutikapandya23
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
44 views4 pages

Implementing SHA-1 in Python

This document outlines an implementation of the SHA-1 hash algorithm in Python for educational purposes. It includes the class definition, methods for preprocessing messages, processing blocks, and calculating the final hash value, along with example usage. The implementation demonstrates both single and incremental hashing of messages.

Uploaded by

krutikapandya23
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Universal College of Engineering, Kaman

Department of Computer Engineering


Subject:CSS
Experiment no: 6
Roll No: 55 Name: Krutika Pandya Div: B Batch: B1

AIM: To implement SHA Algorithm

PROGRAM:

import struct

class SHA1:
"""
A pure Python implementation of the SHA-1 hash function.
This implementation is for educational purposes only and should
not be used for production environments due to its potential
performance limitations and lack of optimizations.
"""
def __init__(self):
# Initial hash values
self.h = [
0x67452301,
0xEFCDAB89,
0x98BADCFE,
0x10325476,
0xC3D2E1F0,
]
# Message block buffer
[Link] = bytearray()
# Length of the original message (in bits)
self.message_len = 0

def _preprocess(self, message):
"""
Preprocesses the message by padding it according to the SHA-1
standard.
"""
# Convert message to bytearray if it's not already
if isinstance(message, str):
message = [Link]('utf-8')
elif isinstance(message, bytes):
message = bytearray(message)

[Link] = message
self.message_len = len(message) * 8 # Length in bits
# Append "1" bit (followed by 0s)
[Link](0x80) # 0x80 is 10000000 in binary
# Pad with zeros until length is congruent to 448 mod 512
while (len([Link]) * 8) % 512 != 448:
[Link](0x00)
# Append length (in bits) as a 64-bit big-endian integer
[Link] += [Link]('>Q', self.message_len) # >Q for big-endian unsigned long long
return [Link]

def _process_block(self, block):
"""
Processes a single 512-bit (64-byte) block of the message.
"""
# Initialize message schedule (W)
w = [0] * 80
# Break block into 16 big-endian words
for i in range(16):
w[i] = [Link]('>I', block[i * 4:i * 4 + 4])[0] # >I for big-endian unsigned int
# Extend the first 16 words into the remaining 64 words
for i in range(16, 80):
w[i] = self._leftrotate(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1)
# Initialize working variables to current hash value
a, b, c, d, e = self.h
# SHA-1 main loop (80 rounds)
for i in range(80):
if 0 <= i <= 19:
f = (b & c) | ((~b) & d)
k = 0x5A827999
elif 20 <= i <= 39:
f=b^c^d
k = 0x6ED9EBA1
elif 40 <= i <= 59:
f = (b & c) | (b & d) | (c & d)
k = 0x8F1BBCDC
elif 60 <= i <= 79:
f=b^c^d
k = 0xCA62C1D6
temp = (self._leftrotate(a, 5) + f + e + k + w[i]) & 0xFFFFFFFF # Ensure 32-bit result
e=d
d=c
c = self._leftrotate(b, 30)
b=a
a = temp
# Add the compressed chunk to current hash value
self.h[0] = (self.h[0] + a) & 0xFFFFFFFF
self.h[1] = (self.h[1] + b) & 0xFFFFFFFF
self.h[2] = (self.h[2] + c) & 0xFFFFFFFF
self.h[3] = (self.h[3] + d) & 0xFFFFFFFF
self.h[4] = (self.h[4] + e) & 0xFFFFFFFF

def _leftrotate(self, value, bits):
"""
Performs a left bitwise rotation of a 32-bit value.
"""
value &= 0xFFFFFFFF # Ensure value is 32-bit
return ((value << bits) | (value >> (32 - bits))) & 0xFFFFFFFF # Ensure result is 32-bit

def update(self, message):
"""
Updates the hash with a new chunk of data. This function *can* be
called multiple times to hash data incrementally.
"""
if isinstance(message, str):
message = [Link]('utf-8') # Encode to bytes
[Link] += bytearray(message)
self.message_len += len(message) * 8 # Update the length in bits

def digest(self):
"""
Calculates the final SHA-1 hash value.
"""
# Preprocess the complete message (including any data from `update` calls)
padded_message = self._preprocess(bytes([Link]))

# Process message in 512-bit (64-byte) chunks
for i in range(0, len(padded_message), 64):
block = padded_message[i:i + 64]
self._process_block(block)
# Return the hash as a byte string
return b''.join([Link]('>I', h) for h in self.h)

def hexdigest(self):
"""
Returns the SHA-1 hash value as a hexadecimal string.
"""
return ''.join('%08x' % h for h in self.h)

def hash(self, message):
"""
Hashes the given message in a single call. This is a convenience
function for simple use cases.
"""
self.__init__() # reset the state for reuse
[Link](message)
return [Link]()

# Example usage:
if __name__ == "__main__":
message = "UNIVERSAL ENGINEERING COLLEGE"
sha1 = SHA1()
# Example 1: Hashing in a single call
hash_value = [Link](message)
print(f"SHA-1 hash of '{message}': {hash_value}")
# Example 2: Incremental hashing
sha1 = SHA1() # Create a new SHA1 object
[Link]("Hello")
[Link](", ")
[Link]("world!")
hash_value = [Link]()
print(f"SHA-1 hash of '{message}' (incremental): {hash_value}")
# Example of hashing an empty string
sha1 = SHA1()
empty_hash = [Link]("")
print(f"SHA-1 hash of an empty string: {empty_hash}")
# Testing with a larger message
long_message = "This is a much longer message to demonstrate how the SHA-1 algorithm
handles different message lengths. It should be long enough to trigger the padding process."
sha1 = SHA1()
long_hash = [Link](long_message)
print(f"SHA-1 hash of a longer message: {long_hash}")

OUTPUT:

You might also like