Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-pyOpenSSL for
openSUSE:Factory checked in at 2026-05-12 19:25:56
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pyOpenSSL (Old)
and /work/SRC/openSUSE:Factory/.python-pyOpenSSL.new.1966 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pyOpenSSL"
Tue May 12 19:25:56 2026 rev:65 rq:1352273 version:26.2.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pyOpenSSL/python-pyOpenSSL.changes
2026-04-28 11:54:11.104056221 +0200
+++
/work/SRC/openSUSE:Factory/.python-pyOpenSSL.new.1966/python-pyOpenSSL.changes
2026-05-12 19:25:57.405317786 +0200
@@ -1,0 +2,17 @@
+Sun May 10 00:00:00 UTC 2026 - Gemini CLI <[email protected]>
+
+- update to 26.2.0:
+ * Maximum supported cryptography version is now 48.x.
+ * Added OpenSSL.SSL.Connection.set_options to set options on a
+ per-connection basis.
+ * 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.
+ * It is now an error to calling any mutating method on
+ OpenSSL.SSL.Context after it has been used to create a
+ Connection.
+- refresh skip-networked-test.patch
+
+-------------------------------------------------------------------
Old:
----
pyopenssl-26.1.0.tar.gz
New:
----
pyopenssl-26.2.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-pyOpenSSL.spec ++++++
--- /var/tmp/diff_new_pack.RTPW3h/_old 2026-05-12 19:25:58.521364040 +0200
+++ /var/tmp/diff_new_pack.RTPW3h/_new 2026-05-12 19:25:58.533364537 +0200
@@ -26,7 +26,7 @@
%endif
%{?sle15_python_module_pythons}
Name: python-pyOpenSSL%{psuffix}
-Version: 26.1.0
+Version: 26.2.0
Release: 0
Summary: Python wrapper module around the OpenSSL library
License: Apache-2.0
@@ -42,7 +42,7 @@
BuildRequires: fdupes
BuildRequires: python-rpm-macros
Requires: python-cffi
-Requires: (python-cryptography >= 46.0.0 with python-cryptography < 48)
+Requires: (python-cryptography >= 46.0.0 with python-cryptography < 49)
%if %{python_version_nodots} < 313
Requires: python-typing-extensions >= 4.9
%endif
@@ -51,7 +51,7 @@
%if %{without test}
BuildArch: noarch
%else
-BuildRequires: %{python_module cryptography >= 46.0.0 with
%python-cryptography < 48}
+BuildRequires: %{python_module cryptography >= 46.0.0 with
%python-cryptography < 49}
BuildRequires: %{python_module pretend}
BuildRequires: %{python_module pyOpenSSL >= %version}
BuildRequires: %{python_module pytest >= 3.0.1}
++++++ pyopenssl-26.1.0.tar.gz -> pyopenssl-26.2.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyopenssl-26.1.0/CHANGELOG.rst
new/pyopenssl-26.2.0/CHANGELOG.rst
--- old/pyopenssl-26.1.0/CHANGELOG.rst 2026-04-24 22:23:14.000000000 +0200
+++ new/pyopenssl-26.2.0/CHANGELOG.rst 2026-05-05 01:05:30.000000000 +0200
@@ -4,6 +4,24 @@
Versions are year-based with a strict backward-compatibility policy.
The third digit is only for regressions.
+26.2.0 (2026-05-04)
+-------------------
+
+Backward-incompatible changes:
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- 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.
+- It is now an error to calling any mutating method on ``OpenSSL.SSL.Context``
after it has been used to create a ``Connection``. This was previously
deprecated and has always been unsafe.
+
+Deprecations:
+^^^^^^^^^^^^^
+
+Changes:
+^^^^^^^^
+
+- Maximum supported ``cryptography`` version is now 48.x.
+- Added ``OpenSSL.SSL.Connection.set_options`` to set options on a
per-connection basis.
+
26.1.0 (2026-04-24)
-------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyopenssl-26.1.0/PKG-INFO
new/pyopenssl-26.2.0/PKG-INFO
--- old/pyopenssl-26.1.0/PKG-INFO 2026-04-24 22:23:19.443975000 +0200
+++ new/pyopenssl-26.2.0/PKG-INFO 2026-05-05 01:05:34.877339600 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: pyOpenSSL
-Version: 26.1.0
+Version: 26.2.0
Summary: Python wrapper module around the OpenSSL library
Home-page: https://pyopenssl.org/
Author: The pyOpenSSL developers
@@ -27,7 +27,7 @@
Classifier: Topic :: System :: Networking
Requires-Python: >=3.8
License-File: LICENSE
-Requires-Dist: cryptography<48,>=46.0.0
+Requires-Dist: cryptography<49,>=46.0.0
Requires-Dist: typing-extensions>=4.9; python_version < "3.13" and
python_version >= "3.8"
Provides-Extra: test
Requires-Dist: pytest-rerunfailures; extra == "test"
@@ -96,6 +96,24 @@
Release Information
===================
+26.2.0 (2026-05-04)
+-------------------
+
+Backward-incompatible changes:
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- 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.
+- It is now an error to calling any mutating method on ``OpenSSL.SSL.Context``
after it has been used to create a ``Connection``. This was previously
deprecated and has always been unsafe.
+
+Deprecations:
+^^^^^^^^^^^^^
+
+Changes:
+^^^^^^^^
+
+- Maximum supported ``cryptography`` version is now 48.x.
+- Added ``OpenSSL.SSL.Connection.set_options`` to set options on a
per-connection basis.
+
26.1.0 (2026-04-24)
-------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyopenssl-26.1.0/doc/api/crypto.rst
new/pyopenssl-26.2.0/doc/api/crypto.rst
--- old/pyopenssl-26.1.0/doc/api/crypto.rst 2026-04-24 22:23:14.000000000
+0200
+++ new/pyopenssl-26.2.0/doc/api/crypto.rst 2026-05-05 01:05:30.000000000
+0200
@@ -148,16 +148,6 @@
Key type constants.
-.. _openssl-509ext:
-
-X509Extension objects
----------------------
-
-.. autoclass:: X509Extension
- :members:
- :special-members:
- :exclude-members: __weakref__
-
Exceptions
----------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyopenssl-26.1.0/setup.py
new/pyopenssl-26.2.0/setup.py
--- old/pyopenssl-26.1.0/setup.py 2026-04-24 22:23:14.000000000 +0200
+++ new/pyopenssl-26.2.0/setup.py 2026-05-05 01:05:30.000000000 +0200
@@ -93,7 +93,7 @@
packages=find_packages(where="src"),
package_dir={"": "src"},
install_requires=[
- "cryptography>=46.0.0,<48",
+ "cryptography>=46.0.0,<49",
(
"typing-extensions>=4.9; "
"python_version < '3.13' and python_version >= '3.8'"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyopenssl-26.1.0/src/OpenSSL/SSL.py
new/pyopenssl-26.2.0/src/OpenSSL/SSL.py
--- old/pyopenssl-26.1.0/src/OpenSSL/SSL.py 2026-04-24 22:23:14.000000000
+0200
+++ new/pyopenssl-26.2.0/src/OpenSSL/SSL.py 2026-05-05 01:05:30.000000000
+0200
@@ -856,13 +856,9 @@
@wraps(f)
def inner(self: Context, *args: Any, **kwargs: Any) -> Any:
if self._used:
- warnings.warn(
- (
- "Attempting to mutate a Context after a Connection was "
- "created. In the future, this will raise an exception"
- ),
- DeprecationWarning,
- stacklevel=2,
+ raise ValueError(
+ "Context has already been used to create a Connection, it "
+ "cannot be mutated again"
)
return f(self, *args, **kwargs)
@@ -2105,6 +2101,19 @@
self._context = context
self._context._used = True
+ def set_options(self, options: int) -> int:
+ """
+ Add options. Options set before are not cleared!
+ This method should be used with the :const:`OP_*` constants.
+
+ :param options: The options to add.
+ :return: The new option bitmask.
+ """
+ if not isinstance(options, int):
+ raise TypeError("options must be an integer")
+
+ return _lib.SSL_set_options(self._ssl, options)
+
def get_servername(self) -> bytes | None:
"""
Retrieve the servername extension value if provided in the client hello
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyopenssl-26.1.0/src/OpenSSL/crypto.py
new/pyopenssl-26.2.0/src/OpenSSL/crypto.py
--- old/pyopenssl-26.1.0/src/OpenSSL/crypto.py 2026-04-24 22:23:14.000000000
+0200
+++ new/pyopenssl-26.2.0/src/OpenSSL/crypto.py 2026-05-05 01:05:30.000000000
+0200
@@ -5,9 +5,8 @@
import functools
import sys
import typing
-import warnings
from base64 import b16encode
-from collections.abc import Iterable, Sequence
+from collections.abc import Sequence
from functools import partial
from typing import (
Any,
@@ -63,7 +62,6 @@
"X509",
"Error",
"PKey",
- "X509Extension",
"X509Name",
"X509Req",
"X509Store",
@@ -777,182 +775,6 @@
@deprecated(
- "X509Extension support in pyOpenSSL is deprecated. You should use the "
- "APIs in cryptography."
-)
-class X509Extension:
- """
- An X.509 v3 certificate extension.
-
- .. deprecated:: 23.3.0
- Use cryptography's X509 APIs instead.
- """
-
- def __init__(
- self,
- type_name: bytes,
- critical: bool,
- value: bytes,
- subject: X509 | None = None,
- issuer: X509 | None = None,
- ) -> None:
- """
- Initializes an X509 extension.
-
- :param type_name: The name of the type of extension_ to create.
- :type type_name: :py:data:`bytes`
-
- :param bool critical: A flag indicating whether this is a critical
- extension.
-
- :param value: The OpenSSL textual representation of the extension's
- value.
- :type value: :py:data:`bytes`
-
- :param subject: Optional X509 certificate to use as subject.
- :type subject: :py:class:`X509`
-
- :param issuer: Optional X509 certificate to use as issuer.
- :type issuer: :py:class:`X509`
-
- .. _extension: https://www.openssl.org/docs/manmaster/man5/
- x509v3_config.html#STANDARD-EXTENSIONS
- """
- ctx = _ffi.new("X509V3_CTX*")
-
- # A context is necessary for any extension which uses the r2i
- # conversion method. That is, X509V3_EXT_nconf may segfault if passed
- # a NULL ctx. Start off by initializing most of the fields to NULL.
- _lib.X509V3_set_ctx(ctx, _ffi.NULL, _ffi.NULL, _ffi.NULL, _ffi.NULL, 0)
-
- # We have no configuration database - but perhaps we should (some
- # extensions may require it).
- _lib.X509V3_set_ctx_nodb(ctx)
-
- # Initialize the subject and issuer, if appropriate. ctx is a local,
- # and as far as I can tell none of the X509V3_* APIs invoked here steal
- # any references, so no need to mess with reference counts or
- # duplicates.
- if issuer is not None:
- if not isinstance(issuer, X509):
- raise TypeError("issuer must be an X509 instance")
- ctx.issuer_cert = issuer._x509
- if subject is not None:
- if not isinstance(subject, X509):
- raise TypeError("subject must be an X509 instance")
- ctx.subject_cert = subject._x509
-
- if critical:
- # There are other OpenSSL APIs which would let us pass in critical
- # separately, but they're harder to use, and since value is already
- # a pile of crappy junk smuggling a ton of utterly important
- # structured data, what's the point of trying to avoid nasty stuff
- # with strings? (However, X509V3_EXT_i2d in particular seems like
- # it would be a better API to invoke. I do not know where to get
- # the ext_struc it desires for its last parameter, though.)
- value = b"critical," + value
-
- extension = _lib.X509V3_EXT_nconf(_ffi.NULL, ctx, type_name, value)
- if extension == _ffi.NULL:
- _raise_current_error()
- self._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
-
- @property
- def _nid(self) -> Any:
- return _lib.OBJ_obj2nid(
- _lib.X509_EXTENSION_get_object(self._extension)
- )
-
- _prefixes: typing.ClassVar[dict[int, str]] = {
- _lib.GEN_EMAIL: "email",
- _lib.GEN_DNS: "DNS",
- _lib.GEN_URI: "URI",
- }
-
- def _subjectAltNameString(self) -> str:
- names = _ffi.cast(
- "GENERAL_NAMES*", _lib.X509V3_EXT_d2i(self._extension)
- )
-
- names = _ffi.gc(names, _lib.GENERAL_NAMES_free)
- parts = []
- for i in range(_lib.sk_GENERAL_NAME_num(names)):
- name = _lib.sk_GENERAL_NAME_value(names, i)
- try:
- label = self._prefixes[name.type]
- except KeyError:
- bio = _new_mem_buf()
- _lib.GENERAL_NAME_print(bio, name)
- parts.append(_bio_to_string(bio).decode("utf-8"))
- else:
- asn1_string = _ffi.cast("ASN1_STRING*", name.d.ia5)
- value = _ffi.buffer(
- _lib.ASN1_STRING_get0_data(asn1_string),
- _lib.ASN1_STRING_length(asn1_string),
- )[:].decode("utf-8")
- parts.append(label + ":" + value)
- return ", ".join(parts)
-
- def __str__(self) -> str:
- """
- :return: a nice text representation of the extension
- """
- if _lib.NID_subject_alt_name == self._nid:
- return self._subjectAltNameString()
-
- bio = _new_mem_buf()
- print_result = _lib.X509V3_EXT_print(bio, self._extension, 0, 0)
- _openssl_assert(print_result != 0)
-
- return _bio_to_string(bio).decode("utf-8")
-
- def get_critical(self) -> bool:
- """
- Returns the critical field of this X.509 extension.
-
- :return: The critical field.
- """
- return _lib.X509_EXTENSION_get_critical(self._extension)
-
- def get_short_name(self) -> bytes:
- """
- Returns the short type name of this X.509 extension.
-
- The result is a byte string such as :py:const:`b"basicConstraints"`.
-
- :return: The short type name.
- :rtype: :py:data:`bytes`
-
- .. versionadded:: 0.12
- """
- obj = _lib.X509_EXTENSION_get_object(self._extension)
- nid = _lib.OBJ_obj2nid(obj)
- # OpenSSL 3.1.0 has a bug where nid2sn returns NULL for NIDs that
- # previously returned UNDEF. This is a workaround for that issue.
- # https://github.com/openssl/openssl/commit/908ba3ed9adbb3df90f76
- buf = _lib.OBJ_nid2sn(nid)
- if buf != _ffi.NULL:
- return _ffi.string(buf)
- else:
- return b"UNDEF"
-
- def get_data(self) -> bytes:
- """
- Returns the data of the X509 extension, encoded as ASN.1.
-
- :return: The ASN.1 encoded data of this X509 extension.
- :rtype: :py:data:`bytes`
-
- .. versionadded:: 0.12
- """
- octet_result = _lib.X509_EXTENSION_get_data(self._extension)
- string_result = _ffi.cast("ASN1_STRING*", octet_result)
- char_result = _lib.ASN1_STRING_get0_data(string_result)
- result_length = _lib.ASN1_STRING_length(string_result)
- return _ffi.buffer(char_result, result_length)[:]
-
-
-@deprecated(
"CSR support in pyOpenSSL is deprecated. You should use the APIs "
"in cryptography."
)
@@ -1081,77 +903,6 @@
return name
- def add_extensions(self, extensions: Iterable[X509Extension]) -> None:
- """
- Add extensions to the certificate signing request.
-
- :param extensions: The X.509 extensions to add.
- :type extensions: iterable of :py:class:`X509Extension`
- :return: ``None``
- """
- warnings.warn(
- (
- "This API is deprecated and will be removed in a future "
- "version of pyOpenSSL. You should use pyca/cryptography's "
- "X.509 APIs instead."
- ),
- DeprecationWarning,
- stacklevel=2,
- )
-
- stack = _lib.sk_X509_EXTENSION_new_null()
- _openssl_assert(stack != _ffi.NULL)
-
- stack = _ffi.gc(stack, _lib.sk_X509_EXTENSION_free)
-
- for ext in extensions:
- if not isinstance(ext, X509Extension):
- raise ValueError("One of the elements is not an X509Extension")
-
- # TODO push can fail (here and elsewhere)
- _lib.sk_X509_EXTENSION_push(stack, ext._extension)
-
- add_result = _lib.X509_REQ_add_extensions(self._req, stack)
- _openssl_assert(add_result == 1)
-
- def get_extensions(self) -> list[X509Extension]:
- """
- Get X.509 extensions in the certificate signing request.
-
- :return: The X.509 extensions in this request.
- :rtype: :py:class:`list` of :py:class:`X509Extension` objects.
-
- .. versionadded:: 0.15
- """
- warnings.warn(
- (
- "This API is deprecated and will be removed in a future "
- "version of pyOpenSSL. You should use pyca/cryptography's "
- "X.509 APIs instead."
- ),
- DeprecationWarning,
- stacklevel=2,
- )
-
- exts = []
- native_exts_obj = _lib.X509_REQ_get_extensions(self._req)
- native_exts_obj = _ffi.gc(
- native_exts_obj,
- lambda x: _lib.sk_X509_EXTENSION_pop_free(
- x,
- _ffi.addressof(_lib._original_lib, "X509_EXTENSION_free"),
- ),
- )
-
- for i in range(_lib.sk_X509_EXTENSION_num(native_exts_obj)):
- ext = X509Extension.__new__(X509Extension)
- extension = _lib.X509_EXTENSION_dup(
- _lib.sk_X509_EXTENSION_value(native_exts_obj, i)
- )
- ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
- exts.append(ext)
- return exts
-
def sign(self, pkey: PKey, digest: str) -> None:
"""
Sign the certificate signing request with this key and digest type.
@@ -1629,64 +1380,6 @@
"""
return _lib.X509_get_ext_count(self._x509)
- def add_extensions(self, extensions: Iterable[X509Extension]) -> None:
- """
- Add extensions to the certificate.
-
- :param extensions: The extensions to add.
- :type extensions: An iterable of :py:class:`X509Extension` objects.
- :return: ``None``
- """
- warnings.warn(
- (
- "This API is deprecated and will be removed in a future "
- "version of pyOpenSSL. You should use pyca/cryptography's "
- "X.509 APIs instead."
- ),
- DeprecationWarning,
- stacklevel=2,
- )
-
- for ext in extensions:
- 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) -> X509Extension:
- """
- Get a specific extension of the certificate by index.
-
- Extensions on a certificate are kept in order. The index
- parameter selects which extension will be returned.
-
- :param int index: The index of the extension to retrieve.
- :return: The extension at the specified index.
- :rtype: :py:class:`X509Extension`
- :raises IndexError: If the extension index was out of bounds.
-
- .. versionadded:: 0.12
- """
- warnings.warn(
- (
- "This API is deprecated and will be removed in a future "
- "version of pyOpenSSL. You should use pyca/cryptography's "
- "X.509 APIs instead."
- ),
- DeprecationWarning,
- stacklevel=2,
- )
-
- 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")
-
- extension = _lib.X509_EXTENSION_dup(ext._extension)
- ext._extension = _ffi.gc(extension, _lib.X509_EXTENSION_free)
- return ext
-
class X509StoreFlags:
"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyopenssl-26.1.0/src/OpenSSL/version.py
new/pyopenssl-26.2.0/src/OpenSSL/version.py
--- old/pyopenssl-26.1.0/src/OpenSSL/version.py 2026-04-24 22:23:14.000000000
+0200
+++ new/pyopenssl-26.2.0/src/OpenSSL/version.py 2026-05-05 01:05:30.000000000
+0200
@@ -17,7 +17,7 @@
"__version__",
]
-__version__ = "26.1.0"
+__version__ = "26.2.0"
__title__ = "pyOpenSSL"
__uri__ = "https://pyopenssl.org/"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyopenssl-26.1.0/src/pyOpenSSL.egg-info/PKG-INFO
new/pyopenssl-26.2.0/src/pyOpenSSL.egg-info/PKG-INFO
--- old/pyopenssl-26.1.0/src/pyOpenSSL.egg-info/PKG-INFO 2026-04-24
22:23:19.000000000 +0200
+++ new/pyopenssl-26.2.0/src/pyOpenSSL.egg-info/PKG-INFO 2026-05-05
01:05:34.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: pyOpenSSL
-Version: 26.1.0
+Version: 26.2.0
Summary: Python wrapper module around the OpenSSL library
Home-page: https://pyopenssl.org/
Author: The pyOpenSSL developers
@@ -27,7 +27,7 @@
Classifier: Topic :: System :: Networking
Requires-Python: >=3.8
License-File: LICENSE
-Requires-Dist: cryptography<48,>=46.0.0
+Requires-Dist: cryptography<49,>=46.0.0
Requires-Dist: typing-extensions>=4.9; python_version < "3.13" and
python_version >= "3.8"
Provides-Extra: test
Requires-Dist: pytest-rerunfailures; extra == "test"
@@ -96,6 +96,24 @@
Release Information
===================
+26.2.0 (2026-05-04)
+-------------------
+
+Backward-incompatible changes:
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- 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.
+- It is now an error to calling any mutating method on ``OpenSSL.SSL.Context``
after it has been used to create a ``Connection``. This was previously
deprecated and has always been unsafe.
+
+Deprecations:
+^^^^^^^^^^^^^
+
+Changes:
+^^^^^^^^
+
+- Maximum supported ``cryptography`` version is now 48.x.
+- Added ``OpenSSL.SSL.Connection.set_options`` to set options on a
per-connection basis.
+
26.1.0 (2026-04-24)
-------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyopenssl-26.1.0/src/pyOpenSSL.egg-info/requires.txt
new/pyopenssl-26.2.0/src/pyOpenSSL.egg-info/requires.txt
--- old/pyopenssl-26.1.0/src/pyOpenSSL.egg-info/requires.txt 2026-04-24
22:23:19.000000000 +0200
+++ new/pyopenssl-26.2.0/src/pyOpenSSL.egg-info/requires.txt 2026-05-05
01:05:34.000000000 +0200
@@ -1,4 +1,4 @@
-cryptography<48,>=46.0.0
+cryptography<49,>=46.0.0
[:python_version < "3.13" and python_version >= "3.8"]
typing-extensions>=4.9
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyopenssl-26.1.0/tests/test_crypto.py
new/pyopenssl-26.2.0/tests/test_crypto.py
--- old/pyopenssl-26.1.0/tests/test_crypto.py 2026-04-24 22:23:14.000000000
+0200
+++ new/pyopenssl-26.2.0/tests/test_crypto.py 2026-05-05 01:05:30.000000000
+0200
@@ -36,7 +36,6 @@
X509,
Error,
PKey,
- X509Extension,
X509Name,
X509Req,
X509Store,
@@ -822,198 +821,6 @@
return pkey, x509
-class TestX509Ext:
- """
- Tests for `OpenSSL.crypto.X509Extension`.
- """
-
- def test_str(self) -> None:
- """
- The string representation of `X509Extension` instances as
- returned by `str` includes stuff.
- """
- # This isn't necessarily the best string representation. Perhaps it
- # will be changed/improved in the future.
- assert (
- str(X509Extension(b"basicConstraints", True, b"CA:false"))
- == "CA:FALSE"
- )
-
- def test_construction(self) -> None:
- """
- `X509Extension` accepts an extension type name, a critical flag,
- and an extension value and returns an `X509Extension` instance.
- """
- basic = X509Extension(b"basicConstraints", True, b"CA:true")
- assert isinstance(basic, X509Extension)
-
- comment = X509Extension(b"nsComment", False, b"pyOpenSSL unit test")
- assert isinstance(comment, X509Extension)
-
- @pytest.mark.parametrize(
- "type_name, critical, value",
- [
- (b"thisIsMadeUp", False, b"hi"),
- (b"basicConstraints", False, b"blah blah"),
- # Exercise a weird one (an extension which uses the r2i method).
- # This exercises the codepath that requires a non-NULL ctx to be
- # passed to X509V3_EXT_nconf. It can't work now because we provide
- # no configuration database. It might be made to work in the
- # future.
- (
- b"proxyCertInfo",
- True,
- b"language:id-ppl-anyLanguage,pathlen:1,policy:text:AB",
- ),
- ],
- )
- def test_invalid_extension(
- self, type_name: bytes, critical: bool, value: bytes
- ) -> None:
- """
- `X509Extension` raises something if it is passed a bad
- extension name or value.
- """
- with pytest.raises(Error):
- X509Extension(type_name, critical, value)
-
- @pytest.mark.parametrize("critical_flag", [True, False])
- def test_get_critical(self, critical_flag: bool) -> None:
- """
- `X509ExtensionType.get_critical` returns the value of the
- extension's critical flag.
- """
- ext = X509Extension(b"basicConstraints", critical_flag, b"CA:true")
- assert ext.get_critical() == critical_flag
-
- @pytest.mark.parametrize(
- "short_name, value",
- [(b"basicConstraints", b"CA:true"), (b"nsComment", b"foo bar")],
- )
- def test_get_short_name(self, short_name: bytes, value: bytes) -> None:
- """
- `X509ExtensionType.get_short_name` returns a string giving the
- short type name of the extension.
- """
- ext = X509Extension(short_name, True, value)
- assert ext.get_short_name() == short_name
-
- def test_get_data(self) -> None:
- """
- `X509Extension.get_data` returns a string giving the data of
- the extension.
- """
- ext = X509Extension(b"basicConstraints", True, b"CA:true")
- # Expect to get back the DER encoded form of CA:true.
- assert ext.get_data() == b"0\x03\x01\x01\xff"
-
- def test_unused_subject(self, x509_data: tuple[PKey, X509]) -> None:
- """
- The `subject` parameter to `X509Extension` may be provided for an
- extension which does not use it and is ignored in this case.
- """
- pkey, x509 = x509_data
- ext1 = X509Extension(
- b"basicConstraints", False, b"CA:TRUE", subject=x509
- )
- x509.add_extensions([ext1])
- x509.sign(pkey, "sha256")
- # This is a little lame. Can we think of a better way?
- text = dump_certificate(FILETYPE_TEXT, x509)
- assert b"X509v3 Basic Constraints:" in text
- assert b"CA:TRUE" in text
-
- def test_subject(self, x509_data: tuple[PKey, X509]) -> None:
- """
- If an extension requires a subject, the `subject` parameter to
- `X509Extension` provides its value.
- """
- pkey, x509 = x509_data
- ext3 = X509Extension(
- b"subjectKeyIdentifier", False, b"hash", subject=x509
- )
- x509.add_extensions([ext3])
- x509.sign(pkey, "sha256")
- text = dump_certificate(FILETYPE_TEXT, x509)
- assert b"X509v3 Subject Key Identifier:" in text
-
- def test_missing_subject(self) -> None:
- """
- If an extension requires a subject and the `subject` parameter
- is given no value, something happens.
- """
- with pytest.raises(Error):
- X509Extension(b"subjectKeyIdentifier", False, b"hash")
-
- @pytest.mark.parametrize("bad_obj", [True, object(), "hello", []])
- def test_invalid_subject(self, bad_obj: object) -> None:
- """
- If the `subject` parameter is given a value which is not an
- `X509` instance, `TypeError` is raised.
- """
- with pytest.raises(TypeError):
- X509Extension(
- b"basicConstraints",
- False,
- b"CA:TRUE",
- subject=bad_obj, # type: ignore[arg-type]
- )
-
- def test_unused_issuer(self, x509_data: tuple[PKey, X509]) -> None:
- """
- The `issuer` parameter to `X509Extension` may be provided for an
- extension which does not use it and is ignored in this case.
- """
- pkey, x509 = x509_data
- ext1 = X509Extension(
- b"basicConstraints", False, b"CA:TRUE", issuer=x509
- )
- x509.add_extensions([ext1])
- x509.sign(pkey, "sha256")
- text = dump_certificate(FILETYPE_TEXT, x509)
- assert b"X509v3 Basic Constraints:" in text
- assert b"CA:TRUE" in text
-
- def test_issuer(self, x509_data: tuple[PKey, X509]) -> None:
- """
- If an extension requires an issuer, the `issuer` parameter to
- `X509Extension` provides its value.
- """
- pkey, x509 = x509_data
- ext2 = X509Extension(
- b"authorityKeyIdentifier", False, b"issuer:always", issuer=x509
- )
- x509.add_extensions([ext2])
- x509.sign(pkey, "sha256")
- text = dump_certificate(FILETYPE_TEXT, x509)
- assert b"X509v3 Authority Key Identifier:" in text
- assert b"DirName:/CN=Yoda root CA" in text
-
- def test_missing_issuer(self) -> None:
- """
- If an extension requires an issue and the `issuer` parameter is
- given no value, something happens.
- """
- with pytest.raises(Error):
- X509Extension(
- b"authorityKeyIdentifier", False, b"keyid:always,issuer:always"
- )
-
- @pytest.mark.parametrize("bad_obj", [True, object(), "hello", []])
- def test_invalid_issuer(self, bad_obj: object) -> None:
- """
- If the `issuer` parameter is given a value which is not an
- `X509` instance, `TypeError` is raised.
- """
- with pytest.raises(TypeError):
- X509Extension(
- b"basicConstraints",
- False,
- b"keyid:always,issuer:always",
- issuer=bad_obj, # type: ignore[arg-type]
- )
-
-
class TestPKey:
"""
Tests for `OpenSSL.crypto.PKey`.
@@ -1687,67 +1494,6 @@
subject.commonName = "bar"
assert subject.commonName == "bar"
- def test_add_extensions(self) -> None:
- """
- `X509Req.add_extensions` accepts a `list` of `X509Extension` instances
- and adds them to the X509 request.
- """
- request = X509Req()
- request.add_extensions(
- [X509Extension(b"basicConstraints", True, b"CA:false")]
- )
- exts = request.get_extensions()
- assert len(exts) == 1
- assert exts[0].get_short_name() == b"basicConstraints"
- assert exts[0].get_critical() == 1
- assert exts[0].get_data() == b"0\x00"
-
- def test_get_extensions(self) -> None:
- """
- `X509Req.get_extensions` returns a `list` of extensions added to this
- X509 request.
- """
- request = X509Req()
- exts = request.get_extensions()
- assert exts == []
- request.add_extensions(
- [
- X509Extension(b"basicConstraints", True, b"CA:true"),
- X509Extension(b"keyUsage", False, b"digitalSignature"),
- ]
- )
- exts = request.get_extensions()
- assert len(exts) == 2
- assert exts[0].get_short_name() == b"basicConstraints"
- assert exts[0].get_critical() == 1
- assert exts[0].get_data() == b"0\x03\x01\x01\xff"
- assert exts[1].get_short_name() == b"keyUsage"
- assert exts[1].get_critical() == 0
- assert exts[1].get_data() == b"\x03\x02\x07\x80"
- # Requesting it a second time should return the same list
- exts = request.get_extensions()
- assert len(exts) == 2
-
- def test_undef_oid(self) -> None:
- assert (
- X509Extension(
- b"1.2.3.4.5.6.7", False, b"DER:05:00"
- ).get_short_name()
- == b"UNDEF"
- )
-
- def test_add_extensions_wrong_args(self) -> None:
- """
- `X509Req.add_extensions` raises `TypeError` if called with a
- non-`list`. Or it raises `ValueError` if called with a `list`
- containing objects other than `X509Extension` instances.
- """
- request = X509Req()
- with pytest.raises(TypeError):
- request.add_extensions(object()) # type: ignore[arg-type]
- with pytest.raises(ValueError):
- request.add_extensions([object()]) # type: ignore[list-item]
-
def test_verify_wrong_args(self) -> None:
"""
`X509Req.verify` raises `TypeError` if passed anything other than a
@@ -2149,71 +1895,6 @@
c = self._extcert(pkey, [ca, key, san])
assert c.get_extension_count() == 3
- def test_get_extension(self) -> None:
- """
- `X509.get_extension` takes an integer and returns an
- `X509Extension` corresponding to the extension at that index.
- """
- pkey = load_privatekey(
- FILETYPE_PEM, client_key_pem
- ).to_cryptography_key()
- assert isinstance(pkey, rsa.RSAPrivateKey)
- ca = x509.BasicConstraints(ca=False, path_length=None)
- key = x509.KeyUsage(
- digital_signature=True,
- content_commitment=False,
- key_encipherment=False,
- data_encipherment=False,
- key_agreement=False,
- key_cert_sign=False,
- crl_sign=False,
- encipher_only=False,
- decipher_only=False,
- )
- san = x509.SubjectAlternativeName([x509.DNSName("example.com")])
-
- cert = self._extcert(pkey, [ca, key, san])
-
- ext = cert.get_extension(0)
- assert isinstance(ext, X509Extension)
- assert ext.get_critical()
- assert ext.get_short_name() == b"basicConstraints"
-
- ext = cert.get_extension(1)
- assert isinstance(ext, X509Extension)
- assert not ext.get_critical()
- assert ext.get_short_name() == b"keyUsage"
-
- ext = cert.get_extension(2)
- assert isinstance(ext, X509Extension)
- assert ext.get_critical()
- assert ext.get_short_name() == b"subjectAltName"
-
- with pytest.raises(IndexError):
- cert.get_extension(-1)
- with pytest.raises(IndexError):
- cert.get_extension(4)
- with pytest.raises(TypeError):
- cert.get_extension("hello") # type: ignore[arg-type]
-
- def test_nullbyte_subjectAltName(self) -> None:
- """
- The fields of a `subjectAltName` extension on an X509 may contain NUL
- bytes and this value is reflected in the string representation of the
- extension object.
- """
- cert = load_certificate(FILETYPE_PEM, nulbyteSubjectAltNamePEM)
-
- ext = cert.get_extension(3)
- assert ext.get_short_name() == b"subjectAltName"
- assert (
- b"DNS:altnull.python.org\x00example.com, "
- b"email:[email protected]\[email protected], "
- b"URI:http://null.python.org\x00http://example.org, "
- b"IP Address:192.0.2.1, IP Address:2001:DB8:0:0:0:0:0:1"
- == str(ext).encode("ascii").strip()
- )
-
def test_invalid_digest_algorithm(self) -> None:
"""
`X509.digest` raises `ValueError` if called with an unrecognized hash
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pyopenssl-26.1.0/tests/test_ssl.py
new/pyopenssl-26.2.0/tests/test_ssl.py
--- old/pyopenssl-26.1.0/tests/test_ssl.py 2026-04-24 22:23:14.000000000
+0200
+++ new/pyopenssl-26.2.0/tests/test_ssl.py 2026-05-05 01:05:30.000000000
+0200
@@ -2572,6 +2572,25 @@
connection.set_context(1) # type: ignore[arg-type]
assert ctx is connection.get_context()
+ def test_set_options_wrong_args(self) -> None:
+ """
+ `Connection.set_options` raises `TypeError` if called with
+ a non-`int` argument.
+ """
+ context = Context(SSLv23_METHOD)
+ connection = Connection(context, None)
+ with pytest.raises(TypeError):
+ connection.set_options(None) # type: ignore[arg-type]
+
+ def test_set_options(self) -> None:
+ """
+ `Connection.set_options` returns the new options value.
+ """
+ context = Context(SSLv23_METHOD)
+ connection = Connection(context, None)
+ options = connection.set_options(OP_NO_SSLv2)
+ assert options & OP_NO_SSLv2 == OP_NO_SSLv2
+
def test_set_context(self) -> None:
"""
`Connection.set_context` specifies a new `Context` instance to be
++++++ skip-networked-test.patch ++++++
--- /var/tmp/diff_new_pack.RTPW3h/_old 2026-05-12 19:25:58.781374816 +0200
+++ /var/tmp/diff_new_pack.RTPW3h/_new 2026-05-12 19:25:58.789375148 +0200
@@ -1,8 +1,8 @@
-Index: pyopenssl-25.0.0/tests/test_ssl.py
+Index: pyopenssl-26.2.0/tests/test_ssl.py
===================================================================
---- pyopenssl-25.0.0.orig/tests/test_ssl.py
-+++ pyopenssl-25.0.0/tests/test_ssl.py
-@@ -1303,6 +1303,7 @@ class TestContext:
+--- pyopenssl-26.2.0.orig/tests/test_ssl.py
++++ pyopenssl-26.2.0/tests/test_ssl.py
+@@ -1414,6 +1414,7 @@ class TestContext:
reason="set_default_verify_paths appears not to work on Windows. "
"See LP#404343 and LP#404344.",
)
@@ -10,20 +10,20 @@
def test_set_default_verify_paths(self) -> None:
"""
`Context.set_default_verify_paths` causes the platform-specific CA
-Index: pyopenssl-25.0.0/setup.cfg
+Index: pyopenssl-26.2.0/setup.cfg
===================================================================
---- pyopenssl-25.0.0.orig/setup.cfg
-+++ pyopenssl-25.0.0/setup.cfg
+--- pyopenssl-26.2.0.orig/setup.cfg
++++ pyopenssl-26.2.0/setup.cfg
@@ -11,4 +11,3 @@ doc_files = doc/_build/html
[egg_info]
tag_build =
tag_date = 0
-
-Index: pyopenssl-25.0.0/pyproject.toml
+Index: pyopenssl-26.2.0/pyproject.toml
===================================================================
---- pyopenssl-25.0.0.orig/pyproject.toml
-+++ pyopenssl-25.0.0/pyproject.toml
-@@ -39,6 +39,9 @@ ignore_missing_imports = true
+--- pyopenssl-26.2.0.orig/pyproject.toml
++++ pyopenssl-26.2.0/pyproject.toml
+@@ -40,6 +40,9 @@ ignore_missing_imports = true
[tool.pytest.ini_options]
addopts = "-r s --strict-markers"
testpaths = ["tests"]