Skip to content

Commit

Permalink
Deprecate passing PKey instances to use_privatekey
Browse files Browse the repository at this point in the history
Allow passing cryptography keys instead.

Refs #1321
  • Loading branch information
alex committed Aug 6, 2024
1 parent 0eaef1c commit 8765c30
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Deprecations:
- Deprecated ``OpenSSL.rand`` - callers should use ``os.urandom()`` instead.
- Deprecated ``OpenSSL.crypto.get_elliptic_curves`` and ``OpenSSL.crypto.get_elliptic_curve``, as well as passing the reult of them to ``OpenSSL.SSL.Context.set_tmp_ecdh``, users should instead pass curves from ``cryptography``.
- Deprecated passing ``X509`` objects to ``OpenSSL.SSL.Context.use_certificate``, ``OpenSSL.SSL.Connection.use_certificate``, ``OpenSSL.SSL.Context.add_extra_chain_cert``, and ``OpenSSL.SSL.Context.add_client_ca``, users should instead pass ``cryptography.x509.Certificate`` instances. This is in preparation for deprecating pyOpenSSL's ``X509`` entirely.
- Deprecated passing ``PKey`` objects to ``OpenSSL.SSL.Context.use_privatekey`` and ``OpenSSL.SSL.Connection.use_privatekey``, users should instead pass ``cryptography`` priate key instances. This is in preparation for deprecating pyOpenSSL's ``PKey`` entirely.

Changes:
^^^^^^^^
Expand Down
27 changes: 23 additions & 4 deletions src/OpenSSL/SSL.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
X509Store,
_EllipticCurve,
_PassphraseHelper,
_PrivateKey,
)

__all__ = [
Expand Down Expand Up @@ -1204,7 +1205,7 @@ def use_privatekey_file(
if not use_result:
self._raise_passphrase_exception()

def use_privatekey(self, pkey: PKey) -> None:
def use_privatekey(self, pkey: _PrivateKey | PKey) -> None:
"""
Load a private key from a PKey object
Expand All @@ -1213,7 +1214,16 @@ def use_privatekey(self, pkey: PKey) -> None:
"""
# Mirrored at Connection.use_privatekey
if not isinstance(pkey, PKey):
raise TypeError("pkey must be a PKey instance")
pkey = PKey.from_cryptography_key(pkey)
else:
warnings.warn(
(
"Passing pyOpenSSL PKey objects is deprecated. You "
"should use a cryptography private key instead."
),
DeprecationWarning,
stacklevel=2,
)

use_result = _lib.SSL_CTX_use_PrivateKey(self._context, pkey._pkey)
if not use_result:
Expand Down Expand Up @@ -2070,7 +2080,7 @@ def use_certificate(self, cert: X509 | x509.Certificate) -> None:
if not use_result:
_raise_current_error()

def use_privatekey(self, pkey: PKey) -> None:
def use_privatekey(self, pkey: _PrivateKey | PKey) -> None:
"""
Load a private key from a PKey object
Expand All @@ -2079,7 +2089,16 @@ def use_privatekey(self, pkey: PKey) -> None:
"""
# Mirrored from Context.use_privatekey
if not isinstance(pkey, PKey):
raise TypeError("pkey must be a PKey instance")
pkey = PKey.from_cryptography_key(pkey)
else:
warnings.warn(
(
"Passing pyOpenSSL PKey objects is deprecated. You "
"should use a cryptography private key instead."
),
DeprecationWarning,
stacklevel=2,
)

use_result = _lib.SSL_use_PrivateKey(self._ssl, pkey._pkey)
if not use_result:
Expand Down
17 changes: 11 additions & 6 deletions src/OpenSSL/crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,23 @@
]


_Key = Union[
_PrivateKey = Union[
dsa.DSAPrivateKey,
dsa.DSAPublicKey,
ec.EllipticCurvePrivateKey,
ec.EllipticCurvePublicKey,
ed25519.Ed25519PrivateKey,
ed25519.Ed25519PublicKey,
ed448.Ed448PrivateKey,
ed448.Ed448PublicKey,
rsa.RSAPrivateKey,
rsa.RSAPublicKey,
]
_Key = (
Union[
dsa.DSAPublicKey,
ec.EllipticCurvePublicKey,
ed25519.Ed25519PublicKey,
ed448.Ed448PublicKey,
rsa.RSAPublicKey,
]
| _PrivateKey
)
StrOrBytesPath = Union[str, bytes, PathLike]
PassphraseCallableT = Union[bytes, Callable[..., bytes]]

Expand Down
13 changes: 13 additions & 0 deletions tests/test_ssl.py
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,11 @@ def test_check_privatekey_valid(self):
context.use_certificate(cert)
assert None is context.check_privatekey()

context = Context(SSLv23_METHOD)
context.use_privatekey(key.to_cryptography_key())
context.use_certificate(cert)
assert None is context.check_privatekey()

def test_check_privatekey_invalid(self):
"""
`Context.check_privatekey` raises `Error` if the `Context` instance
Expand All @@ -741,6 +746,12 @@ def test_check_privatekey_invalid(self):
with pytest.raises(Error):
context.check_privatekey()

context = Context(SSLv23_METHOD)
context.use_privatekey(key.to_cryptography_key())
context.use_certificate(cert)
with pytest.raises(Error):
context.check_privatekey()

def test_app_data(self):
"""
`Context.set_app_data` stores an object for later retrieval
Expand Down Expand Up @@ -2163,6 +2174,8 @@ def test_use_privatekey(self, ctx_or_conn):
with pytest.raises(TypeError):
ctx_or_conn.use_privatekey("")

ctx_or_conn.use_privatekey(key.to_cryptography_key())

def test_use_privatekey_wrong_key(self, ctx_or_conn):
"""
`use_privatekey` raises `OpenSSL.SSL.Error` when passed a
Expand Down

0 comments on commit 8765c30

Please sign in to comment.