Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use type-level deprecations #1389

Merged
merged 1 commit into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading