Exemple #1
0
 def fermat(self, n):
     """Fermat attack"""
     a = b = isqrt(n)
     b2 = pow(a, 2) - n
     while pow(b, 2) != b2:
         a += 1
         b2 = pow(a, 2) - n
         b = isqrt(b2)
     p, q = (a + b), (a - b)
     assert n == p * q
     return p, q
Exemple #2
0
    def pollard_P_1(self, n, progress=True):
        """Pollard P1 implementation"""
        z = []
        logn = math.log(int(isqrt(n)))
        prime = primes(997)

        for j in range(0, len(prime)):
            primej = prime[j]
            logp = math.log(primej)
            for i in range(1, int(logn / logp) + 1):
                z.append(primej)

        try:
            for pp in tqdm(prime, disable=(not progress)):
                i = 0
                x = pp
                while 1:
                    x = powmod(x, z[i], n)
                    i = i + 1
                    y = gcd(n, x - 1)
                    if y != 1:
                        p = y
                        q = n // y
                        return p, q
                    if i >= len(z):
                        return 0, None
        except TypeError:
            return 0, None
Exemple #3
0
    def __init__(self, n, e, progress=True):
        """Constructor"""
        self.d = None
        self.p = None
        self.q = None
        sys.setrecursionlimit(100000)
        frac = self.rational_to_contfrac(e, n)
        convergents = self.convergents_from_contfrac(frac, progress)

        for (k, d) in tqdm(convergents, disable=(not progress)):
            if k != 0:
                ed1 = e * d - 1
                phi = ed1 // k
                if ed1 - (k * phi) == 0:  # same as ed1 % k == 0
                    s = n - phi + 1
                    discr = pow(s, 2) - (n << 2)  # same as  s**2 - 4*n
                    if discr >= 0:
                        t = isqrt(discr)
                        if pow(t, 2) == discr:
                            if (s + t) & 1 == 0:
                                self.d = d
                                x = Symbol("x")
                                roots = solve(pow(x, 2) - s * x + n, x)
                                if len(roots) == 2:
                                    self.p = roots[0]
                                    self.q = roots[1]
                                break
Exemple #4
0
def SQUFOF(N):
    s = int(isqrt(N) + 0.5)
    L = int(2 * isqrt(2 * s))

    if s ** 2 == N:
        return s
    for k in range(0, len(multiplier)):
        D = multiplier[k] * N
        Po = Pprev = P = isqrt(D)
        Qprev = 1
        Q = D - pow(Po, 2)
        B = 3 * L
        c0 = True
        i = 2
        while c0:
            b = int((Po + P) // Q)
            P = b * Q - P
            q = Q
            Q = Qprev + b * (Pprev - P)
            r = int(isqrt(Q) + 0.5)
            if not (i & 1) and (pow(r, 2) == Q):
                break
            Qprev = q
            Pprev = P
            i += 1
            c0 = i <= B
        b = (Po - P) // r
        Pprev = P = b * r + P
        Qprev = r
        Q = (D - pow(Pprev, 2)) // Qprev
        i = 0
        c1 = True
        while c1:
            b = int((Po + P) // Q)
            Pprev = P
            P = b * Q - P
            q = Q
            Q = Qprev + b * (Pprev - P)
            Qprev = q
            i += 1
            c1 = P != Pprev
        r = gcd(N, Qprev)
        if 1 < r < N:
            return r, N // r
    return -1
Exemple #5
0
    def euler(self, n):
        if n & 1 == 0:
            return (n >> 1, 2) if n > 2 else (2, 1)
        end = isqrt(n)
        a = 0
        solutionsFound = []
        firstb = -1

        while a < end and len(solutionsFound) < 2:
            bsquare = n - pow(a, 2)
            if bsquare > 0:
                b = isqrt(bsquare)
                if (pow(b, 2) == bsquare) and (a != firstb) and (b != firstb):
                    firstb = b
                    solutionsFound.append([b, a])
            a += 1
        if len(solutionsFound) < 2:
            return None

        a = solutionsFound[0][0]
        b = solutionsFound[0][1]
        c = solutionsFound[1][0]
        d = solutionsFound[1][1]

        k = pow(gcd(a - c, d - b), 2)
        h = pow(gcd(a + c, d + b), 2)
        m = pow(gcd(a + c, d - b), 2)
        l = pow(gcd(a - c, d + b), 2)

        p, q = gcd(k + h, n), gcd(l + m, n)

        if n > p > 1:
            return p, n // p

        if n > q > 1:
            return q, n // q
Exemple #6
0
 def z3_solve(self, n, timeout_amount):
     """Integer factorization using z3 theorem prover implementation:
     We can factor composite integers by SAT solving the model N=PQ directly using the clasuse (n==p*q),
     wich gives a lot of degree of freedom to z3, so we want to contraint the search space.
     Since every composite number n=pq, there always exists some p>sqrt(n) and q<sqrt(n).
     We can safely asume the divisor p is in the range n > p >= next_prime(sqrt(n))
     if this later clause doesn't hold and sqrt(p) is prime the number is a perfect square.
     We can also asume that p and q are alyaws odd otherwise our whole composite is even.
     Not all composite numbers generate a valid model that z3 can SAT.
     SAT solving is efficient with low bit count set in the factors,
     the complexity of the algorithm grows exponential with every bit set.
     The problem of SAT solving integer factorization still is NP complete,
     making this just a showcase. Don't expect big gains.
     """
     s = Solver()
     s.set("timeout", timeout_amount * 1000)
     p = Int("p")
     q = Int("q")
     i = int(isqrt(n))
     np = int(next_prime(i))
     s.add(
         p * q == n,
         n > p,
         n > q,
         p >= np,
         q < i,
         q > 1,
         p > 1,
         q % 2 != 0,
         p % 2 != 0,
     )
     try:
         s_check_output = s.check()
         if s_check_output == sat:
             res = s.model()
             P, Q = res[p].as_long(), res[q].as_long()
             assert P * Q == n
             return P, Q
         else:
             return None, None
     except:
         return None, None
Exemple #7
0
def dixon_factor(N, B=7, explain=False):

    if is_prime(N):
        return N, 1

    start = isqrt(N)

    if (start**2) == N:
        return start, start

    base = primes(B)
    lqbf = pow(base[-1], 2) + 1
    QBF = bitarray.bitarray(lqbf)  # This is our quasi-bloom-filter

    basej2N = []
    for j in range(0, len(base)):
        p = powmod(base[j], 2, N)
        basej2N.append(p)
        QBF[p] = 1  # We populate our quasi-bloom-filter

    i = start
    while i < N:
        i2N = pow(i, 2, N)
        if i2N < lqbf and QBF[i2N] == 1:
            for k in range(0, len(base)):
                if QBF[basej2N[k]] == 1:
                    # if i2N == basej2N[k]: # this is replaced with a quasi-bloom-filter
                    f = gcd(i - base[k], N)
                    if explain:
                        print("N = %d" % N)
                        print("%d = isqrt(N)" % start)
                        print("%d = pow(%d,2,n)" % (i2N, i))
                        print("%d = pow(%d,2,n)" % (basej2N[k], base[k]))
                        print("%d - %d = %d" % (i, base[k], f))
                        print("%d = gcd(%d - % d, N)" % (f, i, base[k]))
                        print("%d = gcd(%d + % d, N)" %
                              (gcd(i + base[k], N), i, base[k]))
                    if 1 < f < N:
                        return f, N // f
        i += 1
    return None, None
Exemple #8
0
    def close_factor(self, n, b, progress=True):
        # approximate phi
        phi_approx = n - 2 * isqrt(n) + 1

        # create a look-up table
        look_up = {}
        z = 1
        for i in tqdm(range(0, b + 1), disable=(not progress)):
            look_up[z] = i
            z = (z << 1) % n

        # check the table
        mu = invmod(powmod(2, phi_approx, n), n)
        fac = powmod(2, b, n)

        for i in tqdm(range(0, b + 1), disable=(not progress)):
            if mu in look_up:
                phi = phi_approx + (look_up[mu] - (i * b))
                r = trivial_factorization_with_n_phi(n, phi)
                if r != None:
                    return r
            mu = (mu * fac) % n
        else:
            return None