Merge pull request #1152 from public/fedora20-ec-fix

Fix EC issue on Fedora 20
diff --git a/cryptography/hazmat/backends/interfaces.py b/cryptography/hazmat/backends/interfaces.py
index 524e0a5..e4faf32 100644
--- a/cryptography/hazmat/backends/interfaces.py
+++ b/cryptography/hazmat/backends/interfaces.py
@@ -196,6 +196,24 @@
         Return True if the parameters are supported by the backend for DSA.
         """
 
+    @abc.abstractmethod
+    def load_dsa_private_numbers(self, numbers):
+        """
+        Returns a DSAPrivateKey provider.
+        """
+
+    @abc.abstractmethod
+    def load_dsa_public_numbers(self, numbers):
+        """
+        Returns a DSAPublicKey provider.
+        """
+
+    @abc.abstractmethod
+    def load_dsa_parameter_numbers(self, numbers):
+        """
+        Returns a DSAParameters provider.
+        """
+
 
 @six.add_metaclass(abc.ABCMeta)
 class TraditionalOpenSSLSerializationBackend(object):
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index bd6cc20..2a7e3cc 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -560,6 +560,15 @@
                                        algorithm)
 
     def mgf1_hash_supported(self, algorithm):
+        warnings.warn(
+            "mgf1_hash_supported is deprecated and will be removed in "
+            "a future version.",
+            utils.DeprecatedIn05,
+            stacklevel=2
+        )
+        return self._mgf1_hash_supported(algorithm)
+
+    def _mgf1_hash_supported(self, algorithm):
         if self._lib.Cryptography_HAS_MGF1_MD:
             return self.hash_supported(algorithm)
         else:
@@ -569,7 +578,7 @@
         if isinstance(padding, PKCS1v15):
             return True
         elif isinstance(padding, PSS) and isinstance(padding._mgf, MGF1):
-            return self.mgf1_hash_supported(padding._mgf._algorithm)
+            return self._mgf1_hash_supported(padding._mgf._algorithm)
         elif isinstance(padding, OAEP) and isinstance(padding._mgf, MGF1):
             return isinstance(padding._mgf._algorithm, hashes.SHA1)
         else:
@@ -1514,7 +1523,7 @@
                 raise ValueError("Digest too large for key size. Use a larger "
                                  "key.")
 
-            if not self._backend.mgf1_hash_supported(padding._mgf._algorithm):
+            if not self._backend._mgf1_hash_supported(padding._mgf._algorithm):
                 raise UnsupportedAlgorithm(
                     "When OpenSSL is older than 1.0.1 then only SHA1 is "
                     "supported with MGF1.",
@@ -1705,7 +1714,7 @@
                     "correct key and digest algorithm."
                 )
 
-            if not self._backend.mgf1_hash_supported(padding._mgf._algorithm):
+            if not self._backend._mgf1_hash_supported(padding._mgf._algorithm):
                 raise UnsupportedAlgorithm(
                     "When OpenSSL is older than 1.0.1 then only SHA1 is "
                     "supported with MGF1.",
diff --git a/cryptography/hazmat/bindings/commoncrypto/common_cryptor.py b/cryptography/hazmat/bindings/commoncrypto/common_cryptor.py
index 9bd03a7..713bc56 100644
--- a/cryptography/hazmat/bindings/commoncrypto/common_cryptor.py
+++ b/cryptography/hazmat/bindings/commoncrypto/common_cryptor.py
@@ -101,7 +101,7 @@
 """
 
 CUSTOMIZATIONS = """
-// Not defined in the public header
+/* Not defined in the public header */
 enum {
     kCCModeGCM = 11
 };
diff --git a/cryptography/hazmat/bindings/openssl/aes.py b/cryptography/hazmat/bindings/openssl/aes.py
index 58ef0cf..e407152 100644
--- a/cryptography/hazmat/bindings/openssl/aes.py
+++ b/cryptography/hazmat/bindings/openssl/aes.py
@@ -49,7 +49,7 @@
 """
 
 CUSTOMIZATIONS = """
-// OpenSSL 0.9.8h+
+/* OpenSSL 0.9.8h+ */
 #if OPENSSL_VERSION_NUMBER >= 0x0090808fL
 static const long Cryptography_HAS_AES_WRAP = 1;
 #else
diff --git a/cryptography/hazmat/bindings/openssl/cms.py b/cryptography/hazmat/bindings/openssl/cms.py
index a3760f2..cbf4b28 100644
--- a/cryptography/hazmat/bindings/openssl/cms.py
+++ b/cryptography/hazmat/bindings/openssl/cms.py
@@ -15,8 +15,8 @@
 
 INCLUDES = """
 #if !defined(OPENSSL_NO_CMS) && OPENSSL_VERSION_NUMBER >= 0x0090808fL
-// The next define should really be in the OpenSSL header, but it is missing.
-// Failing to include this on Windows causes compilation failures.
+/* The next define should really be in the OpenSSL header, but it is missing.
+   Failing to include this on Windows causes compilation failures. */
 #if defined(OPENSSL_SYS_WINDOWS)
 #include <windows.h>
 #endif
diff --git a/cryptography/hazmat/bindings/openssl/dh.py b/cryptography/hazmat/bindings/openssl/dh.py
index a0f9947..e2e8976 100644
--- a/cryptography/hazmat/bindings/openssl/dh.py
+++ b/cryptography/hazmat/bindings/openssl/dh.py
@@ -19,13 +19,13 @@
 
 TYPES = """
 typedef struct dh_st {
-    // prime number (shared)
+    /* Prime number (shared) */
     BIGNUM *p;
-    // generator of Z_p (shared)
+    /* Generator of Z_p (shared) */
     BIGNUM *g;
-    // private DH value x
+    /* Private DH value x */
     BIGNUM *priv_key;
-    // public DH value g^x
+    /* Public DH value g^x */
     BIGNUM *pub_key;
     ...;
 } DH;
diff --git a/cryptography/hazmat/bindings/openssl/dsa.py b/cryptography/hazmat/bindings/openssl/dsa.py
index 7db0332..c9aa888 100644
--- a/cryptography/hazmat/bindings/openssl/dsa.py
+++ b/cryptography/hazmat/bindings/openssl/dsa.py
@@ -19,15 +19,15 @@
 
 TYPES = """
 typedef struct dsa_st {
-    // prime number (public)
+    /* Prime number (public) */
     BIGNUM *p;
-    // 160-bit subprime, q | p-1 (public)
+    /* Subprime (160-bit, q | p-1, public) */
     BIGNUM *q;
-    // generator of subgroup (public)
+    /* Generator of subgroup (public) */
     BIGNUM *g;
-    // private key x
+    /* Private key x */
     BIGNUM *priv_key;
-    // public key y = g^x
+    /* Public key y = g^x */
     BIGNUM *pub_key;
     ...;
 } DSA;
diff --git a/cryptography/hazmat/bindings/openssl/err.py b/cryptography/hazmat/bindings/openssl/err.py
index 49f524d..232060a 100644
--- a/cryptography/hazmat/bindings/openssl/err.py
+++ b/cryptography/hazmat/bindings/openssl/err.py
@@ -290,7 +290,7 @@
 void (*ERR_remove_thread_state)(const CRYPTO_THREADID *) = NULL;
 #endif
 
-// OpenSSL 0.9.8h+
+/* OpenSSL 0.9.8h+ */
 #if OPENSSL_VERSION_NUMBER >= 0x0090808fL
 static const long Cryptography_HAS_098H_ERROR_CODES = 1;
 #else
@@ -304,7 +304,7 @@
 static const int ASN1_R_NO_MULTIPART_BOUNDARY = 0;
 #endif
 
-// OpenSSL 0.9.8c+
+/* OpenSSL 0.9.8c+ */
 #ifdef EVP_F_CAMELLIA_INIT_KEY
 static const long Cryptography_HAS_098C_CAMELLIA_CODES = 1;
 #else
diff --git a/cryptography/hazmat/bindings/openssl/evp.py b/cryptography/hazmat/bindings/openssl/evp.py
index b3d958e..1183450 100644
--- a/cryptography/hazmat/bindings/openssl/evp.py
+++ b/cryptography/hazmat/bindings/openssl/evp.py
@@ -139,7 +139,8 @@
 
 int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *, const EVP_MD *);
 
-// not macros but must be in this section since they're not available in 0.9.8
+/* These aren't macros, but must be in this section because they're not
+   available in 0.9.8. */
 EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *, ENGINE *);
 EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int, ENGINE *);
 EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *);
diff --git a/cryptography/hazmat/bindings/openssl/nid.py b/cryptography/hazmat/bindings/openssl/nid.py
index ea6fd4d..7fa0866 100644
--- a/cryptography/hazmat/bindings/openssl/nid.py
+++ b/cryptography/hazmat/bindings/openssl/nid.py
@@ -193,7 +193,7 @@
 """
 
 CUSTOMIZATIONS = """
-// OpenSSL 0.9.8g+
+/* OpenSSL 0.9.8g+ */
 #if OPENSSL_VERSION_NUMBER >= 0x0090807fL
 static const long Cryptography_HAS_ECDSA_SHA2_NIDS = 1;
 #else
diff --git a/cryptography/hazmat/bindings/openssl/rsa.py b/cryptography/hazmat/bindings/openssl/rsa.py
index c635610..cb8e701 100644
--- a/cryptography/hazmat/bindings/openssl/rsa.py
+++ b/cryptography/hazmat/bindings/openssl/rsa.py
@@ -80,7 +80,7 @@
 #if OPENSSL_VERSION_NUMBER >= 0x10000000
 static const long Cryptography_HAS_PSS_PADDING = 1;
 #else
-// see evp.py for the definition of Cryptography_HAS_PKEY_CTX
+/* see evp.py for the definition of Cryptography_HAS_PKEY_CTX */
 static const long Cryptography_HAS_PSS_PADDING = 0;
 int (*EVP_PKEY_CTX_set_rsa_padding)(EVP_PKEY_CTX *, int) = NULL;
 int (*EVP_PKEY_CTX_set_rsa_pss_saltlen)(EVP_PKEY_CTX *, int) = NULL;
diff --git a/cryptography/hazmat/bindings/openssl/ssl.py b/cryptography/hazmat/bindings/openssl/ssl.py
index 018a141..7d805e7 100644
--- a/cryptography/hazmat/bindings/openssl/ssl.py
+++ b/cryptography/hazmat/bindings/openssl/ssl.py
@@ -456,7 +456,7 @@
 const long SSL_OP_NO_TICKET = 0;
 #endif
 
-// OpenSSL 0.9.8f+
+/* OpenSSL 0.9.8f+ */
 #if OPENSSL_VERSION_NUMBER >= 0x00908070L
 static const long Cryptography_HAS_SSL_SET_SSL_CTX = 1;
 #else
@@ -483,7 +483,7 @@
 static const long Cryptography_HAS_NETBSD_D1_METH = 1;
 #endif
 
-// Workaround for #794 caused by cffi const** bug.
+/* Workaround for #794 caused by cffi const** bug. */
 const SSL_METHOD* Cryptography_SSL_CTX_get_method(const SSL_CTX* ctx) {
     return ctx->method;
 }
@@ -519,7 +519,7 @@
 static const long Cryptography_HAS_NEXTPROTONEG = 1;
 #endif
 
-// ALPN was added in OpenSSL 1.0.2.
+/* ALPN was added in OpenSSL 1.0.2. */
 #if OPENSSL_VERSION_NUMBER < 0x10002001L
 int (*SSL_CTX_set_alpn_protos)(SSL_CTX *,
                                const unsigned char*,
diff --git a/cryptography/hazmat/bindings/openssl/x509.py b/cryptography/hazmat/bindings/openssl/x509.py
index 3785cc6..b74c118 100644
--- a/cryptography/hazmat/bindings/openssl/x509.py
+++ b/cryptography/hazmat/bindings/openssl/x509.py
@@ -24,11 +24,13 @@
  * Note that the result is an opaque type.
  */
 typedef STACK_OF(X509) Cryptography_STACK_OF_X509;
+typedef STACK_OF(X509_CRL) Cryptography_STACK_OF_X509_CRL;
 typedef STACK_OF(X509_REVOKED) Cryptography_STACK_OF_X509_REVOKED;
 """
 
 TYPES = """
 typedef ... Cryptography_STACK_OF_X509;
+typedef ... Cryptography_STACK_OF_X509_CRL;
 typedef ... Cryptography_STACK_OF_X509_REVOKED;
 
 typedef struct {
@@ -243,7 +245,7 @@
 """
 
 CUSTOMIZATIONS = """
-// OpenSSL 0.9.8e does not have this definition
+/* OpenSSL 0.9.8e does not have this definition. */
 #if OPENSSL_VERSION_NUMBER <= 0x0090805fL
 typedef STACK_OF(X509_EXTENSION) X509_EXTENSIONS;
 #endif
diff --git a/cryptography/hazmat/bindings/openssl/x509_vfy.py b/cryptography/hazmat/bindings/openssl/x509_vfy.py
index 031a522..a53716b 100644
--- a/cryptography/hazmat/bindings/openssl/x509_vfy.py
+++ b/cryptography/hazmat/bindings/openssl/x509_vfy.py
@@ -45,7 +45,7 @@
    as longs, just in case they ever grow to large, such as what we saw
    with OP_ALL. */
 
-// Verification error codes
+/* Verification error codes */
 static const int X509_V_OK;
 static const int X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
 static const int X509_V_ERR_UNABLE_TO_GET_CRL;
@@ -110,7 +110,7 @@
 static const int X509_V_ERR_IP_ADDRESS_MISMATCH;
 static const int X509_V_ERR_APPLICATION_VERIFICATION;
 
-// Verification parameters
+/* Verification parameters */
 static const long X509_V_FLAG_CB_ISSUER_CHECK;
 static const long X509_V_FLAG_USE_CHECK_TIME;
 static const long X509_V_FLAG_CRL_CHECK;
@@ -136,12 +136,28 @@
 FUNCTIONS = """
 int X509_verify_cert(X509_STORE_CTX *);
 
-// X509_STORE
+/* X509_STORE */
 X509_STORE *X509_STORE_new(void);
 void X509_STORE_free(X509_STORE *);
 int X509_STORE_add_cert(X509_STORE *, X509 *);
 
-// X509_STORE_CTX
+/* X509_STORE_CTX */
+X509_STORE_CTX *X509_STORE_CTX_new(void);
+void X509_STORE_CTX_cleanup(X509_STORE_CTX *);
+void X509_STORE_CTX_free(X509_STORE_CTX *);
+int X509_STORE_CTX_init(X509_STORE_CTX *, X509_STORE *, X509 *,
+                        Cryptography_STACK_OF_X509 *);
+void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *,
+                                  Cryptography_STACK_OF_X509 *);
+void X509_STORE_CTX_set_cert(X509_STORE_CTX *, X509 *);
+void X509_STORE_CTX_set_chain(X509_STORE_CTX *,Cryptography_STACK_OF_X509 *);
+X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *);
+void X509_STORE_CTX_set0_param(X509_STORE_CTX *, X509_VERIFY_PARAM *);
+int X509_STORE_CTX_set_default(X509_STORE_CTX *, const char *);
+void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *,
+                                  int (*)(int, X509_STORE_CTX *));
+Cryptography_STACK_OF_X509 *X509_STORE_CTX_get_chain(X509_STORE_CTX *);
+Cryptography_STACK_OF_X509 *X509_STORE_CTX_get1_chain(X509_STORE_CTX *);
 int X509_STORE_CTX_get_error(X509_STORE_CTX *);
 void X509_STORE_CTX_set_error(X509_STORE_CTX *, int);
 int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *);
@@ -149,7 +165,7 @@
 int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *, int, void *);
 void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *, int);
 
-// X509_VERIFY_PARAM
+/* X509_VERIFY_PARAM */
 X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void);
 int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *, unsigned long);
 int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *, unsigned long);
@@ -165,6 +181,11 @@
 """
 
 MACROS = """
+/* X509_STORE_CTX */
+void X509_STORE_CTX_set0_crls(X509_STORE_CTX *,
+                              Cryptography_STACK_OF_X509_CRL *);
+
+/* X509_VERIFY_PARAM */
 int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *, const unsigned char *,
                                 size_t);
 void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *, unsigned int);
@@ -176,7 +197,7 @@
 """
 
 CUSTOMIZATIONS = """
-// OpenSSL 1.0.2+, but only some very new releases
+/* OpenSSL 1.0.2+, but only some very new releases */
 #ifdef X509_VERIFY_PARAM_set_hostflags
 static const long Cryptography_HAS_X509_VERIFY_PARAM_SET_HOSTFLAGS = 1;
 #else
@@ -185,7 +206,7 @@
                                         unsigned int) = NULL;
 #endif
 
-// OpenSSL 1.0.2+ verification error codes
+/* OpenSSL 1.0.2+ verification error codes */
 #if OPENSSL_VERSION_NUMBER >= 0x10002000L
 static const long Cryptography_HAS_102_VERIFICATION_ERROR_CODES = 1;
 #else
@@ -201,12 +222,13 @@
 static const long X509_V_ERR_IP_ADDRESS_MISMATCH = 0;
 #endif
 
-// OpenSSL 1.0.2+ verification parameters
+/* OpenSSL 1.0.2+ verification parameters */
 #if OPENSSL_VERSION_NUMBER >= 0x10002000L
 static const long Cryptography_HAS_102_VERIFICATION_PARAMS = 1;
 #else
 static const long Cryptography_HAS_102_VERIFICATION_PARAMS = 0;
-// X509_V_FLAG_TRUSTED_FIRST is also new in 1.0.2, but added separately below
+/* X509_V_FLAG_TRUSTED_FIRST is also new in 1.0.2+, but it is added separately
+   below because it shows up in some earlier 3rd party OpenSSL packages. */
 static const long X509_V_FLAG_SUITEB_128_LOS_ONLY = 0;
 static const long X509_V_FLAG_SUITEB_192_LOS = 0;
 static const long X509_V_FLAG_SUITEB_128_LOS = 0;
@@ -221,7 +243,7 @@
 int (*X509_VERIFY_PARAM_set1_ip_asc)(X509_VERIFY_PARAM *, const char *) = NULL;
 #endif
 
-// OpenSSL 1.0.2+, *or* Fedora 20's flavor of OpenSSL 1.0.1e...
+/* OpenSSL 1.0.2+, *or* Fedora 20's flavor of OpenSSL 1.0.1e... */
 #ifdef X509_V_FLAG_TRUSTED_FIRST
 static const long Cryptography_HAS_X509_V_FLAG_TRUSTED_FIRST = 1;
 #else
@@ -229,7 +251,7 @@
 static const long X509_V_FLAG_TRUSTED_FIRST = 0;
 #endif
 
-// OpenSSL 1.0.0+ verification error codes
+/* OpenSSL 1.0.0+ verification error codes */
 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
 static const long Cryptography_HAS_100_VERIFICATION_ERROR_CODES = 1;
 #else
@@ -245,7 +267,7 @@
 static const long X509_V_ERR_CRL_PATH_VALIDATION_ERROR = 0;
 #endif
 
-// OpenSSL 1.0.0+ verification parameters
+/* OpenSSL 1.0.0+ verification parameters */
 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
 static const long Cryptography_HAS_100_VERIFICATION_PARAMS = 1;
 #else
@@ -254,7 +276,7 @@
 static const long X509_V_FLAG_USE_DELTAS = 0;
 #endif
 
-// OpenSSL 0.9.8recent+
+/* OpenSSL 0.9.8recent+ */
 #ifdef X509_V_FLAG_CHECK_SS_SIGNATURE
 static const long Cryptography_HAS_X509_V_FLAG_CHECK_SS_SIGNATURE = 1;
 #else
diff --git a/cryptography/hazmat/primitives/asymmetric/rsa.py b/cryptography/hazmat/primitives/asymmetric/rsa.py
index fc117cd..15ec52a 100644
--- a/cryptography/hazmat/primitives/asymmetric/rsa.py
+++ b/cryptography/hazmat/primitives/asymmetric/rsa.py
@@ -377,6 +377,9 @@
     def public_numbers(self):
         return self._public_numbers
 
+    def private_key(self, backend):
+        return backend.load_rsa_private_numbers(self)
+
 
 class RSAPublicNumbers(object):
     def __init__(self, e, n):
@@ -396,3 +399,6 @@
     @property
     def n(self):
         return self._n
+
+    def public_key(self, backend):
+        return backend.load_rsa_public_numbers(self)
diff --git a/cryptography/hazmat/primitives/interfaces.py b/cryptography/hazmat/primitives/interfaces.py
index 54821db..dd901aa 100644
--- a/cryptography/hazmat/primitives/interfaces.py
+++ b/cryptography/hazmat/primitives/interfaces.py
@@ -191,6 +191,12 @@
         Returns an AsymmetricSignatureContext used for signing data.
         """
 
+    @abc.abstractmethod
+    def decrypt(self, ciphertext, padding):
+        """
+        Decrypts the provided ciphertext.
+        """
+
     @abc.abstractproperty
     def key_size(self):
         """
@@ -206,6 +212,7 @@
 
 @six.add_metaclass(abc.ABCMeta)
 class RSAPrivateKeyWithNumbers(RSAPrivateKey):
+    @abc.abstractmethod
     def private_numbers(self):
         """
         Returns an RSAPrivateNumbers.
@@ -220,6 +227,12 @@
         Returns an AsymmetricVerificationContext used for verifying signatures.
         """
 
+    @abc.abstractmethod
+    def encrypt(self, plaintext, padding):
+        """
+        Encrypts the given plaintext.
+        """
+
     @abc.abstractproperty
     def key_size(self):
         """
@@ -229,6 +242,7 @@
 
 @six.add_metaclass(abc.ABCMeta)
 class RSAPublicKeyWithNumbers(RSAPublicKey):
+    @abc.abstractmethod
     def public_numbers(self):
         """
         Returns an RSAPublicNumbers
diff --git a/cryptography/hazmat/primitives/serialization.py b/cryptography/hazmat/primitives/serialization.py
index 056d4a0..ed73c4c 100644
--- a/cryptography/hazmat/primitives/serialization.py
+++ b/cryptography/hazmat/primitives/serialization.py
@@ -24,11 +24,3 @@
     return backend.load_pkcs8_pem_private_key(
         data, password
     )
-
-
-def load_rsa_private_numbers(numbers, backend):
-    return backend.load_rsa_private_numbers(numbers)
-
-
-def load_rsa_public_numbers(numbers, backend):
-    return backend.load_rsa_public_numbers(numbers)
diff --git a/docs/development/c-bindings.rst b/docs/development/c-bindings.rst
new file mode 100644
index 0000000..5696337
--- /dev/null
+++ b/docs/development/c-bindings.rst
@@ -0,0 +1,192 @@
+C bindings
+==========
+
+C bindings are bindings to C libraries, using cffi_ whenever possible.
+
+.. _cffi: http://cffi.readthedocs.org
+
+Bindings live in :py:mod:`cryptography.hazmat.bindings`.
+
+Style guide
+-----------
+
+Don't name parameters:
+
+.. code-block:: c
+
+    /* Good */
+    long f(long);
+    /* Bad */
+    long f(long x);
+
+...unless they're inside a struct:
+
+.. code-block:: c
+
+    struct my_struct {
+        char *name;
+        int number;
+        ...;
+    };
+
+Include ``void`` if the function takes no arguments:
+
+.. code-block:: c
+
+    /* Good */
+    long f(void);
+    /* Bad */
+    long f();
+
+Wrap lines at 80 characters like so:
+
+.. code-block:: c
+
+    /* Pretend this went to 80 characters */
+    long f(long, long,
+           int *)
+
+Include a space after commas between parameters:
+
+.. code-block:: c
+
+    /* Good */
+    long f(int, char *)
+    /* Bad */
+    long f(int,char *)
+
+Use C-style ``/* */`` comments instead of C++-style ``//``:
+
+.. code-block:: c
+
+    // Bad
+    /* Good */
+
+Values set by ``#define`` should be assigned the appropriate type. If you see
+this:
+
+.. code-block:: c
+
+    #define SOME_INTEGER_LITERAL 0x0;
+    #define SOME_UNSIGNED_INTEGER_LITERAL 0x0001U;
+    #define SOME_STRING_LITERAL "hello";
+
+...it should be added to the bindings like so:
+
+.. code-block:: c
+
+    static const int SOME_INTEGER_LITERAL;
+    static const unsigned int SOME_UNSIGNED_INTEGER_LITERAL;
+    static const char *const SOME_STRING_LITERAL;
+
+Adding constant, types, functions...
+------------------------------------
+
+You can create bindings for any name that exists in some version of
+the library you're binding against. However, the project also has to
+keep supporting older versions of the library. In order to achieve
+this, binding modules have ``CUSTOMIZATIONS`` and
+``CONDITIONAL_NAMES`` constants.
+
+Let's say you want to enable quantum transmogrification. The upstream
+library implements this as the following API::
+
+    static const int QM_TRANSMOGRIFICATION_ALIGNMENT_LEFT;
+    static const int QM_TRANSMOGRIFICATION_ALIGNMENT_RIGHT;
+    typedef ... QM_TRANSMOGRIFICATION_CTX;
+    int QM_transmogrify(QM_TRANSMOGRIFICATION_CTX *, int);
+
+To start, create a new constant that defines if the *actual* library
+has the feature you want, and add it to ``TYPES``::
+
+    static const long Cryptography_HAS_QUANTUM_TRANSMOGRIFICATION;
+
+This should start with ``Cryptography_``, since we're adding it in
+this library. This prevents namespace collisions.
+
+Then, define the actual features (constants, types, functions...) you
+want to expose. If it's a constant, just add it to ``TYPES``::
+
+    static const int QM_TRANSMOGRIFICATION_ALIGNMENT_LEFT;
+    static const int QM_TRANSMOGRIFICATION_ALIGNMENT_RIGHT;
+
+If it's a struct, add it to ``TYPES`` as well. The following is an
+opaque struct::
+
+    typedef ... QM_TRANSMOGRIFICATION_CTX;
+
+... but you can also make some or all items in the struct accessible::
+
+    typedef struct {
+        /* Fundamental constant k for your particular universe */
+        BIGNUM *k;
+        ...;
+    } QM_TRANSMOGRIFICATION_CTX;
+
+Confusingly, functions that aren't always available on all supported
+versions of the library, should be defined in ``MACROS`` and *not* in
+``FUNCTIONS``. Fortunately, you just have to copy the signature::
+
+    int QM_transmogrify(QM_TRANSMOGRIFICATION_CTX *, int);
+
+Then, we define the ``CUSTOMIZATIONS`` entry. To do that, we have to
+come up with a C preprocessor expression that decides whether or not a
+feature exists in the library. For example::
+
+    #ifdef QM_transmogrify
+
+Then, we set the flag that signifies the feature exists::
+
+    static const long Cryptography_HAS_QUANTUM_TRANSMOGRIFICATION = 1;
+
+Otherwise, we set that flag to 0::
+
+    #else
+    static const long Cryptography_HAS_QUANTUM_TRANSMOGRIFICATION = 0;
+
+Then, in that ``#else`` block, we define the names that aren't
+available as dummy values. For an integer constant, use 0::
+
+    static const int QM_TRANSMOGRIFICATION_ALIGNMENT_LEFT = 0;
+    static const int QM_TRANSMOGRIFICATION_ALIGNMENT_RIGHT = 0;
+
+For a function, it's a bit trickier. You have to define a function
+pointer of the appropriate type to be NULL::
+
+    int (*QM_transmogrify)(QM_TRANSMOGRIFICATION_CTX *, int) = NULL;
+
+(To do that, copy the signature, put a ``*`` in front of the function
+name and wrap it in parentheses, and then put ``= NULL`` at the end).
+
+Note how types don't need to be conditionally defined, as long as all
+the necessarily type definitions are in place.
+
+Finally, add an entry to ``CONDITIONAL_NAMES`` with all of the things
+you want to conditionally export::
+
+    CONDITIONAL_NAMES = {
+        ...
+        "Cryptography_HAS_QUANTUM_TRANSMOGRIFICATION": [
+            "QM_TRANSMOGRIFICATION_ALIGNMENT_LEFT",
+            "QM_TRANSMOGRIFICATION_ALIGNMENT_RIGHT",
+            "QM_transmogrify"
+        ]
+    }
+
+Caveats
+~~~~~~~
+
+Sometimes, a set of loosely related features are added in the same
+version, and it's impractical to create ``#ifdef`` statements for each
+one. In that case, it may make sense to either check for a particular
+version. For example, to check for OpenSSL 1.0.0 or newer::
+
+    #if OPENSSL_VERSION_NUMBER >= 0x10000000L
+
+Sometimes, the version of a library on a particular platform will have
+features that you thought it wouldn't, based on its version.
+Occasionally, packagers appear to ship arbitrary VCS checkouts. As a
+result, sometimes you may have to add separate ``#ifdef`` statements
+for particular features. This kind of issue is typically only caught
+by running the tests on a wide variety of systems, which is the job of
+our continuous integration infrastructure.
diff --git a/docs/development/index.rst b/docs/development/index.rst
index 50b6090..f9bc9ee 100644
--- a/docs/development/index.rst
+++ b/docs/development/index.rst
@@ -14,6 +14,7 @@
     submitting-patches
     reviewing-patches
     test-vectors
+    c-bindings
 
 .. _`GitHub`: https://github.com/pyca/cryptography
 .. _`what to put in your bug report`: http://www.contribution-guide.org/#what-to-put-in-your-bug-report
diff --git a/docs/development/submitting-patches.rst b/docs/development/submitting-patches.rst
index b7f4328..fe2df43 100644
--- a/docs/development/submitting-patches.rst
+++ b/docs/development/submitting-patches.rst
@@ -75,70 +75,8 @@
 C bindings
 ~~~~~~~~~~
 
-When binding C code with ``cffi`` we have our own style guide, it's pretty
-simple.
-
-Don't name parameters:
-
-.. code-block:: c
-
-    // Good
-    long f(long);
-    // Bad
-    long f(long x);
-
-...unless they're inside a struct:
-
-.. code-block:: c
-
-    struct my_struct {
-        char *name;
-        int number;
-        ...;
-    };
-
-Include ``void`` if the function takes no arguments:
-
-.. code-block:: c
-
-    // Good
-    long f(void);
-    // Bad
-    long f();
-
-Wrap lines at 80 characters like so:
-
-.. code-block:: c
-
-    // Pretend this went to 80 characters
-    long f(long, long,
-           int *)
-
-Include a space after commas between parameters:
-
-.. code-block:: c
-
-    // Good
-    long f(int, char *)
-    // Bad
-    long f(int,char *)
-
-Values set by ``#define`` should be assigned the appropriate type. If you see
-this:
-
-.. code-block:: c
-
-    #define SOME_INTEGER_LITERAL 0x0;
-    #define SOME_UNSIGNED_INTEGER_LITERAL 0x0001U;
-    #define SOME_STRING_LITERAL "hello";
-
-...it should be added to the bindings like so:
-
-.. code-block:: c
-
-    static const int SOME_INTEGER_LITERAL;
-    static const unsigned int SOME_UNSIGNED_INTEGER_LITERAL;
-    static const char *const SOME_STRING_LITERAL;
+More information on C bindings can be found in :doc:`the dedicated
+section of the documentation <c-bindings>`.
 
 Tests
 -----
diff --git a/docs/hazmat/backends/interfaces.rst b/docs/hazmat/backends/interfaces.rst
index a18a3d5..5cbd47d 100644
--- a/docs/hazmat/backends/interfaces.rst
+++ b/docs/hazmat/backends/interfaces.rst
@@ -255,10 +255,13 @@
 
     .. method:: mgf1_hash_supported(algorithm)
 
+        ..deprecated:: 0.5
+
         Check if the specified ``algorithm`` is supported for use with
         :class:`~cryptography.hazmat.primitives.asymmetric.padding.MGF1`
         inside :class:`~cryptography.hazmat.primitives.asymmetric.padding.PSS`
-        padding.
+        padding. This method is deprecated in favor of
+        ``rsa_padding_supported``.
 
         :param algorithm: An instance of a
             :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
@@ -467,6 +470,40 @@
         :returns: ``True`` if the given values of ``p``, ``q``, and ``g`` are
             supported by this backend, otherwise ``False``.
 
+    .. method:: load_dsa_parameter_numbers(numbers):
+
+        :param numbers: An instance of
+            :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameterNumbers`.
+
+        :returns: A provider of
+            :class:`~cryptography.hazmat.primitives.interfaces.DSAParameters`.
+
+        :raises cryptography.exceptions.UnsupportedAlgorithm: This raised when
+            any backend specific criteria are not met.
+
+    .. method:: load_dsa_private_numbers(numbers):
+
+        :param numbers: An instance of
+            :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateNumbers`.
+
+        :returns: A provider of
+            :class:`~cryptography.hazmat.primitives.interfaces.DSAPrivateKey`.
+
+        :raises cryptography.exceptions.UnsupportedAlgorithm: This raised when
+            any backend specific criteria are not met.
+
+    .. method:: load_dsa_public_numbers(numbers):
+
+        :param numbers: An instance of
+            :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicNumbers`.
+
+        :returns: A provider of
+            :class:`~cryptography.hazmat.primitives.interfaces.DSAPublicKey`.
+
+        :raises cryptography.exceptions.UnsupportedAlgorithm: This raised when
+            any backend specific criteria are not met.
+
+
 
 .. class:: CMACBackend
 
diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst
index 71b7cd9..c396290 100644
--- a/docs/hazmat/primitives/asymmetric/rsa.rst
+++ b/docs/hazmat/primitives/asymmetric/rsa.rst
@@ -385,6 +385,18 @@
 
     The collection of integers that make up an RSA public key.
 
+    .. method:: public_key(backend)
+
+        :param backend: A
+            :class:`~cryptography.hazmat.backends.interfaces.RSABackend`
+            provider.
+
+        :return: A :class:`~cryptography.hazmat.primitives.interfaces.RSAPublicKey`
+            provider.
+
+        :raises UnsupportedAlgorithm: If the given backend does not support
+            loading numbers.
+
     .. attribute:: n
 
         :type: int
@@ -411,6 +423,18 @@
         secret. Revealing them will compromise the security of any
         cryptographic operations performed with a key loaded from them.
 
+    .. method:: private_key(backend)
+
+        :param backend: A
+            :class:`~cryptography.hazmat.backends.interfaces.RSABackend`
+            provider.
+
+        :return: A :class:`~cryptography.hazmat.primitives.interfaces.RSAPrivateKey`
+            provider.
+
+        :raises UnsupportedAlgorithm: If the given backend does not support
+            loading numbers.
+
     .. attribute:: public_numbers
 
         :type: :class:`~cryptography.hazmat.primitives.rsa.RSAPublicNumbers`
diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt
index e7a63f2..dc12349 100644
--- a/docs/spelling_wordlist.txt
+++ b/docs/spelling_wordlist.txt
@@ -30,8 +30,12 @@
 iOS
 Koblitz
 metadata
+namespace
+namespaces
 pickleable
 plaintext
+preprocessor
+preprocessors
 pseudorandom
 Schneier
 scrypt
diff --git a/tasks.py b/tasks.py
index 9ffdc8a..94a9541 100644
--- a/tasks.py
+++ b/tasks.py
@@ -91,11 +91,14 @@
         "vectors/dist/cryptography_vectors-{0}*".format(version)
     )
 
+    username = getpass.getpass("Input the GitHub/Jenkins username: ")
     token = getpass.getpass("Input the Jenkins token: ")
     response = requests.post(
         "{0}/build".format(JENKINS_URL),
+        auth=requests.auth.HTTPBasicAuth(
+            username, token
+        ),
         params={
-            "token": token,
             "cause": "Building wheels for {0}".format(version)
         }
     )
diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py
index 7aa8f0f..bd99c8f 100644
--- a/tests/hazmat/backends/test_openssl.py
+++ b/tests/hazmat/backends/test_openssl.py
@@ -353,7 +353,10 @@
             )
 
     def test_unsupported_mgf1_hash_algorithm(self):
-        assert backend.mgf1_hash_supported(DummyHash()) is False
+        assert pytest.deprecated_call(
+            backend.mgf1_hash_supported,
+            DummyHash()
+        ) is False
 
     def test_rsa_padding_unsupported_pss_mgf1_hash(self):
         assert backend.rsa_padding_supported(
diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py
index 5c5422e..0490845 100644
--- a/tests/hazmat/primitives/test_rsa.py
+++ b/tests/hazmat/primitives/test_rsa.py
@@ -27,9 +27,6 @@
 )
 from cryptography.hazmat.primitives import hashes, interfaces
 from cryptography.hazmat.primitives.asymmetric import padding, rsa
-from cryptography.hazmat.primitives.serialization import (
-    load_rsa_private_numbers
-)
 
 from .fixtures_rsa import (
     RSA_KEY_1024, RSA_KEY_1025, RSA_KEY_1026, RSA_KEY_1027, RSA_KEY_1028,
@@ -102,6 +99,8 @@
 
         if isinstance(skey, interfaces.RSAPrivateKeyWithNumbers):
             _check_rsa_private_numbers(skey.private_numbers())
+            pkey = skey.public_key()
+            assert isinstance(pkey.public_numbers(), rsa.RSAPublicNumbers)
 
     def test_generate_rsa_key_class_method(self, backend):
         skey = pytest.deprecated_call(
@@ -522,7 +521,7 @@
         skip_message="Does not support PSS."
     )
     def test_deprecated_pss_mgf1_salt_length(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
+        private_key = RSA_KEY_512.private_key(backend)
         signer = private_key.signer(
             pytest.deprecated_call(
                 padding.PSS,
@@ -566,7 +565,7 @@
             pytest.skip(
                 "Does not support {0} in MGF1 using PSS.".format(hash_alg.name)
             )
-        private_key = load_rsa_private_numbers(RSA_KEY_768, backend)
+        private_key = RSA_KEY_768.private_key(backend)
         public_key = private_key.public_key()
         pss = padding.PSS(
             mgf=padding.MGF1(hash_alg),
@@ -592,7 +591,7 @@
         skip_message="Does not support SHA512."
     )
     def test_pss_minimum_key_size_for_digest(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_522, backend)
+        private_key = RSA_KEY_522.private_key(backend)
         signer = private_key.signer(
             padding.PSS(
                 mgf=padding.MGF1(hashes.SHA1()),
@@ -617,7 +616,7 @@
         skip_message="Does not support SHA512."
     )
     def test_pss_signing_digest_too_large_for_key_size(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
+        private_key = RSA_KEY_512.private_key(backend)
         with pytest.raises(ValueError):
             private_key.signer(
                 padding.PSS(
@@ -637,7 +636,7 @@
         skip_message="Does not support PSS."
     )
     def test_pss_signing_salt_length_too_long(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
+        private_key = RSA_KEY_512.private_key(backend)
         signer = private_key.signer(
             padding.PSS(
                 mgf=padding.MGF1(hashes.SHA1()),
@@ -656,7 +655,7 @@
         skip_message="Does not support PKCS1v1.5."
     )
     def test_use_after_finalize(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
+        private_key = RSA_KEY_512.private_key(backend)
         signer = private_key.signer(padding.PKCS1v15(), hashes.SHA1())
         signer.update(b"sign me")
         signer.finalize()
@@ -666,12 +665,12 @@
             signer.update(b"more data")
 
     def test_unsupported_padding(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
+        private_key = RSA_KEY_512.private_key(backend)
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING):
             private_key.signer(DummyPadding(), hashes.SHA1())
 
     def test_padding_incorrect_type(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
+        private_key = RSA_KEY_512.private_key(backend)
         with pytest.raises(TypeError):
             private_key.signer("notpadding", hashes.SHA1())
 
@@ -700,7 +699,7 @@
         skip_message="Does not support PSS."
     )
     def test_unsupported_pss_mgf(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
+        private_key = RSA_KEY_512.private_key(backend)
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_MGF):
             private_key.signer(padding.PSS(mgf=DummyMGF()), hashes.SHA1())
 
@@ -711,7 +710,7 @@
         skip_message="Does not support PKCS1v1.5."
     )
     def test_pkcs1_digest_too_large_for_key_size(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_599, backend)
+        private_key = RSA_KEY_599.private_key(backend)
         signer = private_key.signer(
             padding.PKCS1v15(),
             hashes.SHA512()
@@ -727,7 +726,7 @@
         skip_message="Does not support PKCS1v1.5."
     )
     def test_pkcs1_minimum_key_size(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_745, backend)
+        private_key = RSA_KEY_745.private_key(backend)
         signer = private_key.signer(
             padding.PKCS1v15(),
             hashes.SHA512()
@@ -774,7 +773,7 @@
         skip_message="Does not support PKCS1v1.5."
     )
     def test_invalid_pkcs1v15_signature_wrong_data(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
+        private_key = RSA_KEY_512.private_key(backend)
         public_key = private_key.public_key()
         signer = private_key.signer(padding.PKCS1v15(), hashes.SHA1())
         signer.update(b"sign me")
@@ -795,8 +794,8 @@
         skip_message="Does not support PKCS1v1.5."
     )
     def test_invalid_pkcs1v15_signature_wrong_key(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
-        private_key2 = load_rsa_private_numbers(RSA_KEY_512_ALT, backend)
+        private_key = RSA_KEY_512.private_key(backend)
+        private_key2 = RSA_KEY_512_ALT.private_key(backend)
         public_key = private_key2.public_key()
         signer = private_key.signer(padding.PKCS1v15(), hashes.SHA1())
         signer.update(b"sign me")
@@ -961,7 +960,7 @@
         skip_message="Does not support PKCS1v1.5."
     )
     def test_use_after_finalize(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
+        private_key = RSA_KEY_512.private_key(backend)
         public_key = private_key.public_key()
         signer = private_key.signer(padding.PKCS1v15(), hashes.SHA1())
         signer.update(b"sign me")
@@ -980,13 +979,13 @@
             verifier.update(b"more data")
 
     def test_unsupported_padding(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
+        private_key = RSA_KEY_512.private_key(backend)
         public_key = private_key.public_key()
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING):
             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)
+        private_key = RSA_KEY_512.private_key(backend)
         public_key = private_key.public_key()
         with pytest.raises(TypeError):
             public_key.verifier(b"sig", "notpadding", hashes.SHA1())
@@ -1012,7 +1011,7 @@
         skip_message="Does not support PSS."
     )
     def test_unsupported_pss_mgf(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
+        private_key = RSA_KEY_512.private_key(backend)
         public_key = private_key.public_key()
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_MGF):
             public_key.verifier(b"sig", padding.PSS(mgf=DummyMGF()),
@@ -1032,7 +1031,7 @@
         skip_message="Does not support SHA512."
     )
     def test_pss_verify_digest_too_large_for_key_size(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
+        private_key = RSA_KEY_512.private_key(backend)
         signature = binascii.unhexlify(
             b"8b9a3ae9fb3b64158f3476dd8d8a1f1425444e98940e0926378baa9944d219d8"
             b"534c050ef6b19b1bdc6eb4da422e89161106a6f5b5cc16135b11eb6439b646bd"
@@ -1433,7 +1432,7 @@
         assert message == binascii.unhexlify(example["message"])
 
     def test_unsupported_padding(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
+        private_key = RSA_KEY_512.private_key(backend)
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING):
             private_key.decrypt(b"0" * 64, DummyPadding())
 
@@ -1444,7 +1443,7 @@
         skip_message="Does not support PKCS1v1.5."
     )
     def test_decrypt_invalid_decrypt(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
+        private_key = RSA_KEY_512.private_key(backend)
         with pytest.raises(ValueError):
             private_key.decrypt(
                 b"\x00" * 64,
@@ -1458,7 +1457,7 @@
         skip_message="Does not support PKCS1v1.5."
     )
     def test_decrypt_ciphertext_too_large(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
+        private_key = RSA_KEY_512.private_key(backend)
         with pytest.raises(ValueError):
             private_key.decrypt(
                 b"\x00" * 65,
@@ -1472,7 +1471,7 @@
         skip_message="Does not support PKCS1v1.5."
     )
     def test_decrypt_ciphertext_too_small(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
+        private_key = RSA_KEY_512.private_key(backend)
         ct = binascii.unhexlify(
             b"50b4c14136bd198c2f3c3ed243fce036e168d56517984a263cd66492b80804f1"
             b"69d210f2b9bdfb48b12f9ea05009c77da257cc600ccefe3a6283789d8ea0"
@@ -1539,7 +1538,7 @@
         assert message == binascii.unhexlify(example["message"])
 
     def test_unsupported_oaep_mgf(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
+        private_key = RSA_KEY_512.private_key(backend)
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_MGF):
             private_key.decrypt(
                 b"0" * 64,
@@ -1613,7 +1612,7 @@
         )
     )
     def test_rsa_encrypt_pkcs1v15(self, key_data, pad, backend):
-        private_key = load_rsa_private_numbers(key_data, backend)
+        private_key = key_data.private_key(backend)
         pt = b"encrypt me!"
         public_key = private_key.public_key()
         ct = public_key.encrypt(pt, pad)
@@ -1639,7 +1638,7 @@
         )
     )
     def test_rsa_encrypt_key_too_small(self, key_data, pad, backend):
-        private_key = load_rsa_private_numbers(key_data, backend)
+        private_key = key_data.private_key(backend)
         public_key = private_key.public_key()
         # Slightly smaller than the key size but not enough for padding.
         with pytest.raises(ValueError):
@@ -1670,14 +1669,14 @@
             )
 
     def test_unsupported_padding(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
+        private_key = RSA_KEY_512.private_key(backend)
         public_key = private_key.public_key()
 
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING):
             public_key.encrypt(b"somedata", DummyPadding())
 
     def test_unsupported_oaep_mgf(self, backend):
-        private_key = load_rsa_private_numbers(RSA_KEY_512, backend)
+        private_key = RSA_KEY_512.private_key(backend)
         public_key = private_key.public_key()
 
         with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_MGF):
@@ -1718,6 +1717,14 @@
         assert private_numbers.iqmp == 2
         assert private_numbers.public_numbers == public_numbers
 
+    def test_rsa_private_numbers_create_key(self, backend):
+        private_key = RSA_KEY_1024.private_key(backend)
+        assert private_key
+
+    def test_rsa_public_numbers_create_key(self, backend):
+        public_key = RSA_KEY_1024.public_numbers.public_key(backend)
+        assert public_key
+
     def test_public_numbers_invalid_types(self):
         with pytest.raises(TypeError):
             rsa.RSAPublicNumbers(e=None, n=15)
@@ -1812,19 +1819,19 @@
         # Test a modulus < 3.
 
         with pytest.raises(ValueError):
-            backend.load_rsa_public_numbers(rsa.RSAPublicNumbers(e=7, n=2))
+            rsa.RSAPublicNumbers(e=7, n=2).public_key(backend)
 
         # Test a public_exponent < 3
         with pytest.raises(ValueError):
-            backend.load_rsa_public_numbers(rsa.RSAPublicNumbers(e=1, n=15))
+            rsa.RSAPublicNumbers(e=1, n=15).public_key(backend)
 
         # Test a public_exponent > modulus
         with pytest.raises(ValueError):
-            backend.load_rsa_public_numbers(rsa.RSAPublicNumbers(e=17, n=15))
+            rsa.RSAPublicNumbers(e=17, n=15).public_key(backend)
 
         # Test a public_exponent that is not odd.
         with pytest.raises(ValueError):
-            backend.load_rsa_public_numbers(rsa.RSAPublicNumbers(e=16, n=15))
+            rsa.RSAPublicNumbers(e=16, n=15).public_key(backend)
 
     def test_invalid_private_numbers_argument_values(self, backend):
         # Start with p=3, q=11, private_exponent=3, public_exponent=7,
@@ -1833,221 +1840,195 @@
 
         # Test a modulus < 3.
         with pytest.raises(ValueError):
-            backend.load_rsa_private_numbers(
-                rsa.RSAPrivateNumbers(
-                    p=3,
-                    q=11,
-                    d=3,
-                    dmp1=1,
-                    dmq1=3,
-                    iqmp=2,
-                    public_numbers=rsa.RSAPublicNumbers(
-                        e=7,
-                        n=2
-                    )
+            rsa.RSAPrivateNumbers(
+                p=3,
+                q=11,
+                d=3,
+                dmp1=1,
+                dmq1=3,
+                iqmp=2,
+                public_numbers=rsa.RSAPublicNumbers(
+                    e=7,
+                    n=2
                 )
-            )
+            ).private_key(backend)
 
         # Test a modulus != p * q.
         with pytest.raises(ValueError):
-            backend.load_rsa_private_numbers(
-                rsa.RSAPrivateNumbers(
-                    p=3,
-                    q=11,
-                    d=3,
-                    dmp1=1,
-                    dmq1=3,
-                    iqmp=2,
-                    public_numbers=rsa.RSAPublicNumbers(
-                        e=7,
-                        n=35
-                    )
+            rsa.RSAPrivateNumbers(
+                p=3,
+                q=11,
+                d=3,
+                dmp1=1,
+                dmq1=3,
+                iqmp=2,
+                public_numbers=rsa.RSAPublicNumbers(
+                    e=7,
+                    n=35
                 )
-            )
+            ).private_key(backend)
 
         # Test a p > modulus.
         with pytest.raises(ValueError):
-            backend.load_rsa_private_numbers(
-                rsa.RSAPrivateNumbers(
-                    p=37,
-                    q=11,
-                    d=3,
-                    dmp1=1,
-                    dmq1=3,
-                    iqmp=2,
-                    public_numbers=rsa.RSAPublicNumbers(
-                        e=7,
-                        n=33
-                    )
+            rsa.RSAPrivateNumbers(
+                p=37,
+                q=11,
+                d=3,
+                dmp1=1,
+                dmq1=3,
+                iqmp=2,
+                public_numbers=rsa.RSAPublicNumbers(
+                    e=7,
+                    n=33
                 )
-            )
+            ).private_key(backend)
 
         # Test a q > modulus.
         with pytest.raises(ValueError):
-            backend.load_rsa_private_numbers(
-                rsa.RSAPrivateNumbers(
-                    p=3,
-                    q=37,
-                    d=3,
-                    dmp1=1,
-                    dmq1=3,
-                    iqmp=2,
-                    public_numbers=rsa.RSAPublicNumbers(
-                        e=7,
-                        n=33
-                    )
+            rsa.RSAPrivateNumbers(
+                p=3,
+                q=37,
+                d=3,
+                dmp1=1,
+                dmq1=3,
+                iqmp=2,
+                public_numbers=rsa.RSAPublicNumbers(
+                    e=7,
+                    n=33
                 )
-            )
+            ).private_key(backend)
 
         # Test a dmp1 > modulus.
         with pytest.raises(ValueError):
-            backend.load_rsa_private_numbers(
-                rsa.RSAPrivateNumbers(
-                    p=3,
-                    q=11,
-                    d=3,
-                    dmp1=35,
-                    dmq1=3,
-                    iqmp=2,
-                    public_numbers=rsa.RSAPublicNumbers(
-                        e=7,
-                        n=33
-                    )
+            rsa.RSAPrivateNumbers(
+                p=3,
+                q=11,
+                d=3,
+                dmp1=35,
+                dmq1=3,
+                iqmp=2,
+                public_numbers=rsa.RSAPublicNumbers(
+                    e=7,
+                    n=33
                 )
-            )
+            ).private_key(backend)
 
         # Test a dmq1 > modulus.
         with pytest.raises(ValueError):
-            backend.load_rsa_private_numbers(
-                rsa.RSAPrivateNumbers(
-                    p=3,
-                    q=11,
-                    d=3,
-                    dmp1=1,
-                    dmq1=35,
-                    iqmp=2,
-                    public_numbers=rsa.RSAPublicNumbers(
-                        e=7,
-                        n=33
-                    )
+            rsa.RSAPrivateNumbers(
+                p=3,
+                q=11,
+                d=3,
+                dmp1=1,
+                dmq1=35,
+                iqmp=2,
+                public_numbers=rsa.RSAPublicNumbers(
+                    e=7,
+                    n=33
                 )
-            )
+            ).private_key(backend)
 
         # Test an iqmp > modulus.
         with pytest.raises(ValueError):
-            backend.load_rsa_private_numbers(
-                rsa.RSAPrivateNumbers(
-                    p=3,
-                    q=11,
-                    d=3,
-                    dmp1=1,
-                    dmq1=3,
-                    iqmp=35,
-                    public_numbers=rsa.RSAPublicNumbers(
-                        e=7,
-                        n=33
-                    )
+            rsa.RSAPrivateNumbers(
+                p=3,
+                q=11,
+                d=3,
+                dmp1=1,
+                dmq1=3,
+                iqmp=35,
+                public_numbers=rsa.RSAPublicNumbers(
+                    e=7,
+                    n=33
                 )
-            )
+            ).private_key(backend)
 
         # Test a private_exponent > modulus
         with pytest.raises(ValueError):
-            backend.load_rsa_private_numbers(
-                rsa.RSAPrivateNumbers(
-                    p=3,
-                    q=11,
-                    d=37,
-                    dmp1=1,
-                    dmq1=3,
-                    iqmp=2,
-                    public_numbers=rsa.RSAPublicNumbers(
-                        e=7,
-                        n=33
-                    )
+            rsa.RSAPrivateNumbers(
+                p=3,
+                q=11,
+                d=37,
+                dmp1=1,
+                dmq1=3,
+                iqmp=2,
+                public_numbers=rsa.RSAPublicNumbers(
+                    e=7,
+                    n=33
                 )
-            )
+            ).private_key(backend)
 
         # Test a public_exponent < 3
         with pytest.raises(ValueError):
-            backend.load_rsa_private_numbers(
-                rsa.RSAPrivateNumbers(
-                    p=3,
-                    q=11,
-                    d=3,
-                    dmp1=1,
-                    dmq1=3,
-                    iqmp=2,
-                    public_numbers=rsa.RSAPublicNumbers(
-                        e=1,
-                        n=33
-                    )
+            rsa.RSAPrivateNumbers(
+                p=3,
+                q=11,
+                d=3,
+                dmp1=1,
+                dmq1=3,
+                iqmp=2,
+                public_numbers=rsa.RSAPublicNumbers(
+                    e=1,
+                    n=33
                 )
-            )
+            ).private_key(backend)
 
         # Test a public_exponent > modulus
         with pytest.raises(ValueError):
-            backend.load_rsa_private_numbers(
-                rsa.RSAPrivateNumbers(
-                    p=3,
-                    q=11,
-                    d=3,
-                    dmp1=1,
-                    dmq1=3,
-                    iqmp=35,
-                    public_numbers=rsa.RSAPublicNumbers(
-                        e=65537,
-                        n=33
-                    )
+            rsa.RSAPrivateNumbers(
+                p=3,
+                q=11,
+                d=3,
+                dmp1=1,
+                dmq1=3,
+                iqmp=35,
+                public_numbers=rsa.RSAPublicNumbers(
+                    e=65537,
+                    n=33
                 )
-            )
+            ).private_key(backend)
 
         # Test a public_exponent that is not odd.
         with pytest.raises(ValueError):
-            backend.load_rsa_private_numbers(
-                rsa.RSAPrivateNumbers(
-                    p=3,
-                    q=11,
-                    d=3,
-                    dmp1=1,
-                    dmq1=3,
-                    iqmp=2,
-                    public_numbers=rsa.RSAPublicNumbers(
-                        e=6,
-                        n=33
-                    )
+            rsa.RSAPrivateNumbers(
+                p=3,
+                q=11,
+                d=3,
+                dmp1=1,
+                dmq1=3,
+                iqmp=2,
+                public_numbers=rsa.RSAPublicNumbers(
+                    e=6,
+                    n=33
                 )
-            )
+            ).private_key(backend)
 
         # Test a dmp1 that is not odd.
         with pytest.raises(ValueError):
-            backend.load_rsa_private_numbers(
-                rsa.RSAPrivateNumbers(
-                    p=3,
-                    q=11,
-                    d=3,
-                    dmp1=2,
-                    dmq1=3,
-                    iqmp=2,
-                    public_numbers=rsa.RSAPublicNumbers(
-                        e=7,
-                        n=33
-                    )
+            rsa.RSAPrivateNumbers(
+                p=3,
+                q=11,
+                d=3,
+                dmp1=2,
+                dmq1=3,
+                iqmp=2,
+                public_numbers=rsa.RSAPublicNumbers(
+                    e=7,
+                    n=33
                 )
-            )
+            ).private_key(backend)
 
         # Test a dmq1 that is not odd.
         with pytest.raises(ValueError):
-            backend.load_rsa_private_numbers(
-                rsa.RSAPrivateNumbers(
-                    p=3,
-                    q=11,
-                    d=3,
-                    dmp1=1,
-                    dmq1=4,
-                    iqmp=2,
-                    public_numbers=rsa.RSAPublicNumbers(
-                        e=7,
-                        n=33
-                    )
+            rsa.RSAPrivateNumbers(
+                p=3,
+                q=11,
+                d=3,
+                dmp1=1,
+                dmq1=4,
+                iqmp=2,
+                public_numbers=rsa.RSAPublicNumbers(
+                    e=7,
+                    n=33
                 )
-            )
+            ).private_key(backend)
diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py
index ae990b6..8a90b30 100644
--- a/tests/hazmat/primitives/test_serialization.py
+++ b/tests/hazmat/primitives/test_serialization.py
@@ -23,13 +23,9 @@
 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,
-    load_rsa_private_numbers,
-    load_rsa_public_numbers
+    load_pem_pkcs8_private_key, load_pem_traditional_openssl_private_key
 )
 
-from .fixtures_rsa import RSA_KEY_1024
 from .utils import _check_rsa_private_numbers, load_vectors_from_file
 from ...utils import raises_unsupported_algorithm
 
@@ -553,18 +549,3 @@
                     pemfile.read().encode(), password, backend
                 )
             )
-
-
-@pytest.mark.rsa
-class TestLoadRSANumbers(object):
-    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 54659aa..49b73f0 100644
--- a/tests/hazmat/primitives/utils.py
+++ b/tests/hazmat/primitives/utils.py
@@ -28,9 +28,6 @@
 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
 
@@ -395,7 +392,7 @@
         e=params["public_exponent"],
         n=params["modulus"]
     )
-    public_key = load_rsa_public_numbers(public_numbers, backend)
+    public_key = public_numbers.public_key(backend)
     pad = pad_factory(params, hash_alg)
     verifier = public_key.verifier(
         binascii.unhexlify(params["s"]),