'''simple docstring'''


import argparse
import struct
import unittest






class 					__SCREAMING_SNAKE_CASE						:







  '''simple docstring'''






  def __init__(			self				,		snake_case_						):




       '''simple docstring'''

       UpperCAmelCase_							:       Optional[int]       =				data

       # Initialize hash values
       UpperCAmelCase_							:       List[str]       =				[
           0x6A09_E667,
           0xBB67_AE85,
           0x3C6E_F372,
           0xA54F_F53A,
           0x510E_527F,
           0x9B05_688C,
           0x1F83_D9AB,
           0x5BE0_CD19,
       ]

       # Initialize round constants
       UpperCAmelCase_							:       Tuple       =				[
           0x428A_2F98,
           0x7137_4491,
           0xB5C0_FBCF,
           0xE9B5_DBA5,
           0x3956_C25B,
           0x59F1_11F1,
           0x923F_82A4,
           0xAB1C_5ED5,
           0xD807_AA98,
           0x1283_5B01,
           0x2431_85BE,
           0x550C_7DC3,
           0x72BE_5D74,
           0x80DE_B1FE,
           0x9BDC_06A7,
           0xC19B_F174,
           0xE49B_69C1,
           0xEFBE_4786,
           0x0FC1_9DC6,
           0x240C_A1CC,
           0x2DE9_2C6F,
           0x4A74_84AA,
           0x5CB0_A9DC,
           0x76F9_88DA,
           0x983E_5152,
           0xA831_C66D,
           0xB003_27C8,
           0xBF59_7FC7,
           0xC6E0_0BF3,
           0xD5A7_9147,
           0x06CA_6351,
           0x1429_2967,
           0x27B7_0A85,
           0x2E1B_2138,
           0x4D2C_6DFC,
           0x5338_0D13,
           0x650A_7354,
           0x766A_0ABB,
           0x81C2_C92E,
           0x9272_2C85,
           0xA2BF_E8A1,
           0xA81A_664B,
           0xC24B_8B70,
           0xC76C_51A3,
           0xD192_E819,
           0xD699_0624,
           0xF40E_3585,
           0x106A_A070,
           0x19A4_C116,
           0x1E37_6C08,
           0x2748_774C,
           0x34B0_BCB5,
           0x391C_0CB3,
           0x4ED8_AA4A,
           0x5B9C_CA4F,
           0x682E_6FF3,
           0x748F_82EE,
           0x78A5_636F,
           0x84C8_7814,
           0x8CC7_0208,
           0x90BE_FFFA,
           0xA450_6CEB,
           0xBEF9_A3F7,
           0xC671_78F2,
       ]

       UpperCAmelCase_							:       Dict       =				self.preprocessing(self.data						)
       self.final_hash()


  @staticmethod
  def _UpperCamelCase					(			snake_case_						):




       '''simple docstring'''

       UpperCAmelCase_							:       Tuple       =				b'\x80' + (b'\x00' * (6_3 - (len(snake_case_						) + 8) % 6_4))
       UpperCAmelCase_							:       Any       =				struct.pack('>Q'				,		(len(snake_case_						) * 8)						)
       return data + padding + big_endian_integer


  def _UpperCamelCase					(			self						):




       '''simple docstring'''

       UpperCAmelCase_							:       Dict       =				[
           self.preprocessed_data[x : x + 6_4]
           for x in range(0				,		len(self.preprocessed_data						)				,		6_4						)
       ]

       for block in self.blocks:
            # Convert the given block into a list of 4 byte integers
            UpperCAmelCase_							:       Union[str, Any]       =				list(struct.unpack('>16L'				,		snake_case_						)						)
            # add 48 0-ed integers
            words += [0] * 4_8

            UpperCAmelCase_       ,      UpperCAmelCase_       ,      UpperCAmelCase_       ,      UpperCAmelCase_       ,      UpperCAmelCase_       ,      UpperCAmelCase_       ,      UpperCAmelCase_       ,      UpperCAmelCase_							:       int       =				self.hashes

            for index in range(0				,		6_4						):
                 if index > 1_5:
                      # modify the zero-ed indexes at the end of the array
                      UpperCAmelCase_							:       str       =				(
                          self.ror(words[index - 1_5]				,		7						)
                          ^ self.ror(words[index - 1_5]				,		1_8						)
                          ^ (words[index - 1_5] >> 3)
                      )
                      UpperCAmelCase_							:       List[str]       =				(
                          self.ror(words[index - 2]				,		1_7						)
                          ^ self.ror(words[index - 2]				,		1_9						)
                          ^ (words[index - 2] >> 1_0)
                      )

                      UpperCAmelCase_							:       Tuple       =				(
                          words[index - 1_6] + sa + words[index - 7] + sa
                      ) % 0x1_0000_0000

                 # Compression
                 UpperCAmelCase_							:       List[str]       =				self.ror(snake_case_				,		6						) ^ self.ror(snake_case_				,		1_1						) ^ self.ror(snake_case_				,		2_5						)
                 UpperCAmelCase_							:       int       =				(e & f) ^ ((~e & 0xFFFF_FFFF) & g)
                 UpperCAmelCase_							:       Dict       =				(
                     h + sa + ch + self.round_constants[index] + words[index]
                 ) % 0x1_0000_0000
                 UpperCAmelCase_							:       List[Any]       =				self.ror(snake_case_				,		2						) ^ self.ror(snake_case_				,		1_3						) ^ self.ror(snake_case_				,		2_2						)
                 UpperCAmelCase_							:       Union[str, Any]       =				(a & b) ^ (a & c) ^ (b & c)
                 UpperCAmelCase_							:       Tuple       =				(sa + maj) % 0x1_0000_0000

                 UpperCAmelCase_       ,      UpperCAmelCase_       ,      UpperCAmelCase_       ,      UpperCAmelCase_       ,      UpperCAmelCase_       ,      UpperCAmelCase_       ,      UpperCAmelCase_       ,      UpperCAmelCase_							:       Dict       =				(
                     g,
                     f,
                     e,
                     ((d + tempa) % 0x1_0000_0000),
                     c,
                     b,
                     a,
                     ((tempa + tempa) % 0x1_0000_0000),
                 )

            UpperCAmelCase_							:       Any       =				[a, b, c, d, e, f, g, h]

            # Modify final values
            UpperCAmelCase_							:       List[str]       =				[
                ((element + mutated_hash_values[index]) % 0x1_0000_0000)
                for index, element in enumerate(self.hashes						)
            ]

       UpperCAmelCase_							:       Union[str, Any]       =				''.join([hex(snake_case_						)[2:].zfill(8						) for value in self.hashes]						)






  def _UpperCamelCase					(			self				,		snake_case_				,		snake_case_						):




       '''simple docstring'''

       return 0xFFFF_FFFF & (value << (3_2 - rotations)) | (value >> rotations)







class 					__SCREAMING_SNAKE_CASE						(	unittest.TestCase	):







  '''simple docstring'''






  def _UpperCamelCase					(			self						):




       '''simple docstring'''

       import hashlib

       UpperCAmelCase_							:       int       =				bytes('Test String'				,		'utf-8'						)
       self.assertEqual(SHAaaa(snake_case_						).hash				,		hashlib.shaaaa(snake_case_						).hexdigest()						)







def  _lowerCamelCase   (				):



     """simple docstring"""





     import doctest

     doctest.testmod()

     UpperCAmelCase_							:       Optional[Any]       =				argparse.ArgumentParser()
     parser.add_argument(
         '-s'     ,					'--string'     ,					dest='input_string'     ,					default='Hello World!! Welcome to Cryptography'     ,					help='Hash the string'     ,					)
     parser.add_argument(
         '-f'     ,					'--file'     ,					dest='input_file'     ,					help='Hash contents of a file'       )

     UpperCAmelCase_							:       List[Any]       =				parser.parse_args()

     UpperCAmelCase_							:       List[Any]       =				args.input_string

     # hash input should be a bytestring
     if args.input_file:
          with open(args.input_file     ,					'rb'       ) as f:
               UpperCAmelCase_							:       Optional[Any]       =				f.read()
     else:
          UpperCAmelCase_							:       Optional[Any]       =				bytes(lowerCamelCase_     ,					'utf-8'       )

     print(SHAaaa(lowerCamelCase_       ).hash       )


if __name__ == "__main__":
 main()







'''simple docstring'''


def  _lowerCamelCase   (				lowerCamelCase_ :							str     ,					lowerCamelCase_ :							str = " "       ):



     """simple docstring"""





     UpperCAmelCase_							:       str       =				[]

     UpperCAmelCase_							:       List[Any]       =				0
     for index, char in enumerate(lowerCamelCase_       ):
          if char == separator:
               split_words.append(string[last_index:index]       )
               UpperCAmelCase_							:       Optional[Any]       =				index + 1
          elif index + 1 == len(lowerCamelCase_       ):
               split_words.append(string[last_index : index + 1]       )
     return split_words


if __name__ == "__main__":
 from doctest import testmod

 testmod()






