コード例 #1
0
    def factorize_from_d(d: int, e: int, n: int):
        """
        Factorizes the secret primes from the private key `d`.

        Parameters:
            d (int): Private key.
            e (int): Public exponent.
            n (int): Modulus.
        
        Returns:
            RSA: Full RSA instance.
        """
        import random

        k = d * e - 1
        p = None
        q = None

        while not p:
            g = random.randint(2, n - 1)
            t = k

            while t % 2 == 0:
                t = t // 2
                x = pow(g, t, n)

                if x > 1 and gcd(x - 1, n) > 1:
                    p = gcd(x - 1, n)
                    q = n // p
                    break

        return RSA(0, p=p, q=q, e=e)
コード例 #2
0
ファイル: lcg.py プロジェクト: gcdeshpande/samson
    def check_full_period(self) -> bool:
        """
        Checks whether the LCG will achieve a full period with its current parameters.

        Returns:
            bool: Whether or not it will acheive a full period.
        
        References:
            https://en.wikipedia.org/wiki/Linear_congruential_generator#Period_length
        """
        # Technically, this achieves m-1
        if is_prime(self.m) and self.c == 0 and is_primitive_root(
                self.a, self.m):
            return True

        # Maximially m/4
        elif is_power_of_two(self.m) and self.c == 0:
            return False

        else:
            # 1. m and c are relatively prime
            relatively_prime = gcd(self.m, self.c) == 1

            # 2. a-1 is divisible by all prime factors of m
            factors = [factor for factor in factorint(self.m)]
            divisible_by_all_factors = all([((self.a - 1) % factor) == 0
                                            for factor in factors])

            # 3. a-1 is divisible by 4 if m is divisible by 4
            divisible_by_four = True
            if self.m % 4 == 0:
                divisible_by_four = (self.a - 1) % 4 == 0

            return relatively_prime and divisible_by_all_factors and divisible_by_four
コード例 #3
0
    def is_invertible(self) -> bool:
        """
        Determines if the element is invertible.

        Returns:
            bool: Whether the element is invertible.
        """
        from samson.math.general import gcd
        return gcd(self.val, self.ring.quotient) == self.ring.ring.one()
コード例 #4
0
    def square_free_decomposition(self) -> list:
        """
        Decomposes a Polynomial into its square-free factors. Used as the first step in factorization.

        https://en.wikipedia.org/wiki/Factorization_of_polynomials_over_finite_fields#Square-free_factorization

        Returns:
            list: Square-free factors of self.

        Examples:
            >>> from samson.math.all import Polynomial, ZZ
            >>> from samson.math.symbols import Symbol
            >>> x = Symbol('x')
            >>> _ = ZZ[x]
            >>> poly = 3*x**3+x**7-x**18
            >>> poly.square_free_decomposition()
            {<Polynomial: x**15 + ZZ(-1)*x**4 + ZZ(-3), coeff_ring=ZZ>: 1, <Polynomial: x, coeff_ring=ZZ>: 3}

        """
        f = self.monic()
        c = gcd(f, f.derivative().monic()).monic()
        w = f / c

        factors = {}

        i = 1
        while w != self.ring.one():
            y = gcd(w, c).monic()
            fac = (w / y).monic()

            if fac != self.ring.one():
                add_or_increment(factors, fac, i)

            w, c, i = y, c / y, i + 1

        if c != self.ring.one():
            c = c.trunc_kth_root(self.coeff_ring.characteristic)
            new_facs = c.square_free_decomposition()
            for new_fac in new_facs:
                add_or_increment(factors, new_fac,
                                 self.coeff_ring.characteristic)

        return factors
コード例 #5
0
    def distinct_degree_factorization(self) -> list:
        """
        Factors a Polynomial into factors of different degrees.

        https://en.wikipedia.org/wiki/Factorization_of_polynomials_over_finite_fields#Distinct-degree_factorization

        Returns:
            list: Distinct-degree factors of self.
        """
        from samson.math.general import frobenius_map, frobenius_monomial_base

        f = self
        f_star = f
        S = []
        i = 1

        x = self.symbol
        x_poly = f.ring(x)

        while f_star.degree() > 2 * i:
            if not f_star.is_monic():
                f_star = f_star.monic()

            # Calculate P(x**q**i - x)
            bases = frobenius_monomial_base(f_star)
            h = frobenius_map(bases[1], f_star, bases=bases)

            for _ in range(i - 1):
                h = frobenius_map(h, f_star, bases=bases)

            g = gcd(f_star, h - x_poly).monic()

            if g != self.ring.one():
                S.append((g, i))
                f_star /= g

            i += 1

        if f_star != self.ring.one():
            S.append((f_star, f_star.degree()))

        if not S:
            return [(f, 1)]
        else:
            return S
コード例 #6
0
    def factorize_from_faulty_crt(message: int, faulty_sig: int, e: int,
                                  n: int):
        """
        Factorize the secret primes from a faulty signature produced with CRT-optimized RSA.

        Parameters:
            message    (int): Message.
            faulty_sig (int): Faulty signature of `message`.
            e          (int): Public exponent.
            n          (int): Modulus.
        
        Returns:
            RSA: Cracked RSA instance.
        """
        q = gcd(pow(faulty_sig, e, n) - message, n)
        p = n // q

        return RSA(0, p=p, q=q, e=e)
コード例 #7
0
ファイル: paillier.py プロジェクト: gcdeshpande/samson
    def encrypt(self, plaintext: bytes) -> int:
        """
        Encrypts `plaintext`.

        Parameters:
            plaintext (bytes): Plaintext.
        
        Returns:
            int: Ciphertext.
        """
        m = Bytes.wrap(plaintext).to_int()
        assert m < self.n

        r = random_int(self.n)
        while gcd(r, self.n) != 1:
            r = random_int(self.n)

        n_sqr = self.n ** 2
        return pow(self.g, m, n_sqr) * pow(r, self.n, n_sqr)
コード例 #8
0
    def factorize_from_shared_p(n1: int, n2: int, e: int):
        """
        Factorizes the moduli of two instances that share a common secret prime. See `Batch GCD`.

        Parameters:
            n1 (int): Modulus of the first instance.
            n2 (int): Modulus of the second instance.
            e  (int): Public exponent.
        
        Returns:
            (RSA, RSA): Both cracked RSA instances.
        """
        assert n1 != n2

        # Find shared `p`
        p = gcd(n1, n2)

        q1 = n1 // p
        q2 = n2 // p

        return (RSA(0, p=p, q=q1, e=e), RSA(0, p=p, q=q2, e=e))
コード例 #9
0
    def is_irreducible(self) -> bool:
        """
        Determines if a Polynomial is irreducible over its ring.

        https://en.wikipedia.org/wiki/Factorization_of_polynomials_over_finite_fields#Rabin's_test_of_irreducibility
        https://github.com/sympy/sympy/blob/d1301c58be7ee4cd12fd28f1c5cd0b26322ed277/sympy/polys/galoistools.py

        Returns:
            bool: Whether or not the Polynomial is irreducible over its ring.
        """
        from samson.math.general import frobenius_map, frobenius_monomial_base

        n = self.degree()

        if n <= 1:
            return True

        x = self.symbol
        f = self.monic()
        P = self.ring

        subgroups = {n // fac for fac in factor_int(n)}

        bases = frobenius_monomial_base(f)
        h = bases[1]
        x_poly = P(x)
        one = P.one()

        for idx in range(1, n):
            if idx in subgroups:
                if gcd(f, h - x_poly).monic() != one:
                    return False

            h = frobenius_map(h, f, bases=bases)

        return h == x_poly
コード例 #10
0
    def equal_degree_factorization(self,
                                   d: int,
                                   subgroup_divisor: int = None) -> list:
        """
        Factors a Polynomial into factors of equal degrees.

        Parameters:
            d                (int): Degree to factor into.
            subgroup_divisor (int): Smallest divisor of `order - 1`.

        Returns:
            list: Equal-degree factors of self.
        """
        from samson.math.general import frobenius_map, frobenius_monomial_base
        from samson.math.symbols import oo

        f = self.monic()
        n = f.degree()
        r = n // d
        S = [f]

        f_quot = f.ring / f
        if self.coeff_ring.order != oo:
            q = self.coeff_ring.order
            if not subgroup_divisor:
                subgroup_divisor = [f for f in factor_int((q - 1))][0]

            exponent = (q - 1) // subgroup_divisor

        one = self.ring.one()
        bases = frobenius_monomial_base(f)

        irreducibility_cache = {}

        if n < d or self.is_irreducible():
            return S

        try:
            while len(S) < r and (not irreducibility_cache or not all(
                [irreducibility_cache[poly] for poly in S])):
                h = f.ring.random(f)
                g = gcd(h, f).monic()

                if g == one:
                    h = f_quot(h)
                    j = h
                    for _ in range(d - 1):
                        j = frobenius_map(j, f, bases=bases)
                        h *= j

                    g = (h**exponent).val - one

                for u in S:
                    if u.degree() <= d or (u in irreducibility_cache
                                           and irreducibility_cache[u]):
                        continue

                    gcd_g_u = gcd(g, u).monic()
                    if gcd_g_u != one and gcd_g_u != u:
                        S.remove(u)
                        if u in irreducibility_cache:
                            del irreducibility_cache[u]

                        u_gcd_g_u = u / gcd_g_u
                        S.extend([gcd_g_u, u_gcd_g_u])

                        # Cache irreducibility results
                        irreducibility_cache[gcd_g_u] = gcd_g_u.is_irreducible(
                        )
                        irreducibility_cache[
                            u_gcd_g_u] = u_gcd_g_u.is_irreducible()
        except KeyboardInterrupt:
            pass

        return S
コード例 #11
0
    def __init__(self,
                 bits: int = None,
                 p: int = None,
                 q: int = None,
                 e: int = 65537,
                 n: int = None):
        """
        Parameters:
            bits (int): Number of bits for strength and capacity.
            p    (int): Secret prime modulus.
            q    (int): Secret prime modulus.
            e    (int): Public exponent.
            n    (int): Public modulus.
        """
        Primitive.__init__(self)

        self.e = e
        phi = 0

        if p and q:
            phi = lcm(p - 1, q - 1)
            self.n = p * q

            if gcd(self.e, phi) != 1:
                raise Exception("Invalid 'p' and 'q': GCD(e, phi) != 1")

            bits = p.bit_length() + q.bit_length()

        elif n:
            self.n = n

        else:
            next_p = p
            next_q = q

            # Take into account the bits needed to complete `bits` if `p` or `q` are already defined
            if p:
                q_bits = bits - p.bit_length()
            else:
                q_bits = bits // 2

            if q:
                p_bits = bits - q.bit_length()
            else:
                p_bits = bits // 2

            # Find the primes
            while gcd(self.e, phi) != 1 or next_p == next_q:
                if not p:
                    next_p = find_prime(p_bits)

                if not q:
                    next_q = find_prime(q_bits)

                phi = lcm(next_p - 1, next_q - 1)

            p = next_p
            q = next_q
            self.n = p * q

        self.p = p
        self.q = q
        self.phi = phi

        self.bits = bits

        if self.p and self.q:
            self.d = mod_inv(self.e, phi)
            self.alt_d = mod_inv(self.e, (self.p - 1) * (self.q - 1))

            self.dP = self.d % (self.p - 1)
            self.dQ = self.d % (self.q - 1)
            self.Qi = mod_inv(self.q, self.p)
        else:
            self.d = None
            self.alt_d = None

        self.pub = (self.e, self.n)
        self.priv = (self.d, self.n)