Merge pull request #1193 from reaperhulk/simplify-some-ec-things
reorganize OpenSSL EC backend to remove some unneeded indirection
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 0f26be4..e057b63 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -28,9 +28,20 @@
* Deprecated :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey`
in favor of backend specific providers of the
:class:`~cryptography.hazmat.primitives.interfaces.RSAPublicKey` interface.
+* Deprecated :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateKey`
+ in favor of backend specific providers of the
+ :class:`~cryptography.hazmat.primitives.interfaces.DSAPrivateKey` interface.
+* Deprecated :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicKey`
+ in favor of backend specific providers of the
+ :class:`~cryptography.hazmat.primitives.interfaces.DSAPublicKey` interface.
+* Deprecated :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameters`
+ in favor of backend specific providers of the
+ :class:`~cryptography.hazmat.primitives.interfaces.DSAParameters` interface.
* Deprecated ``encrypt_rsa``, ``decrypt_rsa``, ``create_rsa_signature_ctx`` and
``create_rsa_verification_ctx`` on
:class:`~cryptography.hazmat.backends.interfaces.RSABackend`.
+* Deprecated ``create_dsa_signature_ctx`` and ``create_dsa_verification_ctx``
+ on :class:`~cryptography.hazmat.backends.interfaces.DSABackend`.
0.4 - 2014-05-03
~~~~~~~~~~~~~~~~
diff --git a/cryptography/hazmat/backends/openssl/backend.py b/cryptography/hazmat/backends/openssl/backend.py
index 9f002f1..e8fc3a4 100644
--- a/cryptography/hazmat/backends/openssl/backend.py
+++ b/cryptography/hazmat/backends/openssl/backend.py
@@ -633,12 +633,24 @@
return self.generate_dsa_private_key(parameters)
def create_dsa_signature_ctx(self, private_key, algorithm):
+ warnings.warn(
+ "create_dsa_signature_ctx is deprecated and will be removed in "
+ "a future version.",
+ utils.DeprecatedIn05,
+ stacklevel=2
+ )
dsa_cdata = self._dsa_cdata_from_private_key(private_key)
key = _DSAPrivateKey(self, dsa_cdata)
return _DSASignatureContext(self, key, algorithm)
def create_dsa_verification_ctx(self, public_key, signature,
algorithm):
+ warnings.warn(
+ "create_dsa_verification_ctx is deprecated and will be removed in "
+ "a future version.",
+ utils.DeprecatedIn05,
+ stacklevel=2
+ )
dsa_cdata = self._dsa_cdata_from_public_key(public_key)
key = _DSAPublicKey(self, dsa_cdata)
return _DSAVerificationContext(self, key, signature, algorithm)
@@ -743,122 +755,6 @@
key = _RSAPublicKey(self, rsa_cdata)
return key.encrypt(plaintext, padding)
- def _enc_dec_rsa(self, key, data, padding):
- if isinstance(padding, PKCS1v15):
- padding_enum = self._lib.RSA_PKCS1_PADDING
- elif isinstance(padding, OAEP):
- padding_enum = self._lib.RSA_PKCS1_OAEP_PADDING
- if not isinstance(padding._mgf, MGF1):
- raise UnsupportedAlgorithm(
- "Only MGF1 is supported by this backend.",
- _Reasons.UNSUPPORTED_MGF
- )
-
- if not isinstance(padding._mgf._algorithm, hashes.SHA1):
- raise UnsupportedAlgorithm(
- "This backend supports only SHA1 inside MGF1 when "
- "using OAEP.",
- _Reasons.UNSUPPORTED_HASH
- )
-
- if padding._label is not None and padding._label != b"":
- raise ValueError("This backend does not support OAEP labels.")
-
- if not isinstance(padding._algorithm, hashes.SHA1):
- raise UnsupportedAlgorithm(
- "This backend only supports SHA1 when using OAEP.",
- _Reasons.UNSUPPORTED_HASH
- )
- else:
- raise UnsupportedAlgorithm(
- "{0} is not supported by this backend.".format(
- padding.name
- ),
- _Reasons.UNSUPPORTED_PADDING
- )
-
- if self._lib.Cryptography_HAS_PKEY_CTX:
- return self._enc_dec_rsa_pkey_ctx(key, data, padding_enum)
- else:
- return self._enc_dec_rsa_098(key, data, padding_enum)
-
- def _enc_dec_rsa_pkey_ctx(self, key, data, padding_enum):
- evp_pkey = key._evp_pkey
-
- if isinstance(key, _RSAPublicKey):
- init = self._lib.EVP_PKEY_encrypt_init
- crypt = self._lib.Cryptography_EVP_PKEY_encrypt
- else:
- init = self._lib.EVP_PKEY_decrypt_init
- crypt = self._lib.Cryptography_EVP_PKEY_decrypt
-
- pkey_ctx = self._lib.EVP_PKEY_CTX_new(
- evp_pkey, self._ffi.NULL
- )
- assert pkey_ctx != self._ffi.NULL
- pkey_ctx = self._ffi.gc(pkey_ctx, self._lib.EVP_PKEY_CTX_free)
- res = init(pkey_ctx)
- assert res == 1
- res = self._lib.EVP_PKEY_CTX_set_rsa_padding(
- pkey_ctx, padding_enum)
- assert res > 0
- buf_size = self._lib.EVP_PKEY_size(evp_pkey)
- assert buf_size > 0
- outlen = self._ffi.new("size_t *", buf_size)
- buf = self._ffi.new("char[]", buf_size)
- res = crypt(
- pkey_ctx,
- buf,
- outlen,
- data,
- len(data)
- )
- if res <= 0:
- self._handle_rsa_enc_dec_error(key)
-
- return self._ffi.buffer(buf)[:outlen[0]]
-
- def _enc_dec_rsa_098(self, key, data, padding_enum):
- rsa_cdata = key._rsa_cdata
-
- if isinstance(key, _RSAPublicKey):
- crypt = self._lib.RSA_public_encrypt
- else:
- crypt = self._lib.RSA_private_decrypt
-
- key_size = self._lib.RSA_size(rsa_cdata)
- assert key_size > 0
- buf = self._ffi.new("unsigned char[]", key_size)
- res = crypt(
- len(data),
- data,
- buf,
- rsa_cdata,
- padding_enum
- )
- if res < 0:
- self._handle_rsa_enc_dec_error(key)
-
- return self._ffi.buffer(buf)[:res]
-
- def _handle_rsa_enc_dec_error(self, key):
- errors = self._consume_errors()
- assert errors
- assert errors[0].lib == self._lib.ERR_LIB_RSA
- if isinstance(key, _RSAPublicKey):
- assert (errors[0].reason ==
- self._lib.RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE)
- raise ValueError(
- "Data too long for key size. Encrypt less data or use a "
- "larger key size."
- )
- else:
- assert (
- errors[0].reason == self._lib.RSA_R_BLOCK_TYPE_IS_NOT_01 or
- errors[0].reason == self._lib.RSA_R_BLOCK_TYPE_IS_NOT_02
- )
- raise ValueError("Decryption failed.")
-
def cmac_algorithm_supported(self, algorithm):
return (
self._lib.Cryptography_HAS_CMAC == 1
diff --git a/cryptography/hazmat/backends/openssl/rsa.py b/cryptography/hazmat/backends/openssl/rsa.py
index a62a89f..6f28c54 100644
--- a/cryptography/hazmat/backends/openssl/rsa.py
+++ b/cryptography/hazmat/backends/openssl/rsa.py
@@ -22,7 +22,7 @@
from cryptography.hazmat.primitives import hashes, interfaces
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.asymmetric.padding import (
- MGF1, PKCS1v15, PSS
+ MGF1, OAEP, PKCS1v15, PSS
)
from cryptography.hazmat.primitives.interfaces import (
RSAPrivateKeyWithNumbers, RSAPublicKeyWithNumbers
@@ -45,6 +45,110 @@
return salt
+def _enc_dec_rsa(backend, key, data, padding):
+ if isinstance(padding, PKCS1v15):
+ padding_enum = backend._lib.RSA_PKCS1_PADDING
+ elif isinstance(padding, OAEP):
+ padding_enum = backend._lib.RSA_PKCS1_OAEP_PADDING
+ if not isinstance(padding._mgf, MGF1):
+ raise UnsupportedAlgorithm(
+ "Only MGF1 is supported by this backend.",
+ _Reasons.UNSUPPORTED_MGF
+ )
+
+ if not isinstance(padding._mgf._algorithm, hashes.SHA1):
+ raise UnsupportedAlgorithm(
+ "This backend supports only SHA1 inside MGF1 when "
+ "using OAEP.",
+ _Reasons.UNSUPPORTED_HASH
+ )
+
+ if padding._label is not None and padding._label != b"":
+ raise ValueError("This backend does not support OAEP labels.")
+
+ if not isinstance(padding._algorithm, hashes.SHA1):
+ raise UnsupportedAlgorithm(
+ "This backend only supports SHA1 when using OAEP.",
+ _Reasons.UNSUPPORTED_HASH
+ )
+ else:
+ raise UnsupportedAlgorithm(
+ "{0} is not supported by this backend.".format(
+ padding.name
+ ),
+ _Reasons.UNSUPPORTED_PADDING
+ )
+
+ if backend._lib.Cryptography_HAS_PKEY_CTX:
+ return _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum)
+ else:
+ return _enc_dec_rsa_098(backend, key, data, padding_enum)
+
+
+def _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum):
+ if isinstance(key, _RSAPublicKey):
+ init = backend._lib.EVP_PKEY_encrypt_init
+ crypt = backend._lib.Cryptography_EVP_PKEY_encrypt
+ else:
+ init = backend._lib.EVP_PKEY_decrypt_init
+ crypt = backend._lib.Cryptography_EVP_PKEY_decrypt
+
+ pkey_ctx = backend._lib.EVP_PKEY_CTX_new(
+ key._evp_pkey, backend._ffi.NULL
+ )
+ assert pkey_ctx != backend._ffi.NULL
+ pkey_ctx = backend._ffi.gc(pkey_ctx, backend._lib.EVP_PKEY_CTX_free)
+ res = init(pkey_ctx)
+ assert res == 1
+ res = backend._lib.EVP_PKEY_CTX_set_rsa_padding(
+ pkey_ctx, padding_enum)
+ assert res > 0
+ buf_size = backend._lib.EVP_PKEY_size(key._evp_pkey)
+ assert buf_size > 0
+ outlen = backend._ffi.new("size_t *", buf_size)
+ buf = backend._ffi.new("char[]", buf_size)
+ res = crypt(pkey_ctx, buf, outlen, data, len(data))
+ if res <= 0:
+ _handle_rsa_enc_dec_error(backend, key)
+
+ return backend._ffi.buffer(buf)[:outlen[0]]
+
+
+def _enc_dec_rsa_098(backend, key, data, padding_enum):
+ if isinstance(key, _RSAPublicKey):
+ crypt = backend._lib.RSA_public_encrypt
+ else:
+ crypt = backend._lib.RSA_private_decrypt
+
+ key_size = backend._lib.RSA_size(key._rsa_cdata)
+ assert key_size > 0
+ buf = backend._ffi.new("unsigned char[]", key_size)
+ res = crypt(len(data), data, buf, key._rsa_cdata, padding_enum)
+ if res < 0:
+ _handle_rsa_enc_dec_error(backend, key)
+
+ return backend._ffi.buffer(buf)[:res]
+
+
+def _handle_rsa_enc_dec_error(backend, key):
+ errors = backend._consume_errors()
+ assert errors
+ assert errors[0].lib == backend._lib.ERR_LIB_RSA
+ if isinstance(key, _RSAPublicKey):
+ assert (errors[0].reason ==
+ backend._lib.RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE)
+ raise ValueError(
+ "Data too long for key size. Encrypt less data or use a "
+ "larger key size."
+ )
+ else:
+ assert (
+ errors[0].reason == backend._lib.RSA_R_BLOCK_TYPE_IS_NOT_01 or
+ errors[0].reason == backend._lib.RSA_R_BLOCK_TYPE_IS_NOT_02
+ )
+ raise ValueError("Decryption failed.")
+
+
@utils.register_interface(interfaces.AsymmetricSignatureContext)
class _RSASignatureContext(object):
def __init__(self, backend, private_key, padding, algorithm):
@@ -436,7 +540,7 @@
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)
+ return _enc_dec_rsa(self._backend, self, ciphertext, padding)
def public_key(self):
ctx = self._backend._lib.RSA_new()
@@ -490,7 +594,7 @@
)
def encrypt(self, plaintext, padding):
- return self._backend._enc_dec_rsa(self, plaintext, padding)
+ return _enc_dec_rsa(self._backend, self, plaintext, padding)
def public_numbers(self):
return rsa.RSAPublicNumbers(
diff --git a/cryptography/hazmat/primitives/asymmetric/dsa.py b/cryptography/hazmat/primitives/asymmetric/dsa.py
index 7a8a61c..04b2272 100644
--- a/cryptography/hazmat/primitives/asymmetric/dsa.py
+++ b/cryptography/hazmat/primitives/asymmetric/dsa.py
@@ -13,6 +13,8 @@
from __future__ import absolute_import, division, print_function
+import warnings
+
import six
from cryptography import utils
@@ -56,6 +58,12 @@
@utils.register_interface(interfaces.DSAParameters)
class DSAParameters(object):
def __init__(self, modulus, subgroup_order, generator):
+ warnings.warn(
+ "The DSAParameters class is deprecated and will be removed in a "
+ "future version.",
+ utils.DeprecatedIn05,
+ stacklevel=2
+ )
_check_dsa_parameters(
DSAParameterNumbers(
p=modulus,
@@ -70,6 +78,11 @@
@classmethod
def generate(cls, key_size, backend):
+ warnings.warn(
+ "generate is deprecated and will be removed in a future version.",
+ utils.DeprecatedIn05,
+ stacklevel=2
+ )
if not isinstance(backend, DSABackend):
raise UnsupportedAlgorithm(
"Backend object does not implement DSABackend.",
@@ -112,6 +125,12 @@
@utils.register_interface(interfaces.DSAPrivateKey)
class DSAPrivateKey(object):
def __init__(self, modulus, subgroup_order, generator, x, y):
+ warnings.warn(
+ "The DSAPrivateKey class is deprecated and will be removed in a "
+ "future version.",
+ utils.DeprecatedIn05,
+ stacklevel=2
+ )
if (
not isinstance(x, six.integer_types) or
not isinstance(y, six.integer_types)
@@ -140,6 +159,11 @@
@classmethod
def generate(cls, parameters, backend):
+ warnings.warn(
+ "generate is deprecated and will be removed in a future version.",
+ utils.DeprecatedIn05,
+ stacklevel=2
+ )
if not isinstance(backend, DSABackend):
raise UnsupportedAlgorithm(
"Backend object does not implement DSABackend.",
@@ -189,6 +213,12 @@
@utils.register_interface(interfaces.DSAPublicKey)
class DSAPublicKey(object):
def __init__(self, modulus, subgroup_order, generator, y):
+ warnings.warn(
+ "The DSAPublicKey class is deprecated and will be removed in a "
+ "future version.",
+ utils.DeprecatedIn05,
+ stacklevel=2
+ )
_check_dsa_parameters(
DSAParameterNumbers(
p=modulus,
diff --git a/docs/hazmat/backends/interfaces.rst b/docs/hazmat/backends/interfaces.rst
index fea935c..8622912 100644
--- a/docs/hazmat/backends/interfaces.rst
+++ b/docs/hazmat/backends/interfaces.rst
@@ -439,6 +439,8 @@
.. method:: create_dsa_signature_ctx(private_key, algorithm)
+ .. deprecated:: 0.5
+
:param private_key: An instance of a
:class:`~cryptography.hazmat.primitives.interfaces.DSAPrivateKey`
provider.
@@ -452,6 +454,8 @@
.. method:: create_dsa_verification_ctx(public_key, signature, algorithm)
+ .. deprecated:: 0.5
+
:param public_key: An instance of a
:class:`~cryptography.hazmat.primitives.interfaces.DSAPublicKey`
provider.
diff --git a/docs/hazmat/primitives/asymmetric/dsa.rst b/docs/hazmat/primitives/asymmetric/dsa.rst
index 095c49b..6cb624d 100644
--- a/docs/hazmat/primitives/asymmetric/dsa.rst
+++ b/docs/hazmat/primitives/asymmetric/dsa.rst
@@ -7,6 +7,9 @@
`DSA`_ is a `public-key`_ algorithm for signing messages.
+Generation
+~~~~~~~~~~
+
.. function:: generate_private_key(key_size, backend)
.. versionadded:: 0.5
@@ -28,6 +31,10 @@
:return: A :class:`~cryptography.hazmat.primitives.interfaces.DSAPrivateKey`
provider.
+ :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
+ the provided ``backend`` does not implement
+ :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
+
.. function:: generate_parameters(key_size, backend)
.. versionadded:: 0.5
@@ -52,208 +59,41 @@
the provided ``backend`` does not implement
:class:`~cryptography.hazmat.backends.interfaces.DSABackend`
-.. class:: DSAParameters(modulus, subgroup_order, generator)
+Signing
+~~~~~~~
- .. versionadded:: 0.4
+Using a :class:`~cryptography.hazmat.primitives.interfaces.DSAPrivateKey`
+provider.
- DSA Parameters are required for generating a DSA private key.
+.. doctest::
- You should use :meth:`~generate` to generate new parameters.
+ >>> from cryptography.hazmat.backends import default_backend
+ >>> from cryptography.hazmat.primitives import hashes
+ >>> from cryptography.hazmat.primitives.asymmetric import dsa
+ >>> private_key = dsa.generate_private_key(
+ ... key_size=1024,
+ ... backend=default_backend()
+ ... )
+ >>> signer = private_key.signer(hashes.SHA256())
+ >>> data = b"this is some data I'd like to sign"
+ >>> signer.update(data)
+ >>> signature = signer.finalize()
- .. warning::
- This method only checks a limited set of properties of its arguments.
- Using DSA parameters that you do not trust or with incorrect arguments
- may lead to insecure operation, crashes, and other undefined behavior.
- We recommend that you only ever load parameters that were generated
- with software you trust.
+Verification
+~~~~~~~~~~~~
+Using a :class:`~cryptography.hazmat.primitives.interfaces.DSAPublicKey`
+provider.
- This class conforms to the
- :class:`~cryptography.hazmat.primitives.interfaces.DSAParameters`
- interface.
+.. doctest::
- :raises TypeError: This is raised when the arguments are not all integers.
+ >>> public_key = private_key.public_key()
+ >>> verifier = public_key.verifier(signature, hashes.SHA256())
+ >>> verifier.update(data)
+ >>> verifier.verify()
- :raises ValueError: This is raised when the values of ``modulus``,
- ``subgroup_order``, or ``generator`` do
- not match the bounds specified in `FIPS 186-4`_.
-
- .. classmethod:: generate(key_size, backend)
-
- Generate a new ``DSAParameters`` instance using ``backend``.
-
- :param int key_size: The length of the modulus in bits. It should be
- either 1024, 2048 or 3072. For keys generated in 2014 this should
- be `at least 2048`_ (See page 41). Note that some applications
- (such as SSH) have not yet gained support for larger key sizes
- specified in FIPS 186-3 and are still restricted to only the
- 1024-bit keys specified in FIPS 186-2.
-
- :return: A new instance of ``DSAParameters``
-
- :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
- the provided ``backend`` does not implement
- :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
-
-
-.. class:: DSAPrivateKey(modulus, subgroup_order, generator, x, y)
-
- .. versionadded:: 0.4
-
- A DSA private key is required for signing messages.
-
- You should use :meth:`~generate` to generate new keys.
-
- .. warning::
- This method only checks a limited set of properties of its arguments.
- Using a DSA private key that you do not trust or with incorrect
- parameters may lead to insecure operation, crashes, and other undefined
- behavior. We recommend that you only ever load private keys that were
- generated with software you trust.
-
-
- This class conforms to the
- :class:`~cryptography.hazmat.primitives.interfaces.DSAPrivateKey`
- interface.
-
- :raises TypeError: This is raised when the arguments are not all integers.
-
- :raises ValueError: This is raised when the values of ``modulus``,
- ``subgroup_order``, or ``generator`` do
- not match the bounds specified in `FIPS 186-4`_.
-
- .. classmethod:: generate(parameters, backend)
-
- Generate a new ``DSAPrivateKey`` instance using ``backend``.
-
- :param parameters: A
- :class:`~cryptography.hazmat.primitives.interfaces.DSAParameters`
- provider.
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
- provider.
- :return: A new instance of ``DSAPrivateKey``.
-
- :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
- the provided ``backend`` does not implement
- :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
-
- :raises ValueError: This is raised if the key size is not (1024 or 2048 or 3072)
- or if the OpenSSL version is older than 1.0.0 and the key size is larger than 1024
- because older OpenSSL versions don't support a key size larger than 1024.
-
- .. method:: signer(algorithm, backend)
-
- .. versionadded:: 0.4
-
- Sign data which can be verified later by others using the public key.
-
- .. doctest::
-
- >>> from cryptography.hazmat.backends import default_backend
- >>> from cryptography.hazmat.primitives import hashes
- >>> from cryptography.hazmat.primitives.asymmetric import dsa
- >>> parameters = dsa.DSAParameters.generate(
- ... key_size=1024,
- ... backend=default_backend()
- ... )
- >>> private_key = dsa.DSAPrivateKey.generate(
- ... parameters=parameters,
- ... backend=default_backend()
- ... )
- >>> signer = private_key.signer(
- ... hashes.SHA256(),
- ... default_backend()
- ... )
- >>> data = b"this is some data I'd like to sign"
- >>> signer.update(data)
- >>> signature = signer.finalize()
-
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
- provider.
-
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.RSABackend`
- provider.
-
- :returns:
- :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricSignatureContext`
-
- :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
- the provided ``backend`` does not implement
- :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
-
-
-.. class:: DSAPublicKey(modulus, subgroup_order, generator, y)
-
- .. versionadded:: 0.4
-
- A DSA public key is required for verifying messages.
-
- Normally you do not need to directly construct public keys because you'll
- be loading them from a file, generating them automatically or receiving
- them from a 3rd party.
-
- This class conforms to the
- :class:`~cryptography.hazmat.primitives.interfaces.DSAPublicKey`
- interface.
-
- :raises TypeError: This is raised when the arguments are not all integers.
-
- :raises ValueError: This is raised when the values of ``modulus``,
- ``subgroup_order``, ``generator``, or ``y``
- do not match the bounds specified in `FIPS 186-4`_.
-
- .. method:: verifier(signature, algorithm, backend)
-
- .. versionadded:: 0.4
-
- Verify data was signed by the private key associated with this public
- key.
-
- .. doctest::
-
- >>> from cryptography.hazmat.backends import default_backend
- >>> from cryptography.hazmat.primitives import hashes
- >>> from cryptography.hazmat.primitives.asymmetric import dsa
- >>> parameters = dsa.DSAParameters.generate(
- ... key_size=1024,
- ... backend=default_backend()
- ... )
- >>> private_key = dsa.DSAPrivateKey.generate(
- ... parameters=parameters,
- ... backend=default_backend()
- ... )
- >>> signer = private_key.signer(
- ... hashes.SHA256(),
- ... default_backend()
- ... )
- >>> data = b"this is some data I'd like to sign"
- >>> signer.update(data)
- >>> signature = signer.finalize()
- >>> public_key = private_key.public_key()
- >>> verifier = public_key.verifier(
- ... signature,
- ... hashes.SHA256(),
- ... default_backend()
- ... )
- >>> verifier.update(data)
- >>> verifier.verify()
-
- :param bytes signature: The signature to verify. DER encoded as
- specified in :rfc:`6979`.
-
- :param algorithm: An instance of a
- :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
- provider.
-
- :param backend: A
- :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
- provider.
-
- :returns:
- :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricVerificationContext`
+Numbers
+~~~~~~~
.. class:: DSAParameterNumbers(p, q, g)
@@ -322,6 +162,175 @@
The :class:`~cryptography.hazmat.primitives.dsa.DSAPublicNumbers`
associated with the private key.
+Deprecated Concrete Classes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+These classes were deprecated in version 0.5 in favor of backend specific
+providers of the
+:class:`~cryptography.hazmat.primitives.interfaces.DSAParameters`,
+:class:`~cryptography.hazmat.primitives.interfaces.DSAPrivateKey`, and
+:class:`~cryptography.hazmat.primitives.interfaces.DSAPublicKey` interfaces.
+>>>>>>> deprecate concrete DSA classes and update DSA docs
+
+.. class:: DSAParameters(modulus, subgroup_order, generator)
+
+ .. versionadded:: 0.4
+
+ .. deprecated:: 0.5
+
+ DSA Parameters are required for generating a DSA private key.
+
+ You should use :meth:`~generate` to generate new parameters.
+
+ .. warning::
+ This method only checks a limited set of properties of its arguments.
+ Using DSA parameters that you do not trust or with incorrect arguments
+ may lead to insecure operation, crashes, and other undefined behavior.
+ We recommend that you only ever load parameters that were generated
+ with software you trust.
+
+
+ This class conforms to the
+ :class:`~cryptography.hazmat.primitives.interfaces.DSAParameters`
+ interface.
+
+ :raises TypeError: This is raised when the arguments are not all integers.
+
+ :raises ValueError: This is raised when the values of ``modulus``,
+ ``subgroup_order``, or ``generator`` do
+ not match the bounds specified in `FIPS 186-4`_.
+
+ .. classmethod:: generate(key_size, backend)
+
+ Generate a new ``DSAParameters`` instance using ``backend``.
+
+ :param int key_size: The length of the modulus in bits. It should be
+ either 1024, 2048 or 3072. For keys generated in 2014 this should
+ be `at least 2048`_ (See page 41). Note that some applications
+ (such as SSH) have not yet gained support for larger key sizes
+ specified in FIPS 186-3 and are still restricted to only the
+ 1024-bit keys specified in FIPS 186-2.
+
+ :return: A new instance of ``DSAParameters``
+
+ :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
+ the provided ``backend`` does not implement
+ :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
+
+
+.. class:: DSAPrivateKey(modulus, subgroup_order, generator, x, y)
+
+ .. versionadded:: 0.4
+
+ .. deprecated:: 0.5
+
+ A DSA private key is required for signing messages.
+
+ You should use :meth:`~generate` to generate new keys.
+
+ .. warning::
+ This method only checks a limited set of properties of its arguments.
+ Using a DSA private key that you do not trust or with incorrect
+ parameters may lead to insecure operation, crashes, and other undefined
+ behavior. We recommend that you only ever load private keys that were
+ generated with software you trust.
+
+
+ This class conforms to the
+ :class:`~cryptography.hazmat.primitives.interfaces.DSAPrivateKey`
+ interface.
+
+ :raises TypeError: This is raised when the arguments are not all integers.
+
+ :raises ValueError: This is raised when the values of ``modulus``,
+ ``subgroup_order``, or ``generator`` do
+ not match the bounds specified in `FIPS 186-4`_.
+
+ .. classmethod:: generate(parameters, backend)
+
+ Generate a new ``DSAPrivateKey`` instance using ``backend``.
+
+ :param parameters: A
+ :class:`~cryptography.hazmat.primitives.interfaces.DSAParameters`
+ provider.
+ :param backend: A
+ :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
+ provider.
+ :return: A new instance of ``DSAPrivateKey``.
+
+ :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
+ the provided ``backend`` does not implement
+ :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
+
+ :raises ValueError: This is raised if the key size is not (1024 or 2048 or 3072)
+ or if the OpenSSL version is older than 1.0.0 and the key size is larger than 1024
+ because older OpenSSL versions don't support a key size larger than 1024.
+
+ .. method:: signer(algorithm, backend)
+
+ .. versionadded:: 0.4
+
+ Sign data which can be verified later by others using the public key.
+
+ :param algorithm: An instance of a
+ :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+ provider.
+
+ :param backend: A
+ :class:`~cryptography.hazmat.backends.interfaces.RSABackend`
+ provider.
+
+ :returns:
+ :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricSignatureContext`
+
+ :raises cryptography.exceptions.UnsupportedAlgorithm: This is raised if
+ the provided ``backend`` does not implement
+ :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
+
+
+.. class:: DSAPublicKey(modulus, subgroup_order, generator, y)
+
+ .. versionadded:: 0.4
+
+ .. deprecated:: 0.5
+
+ A DSA public key is required for verifying messages.
+
+ Normally you do not need to directly construct public keys because you'll
+ be loading them from a file, generating them automatically or receiving
+ them from a 3rd party.
+
+ This class conforms to the
+ :class:`~cryptography.hazmat.primitives.interfaces.DSAPublicKey`
+ interface.
+
+ :raises TypeError: This is raised when the arguments are not all integers.
+
+ :raises ValueError: This is raised when the values of ``modulus``,
+ ``subgroup_order``, ``generator``, or ``y``
+ do not match the bounds specified in `FIPS 186-4`_.
+
+ .. method:: verifier(signature, algorithm, backend)
+
+ .. versionadded:: 0.4
+
+ Verify data was signed by the private key associated with this public
+ key.
+
+ :param bytes signature: The signature to verify. DER encoded as
+ specified in :rfc:`6979`.
+
+ :param algorithm: An instance of a
+ :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
+ provider.
+
+ :param backend: A
+ :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
+ provider.
+
+ :returns:
+ :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricVerificationContext`
+
.. _`DSA`: https://en.wikipedia.org/wiki/Digital_Signature_Algorithm
.. _`public-key`: https://en.wikipedia.org/wiki/Public-key_cryptography
.. _`FIPS 186-4`: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py
index bd99c8f..696a0f7 100644
--- a/tests/hazmat/backends/test_openssl.py
+++ b/tests/hazmat/backends/test_openssl.py
@@ -524,3 +524,25 @@
ct,
padding.PKCS1v15()
)
+
+
+class TestDeprecatedDSABackendMethods(object):
+ def test_create_dsa_signature_ctx(self):
+ params = dsa.DSAParameters.generate(1024, backend)
+ key = dsa.DSAPrivateKey.generate(params, backend)
+ pytest.deprecated_call(
+ backend.create_dsa_signature_ctx,
+ key,
+ hashes.SHA1()
+ )
+
+ def test_create_dsa_verification_ctx(self):
+ params = dsa.DSAParameters.generate(1024, backend)
+ key = dsa.DSAPrivateKey.generate(params, backend)
+ public_key = key.public_key()
+ pytest.deprecated_call(
+ backend.create_dsa_verification_ctx,
+ public_key,
+ b"\x00" * 128,
+ hashes.SHA1()
+ )
diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py
index 531b448..8c87cfd 100644
--- a/tests/hazmat/primitives/test_dsa.py
+++ b/tests/hazmat/primitives/test_dsa.py
@@ -698,9 +698,17 @@
verifier.verify()
def test_dsa_verify_invalid_asn1(self, backend):
- parameters = dsa.DSAParameters.generate(1024, backend)
- private_key = dsa.DSAPrivateKey.generate(parameters, backend)
- public_key = private_key.public_key()
+ parameters = pytest.deprecated_call(
+ dsa.DSAParameters.generate,
+ 1024,
+ backend
+ )
+ private_key = pytest.deprecated_call(
+ dsa.DSAPrivateKey.generate,
+ parameters,
+ backend
+ )
+ public_key = pytest.deprecated_call(private_key.public_key)
verifier = public_key.verifier(b'fakesig', hashes.SHA1(), backend)
verifier.update(b'fakesig')
with pytest.raises(InvalidSignature):