Merge pull request #1130 from dreid/isolate-openssl-urandom-default

Attempt to better isolate this test by getting the backend name from a subprocess.
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index a38534d..7a65454 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -19,6 +19,9 @@
   :class:`~cryptography.hazmat.backends.interfaces.TraditionalOpenSSLSerializationBackend`
   support to the :doc:`/hazmat/backends/openssl`.
 * Added :class:`~cryptography.hazmat.backends.interfaces.EllipticCurveBackend`.
+* Added :class:`~cryptography.hazmat.primitives.ciphers.modes.ECB` support
+  for :class:`~cryptography.hazmat.primitives.ciphers.algorithms.TripleDES` on
+  :doc:`/hazmat/backends/commoncrypto` and :doc:`/hazmat/backends/openssl`.
 
 0.4 - 2014-05-03
 ~~~~~~~~~~~~~~~~
diff --git a/cryptography/hazmat/backends/commoncrypto/backend.py b/cryptography/hazmat/backends/commoncrypto/backend.py
index 213cbd8..41be11f 100644
--- a/cryptography/hazmat/backends/commoncrypto/backend.py
+++ b/cryptography/hazmat/backends/commoncrypto/backend.py
@@ -178,6 +178,7 @@
             )
         for mode_cls, mode_const in [
             (CBC, self._lib.kCCModeCBC),
+            (ECB, self._lib.kCCModeECB),
             (CFB, self._lib.kCCModeCFB),
             (CFB8, self._lib.kCCModeCFB8),
             (OFB, self._lib.kCCModeOFB),
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index ab3f947..0a7a28b 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -41,6 +41,9 @@
 from cryptography.hazmat.primitives.ciphers.modes import (
     CBC, CFB, CFB8, CTR, ECB, GCM, OFB
 )
+from cryptography.hazmat.primitives.interfaces import (
+    RSAPrivateKeyWithNumbers, RSAPublicKeyWithNumbers
+)
 
 
 _MemoryBIO = collections.namedtuple("_MemoryBIO", ["bio", "char_ptr"])
@@ -181,6 +184,11 @@
                 mode_cls,
                 GetCipherByName("des-ede3-{mode.name}")
             )
+        self.register_cipher_adapter(
+            TripleDES,
+            ECB,
+            GetCipherByName("des-ede3")
+        )
         for mode_cls in [CBC, CFB, OFB, ECB]:
             self.register_cipher_adapter(
                 Blowfish,
@@ -360,64 +368,62 @@
     def generate_rsa_private_key(self, public_exponent, key_size):
         rsa._verify_rsa_parameters(public_exponent, key_size)
 
-        ctx = self._lib.RSA_new()
-        assert ctx != self._ffi.NULL
-        ctx = self._ffi.gc(ctx, self._lib.RSA_free)
+        rsa_cdata = self._lib.RSA_new()
+        assert rsa_cdata != self._ffi.NULL
+        rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free)
 
         bn = self._int_to_bn(public_exponent)
         bn = self._ffi.gc(bn, self._lib.BN_free)
 
         res = self._lib.RSA_generate_key_ex(
-            ctx, key_size, bn, self._ffi.NULL
+            rsa_cdata, key_size, bn, self._ffi.NULL
         )
         assert res == 1
 
-        return self._rsa_cdata_to_private_key(ctx)
+        return _RSAPrivateKey(self, rsa_cdata)
 
     def generate_rsa_parameters_supported(self, public_exponent, key_size):
         return (public_exponent >= 3 and public_exponent & 1 != 0 and
                 key_size >= 512)
 
     def load_rsa_private_numbers(self, numbers):
-        return rsa.RSAPrivateKey(
-            p=numbers.p,
-            q=numbers.q,
-            private_exponent=numbers.d,
-            dmp1=numbers.dmp1,
-            dmq1=numbers.dmq1,
-            iqmp=numbers.iqmp,
-            public_exponent=numbers.public_numbers.e,
-            modulus=numbers.public_numbers.n
+        rsa._check_private_key_components(
+            numbers.p,
+            numbers.q,
+            numbers.d,
+            numbers.dmp1,
+            numbers.dmq1,
+            numbers.iqmp,
+            numbers.public_numbers.e,
+            numbers.public_numbers.n
         )
+        rsa_cdata = self._lib.RSA_new()
+        assert rsa_cdata != self._ffi.NULL
+        rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free)
+        rsa_cdata.p = self._int_to_bn(numbers.p)
+        rsa_cdata.q = self._int_to_bn(numbers.q)
+        rsa_cdata.d = self._int_to_bn(numbers.d)
+        rsa_cdata.dmp1 = self._int_to_bn(numbers.dmp1)
+        rsa_cdata.dmq1 = self._int_to_bn(numbers.dmq1)
+        rsa_cdata.iqmp = self._int_to_bn(numbers.iqmp)
+        rsa_cdata.e = self._int_to_bn(numbers.public_numbers.e)
+        rsa_cdata.n = self._int_to_bn(numbers.public_numbers.n)
+        res = self._lib.RSA_blinding_on(rsa_cdata, self._ffi.NULL)
+        assert res == 1
+
+        return _RSAPrivateKey(self, rsa_cdata)
 
     def load_rsa_public_numbers(self, numbers):
-        return rsa.RSAPublicKey(
-            public_exponent=numbers.e,
-            modulus=numbers.n
-        )
-
-    def _new_evp_pkey(self):
-        evp_pkey = self._lib.EVP_PKEY_new()
-        assert evp_pkey != self._ffi.NULL
-        return self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free)
-
-    def _rsa_private_key_to_evp_pkey(self, private_key):
-        evp_pkey = self._new_evp_pkey()
-        rsa_cdata = self._rsa_cdata_from_private_key(private_key)
-
-        res = self._lib.EVP_PKEY_assign_RSA(evp_pkey, rsa_cdata)
+        rsa._check_public_key_components(numbers.e, numbers.n)
+        rsa_cdata = self._lib.RSA_new()
+        assert rsa_cdata != self._ffi.NULL
+        rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free)
+        rsa_cdata.e = self._int_to_bn(numbers.e)
+        rsa_cdata.n = self._int_to_bn(numbers.n)
+        res = self._lib.RSA_blinding_on(rsa_cdata, self._ffi.NULL)
         assert res == 1
 
-        return evp_pkey
-
-    def _rsa_public_key_to_evp_pkey(self, public_key):
-        evp_pkey = self._new_evp_pkey()
-        rsa_cdata = self._rsa_cdata_from_public_key(public_key)
-
-        res = self._lib.EVP_PKEY_assign_RSA(evp_pkey, rsa_cdata)
-        assert res == 1
-
-        return evp_pkey
+        return _RSAPublicKey(self, rsa_cdata)
 
     def _bytes_to_bio(self, data):
         """
@@ -446,7 +452,7 @@
             rsa_cdata = self._lib.EVP_PKEY_get1_RSA(evp_pkey)
             assert rsa_cdata != self._ffi.NULL
             rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free)
-            return self._rsa_cdata_to_private_key(rsa_cdata)
+            return _RSAPrivateKey(self, rsa_cdata)
         elif type == self._lib.EVP_PKEY_DSA:
             dsa_cdata = self._lib.EVP_PKEY_get1_DSA(evp_pkey)
             assert dsa_cdata != self._ffi.NULL
@@ -464,18 +470,6 @@
             y=self._bn_to_int(cdata.pub_key)
         )
 
-    def _rsa_cdata_to_private_key(self, cdata):
-        return rsa.RSAPrivateKey(
-            p=self._bn_to_int(cdata.p),
-            q=self._bn_to_int(cdata.q),
-            dmp1=self._bn_to_int(cdata.dmp1),
-            dmq1=self._bn_to_int(cdata.dmq1),
-            iqmp=self._bn_to_int(cdata.iqmp),
-            private_exponent=self._bn_to_int(cdata.d),
-            public_exponent=self._bn_to_int(cdata.e),
-            modulus=self._bn_to_int(cdata.n),
-        )
-
     def _pem_password_cb(self, password):
         """
         Generate a pem_password_cb function pointer that copied the password to
@@ -539,11 +533,17 @@
         return ctx
 
     def create_rsa_signature_ctx(self, private_key, padding, algorithm):
-        return _RSASignatureContext(self, private_key, padding, algorithm)
+        rsa_cdata = self._rsa_cdata_from_private_key(private_key)
+        rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free)
+        key = _RSAPrivateKey(self, rsa_cdata)
+        return _RSASignatureContext(self, key, padding, algorithm)
 
     def create_rsa_verification_ctx(self, public_key, signature, padding,
                                     algorithm):
-        return _RSAVerificationContext(self, public_key, signature, padding,
+        rsa_cdata = self._rsa_cdata_from_public_key(public_key)
+        rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free)
+        key = _RSAPublicKey(self, rsa_cdata)
+        return _RSAVerificationContext(self, key, signature, padding,
                                        algorithm)
 
     def mgf1_hash_supported(self, algorithm):
@@ -654,14 +654,16 @@
             return True
 
     def decrypt_rsa(self, private_key, ciphertext, padding):
-        key_size_bytes = int(math.ceil(private_key.key_size / 8.0))
-        if key_size_bytes != len(ciphertext):
-            raise ValueError("Ciphertext length must be equal to key size.")
-
-        return self._enc_dec_rsa(private_key, ciphertext, padding)
+        rsa_cdata = self._rsa_cdata_from_private_key(private_key)
+        rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free)
+        key = _RSAPrivateKey(self, rsa_cdata)
+        return key.decrypt(ciphertext, padding)
 
     def encrypt_rsa(self, public_key, plaintext, padding):
-        return self._enc_dec_rsa(public_key, plaintext, padding)
+        rsa_cdata = self._rsa_cdata_from_public_key(public_key)
+        rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free)
+        key = _RSAPublicKey(self, rsa_cdata)
+        return key.encrypt(plaintext, padding)
 
     def _enc_dec_rsa(self, key, data, padding):
         if isinstance(padding, PKCS1v15):
@@ -703,14 +705,14 @@
             return self._enc_dec_rsa_098(key, data, padding_enum)
 
     def _enc_dec_rsa_pkey_ctx(self, key, data, padding_enum):
-        if isinstance(key, rsa.RSAPublicKey):
+        evp_pkey = key._evp_pkey
+
+        if isinstance(key, _RSAPublicKey):
             init = self._lib.EVP_PKEY_encrypt_init
             crypt = self._lib.Cryptography_EVP_PKEY_encrypt
-            evp_pkey = self._rsa_public_key_to_evp_pkey(key)
         else:
             init = self._lib.EVP_PKEY_decrypt_init
             crypt = self._lib.Cryptography_EVP_PKEY_decrypt
-            evp_pkey = self._rsa_private_key_to_evp_pkey(key)
 
         pkey_ctx = self._lib.EVP_PKEY_CTX_new(
             evp_pkey, self._ffi.NULL
@@ -739,14 +741,13 @@
         return self._ffi.buffer(buf)[:outlen[0]]
 
     def _enc_dec_rsa_098(self, key, data, padding_enum):
-        if isinstance(key, rsa.RSAPublicKey):
+        rsa_cdata = key._rsa_cdata
+
+        if isinstance(key, _RSAPublicKey):
             crypt = self._lib.RSA_public_encrypt
-            rsa_cdata = self._rsa_cdata_from_public_key(key)
         else:
             crypt = self._lib.RSA_private_decrypt
-            rsa_cdata = self._rsa_cdata_from_private_key(key)
 
-        rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free)
         key_size = self._lib.RSA_size(rsa_cdata)
         assert key_size > 0
         buf = self._ffi.new("unsigned char[]", key_size)
@@ -766,7 +767,7 @@
         errors = self._consume_errors()
         assert errors
         assert errors[0].lib == self._lib.ERR_LIB_RSA
-        if isinstance(key, rsa.RSAPublicKey):
+        if isinstance(key, _RSAPublicKey):
             assert (errors[0].reason ==
                     self._lib.RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE)
             raise ValueError(
@@ -1468,6 +1469,10 @@
             raise TypeError(
                 "Expected provider of interfaces.AsymmetricPadding.")
 
+        self._pkey_size = self._backend._lib.EVP_PKEY_size(
+            self._private_key._evp_pkey
+        )
+
         if isinstance(padding, PKCS1v15):
             if self._backend._lib.Cryptography_HAS_PKEY_CTX:
                 self._finalize_method = self._finalize_pkey_ctx
@@ -1483,8 +1488,8 @@
 
             # Size of key in bytes - 2 is the maximum
             # PSS signature length (salt length is checked later)
-            key_size_bytes = int(math.ceil(private_key.key_size / 8.0))
-            if key_size_bytes - algorithm.digest_size - 2 < 0:
+            assert self._pkey_size > 0
+            if self._pkey_size - algorithm.digest_size - 2 < 0:
                 raise ValueError("Digest too large for key size. Use a larger "
                                  "key.")
 
@@ -1514,20 +1519,15 @@
         self._hash_ctx.update(data)
 
     def finalize(self):
-        evp_pkey = self._backend._rsa_private_key_to_evp_pkey(
-            self._private_key)
-
         evp_md = self._backend._lib.EVP_get_digestbyname(
             self._algorithm.name.encode("ascii"))
         assert evp_md != self._backend._ffi.NULL
-        pkey_size = self._backend._lib.EVP_PKEY_size(evp_pkey)
-        assert pkey_size > 0
 
-        return self._finalize_method(evp_pkey, pkey_size, evp_md)
+        return self._finalize_method(evp_md)
 
-    def _finalize_pkey_ctx(self, evp_pkey, pkey_size, evp_md):
+    def _finalize_pkey_ctx(self, evp_md):
         pkey_ctx = self._backend._lib.EVP_PKEY_CTX_new(
-            evp_pkey, self._backend._ffi.NULL
+            self._private_key._evp_pkey, self._backend._ffi.NULL
         )
         assert pkey_ctx != self._backend._ffi.NULL
         pkey_ctx = self._backend._ffi.gc(pkey_ctx,
@@ -1590,17 +1590,17 @@
 
         return self._backend._ffi.buffer(buf)[:]
 
-    def _finalize_pkcs1(self, evp_pkey, pkey_size, evp_md):
+    def _finalize_pkcs1(self, evp_md):
         if self._hash_ctx._ctx is None:
             raise AlreadyFinalized("Context has already been finalized.")
 
-        sig_buf = self._backend._ffi.new("char[]", pkey_size)
+        sig_buf = self._backend._ffi.new("char[]", self._pkey_size)
         sig_len = self._backend._ffi.new("unsigned int *")
         res = self._backend._lib.EVP_SignFinal(
             self._hash_ctx._ctx._ctx,
             sig_buf,
             sig_len,
-            evp_pkey
+            self._private_key._evp_pkey
         )
         self._hash_ctx.finalize()
         if res == 0:
@@ -1613,15 +1613,11 @@
 
         return self._backend._ffi.buffer(sig_buf)[:sig_len[0]]
 
-    def _finalize_pss(self, evp_pkey, pkey_size, evp_md):
+    def _finalize_pss(self, evp_md):
         data_to_sign = self._hash_ctx.finalize()
-        padded = self._backend._ffi.new("unsigned char[]", pkey_size)
-        rsa_cdata = self._backend._lib.EVP_PKEY_get1_RSA(evp_pkey)
-        assert rsa_cdata != self._backend._ffi.NULL
-        rsa_cdata = self._backend._ffi.gc(rsa_cdata,
-                                          self._backend._lib.RSA_free)
+        padded = self._backend._ffi.new("unsigned char[]", self._pkey_size)
         res = self._backend._lib.RSA_padding_add_PKCS1_PSS(
-            rsa_cdata,
+            self._private_key._rsa_cdata,
             padded,
             data_to_sign,
             evp_md,
@@ -1639,12 +1635,12 @@
             raise ValueError("Salt length too long for key size. Try using "
                              "MAX_LENGTH instead.")
 
-        sig_buf = self._backend._ffi.new("char[]", pkey_size)
+        sig_buf = self._backend._ffi.new("char[]", self._pkey_size)
         sig_len = self._backend._lib.RSA_private_encrypt(
-            pkey_size,
+            self._pkey_size,
             padded,
             sig_buf,
-            rsa_cdata,
+            self._private_key._rsa_cdata,
             self._backend._lib.RSA_NO_PADDING
         )
         assert sig_len != -1
@@ -1662,6 +1658,10 @@
             raise TypeError(
                 "Expected provider of interfaces.AsymmetricPadding.")
 
+        self._pkey_size = self._backend._lib.EVP_PKEY_size(
+            self._public_key._evp_pkey
+        )
+
         if isinstance(padding, PKCS1v15):
             if self._backend._lib.Cryptography_HAS_PKEY_CTX:
                 self._verify_method = self._verify_pkey_ctx
@@ -1677,8 +1677,8 @@
 
             # Size of key in bytes - 2 is the maximum
             # PSS signature length (salt length is checked later)
-            key_size_bytes = int(math.ceil(public_key.key_size / 8.0))
-            if key_size_bytes - algorithm.digest_size - 2 < 0:
+            assert self._pkey_size > 0
+            if self._pkey_size - algorithm.digest_size - 2 < 0:
                 raise ValueError(
                     "Digest too large for key size. Check that you have the "
                     "correct key and digest algorithm."
@@ -1710,18 +1710,15 @@
         self._hash_ctx.update(data)
 
     def verify(self):
-        evp_pkey = self._backend._rsa_public_key_to_evp_pkey(
-            self._public_key)
-
         evp_md = self._backend._lib.EVP_get_digestbyname(
             self._algorithm.name.encode("ascii"))
         assert evp_md != self._backend._ffi.NULL
 
-        self._verify_method(evp_pkey, evp_md)
+        self._verify_method(evp_md)
 
-    def _verify_pkey_ctx(self, evp_pkey, evp_md):
+    def _verify_pkey_ctx(self, evp_md):
         pkey_ctx = self._backend._lib.EVP_PKEY_CTX_new(
-            evp_pkey, self._backend._ffi.NULL
+            self._public_key._evp_pkey, self._backend._ffi.NULL
         )
         assert pkey_ctx != self._backend._ffi.NULL
         pkey_ctx = self._backend._ffi.gc(pkey_ctx,
@@ -1772,7 +1769,7 @@
             assert errors
             raise InvalidSignature
 
-    def _verify_pkcs1(self, evp_pkey, evp_md):
+    def _verify_pkcs1(self, evp_md):
         if self._hash_ctx._ctx is None:
             raise AlreadyFinalized("Context has already been finalized.")
 
@@ -1780,7 +1777,7 @@
             self._hash_ctx._ctx._ctx,
             self._signature,
             len(self._signature),
-            evp_pkey
+            self._public_key._evp_pkey
         )
         self._hash_ctx.finalize()
         # The previous call can return negative numbers in the event of an
@@ -1792,29 +1789,23 @@
             assert errors
             raise InvalidSignature
 
-    def _verify_pss(self, evp_pkey, evp_md):
-        pkey_size = self._backend._lib.EVP_PKEY_size(evp_pkey)
-        assert pkey_size > 0
-        rsa_cdata = self._backend._lib.EVP_PKEY_get1_RSA(evp_pkey)
-        assert rsa_cdata != self._backend._ffi.NULL
-        rsa_cdata = self._backend._ffi.gc(rsa_cdata,
-                                          self._backend._lib.RSA_free)
-        buf = self._backend._ffi.new("unsigned char[]", pkey_size)
+    def _verify_pss(self, evp_md):
+        buf = self._backend._ffi.new("unsigned char[]", self._pkey_size)
         res = self._backend._lib.RSA_public_decrypt(
             len(self._signature),
             self._signature,
             buf,
-            rsa_cdata,
+            self._public_key._rsa_cdata,
             self._backend._lib.RSA_NO_PADDING
         )
-        if res != pkey_size:
+        if res != self._pkey_size:
             errors = self._backend._consume_errors()
             assert errors
             raise InvalidSignature
 
         data_to_verify = self._hash_ctx.finalize()
         res = self._backend._lib.RSA_verify_PKCS1_PSS(
-            rsa_cdata,
+            self._public_key._rsa_cdata,
             data_to_verify,
             evp_md,
             buf,
@@ -2110,4 +2101,88 @@
                 _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM)
 
 
+@utils.register_interface(RSAPrivateKeyWithNumbers)
+class _RSAPrivateKey(object):
+    def __init__(self, backend, rsa_cdata):
+        self._backend = backend
+        self._rsa_cdata = rsa_cdata
+
+        evp_pkey = self._backend._lib.EVP_PKEY_new()
+        assert evp_pkey != self._backend._ffi.NULL
+        evp_pkey = self._backend._ffi.gc(
+            evp_pkey, self._backend._lib.EVP_PKEY_free
+        )
+        res = self._backend._lib.EVP_PKEY_set1_RSA(evp_pkey, rsa_cdata)
+        assert res == 1
+        self._evp_pkey = evp_pkey
+
+        self.key_size = self._backend._lib.BN_num_bits(self._rsa_cdata.n)
+
+    def signer(self, padding, algorithm):
+        return _RSASignatureContext(self._backend, self, padding, algorithm)
+
+    def decrypt(self, ciphertext, padding):
+        key_size_bytes = int(math.ceil(self.key_size / 8.0))
+        if key_size_bytes != len(ciphertext):
+            raise ValueError("Ciphertext length must be equal to key size.")
+
+        return self._backend._enc_dec_rsa(self, ciphertext, padding)
+
+    def public_key(self):
+        ctx = self._backend._lib.RSA_new()
+        assert ctx != self._backend._ffi.NULL
+        ctx = self._backend._ffi.gc(ctx, self._backend._lib.RSA_free)
+        ctx.e = self._backend._lib.BN_dup(self._rsa_cdata.e)
+        ctx.n = self._backend._lib.BN_dup(self._rsa_cdata.n)
+        res = self._backend._lib.RSA_blinding_on(ctx, self._backend._ffi.NULL)
+        assert res == 1
+        return _RSAPublicKey(self._backend, ctx)
+
+    def private_numbers(self):
+        return rsa.RSAPrivateNumbers(
+            p=self._backend._bn_to_int(self._rsa_cdata.p),
+            q=self._backend._bn_to_int(self._rsa_cdata.q),
+            d=self._backend._bn_to_int(self._rsa_cdata.d),
+            dmp1=self._backend._bn_to_int(self._rsa_cdata.dmp1),
+            dmq1=self._backend._bn_to_int(self._rsa_cdata.dmq1),
+            iqmp=self._backend._bn_to_int(self._rsa_cdata.iqmp),
+            public_numbers=rsa.RSAPublicNumbers(
+                e=self._backend._bn_to_int(self._rsa_cdata.e),
+                n=self._backend._bn_to_int(self._rsa_cdata.n),
+            )
+        )
+
+
+@utils.register_interface(RSAPublicKeyWithNumbers)
+class _RSAPublicKey(object):
+    def __init__(self, backend, rsa_cdata):
+        self._backend = backend
+        self._rsa_cdata = rsa_cdata
+
+        evp_pkey = self._backend._lib.EVP_PKEY_new()
+        assert evp_pkey != self._backend._ffi.NULL
+        evp_pkey = self._backend._ffi.gc(
+            evp_pkey, self._backend._lib.EVP_PKEY_free
+        )
+        res = self._backend._lib.EVP_PKEY_set1_RSA(evp_pkey, rsa_cdata)
+        assert res == 1
+        self._evp_pkey = evp_pkey
+
+        self.key_size = self._backend._lib.BN_num_bits(self._rsa_cdata.n)
+
+    def verifier(self, signature, padding, algorithm):
+        return _RSAVerificationContext(
+            self._backend, self, signature, padding, algorithm
+        )
+
+    def encrypt(self, plaintext, padding):
+        return self._backend._enc_dec_rsa(self, plaintext, padding)
+
+    def public_numbers(self):
+        return rsa.RSAPublicNumbers(
+            e=self._backend._bn_to_int(self._rsa_cdata.e),
+            n=self._backend._bn_to_int(self._rsa_cdata.n),
+        )
+
+
 backend = Backend()
diff --git a/cryptography/hazmat/primitives/asymmetric/rsa.py b/cryptography/hazmat/primitives/asymmetric/rsa.py
index be7edad..18ca0db 100644
--- a/cryptography/hazmat/primitives/asymmetric/rsa.py
+++ b/cryptography/hazmat/primitives/asymmetric/rsa.py
@@ -220,7 +220,18 @@
             )
 
         _verify_rsa_parameters(public_exponent, key_size)
-        return backend.generate_rsa_private_key(public_exponent, key_size)
+        key = backend.generate_rsa_private_key(public_exponent, key_size)
+        private_numbers = key.private_numbers()
+        return RSAPrivateKey(
+            p=private_numbers.p,
+            q=private_numbers.q,
+            dmp1=private_numbers.dmp1,
+            dmq1=private_numbers.dmq1,
+            iqmp=private_numbers.iqmp,
+            private_exponent=private_numbers.d,
+            public_exponent=private_numbers.public_numbers.e,
+            modulus=private_numbers.public_numbers.n
+        )
 
     def signer(self, padding, algorithm, backend):
         if not isinstance(backend, RSABackend):
diff --git a/tests/hazmat/primitives/test_3des.py b/tests/hazmat/primitives/test_3des.py
index b9354f0..6566038 100644
--- a/tests/hazmat/primitives/test_3des.py
+++ b/tests/hazmat/primitives/test_3des.py
@@ -174,3 +174,40 @@
         ),
         lambda iv, **kwargs: modes.CFB8(binascii.unhexlify(iv)),
     )
+
+
+@pytest.mark.supported(
+    only_if=lambda backend: backend.cipher_supported(
+        algorithms.TripleDES("\x00" * 8), modes.ECB()
+    ),
+    skip_message="Does not support TripleDES ECB",
+)
+@pytest.mark.cipher
+class TestTripleDESModeECB(object):
+    test_KAT = generate_encrypt_test(
+        load_nist_vectors,
+        os.path.join("ciphers", "3DES", "ECB"),
+        [
+            "TECBinvperm.rsp",
+            "TECBpermop.rsp",
+            "TECBsubtab.rsp",
+            "TECBvarkey.rsp",
+            "TECBvartext.rsp",
+        ],
+        lambda keys, **kwargs: algorithms.TripleDES(binascii.unhexlify(keys)),
+        lambda **kwargs: modes.ECB(),
+    )
+
+    test_MMT = generate_encrypt_test(
+        load_nist_vectors,
+        os.path.join("ciphers", "3DES", "ECB"),
+        [
+            "TECBMMT1.rsp",
+            "TECBMMT2.rsp",
+            "TECBMMT3.rsp",
+        ],
+        lambda key1, key2, key3, **kwargs: algorithms.TripleDES(
+            binascii.unhexlify(key1 + key2 + key3)
+        ),
+        lambda **kwargs: modes.ECB(),
+    )
diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py
index 8f10fb1..ffaaf58 100644
--- a/tests/hazmat/primitives/test_rsa.py
+++ b/tests/hazmat/primitives/test_rsa.py
@@ -38,7 +38,7 @@
     RSA_KEY_768,
 )
 from .utils import (
-    _check_rsa_private_key, generate_rsa_verification_test
+    _check_rsa_private_numbers, generate_rsa_verification_test
 )
 from ...utils import (
     load_pkcs1_vectors, load_rsa_nist_vectors, load_vectors_from_file,
@@ -98,13 +98,13 @@
     )
     def test_generate_rsa_keys(self, backend, public_exponent, key_size):
         skey = rsa.generate_private_key(public_exponent, key_size, backend)
-        _check_rsa_private_key(skey)
         assert skey.key_size == key_size
-        assert skey.public_exponent == public_exponent
+
+        if isinstance(skey, interfaces.RSAPrivateKeyWithNumbers):
+            _check_rsa_private_numbers(skey.private_numbers())
 
     def test_generate_rsa_key_class_method(self, backend):
         skey = rsa.RSAPrivateKey.generate(65537, 512, backend)
-        _check_rsa_private_key(skey)
         assert skey.key_size == 512
         assert skey.public_exponent == 65537
 
@@ -141,43 +141,31 @@
     def test_load_pss_vect_example_keys(self, pkcs1_example):
         secret, public = pkcs1_example
 
-        skey = rsa.RSAPrivateKey(
+        private_num = rsa.RSAPrivateNumbers(
             p=secret["p"],
             q=secret["q"],
-            private_exponent=secret["private_exponent"],
+            d=secret["private_exponent"],
             dmp1=secret["dmp1"],
             dmq1=secret["dmq1"],
             iqmp=secret["iqmp"],
-            public_exponent=secret["public_exponent"],
-            modulus=secret["modulus"]
+            public_numbers=rsa.RSAPublicNumbers(
+                e=secret["public_exponent"],
+                n=secret["modulus"]
+            )
         )
-        assert skey
-        _check_rsa_private_key(skey)
+        _check_rsa_private_numbers(private_num)
 
-        pkey = rsa.RSAPublicKey(
-            public_exponent=public["public_exponent"],
-            modulus=public["modulus"]
+        public_num = rsa.RSAPublicNumbers(
+            e=public["public_exponent"],
+            n=public["modulus"]
         )
-        assert pkey
+        assert public_num
 
-        pkey2 = skey.public_key()
-        assert pkey2
+        public_num2 = private_num.public_numbers
+        assert public_num2
 
-        assert skey.modulus == pkey.modulus
-        assert skey.modulus == skey.n
-        assert skey.public_exponent == pkey.public_exponent
-        assert skey.public_exponent == skey.e
-        assert skey.private_exponent == skey.d
-
-        assert pkey.modulus
-        assert pkey.modulus == pkey2.modulus
-        assert pkey.modulus == pkey.n
-        assert pkey.public_exponent == pkey2.public_exponent
-        assert pkey.public_exponent == pkey.e
-
-        assert skey.key_size
-        assert skey.key_size == pkey.key_size
-        assert skey.key_size == pkey2.key_size
+        assert public_num.n == public_num2.n
+        assert public_num.e == public_num2.e
 
     def test_invalid_private_key_argument_types(self):
         with pytest.raises(TypeError):
@@ -504,8 +492,7 @@
                     salt_length=padding.MGF1.MAX_LENGTH
                 )
             ),
-            hashes.SHA1(),
-            backend
+            hashes.SHA1()
         )
         signer.update(b"so deprecated")
         signature = signer.finalize()
@@ -520,8 +507,7 @@
                     salt_length=padding.MGF1.MAX_LENGTH
                 )
             ),
-            hashes.SHA1(),
-            backend
+            hashes.SHA1()
         )
         verifier.update(b"so deprecated")
         verifier.verify()
@@ -546,19 +532,10 @@
             mgf=padding.MGF1(hash_alg),
             salt_length=padding.PSS.MAX_LENGTH
         )
-        signer = private_key.signer(
-            pss,
-            hash_alg,
-            backend
-        )
+        signer = private_key.signer(pss, hash_alg)
         signer.update(b"testing signature")
         signature = signer.finalize()
-        verifier = public_key.verifier(
-            signature,
-            pss,
-            hash_alg,
-            backend
-        )
+        verifier = public_key.verifier(signature, pss, hash_alg)
         verifier.update(b"testing signature")
         verifier.verify()
 
@@ -581,8 +558,7 @@
                 mgf=padding.MGF1(hashes.SHA1()),
                 salt_length=padding.PSS.MAX_LENGTH
             ),
-            hashes.SHA512(),
-            backend
+            hashes.SHA512()
         )
         signer.update(b"no failure")
         signer.finalize()
@@ -608,8 +584,7 @@
                     mgf=padding.MGF1(hashes.SHA1()),
                     salt_length=padding.PSS.MAX_LENGTH
                 ),
-                hashes.SHA512(),
-                backend
+                hashes.SHA512()
             )
 
     @pytest.mark.supported(
@@ -628,8 +603,7 @@
                 mgf=padding.MGF1(hashes.SHA1()),
                 salt_length=1000000
             ),
-            hashes.SHA1(),
-            backend
+            hashes.SHA1()
         )
         signer.update(b"failure coming")
         with pytest.raises(ValueError):
@@ -643,7 +617,7 @@
     )
     def test_use_after_finalize(self, backend):
         private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
-        signer = private_key.signer(padding.PKCS1v15(), hashes.SHA1(), backend)
+        signer = private_key.signer(padding.PKCS1v15(), hashes.SHA1())
         signer.update(b"sign me")
         signer.finalize()
         with pytest.raises(AlreadyFinalized):
@@ -654,16 +628,25 @@
     def test_unsupported_padding(self, backend):
         private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING):
-            private_key.signer(DummyPadding(), hashes.SHA1(), backend)
+            private_key.signer(DummyPadding(), hashes.SHA1())
 
     def test_padding_incorrect_type(self, backend):
         private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
         with pytest.raises(TypeError):
-            private_key.signer("notpadding", hashes.SHA1(), backend)
+            private_key.signer("notpadding", hashes.SHA1())
 
     def test_rsa_signer_invalid_backend(self, backend):
         pretend_backend = object()
-        private_key = load_rsa_private_numbers(RSA_KEY_2048, backend)
+        private_key = rsa.RSAPrivateKey(
+            p=RSA_KEY_512.p,
+            q=RSA_KEY_512.q,
+            private_exponent=RSA_KEY_512.d,
+            dmp1=RSA_KEY_512.dmp1,
+            dmq1=RSA_KEY_512.dmq1,
+            iqmp=RSA_KEY_512.iqmp,
+            public_exponent=RSA_KEY_512.public_numbers.e,
+            modulus=RSA_KEY_512.public_numbers.n
+        )
 
         with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE):
             private_key.signer(
@@ -678,8 +661,7 @@
     def test_unsupported_pss_mgf(self, backend):
         private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_MGF):
-            private_key.signer(padding.PSS(mgf=DummyMGF()), hashes.SHA1(),
-                               backend)
+            private_key.signer(padding.PSS(mgf=DummyMGF()), hashes.SHA1())
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
@@ -691,8 +673,7 @@
         private_key = load_rsa_private_numbers(RSA_KEY_599, backend)
         signer = private_key.signer(
             padding.PKCS1v15(),
-            hashes.SHA512(),
-            backend
+            hashes.SHA512()
         )
         signer.update(b"failure coming")
         with pytest.raises(ValueError):
@@ -708,8 +689,7 @@
         private_key = load_rsa_private_numbers(RSA_KEY_745, backend)
         signer = private_key.signer(
             padding.PKCS1v15(),
-            hashes.SHA512(),
-            backend
+            hashes.SHA512()
         )
         signer.update(b"no failure")
         signer.finalize()
@@ -755,14 +735,13 @@
     def test_invalid_pkcs1v15_signature_wrong_data(self, backend):
         private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
         public_key = private_key.public_key()
-        signer = private_key.signer(padding.PKCS1v15(), hashes.SHA1(), backend)
+        signer = private_key.signer(padding.PKCS1v15(), hashes.SHA1())
         signer.update(b"sign me")
         signature = signer.finalize()
         verifier = public_key.verifier(
             signature,
             padding.PKCS1v15(),
-            hashes.SHA1(),
-            backend
+            hashes.SHA1()
         )
         verifier.update(b"incorrect data")
         with pytest.raises(InvalidSignature):
@@ -778,14 +757,13 @@
         private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
         private_key2 = load_rsa_private_numbers(RSA_KEY_512_ALT, backend)
         public_key = private_key2.public_key()
-        signer = private_key.signer(padding.PKCS1v15(), hashes.SHA1(), backend)
+        signer = private_key.signer(padding.PKCS1v15(), hashes.SHA1())
         signer.update(b"sign me")
         signature = signer.finalize()
         verifier = public_key.verifier(
             signature,
             padding.PKCS1v15(),
-            hashes.SHA1(),
-            backend
+            hashes.SHA1()
         )
         verifier.update(b"sign me")
         with pytest.raises(InvalidSignature):
@@ -944,15 +922,14 @@
     def test_use_after_finalize(self, backend):
         private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
         public_key = private_key.public_key()
-        signer = private_key.signer(padding.PKCS1v15(), hashes.SHA1(), backend)
+        signer = private_key.signer(padding.PKCS1v15(), hashes.SHA1())
         signer.update(b"sign me")
         signature = signer.finalize()
 
         verifier = public_key.verifier(
             signature,
             padding.PKCS1v15(),
-            hashes.SHA1(),
-            backend
+            hashes.SHA1()
         )
         verifier.update(b"sign me")
         verifier.verify()
@@ -965,17 +942,17 @@
         private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
         public_key = private_key.public_key()
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING):
-            public_key.verifier(b"sig", DummyPadding(), hashes.SHA1(), backend)
+            public_key.verifier(b"sig", DummyPadding(), hashes.SHA1())
 
     def test_padding_incorrect_type(self, backend):
         private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
         public_key = private_key.public_key()
         with pytest.raises(TypeError):
-            public_key.verifier(b"sig", "notpadding", hashes.SHA1(), backend)
+            public_key.verifier(b"sig", "notpadding", hashes.SHA1())
 
     def test_rsa_verifier_invalid_backend(self, backend):
         pretend_backend = object()
-        private_key = rsa.generate_private_key(65537, 2048, backend)
+        private_key = rsa.RSAPrivateKey.generate(65537, 2048, backend)
         public_key = private_key.public_key()
 
         with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE):
@@ -993,7 +970,7 @@
         public_key = private_key.public_key()
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_MGF):
             public_key.verifier(b"sig", padding.PSS(mgf=DummyMGF()),
-                                hashes.SHA1(), backend)
+                                hashes.SHA1())
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
@@ -1022,8 +999,7 @@
                     mgf=padding.MGF1(algorithm=hashes.SHA1()),
                     salt_length=padding.PSS.MAX_LENGTH
                 ),
-                hashes.SHA512(),
-                backend
+                hashes.SHA512()
             )
 
     @pytest.mark.supported(
@@ -1413,7 +1389,7 @@
     def test_unsupported_padding(self, backend):
         private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING):
-            private_key.decrypt(b"0" * 64, DummyPadding(), backend)
+            private_key.decrypt(b"0" * 64, DummyPadding())
 
     @pytest.mark.supported(
         only_if=lambda backend: backend.rsa_padding_supported(
@@ -1426,8 +1402,7 @@
         with pytest.raises(ValueError):
             private_key.decrypt(
                 b"\x00" * 64,
-                padding.PKCS1v15(),
-                backend
+                padding.PKCS1v15()
             )
 
     @pytest.mark.supported(
@@ -1441,8 +1416,7 @@
         with pytest.raises(ValueError):
             private_key.decrypt(
                 b"\x00" * 65,
-                padding.PKCS1v15(),
-                backend
+                padding.PKCS1v15()
             )
 
     @pytest.mark.supported(
@@ -1460,8 +1434,7 @@
         with pytest.raises(ValueError):
             private_key.decrypt(
                 ct,
-                padding.PKCS1v15(),
-                backend
+                padding.PKCS1v15()
             )
 
     def test_rsa_decrypt_invalid_backend(self, backend):
@@ -1525,8 +1498,7 @@
                     mgf=DummyMGF(),
                     algorithm=hashes.SHA1(),
                     label=None
-                ),
-                backend
+                )
             )
 
 
@@ -1558,21 +1530,22 @@
         )
     )
     def test_rsa_encrypt_oaep(self, key_data, pad, backend):
-        private_key = load_rsa_private_numbers(key_data, backend)
+        private_key = rsa.RSAPrivateKey(
+            p=key_data.p,
+            q=key_data.q,
+            private_exponent=key_data.d,
+            dmp1=key_data.dmp1,
+            dmq1=key_data.dmq1,
+            iqmp=key_data.iqmp,
+            public_exponent=key_data.public_numbers.e,
+            modulus=key_data.public_numbers.n
+        )
         pt = b"encrypt me!"
         public_key = private_key.public_key()
-        ct = public_key.encrypt(
-            pt,
-            pad,
-            backend
-        )
+        ct = public_key.encrypt(pt, pad, backend)
         assert ct != pt
         assert len(ct) == math.ceil(public_key.key_size / 8.0)
-        recovered_pt = private_key.decrypt(
-            ct,
-            pad,
-            backend
-        )
+        recovered_pt = private_key.decrypt(ct, pad, backend)
         assert recovered_pt == pt
 
     @pytest.mark.supported(
@@ -1594,18 +1567,10 @@
         private_key = load_rsa_private_numbers(key_data, backend)
         pt = b"encrypt me!"
         public_key = private_key.public_key()
-        ct = public_key.encrypt(
-            pt,
-            pad,
-            backend
-        )
+        ct = public_key.encrypt(pt, pad)
         assert ct != pt
         assert len(ct) == math.ceil(public_key.key_size / 8.0)
-        recovered_pt = private_key.decrypt(
-            ct,
-            pad,
-            backend
-        )
+        recovered_pt = private_key.decrypt(ct, pad)
         assert recovered_pt == pt
 
     @pytest.mark.parametrize(
@@ -1631,16 +1596,14 @@
         with pytest.raises(ValueError):
             public_key.encrypt(
                 b"\x00" * (private_key.key_size // 8 - 1),
-                pad,
-                backend
+                pad
             )
 
         # Larger than the key size.
         with pytest.raises(ValueError):
             public_key.encrypt(
                 b"\x00" * (private_key.key_size // 8 + 5),
-                pad,
-                backend
+                pad
             )
 
     def test_rsa_encrypt_invalid_backend(self, backend):
@@ -1660,7 +1623,7 @@
         public_key = private_key.public_key()
 
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING):
-            public_key.encrypt(b"somedata", DummyPadding(), backend)
+            public_key.encrypt(b"somedata", DummyPadding())
 
     def test_unsupported_oaep_mgf(self, backend):
         private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
@@ -1673,8 +1636,7 @@
                     mgf=DummyMGF(),
                     algorithm=hashes.SHA1(),
                     label=None
-                ),
-                backend
+                )
             )
 
 
diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py
index 4aa9707..ae990b6 100644
--- a/tests/hazmat/primitives/test_serialization.py
+++ b/tests/hazmat/primitives/test_serialization.py
@@ -20,7 +20,8 @@
 import pytest
 
 from cryptography.exceptions import _Reasons
-from cryptography.hazmat.primitives.asymmetric import dsa, rsa
+from cryptography.hazmat.primitives import interfaces
+from cryptography.hazmat.primitives.asymmetric import dsa
 from cryptography.hazmat.primitives.serialization import (
     load_pem_pkcs8_private_key,
     load_pem_traditional_openssl_private_key,
@@ -29,7 +30,7 @@
 )
 
 from .fixtures_rsa import RSA_KEY_1024
-from .utils import _check_rsa_private_key, load_vectors_from_file
+from .utils import _check_rsa_private_numbers, load_vectors_from_file
 from ...utils import raises_unsupported_algorithm
 
 
@@ -54,8 +55,9 @@
         )
 
         assert key
-        assert isinstance(key, rsa.RSAPrivateKey)
-        _check_rsa_private_key(key)
+        assert isinstance(key, interfaces.RSAPrivateKey)
+        if isinstance(key, interfaces.RSAPrivateKeyWithNumbers):
+            _check_rsa_private_numbers(key.private_numbers())
 
     @pytest.mark.parametrize(
         ("key_file", "password"),
@@ -87,33 +89,34 @@
         )
         assert pkey
 
-        assert pkey.p == int(
+        numbers = pkey.private_numbers()
+        assert numbers.p == int(
             "fb7d316fc51531b36d93adaefaf52db6ad5beb793d37c4cf9dfc1ddd17cfbafb",
             16
         )
-        assert pkey.q == int(
+        assert numbers.q == int(
             "df98264e646de9a0fbeab094e31caad5bc7adceaaae3c800ca0275dd4bb307f5",
             16
         )
-        assert pkey.private_exponent == int(
+        assert numbers.d == int(
             "db4848c36f478dd5d38f35ae519643b6b810d404bcb76c00e44015e56ca1cab0"
             "7bb7ae91f6b4b43fcfc82a47d7ed55b8c575152116994c2ce5325ec24313b911",
             16
         )
-        assert pkey.dmp1 == int(
+        assert numbers.dmp1 == int(
             "ce997f967192c2bcc3853186f1559fd355c190c58ddc15cbf5de9b6df954c727",
             16
         )
-        assert pkey.dmq1 == int(
+        assert numbers.dmq1 == int(
             "b018a57ab20ffaa3862435445d863369b852cf70a67c55058213e3fe10e3848d",
             16
         )
-        assert pkey.iqmp == int(
+        assert numbers.iqmp == int(
             "6a8d830616924f5cf2d1bc1973f97fde6b63e052222ac7be06aa2532d10bac76",
             16
         )
-        assert pkey.public_exponent == 65537
-        assert pkey.modulus == int(
+        assert numbers.public_numbers.e == 65537
+        assert numbers.public_numbers.n == int(
             "dba786074f2f0350ce1d99f5aed5b520cfe0deb5429ec8f2a88563763f566e77"
             "9814b7c310e5326edae31198eed439b845dd2db99eaa60f5c16a43f4be6bcf37",
             16
@@ -283,8 +286,9 @@
         )
 
         assert key
-        assert isinstance(key, rsa.RSAPrivateKey)
-        _check_rsa_private_key(key)
+        assert isinstance(key, interfaces.RSAPrivateKey)
+        if isinstance(key, interfaces.RSAPrivateKeyWithNumbers):
+            _check_rsa_private_numbers(key.private_numbers())
 
     def test_unused_password(self, backend):
         key_file = os.path.join(
@@ -415,7 +419,9 @@
         )
         assert pkey
 
-        assert pkey.modulus == int(
+        numbers = pkey.private_numbers()
+
+        assert numbers.public_numbers.n == int(
             "00beec64d6db5760ac2fd4c971145641b9bd7f5c56558ece608795c79807"
             "376a7fe5b19f95b35ca358ea5c8abd7ae051d49cd2f1e45969a1ae945460"
             "3c14b278664a0e414ebc8913acb6203626985525e17a600611b028542dd0"
@@ -423,9 +429,9 @@
             "dd68480567c99b1a57", 16
         )
 
-        assert pkey.public_exponent == 65537
+        assert numbers.public_numbers.e == 65537
 
-        assert pkey.private_exponent == int(
+        assert numbers.d == int(
             "0cfe316e9dc6b8817f4fcfd5ae38a0886f68f773b8a6db4c9e6d8703c599"
             "f3d9785c3a2c09e4c8090909fb3721e19a3009ec21221523a729265707a5"
             "8f13063671c42a4096cad378ef2510cb59e23071489d8893ac4934dd149f"
@@ -433,31 +439,31 @@
             "cf7d995688c86c81", 16
         )
 
-        assert pkey.p == int(
+        assert numbers.p == int(
             "00db122ac857b2c0437d7616daa98e597bb75ca9ad3a47a70bec10c10036"
             "03328794b225c8e3eee6ffd3fd6d2253d28e071fe27d629ab072faa14377"
             "ce6118cb67", 16
         )
 
-        assert pkey.q == int(
+        assert numbers.q == int(
             "00df1b8aa8506fcbbbb9d00257f2975e38b33d2698fd0f37e82d7ef38c56"
             "f21b6ced63c825383782a7115cfcc093300987dbd2853b518d1c8f26382a"
             "2d2586d391", 16
         )
 
-        assert pkey.dmp1 == int(
+        assert numbers.dmp1 == int(
             "00be18aca13e60712fdf5daa85421eb10d86d654b269e1255656194fb0c4"
             "2dd01a1070ea12c19f5c39e09587af02f7b1a1030d016a9ffabf3b36d699"
             "ceaf38d9bf", 16
         )
 
-        assert pkey.dmq1 == int(
+        assert numbers.dmq1 == int(
             "71aa8978f90a0c050744b77cf1263725b203ac9f730606d8ae1d289dce4a"
             "28b8d534e9ea347aeb808c73107e583eb80c546d2bddadcdb3c82693a4c1"
             "3d863451", 16
         )
 
-        assert pkey.iqmp == int(
+        assert numbers.iqmp == int(
             "136b7b1afac6e6279f71b24217b7083485a5e827d156024609dae39d48a6"
             "bdb55af2f062cc4a3b077434e6fffad5faa29a2b5dba2bed3e4621e478c0"
             "97ccfe7f", 16
@@ -554,9 +560,11 @@
     def test_load_private_numbers(self, backend):
         private_key = load_rsa_private_numbers(RSA_KEY_1024, backend)
         assert private_key
+        assert private_key.private_numbers()
 
     def test_load_public_numbers(self, backend):
         public_key = load_rsa_public_numbers(
             RSA_KEY_1024.public_numbers, backend
         )
         assert public_key
+        assert public_key.public_numbers()
diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py
index a496459..54659aa 100644
--- a/tests/hazmat/primitives/utils.py
+++ b/tests/hazmat/primitives/utils.py
@@ -28,6 +28,9 @@
 from cryptography.hazmat.primitives.ciphers import Cipher
 from cryptography.hazmat.primitives.kdf.hkdf import HKDF, HKDFExpand
 from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
+from cryptography.hazmat.primitives.serialization import (
+    load_rsa_public_numbers
+)
 
 from ...utils import load_vectors_from_file
 
@@ -388,16 +391,16 @@
 
 
 def rsa_verification_test(backend, params, hash_alg, pad_factory):
-    public_key = rsa.RSAPublicKey(
-        public_exponent=params["public_exponent"],
-        modulus=params["modulus"]
+    public_numbers = rsa.RSAPublicNumbers(
+        e=params["public_exponent"],
+        n=params["modulus"]
     )
+    public_key = load_rsa_public_numbers(public_numbers, backend)
     pad = pad_factory(params, hash_alg)
     verifier = public_key.verifier(
         binascii.unhexlify(params["s"]),
         pad,
-        hash_alg,
-        backend
+        hash_alg
     )
     verifier.update(binascii.unhexlify(params["msg"]))
     if params["fail"]:
@@ -407,19 +410,14 @@
         verifier.verify()
 
 
-def _check_rsa_private_key(skey):
+def _check_rsa_private_numbers(skey):
     assert skey
-    assert skey.modulus
-    assert skey.public_exponent
-    assert skey.private_exponent
-    assert skey.p * skey.q == skey.modulus
-    assert skey.key_size
+    pkey = skey.public_numbers
+    assert pkey
+    assert pkey.e
+    assert pkey.n
+    assert skey.d
+    assert skey.p * skey.q == pkey.n
     assert skey.dmp1 == rsa.rsa_crt_dmp1(skey.d, skey.p)
     assert skey.dmq1 == rsa.rsa_crt_dmq1(skey.d, skey.q)
     assert skey.iqmp == rsa.rsa_crt_iqmp(skey.p, skey.q)
-
-    pkey = skey.public_key()
-    assert pkey
-    assert skey.modulus == pkey.modulus
-    assert skey.public_exponent == pkey.public_exponent
-    assert skey.key_size == pkey.key_size