예제 #1
0
def attack(attack_rsa_obj, publickey, cipher=[]):
    """Run tests against mersenne composites"""
    with timeout(attack_rsa_obj.args.timeout):
        try:
            p = q = None
            for i in range(2, int(log2(publickey.n))):
                i2 = 2**i
                mersenne = [i2 - 1, i2 + 1]
                g0, g1 = gcd(mersenne[0],
                             publickey.n), gcd(mersenne[1], publickey.n)
                if 1 < g0 < publickey.n:
                    p = publickey.n // g0
                    q = g0
                    break
                if 1 < g1 < publickey.n:
                    p = publickey.n // g1
                    q = g1
                    break
            if p is not None and q is not None:
                priv_key = PrivateKey(int(p), int(q), int(publickey.e),
                                      int(publickey.n))
                return (priv_key, None)
            return (None, None)
        except TimeoutError:
            return (None, None)
예제 #2
0
    def attack(self, publickey, cipher=[]):
        """Run fermat attack with a timeout"""
        try:
            with timeout(seconds=self.timeout):
                try:
                    publickey.p, publickey.q = self.fermat(publickey.n)
                except TimeoutError:
                    return (None, None)

        except FactorizationError:
            return (None, None)

        if publickey.p is not None and publickey.q is not None:
            try:
                priv_key = PrivateKey(
                    n=publickey.p,
                    p=int(publickey.p),
                    q=int(publickey.q),
                    e=int(publickey.e),
                )
                return (priv_key, None)
            except ValueError:
                return (None, None)

        return (None, None)
예제 #3
0
 def attack(self, publickey, cipher=[], progress=True):
     """Try to uncipher c if m < n/e and small e"""
     with timeout(self.timeout):
         try:
             if publickey.e == 3 or publickey.e == 5:
                 plain = []
                 if (cipher is None) or (len(cipher) < 1):
                     self.logger.info(
                         "[-] No ciphertexts specified, skiping the cube_root test..."
                     )
                     return (None, None)
                 for c in cipher:
                     cipher_int = int.from_bytes(c, "big")
                     low = 0
                     high = cipher_int
                     while low < high:
                         mid = (low + high) >> 1
                         if pow(mid, publickey.e) < cipher_int:
                             low = mid + 1
                         else:
                             high = mid
                     plain.append(
                         low.to_bytes((low.bit_length() + 7) // 8,
                                      byteorder="big"))
                 return (None, plain)
         except TimeoutError:
             return (None, None)
     return (None, None)
예제 #4
0
    def attack(self, publickey, cipher=[], progress=True):
        """Same n huge e attack"""
        if not isinstance(publickey, list):
            return (None, None)

        with timeout(self.timeout):
            try:
                if len(set([_.n for _ in publickey])) == 1:
                    new_e = 1
                    for k in publickey:
                        new_e = new_e * k.e

                    new_key = (RSA.construct(
                        (publickey[0].n, new_e)).publickey().exportKey())

                    tmpfile = tempfile.NamedTemporaryFile()
                    with open(tmpfile.name, "wb") as tmpfd:
                        tmpfd.write(new_key)
                        tmpfd.flush()
                        result = self.attack_rsa_obj.attack_single_key(
                            tmpfile.name)
                        if result:
                            return (self.attack_rsa_obj.priv_key, None)
            except TimeoutError:
                return (None, None)
        return (None, None)
예제 #5
0
    def attack(self, publickey, cipher=[]):
        """Try to factorize using yafu"""
        with timeout(self.timeout):
            try:
                if publickey.n.bit_length() > 1024:
                    self.logger.error(
                        "[!] Warning: Modulus too large for SIQS attack module"
                    )
                    return (None, None)

                siqsobj = SiqsAttack(self.attack_rsa_obj, publickey.n)

                siqsobj.checkyafu()
                siqsobj.testyafu()

                if siqsobj.checkyafu() and siqsobj.testyafu():
                    siqsobj.doattack()

                if siqsobj.p and siqsobj.q:
                    publickey.q = siqsobj.q
                    publickey.p = siqsobj.p
                    priv_key = PrivateKey(
                        int(publickey.p),
                        int(publickey.q),
                        int(publickey.e),
                        int(publickey.n),
                    )
                    return (priv_key, None)
            except TimeoutError:
                return (None, None)
        return (None, None)
예제 #6
0
    def attack(self, publickey, cipher=[], progress=True):
        """Run dixon attack with a timeout"""
        try:
            with timeout(seconds=self.timeout):
                try:
                    if publickey.n <= 10**10:
                        publickey.p, publickey.q = dixon_factor(publickey.n)
                    else:
                        self.logger.info(
                            "[-] Dixon is too slow for pubkeys > 10^10...")
                        return (None, None)
                except TimeoutError:
                    return (None, None)

        except FactorizationError:
            return (None, None)

        if publickey.p is not None and publickey.q is not None:
            try:
                priv_key = PrivateKey(
                    n=publickey.n,
                    p=int(publickey.p),
                    q=int(publickey.q),
                    e=int(publickey.e),
                )
                return (priv_key, None)
            except ValueError:
                return (None, None)

        return (None, None)
예제 #7
0
    def attack(self, publickey, cipher=[]):
        """Run attack with Euler method"""
        if not hasattr(publickey, "p"):
            publickey.p = None
        if not hasattr(publickey, "q"):
            publickey.q = None

        # Euler attack
        with timeout(self.timeout):
            try:
                try:
                    euler_res = self.euler(publickey.n)
                except:
                    print("Euler: Internal Error")
                    return (None, None)
                if euler_res and len(euler_res) > 1:
                    publickey.p, publickey.q = euler_res

                if publickey.q is not None:
                    priv_key = PrivateKey(
                        int(publickey.p),
                        int(publickey.q),
                        int(publickey.e),
                        int(publickey.n),
                    )
                    return (priv_key, None)
            except TimeoutError:
                return (None, None)

        return (None, None)
예제 #8
0
def attack(attack_rsa_obj, publickey, cipher=[]):
    """Run tests against primorial +-1 composites"""
    with timeout(attack_rsa_obj.args.timeout):
        try:
            limit = 10000
            pc = 0
            prime = 1
            primorial = 1
            p = q = None
            while True:
                prime = next_prime(prime)
                primorial *= prime
                primorial_p1 = [primorial - 1, primorial + 1]
                g0, g1 = gcd(primorial_p1[0],
                             publickey.n), gcd(primorial_p1[1], publickey.n)
                if 1 < g0 < publickey.n:
                    p = publickey.n // g0
                    q = g0
                    break
                if 1 < g1 < publickey.n:
                    p = publickey.n // g1
                    q = g1
                    break
                pc += 1
                if pc == limit:
                    break
            if p is not None and q is not None:
                priv_key = PrivateKey(int(p), int(q), int(publickey.e),
                                      int(publickey.n))
                return (priv_key, None)
            return (None, None)
        except TimeoutError:
            return (None, None)
예제 #9
0
    def attack(self, publickey, cipher=[]):

        if not hasattr(publickey, "p"):
            publickey.p = None
        if not hasattr(publickey, "q"):
            publickey.q = None

        # solve with z3 theorem prover
        with timeout(self.timeout):
            try:
                try:
                    euler_res = self.z3_solve(publickey.n, timeout_amount)
                except:
                    self.logger.warning("[!] z3: Internal Error.")
                    return (None, None)

                if euler_res and len(euler_res) > 1:
                    publickey.p, publickey.q = euler_res

                if publickey.q is not None:
                    priv_key = PrivateKey(
                        int(publickey.p),
                        int(publickey.q),
                        int(publickey.e),
                        int(publickey.n),
                    )
                    return (priv_key, None)
            except TimeoutError:
                return (None, None)

        return (None, None)
예제 #10
0
    def attack(self, publickey, cipher=[], progress=True):

        if not hasattr(publickey, "p"):
            publickey.p = None
        if not hasattr(publickey, "q"):
            publickey.q = None

        # solve with z3 theorem prover
        with timeout(self.timeout):
            try:
                try:
                    z3_res = self.z3_solve(publickey.n, self.timeout)
                except:
                    self.logger.warning("[!] z3: Internal Error.")
                    return (None, None)

                if z3_res and len(z3_res) > 1:
                    p, q = z3_res
                    publickey.p = p
                    publickey.q = q

                if publickey.q is not None:
                    priv_key = PrivateKey(
                        int(publickey.p),
                        int(publickey.q),
                        int(publickey.e),
                        int(publickey.n),
                    )
                    return (priv_key, None)
                else:
                    return (None, None)
            except TimeoutError:
                return (None, None)

        return (None, None)
예제 #11
0
 def attack(self, publickey, cipher=[]):
     """Run tests against primorial +-1 composites"""
     with timeout(self.timeout):
         try:
             limit = 10000
             prime = 1
             primorial = 1
             p = q = None
             for x in tqdm(range(0, limit)):
                 prime = next_prime(prime)
                 primorial *= prime
                 primorial_p1 = [primorial - 1, primorial + 1]
                 g0, g1 = gcd(primorial_p1[0],
                              publickey.n), gcd(primorial_p1[1],
                                                publickey.n)
                 if 1 < g0 < publickey.n:
                     p = publickey.n // g0
                     q = g0
                     break
                 if 1 < g1 < publickey.n:
                     p = publickey.n // g1
                     q = g1
                     break
             if p is not None and q is not None:
                 priv_key = PrivateKey(int(p), int(q), int(publickey.e),
                                       int(publickey.n))
                 return (priv_key, None)
             return (None, None)
         except TimeoutError:
             return (None, None)
예제 #12
0
 def attack(self, publickey, cipher=[], progress=True):
     """Run tests against mersenne composites"""
     with timeout(self.timeout):
         try:
             p = q = None
             for i in tqdm(range(2, ilog2(publickey.n)), disable=(not progress)):
                 i2 = 2 ** i
                 mersenne = [i2 - 1, i2 + 1]
                 g0, g1 = gcd(mersenne[0], publickey.n), gcd(
                     mersenne[1], publickey.n
                 )
                 if 1 < g0 < publickey.n:
                     p = publickey.n // g0
                     q = g0
                     break
                 if 1 < g1 < publickey.n:
                     p = publickey.n // g1
                     q = g1
                     break
             if p is not None and q is not None:
                 priv_key = PrivateKey(
                     int(p), int(q), int(publickey.e), int(publickey.n)
                 )
                 return (priv_key, None)
             return (None, None)
         except TimeoutError:
             return (None, None)
예제 #13
0
    def attack(self, publickey, cipher=[], progress=True):
        """Same n huge e attack"""
        if not isinstance(publickey, list):
            return (None, None)

        with timeout(self.timeout):
            try:
                if len(set([_.n for _ in publickey])) == 1:
                    n = publickey[0].n

                    e_array = []
                    for k in publickey:
                        e_array.append(k.e)

                    if (cipher is None) or (len(cipher) < 2):
                        self.logger.info(
                            "[-] Lack of ciphertexts, skiping the same_n_huge_e test..."
                        )
                        return (None, None)

                    # e1*s1 + e2*s2 = 1
                    _, s1, s2 = gcdext(e_array[0], e_array[1])

                    # m ≡ c1^s1 * c2*s2 mod n
                    plain = (
                        powmod(int.from_bytes(cipher[0], "big"), s1, n) *
                        powmod(int.from_bytes(cipher[1], "big"), s2, n)) % n

                    return (None, number.long_to_bytes(plain))
            except TimeoutError:
                return (None, None)
        return (None, None)
예제 #14
0
def attack(attack_rsa_obj, publickey, cipher=[]):
    """Run attack with Pollard Rho"""
    if not hasattr(publickey, "p"):
        publickey.p = None
    if not hasattr(publickey, "q"):
        publickey.q = None

    # pollard Rho attack

    with timeout(attack_rsa_obj.args.timeout):
        try:
            try:
                poll_res = pollard_rho(publickey.n)
            except RecursionError:
                print("RecursionError")
                return (None, None)

            if poll_res != None:
                publickey.p = poll_res
                publickey.q = publickey.n // publickey.p

            if publickey.q is not None:
                priv_key = PrivateKey(
                    int(publickey.p),
                    int(publickey.q),
                    int(publickey.e),
                    int(publickey.n),
                )
                return (priv_key, None)
        except TimeoutError:
            return (None, None)
        except TypeError:
            return (None, None)

    return (None, None)
예제 #15
0
 def attack(self, publickey, cipher=[], progress=True):
     """
     Pisano(mersenne) period factorization algorithm optimal for keys sub 70 bits in less than a minute.
     The attack is very similar to londahl's
     """
     Fib = Fibonacci(progress=progress)
     with timeout(self.timeout):
         try:
             B1, B2 = (
                 pow(10, (ilog10(publickey.n) // 2) - 4),
                 0,
             )  # Arbitrary selected bounds, biger b2 is more faster but more failed factorizations.
             try:
                 r = Fib.factorization(publickey.n, B1, B2)
             except OverflowError:
                 r = None
             if r is not None:
                 publickey.p, publickey.q = r
                 priv_key = PrivateKey(
                     int(publickey.p),
                     int(publickey.q),
                     int(publickey.e),
                     int(publickey.n),
                 )
                 return (priv_key, None)
             return (None, None)
         except TimeoutError:
             return (None, None)
     return (None, None)
예제 #16
0
def attack(attack_rsa_obj, publickey, cipher=[]):
    """Run attack with Pollard P1
    """
    if not hasattr(publickey, "p"):
        publickey.p = None
    if not hasattr(publickey, "q"):
        publickey.q = None

    with timeout(attack_rsa_obj.args.timeout):
        try:
            # Pollard P-1 attack
            try:
                poll_res = pollard_P_1(publickey.n)
            except RecursionError:
                print("RecursionError")
                return (None, None)
            if poll_res and len(poll_res) > 1:
                publickey.p, publickey.q = poll_res

            if publickey.q is not None:
                priv_key = PrivateKey(
                    int(publickey.p), int(publickey.q), int(publickey.e), int(publickey.n)
                )
                return (priv_key, None)
        except TimeoutError:
            return (None, None)
    return (None, None)
예제 #17
0
    def attack(self, publickey, cipher=[], progress=True):
        """Run attack with Pollard P1"""
        if not hasattr(publickey, "p"):
            publickey.p = None
        if not hasattr(publickey, "q"):
            publickey.q = None

        with timeout(self.timeout):
            try:
                # Pollard P-1 attack
                try:
                    poll_res = self.pollard_P_1(publickey.n, progress)
                except RecursionError:
                    return (None, None)
                if poll_res and len(poll_res) > 1:
                    publickey.p, publickey.q = poll_res

                if publickey.q is not None:
                    priv_key = PrivateKey(
                        int(publickey.p),
                        int(publickey.q),
                        int(publickey.e),
                        int(publickey.n),
                    )
                    return (priv_key, None)
            except TimeoutError:
                return (None, None)
        return (None, None)
예제 #18
0
    def attack(self, publickey, cipher=[], progress=True):
        """Run attack with Euler method"""
        if not hasattr(publickey, "p"):
            publickey.p = None
        if not hasattr(publickey, "q"):
            publickey.q = None

        # Euler attack
        with timeout(self.timeout):
            try:
                try:
                    if ((publickey.n - 1) % 4 == 0):
                        euler_res = self.euler(publickey.n)
                    else:
                        self.logger.error(
                            "[!] Public key modulus must be congruent 1 mod 4 to work with euler method."
                        )
                        return (None, None)
                except:
                    return (None, None)
                if euler_res and len(euler_res) > 1:
                    publickey.p, publickey.q = euler_res

                if publickey.q is not None:
                    priv_key = PrivateKey(
                        int(publickey.p),
                        int(publickey.q),
                        int(publickey.e),
                        int(publickey.n),
                    )
                    return (priv_key, None)
            except TimeoutError:
                return (None, None)

        return (None, None)
예제 #19
0
 def attack(self, publickey, cipher=[]):
     """Try an attack where the public key has a common factor with the ciphertext - sourcekris"""
     if cipher is not None:
         try:
             with timeout(self.timeout):
                 return self.comfact(cipher, publickey)
         except TimeoutError:
             return (None, None)
     return (None, None)
예제 #20
0
def attack(attack_rsa_obj, publickey, cipher=[]):
    """Try an attack where the public key has a common factor with the ciphertext - sourcekris"""
    timeout_delay = attack_rsa_obj.args.timeout
    if cipher is not None:
        try:
            with timeout(attack_rsa_obj.args.timeout):
                return comfact(cipher, publickey)
        except TimeoutError:
            return (None, None)
    return (None, None)
예제 #21
0
    def attack(self, publickeys, cipher=[]):
        """Hastad attack for low public exponent
        this has found success for e = 3
        """
        if not isinstance(publickeys, list):
            return (None, None)

        if cipher is None or len(cipher) == 0:
            return (None, None)

        with timeout(self.timeout):
            try:
                c = []
                for _ in cipher:
                    c.append(int.from_bytes(_, byteorder="big"))

                n = []
                e = []
                for publickey in publickeys:
                    if publickey.e < 11:
                        n.append(publickey.n)
                        e.append(publickey.e)

                e = set(e)
                if len(e) != 1:
                    return (None, None)
                e = e.pop()
                if e != 3:
                    return (None, None)

                result = self.chinese_remainder(n, c)
                nth = self.find_invpow(result, 3)

                unciphered = []
                unciphered.append(
                    nth.to_bytes((nth.bit_length() + 7) // 8, byteorder="big")
                )

                try:
                    unciphered_ = b""
                    for i in range(0, len(str(nth)), 3):
                        _ = str(nth)[i : i + 3]
                        unciphered_ += bytes([int(_)])
                    unciphered.append(unciphered_)
                except:
                    return (None, None)

            except TimeoutError:
                return (None, None)

        return (None, unciphered)
예제 #22
0
    def attack(self, publickey, cipher=[]):
        """Factors available online?"""

        try:
            wa_enabled = True
            import wolframalpha

            app_id = os.environ.get("WA_API_KEY")
            wa_enabled = app_id != None
        except Exception:
            self.logger.warning(
                "[!] Wolfram Alpha is not enabled, install the lib.")
            wa_enabled = False

        if not wa_enabled:
            self.logger.warning(
                "[!] Wolfram Alpha is not enabled, check if ENV WA_API_KEY is set."
            )
            self.logger.warning(
                "[!] follow: https://products.wolframalpha.com/api/documentation/"
            )
            self.logger.warning("[!] export WA_API_KEY=XXXXXX-XXXXXXXXXX")
            self.wa_client = None
            return (None, None)
        else:
            self.wa_client = wolframalpha.Client(app_id)

        with timeout(self.timeout):
            try:
                factors = self.wa_query_factors(publickey.n)
                self.logger.info("Factors: %s" % str(factors))
                if factors != None and len(factors) > 1:
                    publickey.q = factors[
                        -1]  # Let it be the last prime wich is the bigger one
                    publickey.p = publickey.n // publickey.q
                    priv_key = PrivateKey(
                        p=int(publickey.p),
                        q=int(publickey.q),
                        e=int(publickey.e),
                        n=int(publickey.n),
                    )
                    return (priv_key, None)
                else:
                    return (None, None)
            except Exception as e:
                self.logger.error(
                    "[*] wolfram alpha could not get a factorization.")
                self.logger.debug(str(e))
                return (None, None)
            except TimeoutError:
                return (None, None)
예제 #23
0
def attack(attack_rsa_obj, publickey, cipher=[]):
    """Try an attack where q < 100,000, from BKPCTF2016 - sourcekris
    """
    with timeout(attack_rsa_obj.args.timeout):
        try:
            for prime in primes(100000):
                if publickey.n % prime == 0:
                    publickey.q = prime
                    publickey.p = publickey.n // publickey.q
                    priv_key = PrivateKey(int(publickey.p), int(publickey.q),
                                          int(publickey.e), int(publickey.n))
                    return (priv_key, None)
        except TimeoutError:
            return (None, None)
    return (None, None)
예제 #24
0
def attack(attack_rsa_obj, publickey, cipher=[]):
    """Wiener's attack
    """
    with timeout(attack_rsa_obj.args.timeout):
        try:
            wiener = WienerAttack(publickey.n, publickey.e)
            if wiener.p is not None and wiener.q is not None:
                publickey.p = wiener.p
                publickey.q = wiener.q
                priv_key = PrivateKey(int(publickey.p), int(publickey.q),
                                      int(publickey.e), int(publickey.n))
                return (priv_key, None)
        except TimeoutError:
            return (None, None)

    return (None, None)
예제 #25
0
 def attack(self, publickey, cipher=[], progress=True):
     """Try an attack where q < 100,000, from BKPCTF2016 - sourcekris"""
     with timeout(self.timeout):
         try:
             for prime in self.primes(100000):
                 if publickey.n % prime == 0:
                     publickey.q = prime
                     publickey.p = publickey.n // publickey.q
                     priv_key = PrivateKey(
                         int(publickey.p),
                         int(publickey.q),
                         int(publickey.e),
                         int(publickey.n),
                     )
                     return (priv_key, None)
         except TimeoutError:
             return (None, None)
     return (None, None)
예제 #26
0
    def attack(self, publickey, cipher=[], progress=True):
        """Wiener's attack"""
        with timeout(self.timeout):
            try:
                wiener = WienerAttack(publickey.n, publickey.e, progress)
                if wiener.p is not None and wiener.q is not None:
                    publickey.p = wiener.p
                    publickey.q = wiener.q
                    priv_key = PrivateKey(
                        int(publickey.p),
                        int(publickey.q),
                        int(publickey.e),
                        int(publickey.n),
                    )
                    return (priv_key, None)
            except TimeoutError:
                return (None, None)

        return (None, None)
예제 #27
0
 def attack(self, publickey, cipher=[], progress=True):
     """Run tests against fermat composites"""
     with timeout(self.timeout):
         try:
             limit = 10000
             p = q = None
             for x in tqdm(range(1, limit), disable=(not progress)):
                 f = gcd(fib(x), publickey.n)
                 if 1 < f < publickey.n:
                     p = publickey.n // f
                     q = f
                     break
             if p is not None and q is not None:
                 priv_key = PrivateKey(int(p), int(q), int(publickey.e),
                                       int(publickey.n))
                 return (priv_key, None)
             return (None, None)
         except TimeoutError:
             return (None, None)
예제 #28
0
def attack(attack_rsa_obj, publickey, cipher=[]):
    """Run tests against fermat composites"""
    with timeout(attack_rsa_obj.args.timeout):
        try:
            limit = 10000
            p = q = None
            for x in tqdm(range(1, limit)):
                f = gcd(fib(x), publickey.n)
                if 1 < f < publickey.n:
                    p = publickey.n // f
                    q = f
                    break
            if p is not None and q is not None:
                priv_key = PrivateKey(int(p), int(q), int(publickey.e),
                                      int(publickey.n))
                return (priv_key, None)
            return (None, None)
        except TimeoutError:
            return (None, None)
예제 #29
0
    def attack(self, publickey, cipher=[], progress=True):
        """Do nothing, used for multi-key attacks that succeeded so we just print the
        private key without spending any time factoring
        """
        londahl_b = 20000000
        with timeout(self.timeout):
            try:
                factors = self.close_factor(publickey.n, londahl_b, progress)

                if factors is not None:
                    p, q = factors
                    priv_key = PrivateKey(int(p), int(q), int(publickey.e),
                                          int(publickey.n))
                    return (priv_key, None)
                else:
                    return (None, None)
            except TimeoutError:
                return (None, None)
        return (None, None)
예제 #30
0
 def attack(self, publickey, cipher=[], progress=True):
     """System primes in crypto constants"""
     with timeout(self.timeout):
         try:
             primes = load_system_consts()
             for prp in tqdm(primes, disable=(not progress)):
                 g = gcd(publickey.n, prp)
                 if publickey.n > g > 1:
                     publickey.q = g
                     publickey.p = publickey.n // publickey.q
                     priv_key = PrivateKey(
                         int(publickey.p),
                         int(publickey.q),
                         int(publickey.e),
                         int(publickey.n),
                     )
                     return (priv_key, None)
         except TimeoutError:
             return (None, None)
     return (None, None)