def test_curve(q,t,r,k,D,E): 
    """
    Description:
    
       Tests that E is an elliptic curve over F_q with trace t, a subgroup of order r with embedding degree k, and fundamental discriminant D
    
    Input:
    
        q - size of prime field
        t - trace of Frobenius
        r - size of prime order subgroup
        k - embedding degree
        D - (negative) fundamental discriminant
    
    Output:
    
        bool - true iff E is an elliptic curve over F_q with trace t, a subgroup of order r with embedding degree k, and fundamental discriminant D
    
    """    
    bool = True
    bool = bool and (power_mod(q, k, r) == 1) #q^k -1 ==0 mod r
    bool = bool and (E.trace_of_frobenius() == t)
    bool = bool and (kronecker((t*t-4*q) * Integer(D).inverse_mod(q),q) == 1)
    bool = bool and (E.cardinality() == q+1-t)
    bool = bool and (E.cardinality() % r ==0)
    return bool
def find_element_of_order(k, r):
    """
    Description:
    
        Finds a random element of order k in Z_r^*
    
    Input:
    
        k - integer such that r % k == 1
        r - prime
    
    Output:
    
        h - element of order k in Z_r^*
    
    """
    assert r % k == 1
    h = 0

    def order(h, k, p):
        bool = True
        g = h
        for i in range(1, k):
            bool = bool and g != 1
            g = Mod(g * h, p)
        bool = bool and g == 1
        return bool

    while not order(h, k,
                    r):  # expected number of iterations is k/euler_phi(k)
        h = power_mod(randint(2, r - 1), (r - 1) // k, r)
    return h
示例#3
0
 def galoisorbit(self):
     order = self.order
     mod, num = self.modulus, self.number
     prim = self.isprimitive
     #beware this **must** be a generator
     orbit = ( power_mod(num, k, mod) for k in xsrange(1, order) if gcd(k, order) == 1) # use xsrange not xrange
     return ( self._char_desc(num, prim=prim) for num in orbit )
def small_A_twist(E):
    """
    Description:
        
        Finds a curve isogenous to E that has small A in the curve equation y^2 = x^3 + A*x + B
    
    Input:
    
        E - elliptic curve
    
    Output:
    
        E' - elliptic curve isogenous to E that has small A in the curve equation y^2 = x^3 + A*x + B
    
    """
    a = E.ainvs()[3]
    q = E.base_field().order()
    a = power_mod(Integer(a), -1, q)
    if kronecker(a,q) == -1:
        b = 2
        while kronecker(b,q) == 1:
            b += 1
        a = a*b
    assert kronecker(a,q) == 1
    d = Mod(a,q).sqrt()
    ainvs = [i for i in E.ainvs()]
    ainvs[3]*= d**2
    ainvs[4] *= d**3
    return EllipticCurve(E.base_field(), ainvs)
示例#5
0
def find_element_of_order(k,r):
    """
    Description:
    
        Finds a random element of order k in Z_r^*
    
    Input:
    
        k - integer such that r % k == 1
        r - prime
    
    Output:
    
        h - element of order k in Z_r^*
    
    """
    assert r % k == 1
    h = 0
    def order(h,k,p):
        bool = True
        g = h
        for i in range(1,k):
            bool = bool and g != 1
            g = Mod(g * h, p)
        bool = bool and g == 1
        return bool
    while not order(h,k,r): # expected number of iterations is k/euler_phi(k)
        h = power_mod(randint(2, r-1), (r-1)//k, r)
    return h
def small_B_twist(E):
    """
    Description:
        
        Finds a curve isogenous to E that has small B in the curve equation y^2 = x^3 + A*x + B
    
    Input:
    
        E - elliptic curve
    
    Output:
    
        E' - elliptic curve isogenous to E that has small B in the curve equation y^2 = x^3 + A*x + B
    
    """
    b = E.ainvs()[4]
    q = E.base_field().order()
    b = power_mod(Integer(b), -1, q)
    d = 0
    s = Mod(1,q)
    bool = True
    while bool:
        try:
            d = (s*b)
            d = d.nth_root(3)
            d = Integer(d)
            bool = False
        except ValueError as e:
            s+=1 
            pass
    ainvs = [i for i in E.ainvs()]
    ainvs[3] *= d**2
    ainvs[4] *= d**3
    return EllipticCurve(E.base_field(), ainvs)
def test_curve(q, t, r, k, D, E):
    """
    Description:
    
       Tests that E is an elliptic curve over F_q with trace t, a subgroup of order r with embedding degree k, and fundamental discriminant D
    
    Input:
    
        q - size of prime field
        t - trace of Frobenius
        r - size of prime order subgroup
        k - embedding degree
        D - (negative) fundamental discriminant
    
    Output:
    
        bool - true iff E is an elliptic curve over F_q with trace t, a subgroup of order r with embedding degree k, and fundamental discriminant D
    
    """
    bool = True
    bool = bool and (power_mod(q, k, r) == 1)  #q^k -1 ==0 mod r
    bool = bool and (E.trace_of_frobenius() == t)
    bool = bool and (kronecker(
        (t * t - 4 * q) * Integer(D).inverse_mod(q), q) == 1)
    bool = bool and (E.cardinality() == q + 1 - t)
    bool = bool and (E.cardinality() % r == 0)
    return bool
def small_A_twist(E):
    """
    Description:
        
        Finds a curve isogenous to E that has small A in the curve equation y^2 = x^3 + A*x + B
    
    Input:
    
        E - elliptic curve
    
    Output:
    
        E' - elliptic curve isogenous to E that has small A in the curve equation y^2 = x^3 + A*x + B
    
    """
    a = E.ainvs()[3]
    q = E.base_field().order()
    a = power_mod(Integer(a), -1, q)
    if kronecker(a, q) == -1:
        b = 2
        while kronecker(b, q) == 1:
            b += 1
        a = a * b
    assert kronecker(a, q) == 1
    d = Mod(a, q).sqrt()
    ainvs = [i for i in E.ainvs()]
    ainvs[3] *= d**2
    ainvs[4] *= d**3
    return EllipticCurve(E.base_field(), ainvs)
示例#9
0
 def galoisorbit(self):
     order = self.order
     mod, num = self.modulus, self.number
     prim = self.isprimitive
     #beware this **must** be a generator
     orbit = ( power_mod(num, k, mod) for k in xsrange(1, order) if gcd(k, order) == 1) # use xsrange not xrange
     return ( self._char_desc(num, prim=prim) for num in orbit )
def small_B_twist(E):
    """
    Description:
        
        Finds a curve isogenous to E that has small B in the curve equation y^2 = x^3 + A*x + B
    
    Input:
    
        E - elliptic curve
    
    Output:
    
        E' - elliptic curve isogenous to E that has small B in the curve equation y^2 = x^3 + A*x + B
    
    """
    b = E.ainvs()[4]
    q = E.base_field().order()
    b = power_mod(Integer(b), -1, q)
    d = 0
    s = Mod(1, q)
    bool = True
    while bool:
        try:
            d = (s * b)
            d = d.nth_root(3)
            d = Integer(d)
            bool = False
        except ValueError as e:
            s += 1
            pass
    ainvs = [i for i in E.ainvs()]
    ainvs[3] *= d**2
    ainvs[4] *= d**3
    return EllipticCurve(E.base_field(), ainvs)
示例#11
0
def encrypt_message(message, public_key):
    if isinstance(public_key, str):
        public_key = json_key(public_key)
    if not public_key:
        return None
    public_exponent, modulus = public_key

    cipher_text = " ".join([
        str(sage_all.power_mod(ord(char), public_exponent, modulus))
        for char in message
    ])
    return cipher_text
示例#12
0
def method(r, k, D, max_trials=10000, g=0):
    """
    Description:
        
        Run the Cocks-Pinch method to find an elliptic curve
    
    Input:
    
        r - prime
        k - embedding degree, r % k == 1
        D - (negative) fundamental discriminant where D is a square mod r
        max_trials - the number of integers q to test for primality in the CP method
        g - an element of order k in Z_r^*

    Output:
    
        (q,t) - tuple where q is a prime and t is chosen such that there exists
                an elliptic curve E over F_q with trace t, and r | q+1-t;
                if the algorithm fails to find (q,t), it will return (0,0)
    
    """
    assert test_promise(r, k, D), 'Invalid inputs'
    if g != 0:
        assert power_mod(g, k, r) == 1, 'Invalid inputs'
    else:
        g = find_element_of_order(k, r)
    D = Integer(D)
    t = Integer(g) + 1
    root_d = Integer(Mod(D, r).sqrt())
    u = Integer(Mod((t - 2) * root_d.inverse_mod(r), r))
    q = 1
    j = Integer(0)
    i = Integer(0)
    count = 0
    while (count < max_trials):
        q = Integer((t + i * r)**2 - D * (u + j * r)**2)
        if q % 4 == 0:
            q = q // 4
            if utils.is_suitable_q(q):
                return (q, t + i * r)
            q = 1
        if random() < 0.5:
            j += 1
        else:
            i += 1
        count += 1
    return (0, 0)  # no prime found, so end
示例#13
0
def method(r,k,D,max_trials=10000, g=0): 
    """
    Description:
        
        Run the Cocks-Pinch method to find an elliptic curve
    
    Input:
    
        r - prime
        k - embedding degree, r % k == 1
        D - (negative) fundamental discriminant where D is a square mod r
        max_trials - the number of integers q to test for primality in the CP method
        g - an element of order k in Z_r^*

    Output:
    
        (q,t) - tuple where q is a prime and t is chosen such that there exists
                an elliptic curve E over F_q with trace t, and r | q+1-t;
                if the algorithm fails to find (q,t), it will return (0,0)
    
    """
    assert test_promise(r,k,D), 'Invalid inputs'
    if g != 0:
        assert power_mod(g,k,r) == 1, 'Invalid inputs'
    else:
        g = find_element_of_order(k,r)
    D = Integer(D)
    t = Integer(g) + 1
    root_d = Integer(Mod(D, r).sqrt())
    u = Integer(Mod((t-2)*root_d.inverse_mod(r) ,r))
    q = 1
    j = Integer(0)
    i = Integer(0)
    count = 0
    while (count < max_trials):
           q = Integer( (t+i*r)**2 - D*(u + j*r)**2)
           if q % 4 ==0:
                q = q//4
                if utils.is_suitable_q(q):
                    return (q, t+i*r)
                q = 1
           if random() < 0.5:
                j+=1
           else:
                i+=1
           count+=1
    return (0, 0) # no prime found, so end
示例#14
0
def decrypt_message(cipher_text, private_key):
    if isinstance(private_key, str):
        private_key = json_key(private_key)
    if not private_key:
        return None

    private_exponent, modulus = private_key

    block_num = [(int(block)) for block in cipher_text.split()]
    decrypted_num = ""

    for block in block_num:
        message = sage_all.power_mod(block, private_exponent, modulus)
        decrypted_num += " " + str(message)

    message = "".join([chr(int(num)) for num in decrypted_num.split()])
    return message
示例#15
0
def is_valid_curve(q, t, r, k, D):
    """
    Description:
    
        Tests that (q,t,r,k,D) is a valid elliptic curve
    
    Input:
    
        q - size of prime field
        t - trace of Frobenius
        r - size of prime order subgroup
        k - embedding degree
        D - (negative) fundamental discriminant
    
    Output:
    
        bool - true iff there exists an elliptic curve over F_q with trace t, a subgroup of order r with embedding degree k, and fundamental discriminant D
    
    """
    if q == 0 or t == 0 or r == 0 or k == 0 or D == 0:
        return False
    if not is_prime(q):
        return False
    if not is_prime(r):
        return False
    if not fundamental_discriminant(D) == D:
        return False
    if D % 4 == 0:  #check CM equation
        if not is_square(4 * (t * t - 4 * q) // D):
            return False
    if D % 4 == 1:
        if not is_square((t * t - 4 * q) // D):
            return False
    if not (q + 1 - t) % r == 0:  #check r | #E(F_q)
        return False
    if not power_mod(q, k, r) == 1:  #check embedding degree is k
        return False
    return True
示例#16
0
def is_valid_curve(q,t,r,k,D): 
    """
    Description:
    
        Tests that (q,t,r,k,D) is a valid elliptic curve
    
    Input:
    
        q - size of prime field
        t - trace of Frobenius
        r - size of prime order subgroup
        k - embedding degree
        D - (negative) fundamental discriminant
    
    Output:
    
        bool - true iff there exists an elliptic curve over F_q with trace t, a subgroup of order r with embedding degree k, and fundamental discriminant D
    
    """
    if q == 0 or t == 0 or r == 0 or k == 0 or D == 0:
        return False
    if not is_prime(q):
        return False 
    if not is_prime(r):
        return False
    if not fundamental_discriminant(D) == D:
        return False
    if D % 4 == 0: #check CM equation
        if not is_square(4*(t*t - 4*q)//D):
            return False
    if D % 4 == 1:
        if not is_square((t*t - 4*q)//D):
            return False
    if not (q+1-t) % r == 0: #check r | #E(F_q)
        return False
    if not power_mod(q,k,r) == 1: #check embedding degree is k
        return False
    return True
def make_curve(q,t,r,k,D,debug=False):
    """
    Description:
    
        Finds the curve equation for the elliptic curve (q,t,r,k,D) using the Complex Multiplication method
    
    Input:
    
        q - size of prime field
        t - trace of Frobenius
        r - size of prime order subgroup
        k - embedding degree
        D - (negative) fundamental discriminant
    
    Output:
    
        E - elliptic curve over F_q with trace t,
            a subgroup of order r with embedding degree k,
            and fundamental discriminant D
    
    """
    assert is_valid_curve(q,t,r,k,D), 'Invalid input. No curve exists.' # check inputs
    if debug:
        print('Tested input')
    poly = hilbert_class_polynomial(D) # compute hilbert class polynomial
    if debug:
        print('Computed Hilbert class polynomial')
    check = False
    j_inv = poly.any_root(GF(q)) # find j-invariant    
    orig_curve = EllipticCurve(GF(q), j=j_inv) # make a curve
    E = orig_curve
    check = test_curve(q,t,r,k,D,E) # see if this is the right curve
    twist = False
    if not check: # not the right curve, use quadratic twist
        E = E.quadratic_twist()
        check = test_curve(q,t,r,k,D,E)
        if check:
            twist = True
        else: # twist didnt work => j = 0 or 1728
            if j_inv == 0: # for j = 0, use sextic twists
                prim = primitive_root(q)
                i = 1
                while t != E.trace_of_frobenius() and i < 6:
                    E = orig_curve.sextic_twist(power_mod(prim,i,q))
                    i+=1
            elif j_inv == 1728: # for j = 1728, use quartic twists
                prim = primitive_root(q)
                i = 1
                while t != E.trace_of_frobenius() and i < 4:
                    E = orig_curve.quartic_twist(power_mod(prim,i,q))
                    i+=1
            else: # twist didnt work and j != 0, 1728. this should never happen, so write input to a file for debugging
                print('Error. Quadratic twist failed to find the correct curve with j != 0, 1728. Logging output to debug.txt') # this line should never be reached'
                f = open('debug.txt', 'w')
                f.write('Twist: ' + str(twist) + '\n')
                f.write('q: ' + str(q) + '\n')
                f.write('t: ' + str(t) + '\n')
                f.write('r: ' + str(r) + '\n')
                f.write('k: ' + str(k) + '\n')
                f.write('D: ' + str(D) + '\n')
                f.write('E: ' + str(E) + '\n')
                f.write('orig_curve: ' + str(orig_curve))
                f.close()
                return False
            check = test_curve(q,t,r,k,D,E)
            twist = True
    if not check: # didnt find a curve. this should never happen, so write input to a file for debugging
        print('Error. Failed to find curve. Logging output to debug.txt')
        f = open('debug.txt', 'w')
        f.write('Twist: ' + str(twist) + '\n')
        f.write('q: ' + str(q) + '\n')
        f.write('t: ' + str(t) + '\n')
        f.write('r: ' + str(r) + '\n')
        f.write('k: ' + str(k) + '\n')
        f.write('D: ' + str(D) + '\n')
        f.write('E: ' + str(E) + '\n')
        f.write('orig_curve: ' + str(orig_curve))
        f.close()
        return False
    return E
 def gen_inv_n(self):
     temp = []
     for n in self.n:
         temp.append(power_mod(n, -1, self.p - 1))
     self.n = temp
 def gen_inv_k(self):
     temp = []
     for n in self.k:
         temp.append(power_mod(n, -1, self.p))
     self.k = temp
def make_curve(q, t, r, k, D, debug=False):
    """
    Description:
    
        Finds the curve equation for the elliptic curve (q,t,r,k,D) using the Complex Multiplication method
    
    Input:
    
        q - size of prime field
        t - trace of Frobenius
        r - size of prime order subgroup
        k - embedding degree
        D - (negative) fundamental discriminant
    
    Output:
    
        E - elliptic curve over F_q with trace t,
            a subgroup of order r with embedding degree k,
            and fundamental discriminant D
    
    """
    assert is_valid_curve(q, t, r, k,
                          D), 'Invalid input. No curve exists.'  # check inputs
    if debug:
        print('Tested input')
    poly = hilbert_class_polynomial(D)  # compute hilbert class polynomial
    if debug:
        print('Computed Hilbert class polynomial')
    check = False
    j_inv = poly.any_root(GF(q))  # find j-invariant
    orig_curve = EllipticCurve(GF(q), j=j_inv)  # make a curve
    E = orig_curve
    check = test_curve(q, t, r, k, D, E)  # see if this is the right curve
    twist = False
    if not check:  # not the right curve, use quadratic twist
        E = E.quadratic_twist()
        check = test_curve(q, t, r, k, D, E)
        if check:
            twist = True
        else:  # twist didnt work => j = 0 or 1728
            if j_inv == 0:  # for j = 0, use sextic twists
                prim = primitive_root(q)
                i = 1
                while t != E.trace_of_frobenius() and i < 6:
                    E = orig_curve.sextic_twist(power_mod(prim, i, q))
                    i += 1
            elif j_inv == 1728:  # for j = 1728, use quartic twists
                prim = primitive_root(q)
                i = 1
                while t != E.trace_of_frobenius() and i < 4:
                    E = orig_curve.quartic_twist(power_mod(prim, i, q))
                    i += 1
            else:  # twist didnt work and j != 0, 1728. this should never happen, so write input to a file for debugging
                print(
                    'Error. Quadratic twist failed to find the correct curve with j != 0, 1728. Logging output to debug.txt'
                )  # this line should never be reached'
                f = open('debug.txt', 'w')
                f.write('Twist: ' + str(twist) + '\n')
                f.write('q: ' + str(q) + '\n')
                f.write('t: ' + str(t) + '\n')
                f.write('r: ' + str(r) + '\n')
                f.write('k: ' + str(k) + '\n')
                f.write('D: ' + str(D) + '\n')
                f.write('E: ' + str(E) + '\n')
                f.write('orig_curve: ' + str(orig_curve))
                f.close()
                return False
            check = test_curve(q, t, r, k, D, E)
            twist = True
    if not check:  # didnt find a curve. this should never happen, so write input to a file for debugging
        print('Error. Failed to find curve. Logging output to debug.txt')
        f = open('debug.txt', 'w')
        f.write('Twist: ' + str(twist) + '\n')
        f.write('q: ' + str(q) + '\n')
        f.write('t: ' + str(t) + '\n')
        f.write('r: ' + str(r) + '\n')
        f.write('k: ' + str(k) + '\n')
        f.write('D: ' + str(D) + '\n')
        f.write('E: ' + str(E) + '\n')
        f.write('orig_curve: ' + str(orig_curve))
        f.close()
        return False
    return E
 def gen_inv_e(self):
     temp = []
     for n in self.e:
         temp.append(power_mod(n, -1, self.p))
     self.e = temp