Skip to content

Commit 5f6575b

Browse files
committed
Remove X509Extension, which has been deprecated for a year
1 parent 7e1660b commit 5f6575b

File tree

4 files changed

+1
-659
lines changed

4 files changed

+1
-659
lines changed

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Backward-incompatible changes:
1111
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1212

1313
- Removed the deprecated ``OpenSSL.crypto.CRL``, ``OpenSSL.crypto.Revoked``, ``OpenSSL.crypto.dump_crl``, and ``OpenSSL.crypto.load_crl``. ``cryptography.x509``'s CRL functionality should be used instead.
14+
- Removed deprecated ``OpenSSL.crypto.X509Extension``, ``OpenSSL.crypto.X509Req.add_extension``, ``OpenSSL.crypto.X509Req.get_extensions``, ``OpenSSL.crypto.X509.add_extension``, ``OpenSSL.crypto.X509.get_extensions``. ``cryptography.x509`` should be used instead.
1415
- Removed the deprecated ``OpenSSL.crypto.sign`` and ``OpenSSL.crypto.verify``. ``cryptography.hazmat.primitives.asymmetric``'s signature APIs should be used instead.
1516

1617
Deprecations:

doc/api/crypto.rst

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -148,16 +148,6 @@ PKey objects
148148
149149
Key type constants.
150150

151-
.. _openssl-509ext:
152-
153-
X509Extension objects
154-
---------------------
155-
156-
.. autoclass:: X509Extension
157-
:members:
158-
:special-members:
159-
:exclude-members: __weakref__
160-
161151
Exceptions
162152
----------
163153

src/OpenSSL/crypto.py

Lines changed: 0 additions & 320 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,12 @@
33
import calendar
44
import datetime
55
import functools
6-
import typing
7-
import warnings
86
from base64 import b16encode
97
from functools import partial
108
from os import PathLike
119
from typing import (
1210
Any,
1311
Callable,
14-
Iterable,
1512
Sequence,
1613
Union,
1714
)
@@ -53,7 +50,6 @@
5350
"X509",
5451
"Error",
5552
"PKey",
56-
"X509Extension",
5753
"X509Name",
5854
"X509Req",
5955
"X509Store",
@@ -785,189 +781,6 @@ def get_components(self) -> list[tuple[bytes, bytes]]:
785781
return result
786782

787783

788-
class X509Extension:
789-
"""
790-
An X.509 v3 certificate extension.
791-
792-
.. deprecated:: 23.3.0
793-
Use cryptography's X509 APIs instead.
794-
"""
795-
796-
def __init__(
797-
self,
798-
type_name: bytes,
799-
critical: bool,
800-
value: bytes,
801-
subject: X509 | None = None,
802-
issuer: X509 | None = None,
803-
) -> None:
804-
"""
805-
Initializes an X509 extension.
806-
807-
:param type_name: The name of the type of extension_ to create.
808-
:type type_name: :py:data:`bytes`
809-
810-
:param bool critical: A flag indicating whether this is a critical
811-
extension.
812-
813-
:param value: The OpenSSL textual representation of the extension's
814-
value.
815-
:type value: :py:data:`bytes`
816-
817-
:param subject: Optional X509 certificate to use as subject.
818-
:type subject: :py:class:`X509`
819-
820-
:param issuer: Optional X509 certificate to use as issuer.
821-
:type issuer: :py:class:`X509`
822-
823-
.. _extension: https://www.openssl.org/docs/manmaster/man5/
824-
x509v3_config.html#STANDARD-EXTENSIONS
825-
"""
826-
ctx = _ffi.new("X509V3_CTX*")
827-
828-
# A context is necessary for any extension which uses the r2i
829-
# conversion method. That is, X509V3_EXT_nconf may segfault if passed
830-
# a NULL ctx. Start off by initializing most of the fields to NULL.
831-
_lib.X509V3_set_ctx(ctx, _ffi.NULL, _ffi.NULL, _ffi.NULL, _ffi.NULL, 0)
832-
833-
# We have no configuration database - but perhaps we should (some
834-
# extensions may require it).
835-
_lib.X509V3_set_ctx_nodb(ctx)
836-
837-
# Initialize the subject and issuer, if appropriate. ctx is a local,
838-
# and as far as I can tell none of the X509V3_* APIs invoked here steal
839-
# any references, so no need to mess with reference counts or
840-
# duplicates.
841-
if issuer is not None:
842-
if not isinstance(issuer, X509):
843-
raise TypeError("issuer must be an X509 instance")
844-
ctx.issuer_cert = issuer._x509
845-
if subject is not None:
846-
if not isinstance(subject, X509):
847-
raise TypeError("subject must be an X509 instance")
848-
ctx.subject_cert = subject._x509
849-
850-
if critical:
851-
# There are other OpenSSL APIs which would let us pass in critical
852-
# separately, but they're harder to use, and since value is already
853-
# a pile of crappy junk smuggling a ton of utterly important
854-
# structured data, what's the point of trying to avoid nasty stuff
855-
# with strings? (However, X509V3_EXT_i2d in particular seems like
856-
# it would be a better API to invoke. I do not know where to get
857-
# the ext_struc it desires for its last parameter, though.)
858-
value = b"critical," + value
859-
860-
extension = _lib.X509V3_EXT_nconf(_ffi.NULL, ctx, type_name, value)
861-
if extension == _ffi.NULL:
862-
_raise_current_error()
863-
self._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
864-
865-
@property
866-
def _nid(self) -> Any:
867-
return _lib.OBJ_obj2nid(
868-
_lib.X509_EXTENSION_get_object(self._extension)
869-
)
870-
871-
_prefixes: typing.ClassVar[dict[int, str]] = {
872-
_lib.GEN_EMAIL: "email",
873-
_lib.GEN_DNS: "DNS",
874-
_lib.GEN_URI: "URI",
875-
}
876-
877-
def _subjectAltNameString(self) -> str:
878-
names = _ffi.cast(
879-
"GENERAL_NAMES*", _lib.X509V3_EXT_d2i(self._extension)
880-
)
881-
882-
names = _ffi.gc(names, _lib.GENERAL_NAMES_free)
883-
parts = []
884-
for i in range(_lib.sk_GENERAL_NAME_num(names)):
885-
name = _lib.sk_GENERAL_NAME_value(names, i)
886-
try:
887-
label = self._prefixes[name.type]
888-
except KeyError:
889-
bio = _new_mem_buf()
890-
_lib.GENERAL_NAME_print(bio, name)
891-
parts.append(_bio_to_string(bio).decode("utf-8"))
892-
else:
893-
value = _ffi.buffer(name.d.ia5.data, name.d.ia5.length)[
894-
:
895-
].decode("utf-8")
896-
parts.append(label + ":" + value)
897-
return ", ".join(parts)
898-
899-
def __str__(self) -> str:
900-
"""
901-
:return: a nice text representation of the extension
902-
"""
903-
if _lib.NID_subject_alt_name == self._nid:
904-
return self._subjectAltNameString()
905-
906-
bio = _new_mem_buf()
907-
print_result = _lib.X509V3_EXT_print(bio, self._extension, 0, 0)
908-
_openssl_assert(print_result != 0)
909-
910-
return _bio_to_string(bio).decode("utf-8")
911-
912-
def get_critical(self) -> bool:
913-
"""
914-
Returns the critical field of this X.509 extension.
915-
916-
:return: The critical field.
917-
"""
918-
return _lib.X509_EXTENSION_get_critical(self._extension)
919-
920-
def get_short_name(self) -> bytes:
921-
"""
922-
Returns the short type name of this X.509 extension.
923-
924-
The result is a byte string such as :py:const:`b"basicConstraints"`.
925-
926-
:return: The short type name.
927-
:rtype: :py:data:`bytes`
928-
929-
.. versionadded:: 0.12
930-
"""
931-
obj = _lib.X509_EXTENSION_get_object(self._extension)
932-
nid = _lib.OBJ_obj2nid(obj)
933-
# OpenSSL 3.1.0 has a bug where nid2sn returns NULL for NIDs that
934-
# previously returned UNDEF. This is a workaround for that issue.
935-
# https://github.com/openssl/openssl/commit/908ba3ed9adbb3df90f76
936-
buf = _lib.OBJ_nid2sn(nid)
937-
if buf != _ffi.NULL:
938-
return _ffi.string(buf)
939-
else:
940-
return b"UNDEF"
941-
942-
def get_data(self) -> bytes:
943-
"""
944-
Returns the data of the X509 extension, encoded as ASN.1.
945-
946-
:return: The ASN.1 encoded data of this X509 extension.
947-
:rtype: :py:data:`bytes`
948-
949-
.. versionadded:: 0.12
950-
"""
951-
octet_result = _lib.X509_EXTENSION_get_data(self._extension)
952-
string_result = _ffi.cast("ASN1_STRING*", octet_result)
953-
char_result = _lib.ASN1_STRING_get0_data(string_result)
954-
result_length = _lib.ASN1_STRING_length(string_result)
955-
return _ffi.buffer(char_result, result_length)[:]
956-
957-
958-
_X509ExtensionInternal = X509Extension
959-
utils.deprecated(
960-
X509Extension,
961-
__name__,
962-
(
963-
"X509Extension support in pyOpenSSL is deprecated. You should use the "
964-
"APIs in cryptography."
965-
),
966-
DeprecationWarning,
967-
name="X509Extension",
968-
)
969-
970-
971784
class X509Req:
972785
"""
973786
An X.509 certificate signing requests.
@@ -1093,79 +906,6 @@ def get_subject(self) -> X509Name:
1093906

1094907
return name
1095908

1096-
def add_extensions(
1097-
self, extensions: Iterable[_X509ExtensionInternal]
1098-
) -> None:
1099-
"""
1100-
Add extensions to the certificate signing request.
1101-
1102-
:param extensions: The X.509 extensions to add.
1103-
:type extensions: iterable of :py:class:`X509Extension`
1104-
:return: ``None``
1105-
"""
1106-
warnings.warn(
1107-
(
1108-
"This API is deprecated and will be removed in a future "
1109-
"version of pyOpenSSL. You should use pyca/cryptography's "
1110-
"X.509 APIs instead."
1111-
),
1112-
DeprecationWarning,
1113-
stacklevel=2,
1114-
)
1115-
1116-
stack = _lib.sk_X509_EXTENSION_new_null()
1117-
_openssl_assert(stack != _ffi.NULL)
1118-
1119-
stack = _ffi.gc(stack, _lib.sk_X509_EXTENSION_free)
1120-
1121-
for ext in extensions:
1122-
if not isinstance(ext, _X509ExtensionInternal):
1123-
raise ValueError("One of the elements is not an X509Extension")
1124-
1125-
# TODO push can fail (here and elsewhere)
1126-
_lib.sk_X509_EXTENSION_push(stack, ext._extension)
1127-
1128-
add_result = _lib.X509_REQ_add_extensions(self._req, stack)
1129-
_openssl_assert(add_result == 1)
1130-
1131-
def get_extensions(self) -> list[_X509ExtensionInternal]:
1132-
"""
1133-
Get X.509 extensions in the certificate signing request.
1134-
1135-
:return: The X.509 extensions in this request.
1136-
:rtype: :py:class:`list` of :py:class:`X509Extension` objects.
1137-
1138-
.. versionadded:: 0.15
1139-
"""
1140-
warnings.warn(
1141-
(
1142-
"This API is deprecated and will be removed in a future "
1143-
"version of pyOpenSSL. You should use pyca/cryptography's "
1144-
"X.509 APIs instead."
1145-
),
1146-
DeprecationWarning,
1147-
stacklevel=2,
1148-
)
1149-
1150-
exts = []
1151-
native_exts_obj = _lib.X509_REQ_get_extensions(self._req)
1152-
native_exts_obj = _ffi.gc(
1153-
native_exts_obj,
1154-
lambda x: _lib.sk_X509_EXTENSION_pop_free(
1155-
x,
1156-
_ffi.addressof(_lib._original_lib, "X509_EXTENSION_free"),
1157-
),
1158-
)
1159-
1160-
for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)):
1161-
ext = _X509ExtensionInternal.__new__(_X509ExtensionInternal)
1162-
extension = _lib.X509_EXTENSION_dup(
1163-
_lib.sk_X509_EXTENSION_value(native_exts_obj, i)
1164-
)
1165-
ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
1166-
exts.append(ext)
1167-
return exts
1168-
1169909
def sign(self, pkey: PKey, digest: str) -> None:
1170910
"""
1171911
Sign the certificate signing request with this key and digest type.
@@ -1657,66 +1397,6 @@ def get_extension_count(self) -> int:
16571397
"""
16581398
return _lib.X509_get_ext_count(self._x509)
16591399

1660-
def add_extensions(
1661-
self, extensions: Iterable[_X509ExtensionInternal]
1662-
) -> None:
1663-
"""
1664-
Add extensions to the certificate.
1665-
1666-
:param extensions: The extensions to add.
1667-
:type extensions: An iterable of :py:class:`X509Extension` objects.
1668-
:return: ``None``
1669-
"""
1670-
warnings.warn(
1671-
(
1672-
"This API is deprecated and will be removed in a future "
1673-
"version of pyOpenSSL. You should use pyca/cryptography's "
1674-
"X.509 APIs instead."
1675-
),
1676-
DeprecationWarning,
1677-
stacklevel=2,
1678-
)
1679-
1680-
for ext in extensions:
1681-
if not isinstance(ext, _X509ExtensionInternal):
1682-
raise ValueError("One of the elements is not an X509Extension")
1683-
1684-
add_result = _lib.X509_add_ext(self._x509, ext._extension, -1)
1685-
_openssl_assert(add_result == 1)
1686-
1687-
def get_extension(self, index: int) -> _X509ExtensionInternal:
1688-
"""
1689-
Get a specific extension of the certificate by index.
1690-
1691-
Extensions on a certificate are kept in order. The index
1692-
parameter selects which extension will be returned.
1693-
1694-
:param int index: The index of the extension to retrieve.
1695-
:return: The extension at the specified index.
1696-
:rtype: :py:class:`X509Extension`
1697-
:raises IndexError: If the extension index was out of bounds.
1698-
1699-
.. versionadded:: 0.12
1700-
"""
1701-
warnings.warn(
1702-
(
1703-
"This API is deprecated and will be removed in a future "
1704-
"version of pyOpenSSL. You should use pyca/cryptography's "
1705-
"X.509 APIs instead."
1706-
),
1707-
DeprecationWarning,
1708-
stacklevel=2,
1709-
)
1710-
1711-
ext = _X509ExtensionInternal.__new__(_X509ExtensionInternal)
1712-
ext._extension = _lib.X509_get_ext(self._x509, index)
1713-
if ext._extension == _ffi.NULL:
1714-
raise IndexError("extension index out of bounds")
1715-
1716-
extension = _lib.X509_EXTENSION_dup(ext._extension)
1717-
ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
1718-
return ext
1719-
17201400

17211401
class X509StoreFlags:
17221402
"""

0 commit comments

Comments
 (0)