Пример #1
0
 def test_gcd_n_phi_n_try_again_q(self):
     with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir):
         PrimeDB().add(0x3f25fbdd02563798a3ee15, 0x3c1e53497fe2626fa6d389,
                       0x3bf7ae07a1892c3881ee69).write()
         result = self._run_x509sak(
             ["genbrokenrsa", "--bitlen", "259", "--gcd-n-phi-n", "-vv"],
             success_return_codes=[1])
         self.assertIn(b"exhausted", result.stderr)
Пример #2
0
 def test_retry_q(self):
     with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir):
         PrimeDB().add(0xd7627ea571293d6bd1dc8d4664bc6ab1).write()
         result = self._run_x509sak([
             "genbrokenrsa", "--bitlen", "256", "-v", "--close-q",
             "--public-exponent", "3", "-vv"
         ])
         self.assertIn(b"retrying", result.stderr)
Пример #3
0
 def test_create_close_q_rsa_key(self):
     with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir):
         PrimeDB().add(0xd7627ea571293d6bd1dc8d4664bc6ab1).write()
         self._run_x509sak(["genbrokenrsa", "--bitlen", "256", "--close-q"])
         key = RSAPrivateKey.read_pemfile("broken_rsa.key")[0]
         self.assertEqual(key.n.bit_length(), 256)
         self.assertEqual(key.p, 0xd7627ea571293d6bd1dc8d4664bc6ab1)
         self.assertEqual(key.q, key.p + 94)
         key.check_integrity()
Пример #4
0
 def test_automatic_e(self):
     with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir):
         PrimeDB().add(0xd06bda6bd4031ec96cb8023fd89fc9bb,
                       0xd578117dc5a445697a7c6e04e09c801f).write()
         self._run_x509sak(["genbrokenrsa", "--bitlen", "256", "-e", "-1"])
         key = RSAPrivateKey.read_pemfile("broken_rsa.key")[0]
         self.assertEqual(key.n.bit_length(), 256)
         self.assertEqual(key.p, 0xd06bda6bd4031ec96cb8023fd89fc9bb)
         self.assertEqual(key.q, 0xd578117dc5a445697a7c6e04e09c801f)
         self.assertNotEqual(key.e, 0x10001)
         key.check_integrity()
Пример #5
0
    def __init__(self, cmdname, args):
        BaseAction.__init__(self, cmdname, args)

        if (not self._args.force) and os.path.exists(self._args.outfile):
            raise UnfulfilledPrerequisitesException(
                "File/directory %s already exists. Remove it first or use --force."
                % (self._args.outfile))

        self._prime_db = PrimeDB(self._args.prime_db,
                                 generator_program=self._args.generator)
        q = self._prime_db.get(args.N_bits)
        if self._args.verbose >= 1:
            print("Chosen q = 0x%x" % (q))

        bit_diff = args.L_bits - q.bit_length()
        while True:
            r = NumberTheory.randint_bits(bit_diff, two_msb_set=True)
            p = (r * q) + 1
            if NumberTheory.is_probable_prime(p):
                break
        if self._args.verbose >= 1:
            print("Chosen p = 0x%x" % (p))

        assert (q.bit_length() == args.N_bits)
        assert (p.bit_length() == args.L_bits)
        assert ((p - 1) % q == 0)

        # Non-verifiable method of generating g, see A.2.1 of FIPS 186-4, pg. 41
        e = (p - 1) // q
        while True:
            h = random.randint(2, p - 2)
            g = pow(h, e, p)
            if g == 1:
                continue
            break

        if self._args.verbose >= 1:
            print("Chosen g = 0x%x" % (g))

        dsa_parameters = DSAParameters.create(p=p, q=q, g=g)
        dsa_parameters.write_pemfile(self._args.outfile)
Пример #6
0
 def test_create_rsa_key(self):
     with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir):
         PrimeDB().add(0xd06bda6bd4031ec96cb8023fd89fc9bb,
                       0xd578117dc5a445697a7c6e04e09c801f).write()
         self._run_x509sak(["genbrokenrsa", "--bitlen", "256"])
         key = RSAPrivateKey.read_pemfile("broken_rsa.key")[0]
         self.assertEqual(key.n.bit_length(), 256)
         self.assertEqual(key.p, 0xd06bda6bd4031ec96cb8023fd89fc9bb)
         self.assertEqual(key.q, 0xd578117dc5a445697a7c6e04e09c801f)
         self.assertEqual(key.e, 0x10001)
         self.assertEqual(
             key.d,
             0x5a360028c4c14b78b770d19ce099e80b0a9b25ab6ae35098ce9e7cc27d08ca19
         )
         key.check_integrity()
Пример #7
0
 def test_carmichael_totient(self):
     with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir):
         PrimeDB().add(0xd06bda6bd4031ec96cb8023fd89fc9bb,
                       0xd578117dc5a445697a7c6e04e09c801f).write()
         self._run_x509sak(
             ["genbrokenrsa", "--bitlen", "256", "--carmichael-totient"])
         key = RSAPrivateKey.read_pemfile("broken_rsa.key")[0]
         self.assertEqual(key.n.bit_length(), 256)
         self.assertEqual(key.p, 0xd06bda6bd4031ec96cb8023fd89fc9bb)
         self.assertEqual(key.q, 0xd578117dc5a445697a7c6e04e09c801f)
         self.assertEqual(key.e, 0x10001)
         self.assertEqual(
             key.d,
             0x3504164f03e88396ab0cbc8200b8d91a19a60e66e09d11d9e69f27802917833
         )
         key.check_integrity()
Пример #8
0
 def test_gcd_n_phi_n(self):
     with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir):
         PrimeDB().add(0x1fd22b50d1e28365855635,
                       0x3af25062dcf148b85084f5).write()
         output = self._run_x509sak(
             ["genbrokenrsa", "--bitlen", "257", "--gcd-n-phi-n",
              "-v"]).stdout
         key = RSAPrivateKey.read_pemfile("broken_rsa.key")[0]
         self.assertEqual(key.n.bit_length(), 257)
         self.assertEqual(key.p, 0x1fd22b50d1e28365855635)
         self.assertEqual(key.q,
                          0xea778f672d05715314fd556a2667dca7743e33da973)
         self.assertEqual((key.q - 1) % (2 * key.p), 0)
         self.assertNotEqual(NumberTheory.gcd(key.n, key.phi_n), 1)
         self.assertEqual(key.e, 0x10001)
         self.assertIn(b"gcd(n, phi(n)) = p", output)
         key.check_integrity()
Пример #9
0
 def test_retry_e(self):
     with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir):
         PrimeDB().add(0xd7627ea571293d6bd1dc8d4664bc6ab1).write()
         # Roughly with p = 0.75 there needs to be at least a retry. The
         # probability that it fails 10 times in a row without there being a
         # bug therefore is roughly one in a million.
         for i in range(10):
             result = self._run_x509sak([
                 "genbrokenrsa", "--bitlen", "256", "-f", "-v", "--close-q",
                 "--public-exponent", "3", "-e", "-1", "-vv"
             ])
             if b"retrying" in result.stderr:
                 break
         else:
             self.fail(
                 "In 10 tries, never was a retry with a different e value chosen. Highly improbable."
             )
Пример #10
0
 def test_verbosity(self):
     with tempfile.TemporaryDirectory() as tempdir, WorkDir(tempdir):
         PrimeDB().add(0xd7627ea571293d6bd1dc8d4664bc6ab1).write()
         output = self._run_x509sak(
             ["genbrokenrsa", "--bitlen", "256", "-v", "--close-q"]).stdout
         self.assertIn(b"p = 0xd7627ea571293d6bd1dc8d4664bc6ab1", output)
Пример #11
0
    def __init__(self, cmdname, args):
        BaseAction.__init__(self, cmdname, args)

        if (not self._args.force) and os.path.exists(self._args.outfile):
            raise UnfulfilledPrerequisitesException(
                "File/directory %s already exists. Remove it first or use --force."
                % (self._args.outfile))

        if not self._args.gcd_n_phi_n:
            self._primetype = "2msb"
            self._p_bitlen = self._args.bitlen // 2
            self._q_bitlen = self._args.bitlen - self._p_bitlen
        else:
            self._primetype = "3msb"
            self._p_bitlen = self._args.bitlen // 3
            self._q_bitlen = self._args.bitlen - (2 * self._p_bitlen) - 1

        if (self._args.close_q) and (self._p_bitlen != self._q_bitlen):
            raise UnfulfilledPrerequisitesException(
                "Generating a close-q keypair with a %d modulus does't work, because p would have to be %d bit and q %d bit. Choose an even modulus bitlength."
                % (self._args.bitlen, self._p_bitlen, self._q_bitlen))

        if self._args.q_stepping < 1:
            raise InvalidInputException(
                "q-stepping value must be greater or equal to 1, was %d." %
                (self._args.q_stepping))

        self._log.debug("Selecting %s primes with p = %d bit and q = %d bit.",
                        self._primetype, self._p_bitlen, self._q_bitlen)

        self._prime_db = PrimeDB(self._args.prime_db,
                                 generator_program=self._args.generator)
        p = None
        q = None
        while True:
            if p is None:
                p = self._prime_db.get(bitlen=self._p_bitlen,
                                       primetype=self._primetype)
                q_generator = self._select_q(p)
            if q is None:
                q = next(q_generator)
            if self._args.gcd_n_phi_n:
                # q = (2 * r * p) + 1
                r = q
                q = 2 * r * p + 1
                if not NumberTheory.is_probable_prime(q):
                    q = None
                    continue

            # Always make p the smaller factor
            if p > q:
                (p, q) = (q, p)

            n = p * q
            if self._args.public_exponent == -1:
                e = random.randint(2, n - 1)
            else:
                e = self._args.public_exponent

            if self._args.carmichael_totient:
                totient = NumberTheory.lcm(p - 1, q - 1)
            else:
                totient = (p - 1) * (q - 1)
            gcd = NumberTheory.gcd(totient, e)
            if self._args.accept_unusable_key or (gcd == 1):
                break
            else:
                # Pair (phi(n), e) wasn't acceptable.
                self._log.debug("gcd(totient, e) was %d, retrying.", gcd)
                if self._args.public_exponent != -1:
                    # Public exponent e is fixed, need to choose another q.
                    if p.bit_length() == q.bit_length():
                        # Can re-use q as next p
                        (p, q) = (q, None)
                        q_generator = self._select_q(p)
                    else:
                        # When they differ in length, need to re-choose both values
                        (p, q) = (None, None)

        rsa_keypair = RSAPrivateKey.create(
            p=p,
            q=q,
            e=e,
            swap_e_d=self._args.switch_e_d,
            valid_only=not self._args.accept_unusable_key,
            carmichael_totient=self._args.carmichael_totient)
        rsa_keypair.write_pemfile(self._args.outfile)
        if self._args.verbose >= 1:
            diff = q - p
            print("Generated %d bit RSA key:" % (rsa_keypair.n.bit_length()))
            print("p = 0x%x" % (rsa_keypair.p))
            if not self._args.gcd_n_phi_n:
                print("q = 0x%x" % (rsa_keypair.q))
            else:
                print("q = 2 * r * p + 1 = 0x%x" % (rsa_keypair.q))
                print("r = 0x%x" % (r))

            print("phi(n) = 0x%x" % (rsa_keypair.phi_n))
            print("lambda(n) = 0x%x" % (rsa_keypair.lambda_n))
            print("phi(n) / lambda(n) = gcd(p - 1, q - 1) = %d" %
                  (rsa_keypair.phi_n // rsa_keypair.lambda_n))
            gcd_n_phin = NumberTheory.gcd(rsa_keypair.n, rsa_keypair.phi_n)
            if gcd_n_phin == rsa_keypair.p:
                print("gcd(n, phi(n)) = p")
            else:
                print("gcd(n, phi(n)) = 0x%x" % (gcd_n_phin))
            if self._args.close_q:
                print("q - p = %d (%d bit)" % (diff, diff.bit_length()))
            print("n = 0x%x" % (rsa_keypair.n))
            print("d = 0x%x" % (rsa_keypair.d))
            print("e = 0x%x" % (rsa_keypair.e))