





"""simple docstring"""





import argparse
import struct
import unittest

class 						lowercase   :





      def __init__(			self ,		lowercase					)						->	None:
            lowerCAmelCase    		=			data

            # Initialize hash values
            lowerCAmelCase    		=			[
                0X6A_09E_667,
                0XBB_67A_E85,
                0X3C_6EF_372,
                0XA5_4FF_53A,
                0X51_0E5_27F,
                0X9B_056_88C,
                0X1F_83D_9AB,
                0X5B_E0C_D19,
            ]

            # Initialize round constants
            lowerCAmelCase    		=			[
                0X42_8A2_F98,
                0X71_374_491,
                0XB5_C0F_BCF,
                0XE9_B5D_BA5,
                0X39_56C_25B,
                0X59_F11_1F1,
                0X92_3F8_2A4,
                0XAB_1C5_ED5,
                0XD8_07A_A98,
                0X12_835_B01,
                0X24_318_5BE,
                0X55_0C7_DC3,
                0X72_BE5_D74,
                0X80_DEB_1FE,
                0X9B_DC0_6A7,
                0XC1_9BF_174,
                0XE4_9B6_9C1,
                0XEF_BE4_786,
                0X0F_C19_DC6,
                0X24_0CA_1CC,
                0X2D_E92_C6F,
                0X4A_748_4AA,
                0X5C_B0A_9DC,
                0X76_F98_8DA,
                0X98_3E5_152,
                0XA8_31C_66D,
                0XB0_032_7C8,
                0XBF_597_FC7,
                0XC6_E00_BF3,
                0XD5_A79_147,
                0X06_CA6_351,
                0X14_292_967,
                0X27_B70_A85,
                0X2E_1B2_138,
                0X4D_2C6_DFC,
                0X53_380_D13,
                0X65_0A7_354,
                0X76_6A0_ABB,
                0X81_C2C_92E,
                0X92_722_C85,
                0XA2_BFE_8A1,
                0XA8_1A6_64B,
                0XC2_4B8_B70,
                0XC7_6C5_1A3,
                0XD1_92E_819,
                0XD6_990_624,
                0XF4_0E3_585,
                0X10_6AA_070,
                0X19_A4C_116,
                0X1E_376_C08,
                0X27_487_74C,
                0X34_B0B_CB5,
                0X39_1C0_CB3,
                0X4E_D8A_A4A,
                0X5B_9CC_A4F,
                0X68_2E6_FF3,
                0X74_8F8_2EE,
                0X78_A56_36F,
                0X84_C87_814,
                0X8C_C70_208,
                0X90_BEF_FFA,
                0XA4_506_CEB,
                0XBE_F9A_3F7,
                0XC6_717_8F2,
            ]

            lowerCAmelCase    		=			self.preprocessing(self.data					)
            self.final_hash()





      @staticmethod
      def        _snake_case     (			lowercase					)						->	bytes:
            lowerCAmelCase    		=			b"""\x80""" + (b"""\x00""" * (63 - (len(lowercase					) + 8) % 64))
            lowerCAmelCase    		=			struct.pack(""">Q""" ,		(len(lowercase					) * 8)					)
            return data + padding + big_endian_integer





      def        _snake_case     (			self					)						->	None:
            # Convert into blocks of 64 bytes
            lowerCAmelCase    		=			[
                self.preprocessed_data[x : x + 64]
                for x in range(0 ,		len(self.preprocessed_data					) ,		64					)
            ]

            for block in self.blocks:
                  # Convert the given block into a list of 4 byte integers
                  lowerCAmelCase    		=			list(struct.unpack(""">16L""" ,		lowercase					)					)
                  # add 48 0-ed integers
                  words += [0] * 48

                  lowerCAmelCase		,						lowerCAmelCase		,						lowerCAmelCase		,						lowerCAmelCase		,						lowerCAmelCase		,						lowerCAmelCase		,						lowerCAmelCase		,						lowerCAmelCase    		=			self.hashes

                  for index in range(0 ,		64					):
                        if index > 15:
                              # modify the zero-ed indexes at the end of the array
                              lowerCAmelCase    		=			(
                                  self.ror(words[index - 15] ,		7					)
                                  ^ self.ror(words[index - 15] ,		18					)
                                  ^ (words[index - 15] >> 3)
                              )
                              lowerCAmelCase    		=			(
                                  self.ror(words[index - 2] ,		17					)
                                  ^ self.ror(words[index - 2] ,		19					)
                                  ^ (words[index - 2] >> 10)
                              )

                              lowerCAmelCase    		=			(
                                  words[index - 16] + sa + words[index - 7] + sa
                              ) % 0X100_000_000

                        # Compression
                        lowerCAmelCase    		=			self.ror(lowercase ,		6					) ^ self.ror(lowercase ,		11					) ^ self.ror(lowercase ,		25					)
                        lowerCAmelCase    		=			(e & f) ^ ((~e & 0XFF_FFF_FFF) & g)
                        lowerCAmelCase    		=			(
                            h + sa + ch + self.round_constants[index] + words[index]
                        ) % 0X100_000_000
                        lowerCAmelCase    		=			self.ror(lowercase ,		2					) ^ self.ror(lowercase ,		13					) ^ self.ror(lowercase ,		22					)
                        lowerCAmelCase    		=			(a & b) ^ (a & c) ^ (b & c)
                        lowerCAmelCase    		=			(sa + maj) % 0X100_000_000

                        lowerCAmelCase		,						lowerCAmelCase		,						lowerCAmelCase		,						lowerCAmelCase		,						lowerCAmelCase		,						lowerCAmelCase		,						lowerCAmelCase		,						lowerCAmelCase    		=			(
                            g,
                            f,
                            e,
                            ((d + tempa) % 0X100_000_000),
                            c,
                            b,
                            a,
                            ((tempa + tempa) % 0X100_000_000),
                        )

                  lowerCAmelCase    		=			[a, b, c, d, e, f, g, h]

                  # Modify final values
                  lowerCAmelCase    		=			[
                      ((element + mutated_hash_values[index]) % 0X100_000_000)
                      for index, element in enumerate(self.hashes					)
                  ]

            lowerCAmelCase    		=			"""""".join([hex(lowercase					)[2:].zfill(8					) for value in self.hashes]					)





      def        _snake_case     (			self ,		lowercase ,		lowercase					)						->	int:
            return 0XFF_FFF_FFF & (value << (32 - rotations)) | (value >> rotations)







class 						lowercase   (   unittest.TestCase   ):





      def        _snake_case     (			self					)						->	None:
            import hashlib

            lowerCAmelCase    		=			bytes("""Test String""" ,		"""utf-8"""					)
            self.assertEqual(SHAaaa(lowercase					).hash ,		hashlib.shaaaa(lowercase					).hexdigest()					)







def      UpperCAmelCase__				(    ):







      '''simple docstring'''




      import doctest

      doctest.testmod()

      lowerCAmelCase    		=			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"""     )

      lowerCAmelCase    		=			parser.parse_args()

      lowerCAmelCase    		=			args.input_string

      # hash input should be a bytestring
      if args.input_file:
            with open(args.input_file				,		"""rb"""     ) as f:
                  lowerCAmelCase    		=			f.read()
      else:
            lowerCAmelCase    		=			bytes(SCREAMING_SNAKE_CASE				,		"""utf-8"""     )

      print(SHAaaa(SCREAMING_SNAKE_CASE     ).hash     )


if __name__ == "__main__":
       main()













"""simple docstring"""





def      UpperCAmelCase__				(    SCREAMING_SNAKE_CASE	:		str     ):







      '''simple docstring'''




      lowerCAmelCase    		=			""""""
      for ch in key:
            if ch == " " or ch not in key_no_dups and ch.isalpha():
                  key_no_dups += ch
      return key_no_dups


def      UpperCAmelCase__				(    SCREAMING_SNAKE_CASE	:		str     ):







      '''simple docstring'''




      lowerCAmelCase    		=			[chr(i + 65     ) for i in range(26     )]
      # Remove duplicate characters from key
      lowerCAmelCase    		=			remove_duplicates(key.upper()     )
      lowerCAmelCase    		=			len(SCREAMING_SNAKE_CASE     )
      # First fill cipher with key characters
      lowerCAmelCase    		=			{alphabet[i]: char for i, char in enumerate(SCREAMING_SNAKE_CASE     )}
      # Then map remaining characters in alphabet to
      # the alphabet from the beginning
      for i in range(len(SCREAMING_SNAKE_CASE     )				,		26     ):
            lowerCAmelCase    		=			alphabet[i - offset]
            # Ensure we are not mapping letters to letters previously mapped
            while char in key:
                  offset -= 1
                  lowerCAmelCase    		=			alphabet[i - offset]
            lowerCAmelCase    		=			char
      return cipher_alphabet


def      UpperCAmelCase__				(    SCREAMING_SNAKE_CASE	:		str				,		SCREAMING_SNAKE_CASE	:		dict[str, str]     ):







      '''simple docstring'''




      return "".join(cipher_map.get(SCREAMING_SNAKE_CASE				,		SCREAMING_SNAKE_CASE     ) for ch in message.upper()     )


def      UpperCAmelCase__				(    SCREAMING_SNAKE_CASE	:		str				,		SCREAMING_SNAKE_CASE	:		dict[str, str]     ):







      '''simple docstring'''




      lowerCAmelCase    		=			{v: k for k, v in cipher_map.items()}
      return "".join(rev_cipher_map.get(SCREAMING_SNAKE_CASE				,		SCREAMING_SNAKE_CASE     ) for ch in message.upper()     )


def      UpperCAmelCase__				(    ):







      '''simple docstring'''




      lowerCAmelCase    		=			input("""Enter message to encode or decode: """     ).strip()
      lowerCAmelCase    		=			input("""Enter keyword: """     ).strip()
      lowerCAmelCase    		=			input("""Encipher or decipher? E/D:"""     ).strip()[0].lower()
      try:
            lowerCAmelCase    		=			{"""e""": encipher, """d""": decipher}[option]
      except KeyError:
            raise KeyError("""invalid input option"""     )
      lowerCAmelCase    		=			create_cipher_map(SCREAMING_SNAKE_CASE     )
      print(func(SCREAMING_SNAKE_CASE				,		SCREAMING_SNAKE_CASE     )     )


if __name__ == "__main__":
       import doctest

       doctest.testmod()
       main()






