11#!/usr/bin/python
2- # Hash: d758637770374a601330b7e5dc60215505a338702c6188b8563034c3e487ab2b
2+ # Hash: 7133c3ec57f1dbdd2b35a409abebd34ea0736fde377056706b32bf955ae7d313
3+ # Author: Ron Stoner
4+ # Github: ronaldstoner
5+ # Website: stoner.com
36
4- # No password is set for this hash as it is used to verify the selfhash module code itself and can be checked against the github repo
7+ # No password is set for this hash as it is used to verify the selfhash module code itself
8+ # This can be checked against the GitHub repository
59
6- """SelfHash - Self hashing and verification python script"""
10+ """SelfHash - Self- hashing and verification Python script"""
711
812import hashlib
913import getpass
1014import sys
1115
16+
1217class SelfHash :
13- """Class for SelfHash"""
18+
19+ """Class to handle the self-hashing and verification of Python source code."""
1420 def __init__ (self , bypass_salt = False ):
15- """Init function"""
16- self .file_data_hash = None
17- self .source_code_hash = None
18- self .known_hash = None
19- self .bypass_salt = bypass_salt
21+ """
22+ Initializes the SelfHash object.
23+
24+ :param bypass_salt: Flag to bypass the salt input (default is False).
25+ """
26+ self .file_data_hash = None # Holds the hash of the file data without the hash line
27+ self .source_code_hash = None # Holds the calculated hash of the source code
28+ self .known_hash = None # Holds the known hash from the source code
29+ self .bypass_salt = bypass_salt # Flag to bypass the salt input
2030
2131 def hash (self , file ):
22- """Function that hashes the source code"""
32+ """
33+ Reads the file, calculates its hash, and verifies the integrity of the code by comparing
34+ it with the known hash embedded in the source.
35+
36+ :param file: The Python file to be hashed and verified.
37+ """
2338 fail = False
2439
40+ # Open the file and read its contents into a list of lines
2541 with open (file , 'r' , encoding = "utf-8" ) as source_file :
2642 file_data = source_file .readlines ()
2743
44+ # Ensure the file has at least 2 lines (the second line will contain the hash)
45+ if len (file_data ) < 2 :
46+ print ("Error: The file is too short. It should have at least 2 lines." )
47+ fail = True
48+ sys .exit (1 ) # Exit immediately if the file is too short
49+
50+ # Extract the hash from the line and fail if not found
2851 try :
2952 hash_line_index = [i for i , line in enumerate (file_data ) if line .strip ().startswith ("# Hash:" )][0 ]
3053 except IndexError :
3154 print ("The '# Hash:' line was not found in the file." )
3255 print ("Please add '# Hash: INSERT_HASH_HERE' at \n the top of your python file and try again." )
3356 fail = True
57+ sys .exit (1 ) # Exit immediately if the '# Hash: ' is not found
3458
35- if fail :
36- sys .exit (1 )
37-
59+ # Remove the hash line from the source file data to compute the rest of the code's hash
3860 self .file_data_hash = '' .join ([line for i , line in enumerate (file_data ) if i != hash_line_index ])
3961
62+ # Prompt for a salt if not bypassing it
4063 if not self .bypass_salt :
4164 salt = getpass .getpass (prompt = 'This python script is protected by SelfHash.\n Please provide a salt for the hash calculation.\n If you do not want to provide one, just press Enter: ' )
42- self .file_data_hash += salt
65+ if salt : # If a salt is provided, add it to the file data hash
66+ self .file_data_hash += salt
4367
68+ # Calculate the SHA-256 hash of the source code (with salt if provided)
4469 self .source_code_hash = hashlib .sha256 (self .file_data_hash .encode ()).hexdigest ()
4570
71+ # Compare the known hash to the calculated hash
4672 self .known_hash = file_data [hash_line_index ].strip ().split (' ' )[- 1 ]
73+ self .known_hash = self .known_hash .strip () # Clean up extra spaces
74+
75+ if len (self .known_hash ) != 64 : # Ensure it is a valid SHA256 hash
76+ print ("Invalid hash format found in the file." )
77+ fail = True
4778
4879 if self .known_hash in ("Hash:" , "INSERT_HASH_HERE" ):
4980 print ("The hash of the source code is not set yet.\n Please run the script once and then replace INSERT_HASH_HERE with the hash." )
@@ -55,5 +86,6 @@ def hash(self, file):
5586 print ("\033 [91mFAIL\033 [0m: The source code may have been tampered with or the salt/passphrase is incorrect." )
5687 fail = True
5788
89+ # Exit with error if there was any failure
5890 if fail :
5991 sys .exit (1 )
0 commit comments