Skip to content

Commit

Permalink
Use type-level deprecations (#1389)
Browse files Browse the repository at this point in the history
  • Loading branch information
alex authored Jan 9, 2025
1 parent 70e2835 commit 1b2b0ed
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 70 deletions.
4 changes: 4 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ def find_meta(meta):
package_dir={"": "src"},
install_requires=[
"cryptography>=41.0.5,<45",
(
"typing-extensions>=4.9; "
"python_version < '3.13' and python_version >= '3.8'"
),
],
extras_require={
"test": ["pytest-rerunfailures", "pretend", "pytest>=3.0.1"],
Expand Down
100 changes: 35 additions & 65 deletions src/OpenSSL/crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import calendar
import datetime
import functools
import sys
import typing
import warnings
from base64 import b16encode
Expand All @@ -14,6 +15,16 @@
Union,
)

if sys.version_info >= (3, 13):
from warnings import deprecated
elif sys.version_info < (3, 8):
_T = typing.TypeVar("T")

def deprecated(msg: str, **kwargs: object) -> Callable[[_T], _T]:
return lambda f: f
else:
from typing_extensions import deprecated

from cryptography import utils, x509
from cryptography.hazmat.primitives.asymmetric import (
dsa,
Expand Down Expand Up @@ -529,6 +540,10 @@ def _to_EC_KEY(self) -> Any:
return _ffi.gc(key, _lib.EC_KEY_free)


@deprecated(
"get_elliptic_curves is deprecated. You should use the APIs in "
"cryptography instead."
)
def get_elliptic_curves() -> set[_EllipticCurve]:
"""
Return a set of objects representing the elliptic curves supported in the
Expand All @@ -544,20 +559,10 @@ def get_elliptic_curves() -> set[_EllipticCurve]:
return _EllipticCurve._get_elliptic_curves(_lib)


_get_elliptic_curves_internal = get_elliptic_curves

utils.deprecated(
get_elliptic_curves,
__name__,
(
"get_elliptic_curves is deprecated. You should use the APIs in "
"cryptography instead."
),
DeprecationWarning,
name="get_elliptic_curves",
@deprecated(
"get_elliptic_curve is deprecated. You should use the APIs in "
"cryptography instead."
)


def get_elliptic_curve(name: str) -> _EllipticCurve:
"""
Return a single curve object selected by name.
Expand All @@ -570,24 +575,12 @@ def get_elliptic_curve(name: str) -> _EllipticCurve:
If the named curve is not supported then :py:class:`ValueError` is raised.
"""
for curve in _get_elliptic_curves_internal():
for curve in get_elliptic_curves():
if curve.name == name:
return curve
raise ValueError("unknown curve name", name)


utils.deprecated(
get_elliptic_curve,
__name__,
(
"get_elliptic_curve is deprecated. You should use the APIs in "
"cryptography instead."
),
DeprecationWarning,
name="get_elliptic_curve",
)


@functools.total_ordering
class X509Name:
"""
Expand Down Expand Up @@ -783,6 +776,10 @@ def get_components(self) -> list[tuple[bytes, bytes]]:
return result


@deprecated(
"X509Extension support in pyOpenSSL is deprecated. You should use the "
"APIs in cryptography."
)
class X509Extension:
"""
An X.509 v3 certificate extension.
Expand Down Expand Up @@ -953,19 +950,10 @@ def get_data(self) -> bytes:
return _ffi.buffer(char_result, result_length)[:]


_X509ExtensionInternal = X509Extension
utils.deprecated(
X509Extension,
__name__,
(
"X509Extension support in pyOpenSSL is deprecated. You should use the "
"APIs in cryptography."
),
DeprecationWarning,
name="X509Extension",
@deprecated(
"CSR support in pyOpenSSL is deprecated. You should use the APIs "
"in cryptography."
)


class X509Req:
"""
An X.509 certificate signing requests.
Expand Down Expand Up @@ -1091,9 +1079,7 @@ def get_subject(self) -> X509Name:

return name

def add_extensions(
self, extensions: Iterable[_X509ExtensionInternal]
) -> None:
def add_extensions(self, extensions: Iterable[X509Extension]) -> None:
"""
Add extensions to the certificate signing request.
Expand All @@ -1117,7 +1103,7 @@ def add_extensions(
stack = _ffi.gc(stack, _lib.sk_X509_EXTENSION_free)

for ext in extensions:
if not isinstance(ext, _X509ExtensionInternal):
if not isinstance(ext, X509Extension):
raise ValueError("One of the elements is not an X509Extension")

# TODO push can fail (here and elsewhere)
Expand All @@ -1126,7 +1112,7 @@ def add_extensions(
add_result = _lib.X509_REQ_add_extensions(self._req, stack)
_openssl_assert(add_result == 1)

def get_extensions(self) -> list[_X509ExtensionInternal]:
def get_extensions(self) -> list[X509Extension]:
"""
Get X.509 extensions in the certificate signing request.
Expand Down Expand Up @@ -1156,7 +1142,7 @@ def get_extensions(self) -> list[_X509ExtensionInternal]:
)

for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)):
ext = _X509ExtensionInternal.__new__(_X509ExtensionInternal)
ext = X509Extension.__new__(X509Extension)
extension = _lib.X509_EXTENSION_dup(
_lib.sk_X509_EXTENSION_value(native_exts_obj, i)
)
Expand Down Expand Up @@ -1210,20 +1196,6 @@ def verify(self, pkey: PKey) -> bool:
return result


_X509ReqInternal = X509Req

utils.deprecated(
X509Req,
__name__,
(
"CSR support in pyOpenSSL is deprecated. You should use the APIs "
"in cryptography."
),
DeprecationWarning,
name="X509Req",
)


class X509:
"""
An X.509 certificate.
Expand Down Expand Up @@ -1655,9 +1627,7 @@ def get_extension_count(self) -> int:
"""
return _lib.X509_get_ext_count(self._x509)

def add_extensions(
self, extensions: Iterable[_X509ExtensionInternal]
) -> None:
def add_extensions(self, extensions: Iterable[X509Extension]) -> None:
"""
Add extensions to the certificate.
Expand All @@ -1676,13 +1646,13 @@ def add_extensions(
)

for ext in extensions:
if not isinstance(ext, _X509ExtensionInternal):
if not isinstance(ext, X509Extension):
raise ValueError("One of the elements is not an X509Extension")

add_result = _lib.X509_add_ext(self._x509, ext._extension, -1)
_openssl_assert(add_result == 1)

def get_extension(self, index: int) -> _X509ExtensionInternal:
def get_extension(self, index: int) -> X509Extension:
"""
Get a specific extension of the certificate by index.
Expand All @@ -1706,7 +1676,7 @@ def get_extension(self, index: int) -> _X509ExtensionInternal:
stacklevel=2,
)

ext = _X509ExtensionInternal.__new__(_X509ExtensionInternal)
ext = X509Extension.__new__(X509Extension)
ext._extension = _lib.X509_get_ext(self._x509, index)
if ext._extension == _ffi.NULL:
raise IndexError("extension index out of bounds")
Expand Down Expand Up @@ -2461,7 +2431,7 @@ def load_certificate_request(type: int, buffer: bytes) -> X509Req:

_openssl_assert(req != _ffi.NULL)

x509req = _X509ReqInternal.__new__(_X509ReqInternal)
x509req = X509Req.__new__(X509Req)
x509req._req = _ffi.gc(req, _lib.X509_REQ_free)
return x509req

Expand Down
6 changes: 1 addition & 5 deletions tests/test_crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
X509,
Error,
PKey,
X509Extension,
X509Name,
X509Req,
X509Store,
Expand All @@ -57,11 +58,6 @@
load_publickey,
)

with pytest.warns(DeprecationWarning):
from OpenSSL.crypto import (
X509Extension,
)

from .util import (
NON_ASCII,
)
Expand Down

0 comments on commit 1b2b0ed

Please sign in to comment.