Skip to content

Commit 9202631

Browse files
committed
Remove X509Extension, which has been deprecated for a year
1 parent 1735f6a commit 9202631

File tree

4 files changed

+2
-659
lines changed

4 files changed

+2
-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: 1 addition & 320 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@
33
import calendar
44
import datetime
55
import functools
6-
import typing
7-
import warnings
86
from base64 import b16encode
9-
from collections.abc import Iterable, Sequence
7+
from collections.abc import Sequence
108
from functools import partial
119
from os import PathLike
1210
from typing import (
@@ -52,7 +50,6 @@
5250
"X509",
5351
"Error",
5452
"PKey",
55-
"X509Extension",
5653
"X509Name",
5754
"X509Req",
5855
"X509Store",
@@ -784,189 +781,6 @@ def get_components(self) -> list[tuple[bytes, bytes]]:
784781
return result
785782

786783

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

1093907
return name
1094908

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

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

17201401
class X509StoreFlags:
17211402
"""

0 commit comments

Comments
 (0)