Daniel Brötzmann pushed to branch cert-convert-cryptography at gajim / gajim
Commits: df1b8a56 by wurstsalat at 2022-11-27T14:57:16+01:00 chore: Update pyright config
- - - - - 7f0fda23 by wurstsalat at 2022-11-27T14:58:41+01:00 refactor: CertificateBox: Use cryptography module for certificate details
- - - - - ec48f5d9 by wurstsalat at 2022-11-27T14:58:41+01:00 change: Dependencies: Remove pyOpenSSL, add python-cryptography
- - - - -
12 changed files:
- README.md - debian/control - flatpak/org.gajim.Gajim.Devel.yaml - flatpak/org.gajim.Gajim.yaml - gajim/common/helpers.py - gajim/gtk/certificate_dialog.py - pyproject.toml - setup.cfg - test/gtk/certificate_dialog.py - test/gtk/util.py - win/_base.sh - win/dev_env.sh
Changes:
===================================== README.md ===================================== @@ -7,7 +7,7 @@ ### Runtime Requirements - [pycairo](https://pypi.org/project/pycairo/) - [cairo](https://gitlab.freedesktop.org/cairo/cairo) (>=1.16.0) - [nbxmpp](https://pypi.org/project/nbxmpp/) (>=3.2.5) -- [pyOpenSSL](https://pypi.org/project/pyOpenSSL/) (>=16.2) +- [cryptography](https://pypi.org/project/cryptography/) (>=3.4.8) - [css-parser](https://pypi.org/project/css-parser/) - [keyring](https://pypi.org/project/keyring/) - [precis_i18n](https://pypi.org/project/precis-i18n/)
===================================== debian/control ===================================== @@ -35,7 +35,7 @@ Depends: python3-gi-cairo (>= 1.14.0~), python3-idna, python3-nbxmpp-nightly (>=20221027), - python3-openssl (>= 0.19), + python3-cryptography (>= 3.4.8), python3-precis-i18n, python3-keyring, python3-packaging,
===================================== flatpak/org.gajim.Gajim.Devel.yaml ===================================== @@ -137,15 +137,6 @@ modules: url: https://files.pythonhosted.org/packages/cp36/c/cryptography/cryptography-38.... sha256: ca9f6784ea96b55ff41708b92c3f6aeaebde4c560308e5fbbd3173fbc466e94e
- - name: python3-pyopenssl - buildsystem: simple - build-commands: - - pip3 install pyOpenSSL-22.0.0-py2.py3-none-any.whl - sources: - - type: file - url: https://files.pythonhosted.org/packages/py2.py3/p/pyOpenSSL/pyOpenSSL-22.0.0... - sha256: ea252b38c87425b64116f808355e8da644ef9b07e429398bfece610f893ee2e0 - - name: python3-dbus-python build-options: env:
===================================== flatpak/org.gajim.Gajim.yaml ===================================== @@ -130,15 +130,6 @@ modules: url: https://files.pythonhosted.org/packages/cp36/c/cryptography/cryptography-38.... sha256: ca9f6784ea96b55ff41708b92c3f6aeaebde4c560308e5fbbd3173fbc466e94e
- - name: python3-pyopenssl - buildsystem: simple - build-commands: - - pip3 install pyOpenSSL-22.0.0-py2.py3-none-any.whl - sources: - - type: file - url: https://files.pythonhosted.org/packages/py2.py3/p/pyOpenSSL/pyOpenSSL-22.0.0... - sha256: ea252b38c87425b64116f808355e8da644ef9b07e429398bfece610f893ee2e0 - - name: python3-dbus-python build-options: env:
===================================== gajim/common/helpers.py ===================================== @@ -62,6 +62,9 @@ from packaging.version import Version as V import unicodedata
+from cryptography import x509 +from cryptography.hazmat.backends import default_backend + from nbxmpp.namespaces import Namespace from nbxmpp.const import Role from nbxmpp.const import Chatstate @@ -75,9 +78,6 @@ from nbxmpp.protocol import InvalidJid from nbxmpp.protocol import Iq
-from OpenSSL.crypto import X509, load_certificate -from OpenSSL.crypto import FILETYPE_PEM - from gi.repository import Gio from gi.repository import GLib from gi.repository import GObject @@ -1429,8 +1429,10 @@ def _on_load_finished(file: Gio.File, file.load_contents_async(None, _on_load_finished)
-def convert_gio_to_openssl_cert(cert: Gio.TlsCertificate) -> X509: - return load_certificate(FILETYPE_PEM, cert.props.certificate_pem.encode()) +def get_x509_cert_from_gio_cert(cert: Gio.TlsCertificate) -> x509.Certificate: + glib_bytes = GLib.ByteArray.free_to_bytes(cert.props.certificate) + return x509.load_der_x509_certificate( + glib_bytes.get_data(), default_backend())
def get_custom_host(account: str) -> Optional[tuple[str,
===================================== gajim/gtk/certificate_dialog.py ===================================== @@ -12,14 +12,14 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see http://www.gnu.org/licenses/.
-from datetime import datetime +from cryptography.hazmat.primitives import hashes
from gi.repository import Gdk from gi.repository import Gio from gi.repository import Gtk
from gajim.common import app -from gajim.common.helpers import convert_gio_to_openssl_cert +from gajim.common.helpers import get_x509_cert_from_gio_cert from gajim.common.i18n import _
from .builder import get_builder @@ -55,47 +55,55 @@ def _on_key_press(self, _widget: Gtk.Widget, event: Gdk.EventKey) -> None:
class CertificateBox(Gtk.Box): - def __init__(self, account: str, cert: Gio.TlsCertificate) -> None: + def __init__(self, account: str, certificate: Gio.TlsCertificate) -> None: Gtk.Box.__init__(self)
self._ui = get_builder('certificate.ui') - - certificate = convert_gio_to_openssl_cert(cert) - - issuer = certificate.get_issuer() - subject = certificate.get_subject() - self._headline = _('Certificate for \n%s') % account - self._it_common_name = subject.commonName or '' - self._it_organization = subject.organizationName or '' - self._it_org_unit = subject.organizationalUnitName or '' - it_serial_no = str(certificate.get_serial_number()) + + cert = get_x509_cert_from_gio_cert(certificate) + + self._it_common_name = '' + self._it_organization = '' + self._it_org_unit = '' + for attribute in cert.subject: + # See https://datatracker.ietf.org/doc/html/rfc4514.html + dotted_string = attribute.oid.dotted_string + if dotted_string == '2.5.4.3': + self._ib_common_name = str(attribute.value) + if dotted_string == '2.5.4.10': + self._ib_organization = str(attribute.value) + if dotted_string == '2.5.4.11': + self._ib_org_unit = str(attribute.value) + + it_serial_no = str(cert.serial_number) it_serial_no_half = int(len(it_serial_no) / 2) self._it_serial_number = '%s\n%s' % ( it_serial_no[:it_serial_no_half], it_serial_no[it_serial_no_half:]) - self._ib_common_name = issuer.commonName or '' - self._ib_organization = issuer.organizationName or '' - self._ib_org_unit = issuer.organizationalUnitName or '' - - before = certificate.get_notBefore() - if before is None: - self._issued = '' - else: - issued = datetime.strptime(before.decode('ascii'), '%Y%m%d%H%M%SZ') - self._issued = issued.strftime('%c %Z') - - after = certificate.get_notAfter() - if after is None: - self._expires = '' - else: - expires = datetime.strptime(after.decode('ascii'), '%Y%m%d%H%M%SZ') - self._expires = expires.strftime('%c %Z') - - sha1 = certificate.digest('sha1').decode('utf-8') + + self._ib_common_name = '' + self._ib_organization = '' + self._ib_org_unit = '' + for attribute in cert.issuer: + # See https://datatracker.ietf.org/doc/html/rfc4514.html + dotted_string = attribute.oid.dotted_string + if dotted_string == '2.5.4.3': + self._ib_common_name = str(attribute.value) + if dotted_string == '2.5.4.10': + self._ib_organization = str(attribute.value) + if dotted_string == '2.5.4.11': + self._ib_org_unit = str(attribute.value) + + self._issued = cert.not_valid_before.strftime('%c %Z') + self._expires = cert.not_valid_after.strftime('%c %Z') + + sha1_bytes = cert.fingerprint(hashes.SHA1()) + sha1 = ':'.join(f'{b:02X}' for b in sha1_bytes) self._sha1 = '%s\n%s' % (sha1[:29], sha1[30:])
- sha256 = certificate.digest('sha256').decode('utf-8') + sha256_bytes = cert.fingerprint(hashes.SHA256()) + sha256 = ':'.join(f'{b:02X}' for b in sha256_bytes) self._sha256 = '%s\n%s\n%s\n%s' % ( sha256[:23], sha256[24:47], sha256[48:71], sha256[72:])
===================================== pyproject.toml ===================================== @@ -93,7 +93,7 @@ include = [ "gajim/gtk/emoji_data_gtk.py", "gajim/gtk/exception.py", "gajim/gtk/features.py", - "gajim/gtk/file_transfer_send.py", + "gajim/gtk/file_transfer_selector.py", "gajim/gtk/groupchat_affiliation.py", "gajim/gtk/groupchat_config.py", "gajim/gtk/groupchat_creation.py",
===================================== setup.cfg ===================================== @@ -44,7 +44,7 @@ install_requires = packaging pillow precis-i18n>=1.0.0 - pyOpenSSL>=16.2 + cryptography>=3.4.8 pycairo>=1.16.0
[options.package_data]
===================================== test/gtk/certificate_dialog.py ===================================== @@ -1,15 +1,15 @@ import gi +gi.require_version('Gio', '2.0') gi.require_version('Gtk', '3.0') +from gi.repository import Gio from gi.repository import Gtk
-import OpenSSL - from gajim import gui gui.init('gtk')
from test.gtk import util from gajim.common.const import CSSPriority -from gajim.gui.dialogs import CertificateDialog +from gajim.gui.certificate_dialog import CertificateDialog
util.load_style('gajim.css', CSSPriority.APPLICATION)
@@ -47,8 +47,8 @@ 8xSTlUlCBTCozjzscZVeVDIojmejWclT -----END CERTIFICATE-----'''
-cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert) -win = CertificateDialog(None, 'testacc', cert) -win.connect("destroy", Gtk.main_quit) +gio_cert = Gio.TlsCertificate.new_from_pem(cert, -1) +win = CertificateDialog(None, 'testacc', gio_cert) +win.connect('destroy', Gtk.main_quit) win.show_all() Gtk.main()
===================================== test/gtk/util.py ===================================== @@ -3,12 +3,15 @@ from gi.repository import Gdk from gi.repository import Gtk
+from gajim.common.const import CSSPriority
-def get_gajim_dir(): + +def get_gajim_dir() -> Path: gajim_path = Path(__file__) / '..' / '..' / '..' / 'gajim' return gajim_path.resolve()
-def load_style(filename, priority): + +def load_style(filename: str, priority: CSSPriority) -> None: path = get_gajim_dir() / 'data' / 'style' / filename try: with open(str(path), 'r', encoding='utf8') as file: @@ -18,6 +21,8 @@ def load_style(filename, priority): return provider = Gtk.CssProvider() provider.load_from_data(bytes(css.encode('utf-8'))) - Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(), + screen = Gdk.Screen.get_default() + assert screen is not None + Gtk.StyleContext.add_provider_for_screen(screen, provider, priority)
===================================== win/_base.sh ===================================== @@ -98,7 +98,7 @@ function install_deps { mingw-w64-"${ARCH}"-python-setuptools \ mingw-w64-"${ARCH}"-python-pillow \ mingw-w64-"${ARCH}"-python-setuptools-scm \ - mingw-w64-"${ARCH}"-python-pyopenssl \ + mingw-w64-"${ARCH}"-python-cryptography \ mingw-w64-"${ARCH}"-python-certifi \ mingw-w64-"${ARCH}"-python-six \ mingw-w64-"${ARCH}"-python-pygments \
===================================== win/dev_env.sh ===================================== @@ -15,7 +15,6 @@ function main { mingw-w64-x86_64-python-setuptools-scm \ mingw-w64-x86_64-python-cryptography \ mingw-w64-x86_64-python-certifi \ - mingw-w64-x86_64-python-pyopenssl \ mingw-w64-x86_64-python-pillow \ mingw-w64-x86_64-python-six \ mingw-w64-x86_64-python-pygments \
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/compare/e499e26f75d71d9e57473849128e98d1...