






"""simple docstring"""


import os
import random
import sys

from . import cryptomath_module as cryptomath
from . import rabin_miller

__SCREAMING_SNAKE_CASE   =   3


def        UpperCAmelCase      (					a__ ):





						'''simple docstring'''






						print('Generating primitive root of p' )
						while True:
												lowerCAmelCase   :List[Any]						=			random.randrange(3     ,      a__ )
												if pow(a__     ,      2     ,      a__ ) == 1:
																		continue
												if pow(a__     ,      a__     ,      a__ ) == 1:
																		continue
												return g


def        UpperCAmelCase      (					a__ ):





						'''simple docstring'''






						print('Generating prime p...' )
						lowerCAmelCase   :List[Any]						=			rabin_miller.generate_large_prime(a__ )  # select large prime number.
						lowerCAmelCase   :Dict						=			primitive_root(a__ )  # one primitive root on modulo p.
						lowerCAmelCase   :Any						=			random.randrange(3     ,      a__ )  # private_key -> have to be greater than 2 for safety.
						lowerCAmelCase   :List[str]						=			cryptomath.find_mod_inverse(pow(a__     ,      a__     ,      a__ )     ,      a__ )

						lowerCAmelCase   :Union[str, Any]						=			(key_size, e_a, e_a, p)
						lowerCAmelCase   :Any						=			(key_size, d)

						return public_key, private_key


def        UpperCAmelCase      (					a__     ,      a__ ):





						'''simple docstring'''






						if os.path.exists(F"""{name}_pubkey.txt""" ) or os.path.exists(F"""{name}_privkey.txt""" ):
												print('\nWARNING:' )
												print(
												    F"""\"{name}_pubkey.txt\" or \"{name}_privkey.txt\" already exists. \n"""
												    'Use a different name or delete these files and re-run this program.' )
												sys.exit()

						lowerCAmelCase	, lowerCAmelCase   :Union[str, Any]						=			generate_key(a__ )
						print(F"""\nWriting public key to file {name}_pubkey.txt...""" )
						with open(F"""{name}_pubkey.txt"""     ,      'w' ) as fo:
												fo.write(F"""{public_key[0]},{public_key[1]},{public_key[2]},{public_key[3]}""" )

						print(F"""Writing private key to file {name}_privkey.txt...""" )
						with open(F"""{name}_privkey.txt"""     ,      'w' ) as fo:
												fo.write(F"""{private_key[0]},{private_key[1]}""" )


def        UpperCAmelCase      (					):





						'''simple docstring'''






						print('Making key files...' )
						make_key_files('elgamal'     ,      20_48 )
						print('Key files generation successful' )


if __name__ == "__main__":
		main()







"""simple docstring"""


import heapq as hq
import math
from collections.abc import Iterator




class 						__UpperCamelCase     :
					def __init__(							self							:	Union[str, Any]     , UpperCAmelCase							:	List[Any]   )	->       List[str]:
											lowerCAmelCase   :Dict						=			str(id_   )
											lowerCAmelCase   :str						=			None
											lowerCAmelCase   :Any						=			None
											lowerCAmelCase   :List[str]						=			[]
											lowerCAmelCase   :List[Any]						=			{}  # {vertex:distance}
					def __lt__(							self							:	Union[str, Any]     , UpperCAmelCase							:	Any   )	->       str:
											return self.key < other.key
					def __repr__(							self							:	Union[str, Any]   )	->       Dict:
											return self.id
					def        UpperCAmelCase__ (							self							:	Any     , UpperCAmelCase							:	Tuple   )	->       List[str]:
											self.neighbors.append(UpperCAmelCase   )
					def        UpperCAmelCase__ (							self							:	str     , UpperCAmelCase							:	Optional[Any]     , UpperCAmelCase							:	List[Any]   )	->       Optional[int]:
											lowerCAmelCase   :str						=			weight


def        UpperCAmelCase      (					a__     ,      a__     ,      a__     ,      a__ ):





						'''simple docstring'''






						graph[a - 1].add_neighbor(graph[b - 1] )
						graph[b - 1].add_neighbor(graph[a - 1] )
						# add the edges:
						graph[a - 1].add_edge(graph[b - 1]     ,      a__ )
						graph[b - 1].add_edge(graph[a - 1]     ,      a__ )


def        UpperCAmelCase      (					a__     ,      a__ ):





						'''simple docstring'''






						lowerCAmelCase   :List[str]						=			[]
						for u in graph:
												lowerCAmelCase   :Tuple						=			math.inf
												lowerCAmelCase   :Any						=			None
						lowerCAmelCase   :Dict						=			0
						lowerCAmelCase   :int						=			graph[:]
						while q:
												lowerCAmelCase   :str						=			min(a__ )
												q.remove(a__ )
												for v in u.neighbors:
																		if (v in q) and (u.edges[v.id] < v.key):
																								lowerCAmelCase   :List[str]						=			u
																								lowerCAmelCase   :List[Any]						=			u.edges[v.id]
						for i in range(1     ,      len(a__ ) ):
												a.append((int(graph[i].id ) + 1, int(graph[i].pi.id ) + 1) )
						return a


def        UpperCAmelCase      (					a__     ,      a__ ):





						'''simple docstring'''






						for u in graph:
												lowerCAmelCase   :List[str]						=			math.inf
												lowerCAmelCase   :str						=			None
						lowerCAmelCase   :Optional[int]						=			0

						lowerCAmelCase   :Dict						=			list(a__ )
						hq.heapify(a__ )

						while h:
												lowerCAmelCase   :Union[str, Any]						=			hq.heappop(a__ )
												for v in u.neighbors:
																		if (v in h) and (u.edges[v.id] < v.key):
																								lowerCAmelCase   :int						=			u
																								lowerCAmelCase   :List[Any]						=			u.edges[v.id]
																								hq.heapify(a__ )

						for i in range(1     ,      len(a__ ) ):
												yield (int(graph[i].id ) + 1, int(graph[i].pi.id ) + 1)


def        UpperCAmelCase      (					):





						'''simple docstring'''








if __name__ == "__main__":
		import doctest

		doctest.testmod()