






import argparse
import hashlib  # hashlib is only used inside the Test class
import struct







class 				UpperCAmelCase_  :




     def __init__(				self	,						_lowerCAmelCase		):
          UpperCAmelCase__      :  Any				      =			data
          UpperCAmelCase__      :  List[Any]				      =			[0X6745_2301, 0Xefcd_ab89, 0X98ba_dcfe, 0X1032_5476, 0Xc3d2_e1f0]




     @staticmethod
     def   __UpperCAmelCase  (				_lowerCAmelCase	,						_lowerCAmelCase		):
          return ((n << b) | (n >> (32 - b))) & 0Xffff_ffff




     def   __UpperCAmelCase  (				self		):
          UpperCAmelCase__      :  List[Any]				      =			B"""\x80""" + B"""\x00""" * (63 - (len(self.data		) + 8) % 64)
          UpperCAmelCase__      :  Optional[int]				      =			self.data + padding + struct.pack(""">Q"""	,						8 * len(self.data		)		)
          return padded_data




     def   __UpperCAmelCase  (				self		):
          return [
              self.padded_data[i : i + 64] for i in range(0	,						len(self.padded_data		)	,						64		)
          ]




     def   __UpperCAmelCase  (				self	,						_lowerCAmelCase		):
          UpperCAmelCase__      :  Dict				      =			list(struct.unpack(""">16L"""	,						_lowerCAmelCase		)		) + [0] * 64
          for i in range(16	,						80		):
               UpperCAmelCase__      :  Optional[int]				      =			self.rotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16])	,						1		)
          return w




     def   __UpperCAmelCase  (				self		):
          UpperCAmelCase__      :  List[str]				      =			self.padding()
          UpperCAmelCase__      :  List[str]				      =			self.split_blocks()
          for block in self.blocks:
               UpperCAmelCase__      :  Tuple				      =			self.expand_block(_lowerCAmelCase		)
               UpperCAmelCase__      ,		UpperCAmelCase__      ,		UpperCAmelCase__      ,		UpperCAmelCase__      ,		UpperCAmelCase__      :  Tuple				      =			self.h
               for i in range(0	,						80		):
                    if 0 <= i < 20:
                         UpperCAmelCase__      :  Optional[int]				      =			(b & c) | ((~b) & d)
                         UpperCAmelCase__      :  int				      =			0X5a82_7999
                    elif 20 <= i < 40:
                         UpperCAmelCase__      :  Tuple				      =			b ^ c ^ d
                         UpperCAmelCase__      :  int				      =			0X6ed9_eba1
                    elif 40 <= i < 60:
                         UpperCAmelCase__      :  List[str]				      =			(b & c) | (b & d) | (c & d)
                         UpperCAmelCase__      :  Tuple				      =			0X8f1b_bcdc
                    elif 60 <= i < 80:
                         UpperCAmelCase__      :  int				      =			b ^ c ^ d
                         UpperCAmelCase__      :  str				      =			0Xca62_c1d6
                    UpperCAmelCase__      ,		UpperCAmelCase__      ,		UpperCAmelCase__      ,		UpperCAmelCase__      ,		UpperCAmelCase__      :  Optional[Any]				      =			(
                        self.rotate(_lowerCAmelCase	,						5		) + f + e + k + expanded_block[i] & 0Xffff_ffff,
                        a,
                        self.rotate(_lowerCAmelCase	,						30		),
                        c,
                        d,
                    )
               UpperCAmelCase__      :  int				      =			(
                   self.h[0] + a & 0Xffff_ffff,
                   self.h[1] + b & 0Xffff_ffff,
                   self.h[2] + c & 0Xffff_ffff,
                   self.h[3] + d & 0Xffff_ffff,
                   self.h[4] + e & 0Xffff_ffff,
               )
          return ("{:08x}" * 5).format(*self.h		)





def  _lowerCamelCase						(						) ->			Union[str, Any]:

     '''simple docstring'''
     UpperCAmelCase__      :  Optional[Any]				      =			B"""Test String"""
     assert SHAaHash(__lowerCamelCase       ).final_hash() == hashlib.shaa(__lowerCamelCase       ).hexdigest()  # noqa: S324





def  _lowerCamelCase						(						) ->			str:

     '''simple docstring'''
     UpperCAmelCase__      :  Optional[int]				      =			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"""       )
     UpperCAmelCase__      :  str				      =			parser.parse_args()
     UpperCAmelCase__      :  Union[str, Any]				      =			args.input_string
     # In any case hash input should be a bytestring
     if args.input_file:
          with open(args.input_file ,							"""rb"""       ) as f:
               UpperCAmelCase__      :  List[Any]				      =			f.read()
     else:
          UpperCAmelCase__      :  int				      =			bytes(__lowerCamelCase ,							"""utf-8"""       )
     print(SHAaHash(__lowerCamelCase       ).final_hash()       )


if __name__ == "__main__":
      main()
      import doctest

      doctest.testmod()








"""simple docstring"""



def 					lowerCamelCase   (     _snake_case    ,_snake_case ):
    UpperCAmelCase__	:      Optional[int]     							=					''
    for i in table:
        res += inp[i - 1]
    return res
def 					lowerCamelCase   (     _snake_case ):
    return data[1:] + data[0]
def 					lowerCamelCase   (     _snake_case    ,_snake_case ):
    UpperCAmelCase__	:      str     							=					''
    for i in range(len(_snake_case ) ):
        if a[i] == b[i]:
            res += "0"
        else:
            res += "1"
    return res
def 					lowerCamelCase   (     _snake_case    ,_snake_case ):
    UpperCAmelCase__	:      str     							=					int('0b' + data[0] + data[-1]    ,2 )
    UpperCAmelCase__	:      Optional[Any]     							=					int('0b' + data[1:3]    ,2 )
    return bin(s[row][col] )[2:]
def 					lowerCamelCase   (     _snake_case    ,_snake_case    ,_snake_case    ,_snake_case    ,_snake_case ):
    UpperCAmelCase__	:      Any     							=					message[:4]
    UpperCAmelCase__	:      Optional[Any]     							=					message[4:]
    UpperCAmelCase__	:      Dict     							=					apply_table(_snake_case    ,_snake_case )
    UpperCAmelCase__	:      Optional[Any]     							=					xor(_snake_case    ,_snake_case )
    UpperCAmelCase__	:      Dict     							=					apply_sbox(_snake_case    ,temp[:4] )  # noqa: E741
    UpperCAmelCase__	:      Tuple     							=					apply_sbox(_snake_case    ,temp[4:] )
    UpperCAmelCase__	:      List[str]     							=					'0' * (2 - len(_snake_case )) + l  # noqa: E741
    UpperCAmelCase__	:      Optional[Any]     							=					'0' * (2 - len(_snake_case )) + r
    UpperCAmelCase__	:      Optional[int]     							=					apply_table(l + r    ,_snake_case )
    UpperCAmelCase__	:      Any     							=					xor(_snake_case    ,_snake_case )
    return temp + right


if __name__ == "__main__":
    UpperCamelCase__          =	input('Enter 10 bit key: ')
    UpperCamelCase__          =	input('Enter 8 bit message: ')

    UpperCamelCase__          =	[6, 3, 7, 4, 8, 5, 10, 9]
    UpperCamelCase__          =	[3, 5, 2, 7, 4, 10, 1, 9, 8, 6]
    UpperCamelCase__          =	[2, 4, 3, 1]
    UpperCamelCase__          =	[2, 6, 3, 1, 4, 8, 5, 7]
    UpperCamelCase__          =	[4, 1, 3, 5, 7, 2, 8, 6]
    UpperCamelCase__          =	[4, 1, 2, 3, 2, 3, 4, 1]
    UpperCamelCase__          =	[[1, 0, 3, 2], [3, 2, 1, 0], [0, 2, 1, 3], [3, 1, 3, 2]]
    UpperCamelCase__          =	[[0, 1, 2, 3], [2, 0, 1, 3], [3, 0, 1, 0], [2, 1, 0, 3]]

    # key generation
    UpperCamelCase__          =	apply_table(key, paa_table)
    UpperCamelCase__          =	temp[:5]
    UpperCamelCase__          =	temp[5:]
    UpperCamelCase__          =	left_shift(left)
    UpperCamelCase__          =	left_shift(right)
    UpperCamelCase__          =	apply_table(left + right, pa_table)
    UpperCamelCase__          =	left_shift(left)
    UpperCamelCase__          =	left_shift(right)
    UpperCamelCase__          =	left_shift(left)
    UpperCamelCase__          =	left_shift(right)
    UpperCamelCase__          =	apply_table(left + right, pa_table)

    # encryption
    UpperCamelCase__          =	apply_table(message, IP)
    UpperCamelCase__          =	function(expansion, sa, sa, keya, temp)
    UpperCamelCase__          =	temp[4:] + temp[:4]
    UpperCamelCase__          =	function(expansion, sa, sa, keya, temp)
    UpperCamelCase__          =	apply_table(temp, IP_inv)
    print('Cipher text is:', CT)

    # decryption
    UpperCamelCase__          =	apply_table(CT, IP)
    UpperCamelCase__          =	function(expansion, sa, sa, keya, temp)
    UpperCamelCase__          =	temp[4:] + temp[:4]
    UpperCamelCase__          =	function(expansion, sa, sa, keya, temp)
    UpperCamelCase__          =	apply_table(temp, IP_inv)
    print('Plain text after decypting is:', PT)

