def SilverPohligHellman(base, gen, element): # El orden del generador es el cardinal de todos los elementos menos el 0 order = base - 1 # Si no tenemos el generador o la base correctos... if base != BASE or gen != GEN: # Generamos las raíces que usaremos GenerateSquareRoots(base, gen) # Lista de restos y subbases subbases = [] remainders = [] # Buscamos el logaritmo for i in P_FACTS: # Inicialmente el exponente es 0 exp = 0 # Recorremos los posibles valores en los que p_i^j es divisor de n for j in range(P_FACTS[i]): y = element * FastExp(gen, order - exp, base) x = ROOTS[i][FastExp(y, order / (i**(j + 1)), base)] exp += x * i**j # Añadimos la ecuación con congruencias subbases.append(i**P_FACTS[i]) remainders.append(exp) # Resolvemos el sistema de congruencias return crt(subbases, remainders)[0]
def EncElGamal(m): # Si los parámetros de cifrado no están establecidos, fijamos unos if base == -1: GenKeysRSA(103, 7) k = randint(2, base-2) # Devolvemos el resultado return (FastExp(gen, k, base), m * FastExp(public, k, base))
def FactD(): # Almacenamos e*d-1 m = cipher * decipher - 1 g = 1 # Mientras el MCD calculado sea un divisor impropio... while g == 1 or g == base: # Establecemos el exponente a m k = m # Tomamos un elemento aleatorio a = randint(2, base - 1) # Calculado el MCD con la base g = gcd(a, base)[0] # Mientras el MCD sea 1 y el exponente sea par... while (g == 1 or g == base) and k % 2 == 0: # Dividimos el exponente entre 2 k /= 2 # Calculamos el MCD entre a^k-1 y la base g = gcd(FastExp(a, k, base) - 1, base)[0] # Devolvemos los dos divisores de la base return (g, base // g)
def DecRSA(c): # Si los parámetros de descifrado no están establecidos, fijamos unos if primes[0] == -1: GenKeysRSA(97, 103) # Devolvemos el resultado return FastExp(c, decipher, base)
def DecElGamal(c): # Si los parámetros de descifrado no están establecidos, fijamos unos if base == -1: GenKeysElGamal(103, 7) # Devolvemos el resultado return c[1] * FastExp(c[0], base-1-private, base) % base
def GenerateSquareRoots(base, gen): # Establecemos las variables globales al nuevo valor global BASE, GEN, P_FACTS, ROOTS BASE = base GEN = gen # El orden del generador es el cardinal de todos los elementos menos el 0 order = base - 1 # Calculamos los factores primos con su exponente P_FACTS = factorint(order) # Tabla con las raíces de la unidad ROOTS = {} # Rellenamos la tabla de raíces for i in P_FACTS: # Raíces p_i-ésimas i_roots = {} # Variables para rellenar ROOTS aux = 1 step = FastExp(gen, order / i, base) # Llenamos la lista for j in range(i): i_roots[aux] = j # Nos ahorramos calcular potencias a cambio de un producto aux = aux * step % base # Las introducimos al resto de raíces ROOTS[i] = i_roots
def BreakElGamal(c, mode_bg): if mode_bg: a = BabyGiant(base, gen, public) else: a = SilverPohligHellman(base, gen, public) # Devolvemos los dos divisores de la base return c[1] * FastExp(c[0], base-1-a, base) % base
def GenKeysElGamal(n, b): # Notificamos que vamos a modificar las variables globales global base, gen, private, public base = n gen = b private = randint(2, base-2) public = FastExp(gen, private, base)
def Pollard(): # b inicial b = 2 # 2^(b!) a = FastExp(2, b, base) # MCD de la base y 2^(b!)-1 g = gcd(base, a - 1)[0] # Hasta encontrar un MCD distinto de 1... while g == 1: # Incrementamos b b += 1 # 2^(b!) a = FastExp(a, b, base) #Recalculamos el MCD y 2^(b!) g = gcd(base, a - 1)[0] # Devolvemos (p, q) return (g, base // g)
def GenerateBabyGiantSteps(base, gen): # Establecemos las variables globales al nuevo valor global BASE, GEN, BABY, GIANT BASE = base GEN = gen # Número de iteraciones root = ceil(sqrt(base)) # Tabla con el paso de bebé BABY = {} # Variable para rellenar BABY aux = 1 # Rellenamos la tabla for i in range(root): BABY[aux] = i # Nos ahorramos calcular potencias a cambio de un producto aux = aux * gen % base # Calculamos el paso de gigante GIANT = FastExp(gen, (base-1)-root, base)