Skip to content

Commit cc7eefc

Browse files
committed
Remove X509Extension, which has been deprecated for a year
1 parent 787f176 commit cc7eefc

File tree

4 files changed

+2
-635
lines changed

4 files changed

+2
-635
lines changed

CHANGELOG.rst

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Backward-incompatible changes:
2626
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2727

2828
- 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.
29+
- 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.
2930
- Removed the deprecated ``OpenSSL.crypto.sign`` and ``OpenSSL.crypto.verify``. ``cryptography.hazmat.primitives.asymmetric``'s signature APIs should be used instead.
3031

3132
Deprecations:

doc/api/crypto.rst

-10
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

+1-306
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@
55
import functools
66
import sys
77
import typing
8-
import warnings
98
from base64 import b16encode
10-
from collections.abc import Iterable, Sequence
9+
from collections.abc import Sequence
1110
from functools import partial
1211
from typing import (
1312
Any,
@@ -63,7 +62,6 @@ def deprecated(msg: str, **kwargs: object) -> Callable[[_T], _T]:
6362
"X509",
6463
"Error",
6564
"PKey",
66-
"X509Extension",
6765
"X509Name",
6866
"X509Req",
6967
"X509Store",
@@ -776,180 +774,6 @@ def get_components(self) -> list[tuple[bytes, bytes]]:
776774
return result
777775

778776

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

1080904
return name
1081905

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

1630-
def add_extensions(self, extensions: Iterable[X509Extension]) -> None:
1631-
"""
1632-
Add extensions to the certificate.
1633-
1634-
:param extensions: The extensions to add.
1635-
:type extensions: An iterable of :py:class:`X509Extension` objects.
1636-
:return: ``None``
1637-
"""
1638-
warnings.warn(
1639-
(
1640-
"This API is deprecated and will be removed in a future "
1641-
"version of pyOpenSSL. You should use pyca/cryptography's "
1642-
"X.509 APIs instead."
1643-
),
1644-
DeprecationWarning,
1645-
stacklevel=2,
1646-
)
1647-
1648-
for ext in extensions:
1649-
if not isinstance(ext, X509Extension):
1650-
raise ValueError("One of the elements is not an X509Extension")
1651-
1652-
add_result = _lib.X509_add_ext(self._x509, ext._extension, -1)
1653-
_openssl_assert(add_result == 1)
1654-
1655-
def get_extension(self, index: int) -> X509Extension:
1656-
"""
1657-
Get a specific extension of the certificate by index.
1658-
1659-
Extensions on a certificate are kept in order. The index
1660-
parameter selects which extension will be returned.
1661-
1662-
:param int index: The index of the extension to retrieve.
1663-
:return: The extension at the specified index.
1664-
:rtype: :py:class:`X509Extension`
1665-
:raises IndexError: If the extension index was out of bounds.
1666-
1667-
.. versionadded:: 0.12
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-
ext = X509Extension.__new__(X509Extension)
1680-
ext._extension = _lib.X509_get_ext(self._x509, index)
1681-
if ext._extension == _ffi.NULL:
1682-
raise IndexError("extension index out of bounds")
1683-
1684-
extension = _lib.X509_EXTENSION_dup(ext._extension)
1685-
ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
1686-
return ext
1687-
16881383

16891384
class X509StoreFlags:
16901385
"""

0 commit comments

Comments
 (0)