def factoriza_n(e, d, n):
    assert(e!=0 and d!=0)
    factores=[]
    a=0
    de=d*e
    de=de-1
    a=am.potencia2(de)
    b=de//am.potencia_modular(2, a, n)
    x=random.randint(1, n-1)
    divisor=am.euclides_extendido(x, n)[0]
    if divisor!=1:
        return (divisor, n//divisor)

    y=am.potencia_modular(x, b, n)
    r1=(y-1)%n
    r2=(y+1)%n
    if r1==0 and r2==0:
        return "Fallo"
    while am.euclides_extendido(y, n)[0]==1:
        z=y
        y=am.potencia_modular(y, 2, n)
        r1=(y-1)%n
        r2=(y+1)%n
        if r2==0:
            return "Fallo"
        if r1==0:
            f1=am.euclides_extendido(z-1, n)[0]
            f2=am.euclides_extendido(z+1, n)[0]
            factores.append(f1)
            factores.append(f2)
            return factores
            break

    return factores
def cifra_ax(m, c_pub):
    p=c_pub[0]
    alfa=c_pub[1]
    y=c_pub[2]
    assert (m<p)
    k=random.randint(2, p-2)
    while am.euclides_extendido(k, p-1)[0]!=1:
        k+=1
    r=am.potencia_modular(alfa, k, p)
    s=am.potencia_modular(y, k, p)
    s=s*m
    return (r,s)
def descifra_ax(rs, c_pub):
    r=rs[0]
    s=rs[1]
    p=c_pub[0]
    global clave_x
    x=clave_x
    m=s*am.potencia_modular(r, (p-1-x), p)
    m=m%p
    return m
def raices_iguales(n):
    f = lambda x:am.potencia_modular(x, 2, n)
    a=random.randint(2, n//2)
    fa=f(a)
    b=random.randint(n//2, n-1)
    while f(b)!=fa:
        b+=1
        b=b%n
    if b==a:
        return "ERROR: No existen a!=b tal que f(a)==f(b)", -1
    return (a,b)
def funcion_ax(p):
    if am.es_primo(p, 30):
        q=(p-1)//2
        alfa=random.randint(1, q)
        temp=am.potencia_modular(alfa, q, p)
        while(temp==1):
            alfa=random.randint(2, p-1)
            temp=am.potencia_modular(alfa, q, p)
        temp=random.randint(1, q)
        while am.euclides_extendido(temp, p-1)[0]!=1:
            temp+=1
        alfa=am.potencia_modular(alfa, temp, p)
        x=random.randint(2, p-2)
        global clave_x
        clave_x=x
        y=am.potencia_modular(alfa, x, p)
        #Clave publica: (p, alfa, y)
        res=(p, alfa, y)
        return res
    else:
        return("P: ", p, " no es primo")
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Fichero: potencia.py
# Autor: César Aguilera
# Fecha: Abril 2012
#
from aritmetica_modular import potencia_modular

print "\n##################################################"
print "################ Potencia Modular ################"
print "##################################################\n"

print "Calcula en Zp la potencia 'a' elevado a 'b'\n"

a = raw_input("Introduce base, a: ")
b = raw_input("Introduce exponente, b: ")
p = raw_input("Introduce módulo, p :")

a, b, p = int(a), int(b), int(p)


print "Potencia modular: ", potencia_modular(a, b, p)
def descifrado_RSA(c, d, n):
    inv=am.potencia_modular(c, d, n)
    return inv
def cifrado_RSA(m, e, n):
    if am.euclides_extendido(m, n)[0]==1:
        c=am.potencia_modular(m, e, n)
        return c
    else:
        return "Mensaje m no es primo relativo con n"
 def h(x):
     res=am.potencia_modular(x, 2, n)*am.potencia_modular(a0, b, n)*am.potencia_modular(a1, b-1, n)
     return res
#
# Fichero: script-pruebas.py
# Autor: César Aguilera
# Fecha: Abril 2012
#

from timeit import Timer
from functools import partial
from aritmetica_modular import potencia_modular, logaritmo_discreto
from random import randint

def get_execution_time_in_seconds(function, args=(), kwargs ={}, numberOfExecTime=1):
    return round(Timer(partial(function, *args, **kwargs)).timeit(numberOfExecTime), 8) # Precision tiempo 8 decimales


mismo_num_cifras = lambda c: randint(10**(len(str(c))-1), 10**( len (str(c) ))  )

P = [52691, 843587, 4872961, 29873761, 537891269, 1547598739, 82376849239, 576382750891, 5134857695843]

A = [mismo_num_cifras(i) for i in P]
B = [mismo_num_cifras(i) for i in P]


print "%s\t%s\t%s\t%s\t%s\t%s\t%s" % ("p", "a", "b", "c", "d", "tc", "td")
for i in range(len(P)):
	a, b, p = A[i], B[i], P[i]
	c = potencia_modular(a, b, p)
	d = logaritmo_discreto(a,c,p)
	tc = get_execution_time_in_seconds(potencia_modular, (a,b,p))
	td = get_execution_time_in_seconds(logaritmo_discreto, (a,c,p))
	print "%s\t%s\t%s\t%s\t%s\t%s\t%s" % (p, a, b, c, d, tc, td)