





from __future__ import annotations



class    A__  :





      def __init__(					self			,				A_ = 0  ):
       '''simple docstring'''




       UpperCamelCase      :   List[str]			      =  key





      def 			__UpperCamelCase(					self			,				A_			,				A_  ):
       '''simple docstring'''




       assert isinstance(A_			,				A_  ) and isinstance(A_			,				A_  )

       UpperCamelCase      :   List[Any]			      =  key or self.__key or 1

       # make sure key is an appropriate size
       key %= 255

       return [chr(ord(A_  ) ^ key  ) for ch in content]





      def 			__UpperCamelCase(					self			,				A_			,				A_  ):
       '''simple docstring'''




       assert isinstance(A_			,				A_  ) and isinstance(A_			,				A_  )

       UpperCamelCase      :   int			      =  key or self.__key or 1

       # make sure key is an appropriate size
       key %= 255

       return [chr(ord(A_  ) ^ key  ) for ch in content]





      def 			__UpperCamelCase(					self			,				A_			,				A_ = 0  ):
       '''simple docstring'''




       assert isinstance(A_			,				A_  ) and isinstance(A_			,				A_  )

       UpperCamelCase      :   List[Any]			      =  key or self.__key or 1

       # make sure key can be any size
       while key > 255:
        key -= 255

       # This will be returned
       UpperCamelCase      :   Union[str, Any]			      =  ""

       for ch in content:
        ans += chr(ord(A_  ) ^ key  )

       return ans





      def 			__UpperCamelCase(					self			,				A_			,				A_ = 0  ):
       '''simple docstring'''




       assert isinstance(A_			,				A_  ) and isinstance(A_			,				A_  )

       UpperCamelCase      :   Dict			      =  key or self.__key or 1

       # make sure key can be any size
       while key > 255:
        key -= 255

       # This will be returned
       UpperCamelCase      :   Optional[Any]			      =  ""

       for ch in content:
        ans += chr(ord(A_  ) ^ key  )

       return ans





      def 			__UpperCamelCase(					self			,				A_			,				A_ = 0  ):
       '''simple docstring'''




       assert isinstance(A_			,				A_  ) and isinstance(A_			,				A_  )

       try:
        with open(A_  ) as fin, open("encrypt.out"			,				"w+"  ) as fout:
         # actual encrypt-process
         for line in fin:
          fout.write(self.encrypt_string(A_			,				A_  )  )

       except OSError:
        return False

       return True





      def 			__UpperCamelCase(					self			,				A_			,				A_  ):
       '''simple docstring'''




       assert isinstance(A_			,				A_  ) and isinstance(A_			,				A_  )

       try:
        with open(A_  ) as fin, open("decrypt.out"			,				"w+"  ) as fout:
         # actual encrypt-process
         for line in fin:
          fout.write(self.decrypt_string(A_			,				A_  )  )

       except OSError:
        return False

       return True


# Tests
# crypt = XORCipher()
# key = 67

# # test encrypt
# print(crypt.encrypt("hallo welt",key))
# # test decrypt
# print(crypt.decrypt(crypt.encrypt("hallo welt",key), key))

# # test encrypt_string
# print(crypt.encrypt_string("hallo welt",key))

# # test decrypt_string
# print(crypt.decrypt_string(crypt.encrypt_string("hallo welt",key),key))

# if (crypt.encrypt_file("test.txt",key)):
#       print("encrypt successful")
# else:
#       print("encrypt unsuccessful")

# if (crypt.decrypt_file("encrypt.out",key)):
#       print("decrypt successful")
# else:
#       print("decrypt unsuccessful")







import numpy as np
import qiskit



def 						A_							(	_lowerCAmelCase = 8				,  _lowerCAmelCase = None	)		->					str:
 UpperCamelCase      :   Tuple			      =  np.random.default_rng(seed=_lowerCAmelCase	)

 # Roughly 25% of the qubits will contribute to the key.
 # So we take more than we need.
 UpperCamelCase      :   List[str]			      =  6 * key_len
 # Measurement basis for Alice's qubits.
 UpperCamelCase      :   List[Any]			      =  rng.integers(2				,  size=_lowerCAmelCase	)
 # The set of states Alice will prepare.
 UpperCamelCase      :   List[Any]			      =  rng.integers(2				,  size=_lowerCAmelCase	)
 # Measurement basis for Bob's qubits.
 UpperCamelCase      :   Optional[int]			      =  rng.integers(2				,  size=_lowerCAmelCase	)

 # Quantum Circuit to simulate BB84
 UpperCamelCase      :   List[Any]			      =  qiskit.QuantumCircuit(_lowerCAmelCase				,  name="BB84"	)

 # Alice prepares her qubits according to rules above.
 for index, _ in enumerate(_lowerCAmelCase	):
  if alice_state[index] == 1:
   bbaa_circ.x(_lowerCAmelCase	)
  if alice_basis[index] == 1:
   bbaa_circ.h(_lowerCAmelCase	)
 bbaa_circ.barrier()

 # Bob measures the received qubits according to rules above.
 for index, _ in enumerate(_lowerCAmelCase	):
  if bob_basis[index] == 1:
   bbaa_circ.h(_lowerCAmelCase	)

 bbaa_circ.barrier()
 bbaa_circ.measure_all()

 # Simulate the quantum circuit.
 UpperCamelCase      :   Union[str, Any]			      =  qiskit.Aer.get_backend("aer_simulator"	)
 # We only need to run one shot because the key is unique.
 # Multiple shots will produce the same key.
 UpperCamelCase      :   Tuple			      =  qiskit.execute(_lowerCAmelCase				,  _lowerCAmelCase				,  shots=1				,  seed_simulator=_lowerCAmelCase	)
 # Returns the result of measurement.
 UpperCamelCase      :   Optional[Any]			      =  job.result().get_counts(_lowerCAmelCase	).most_frequent()

 # Extracting the generated key from the simulation results.
 # Only keep measurement results where Alice and Bob chose the same basis.
 UpperCamelCase      :   Tuple			      =  "".join(
     [
         result_bit
         for alice_basis_bit, bob_basis_bit, result_bit in zip(
             _lowerCAmelCase				,  _lowerCAmelCase				,  _lowerCAmelCase	)
         if alice_basis_bit == bob_basis_bit
     ]	)

 # Get final key. Pad with 0 if too short, otherwise truncate.
 UpperCamelCase      :   Tuple			      =  gen_key[:key_len] if len(_lowerCAmelCase	) >= key_len else gen_key.ljust(_lowerCAmelCase				,  "0"	)
 return key


if __name__ == "__main__":
    print(f"""The generated key is : {bbaa(8, seed=0)}""")
    from doctest import testmod

    testmod()
