Philipp Hörist pushed to branch master at gajim / gajim
Commits:
4 changed files:
- gajim/common/helpers.py
- gajim/common/modules/omemo.py
- gajim/gtk/chat_banner.py
- gajim/gtk/omemo_trust_manager.py
Changes:
| ... | ... | @@ -48,7 +48,6 @@ |
| 48 | 48 | import socket
|
| 49 | 49 | import string
|
| 50 | 50 | import sys
|
| 51 | -import tempfile
|
|
| 52 | 51 | import unicodedata
|
| 53 | 52 | import weakref
|
| 54 | 53 | import webbrowser
|
| ... | ... | @@ -83,6 +82,7 @@ |
| 83 | 82 | from nbxmpp.structs import ProxyData
|
| 84 | 83 | from packaging.requirements import Requirement
|
| 85 | 84 | from packaging.version import Version as V
|
| 85 | +from qrcode.image.pil import PilImage as QrcPilImage
|
|
| 86 | 86 | |
| 87 | 87 | from gajim.common import app
|
| 88 | 88 | from gajim.common import configpaths
|
| ... | ... | @@ -370,9 +370,6 @@ def get_contact_dict_for_account(account: str) -> dict[str, types.BareContact]: |
| 370 | 370 | |
| 371 | 371 | |
| 372 | 372 | def generate_qr_code(content: str) -> GdkPixbuf.Pixbuf | None:
|
| 373 | - image_path = os.path.join(
|
|
| 374 | - tempfile.gettempdir(),
|
|
| 375 | - f'{get_random_string()}.png')
|
|
| 376 | 373 | qr = qrcode.QRCode(version=None,
|
| 377 | 374 | error_correction=qrcode.constants.ERROR_CORRECT_L,
|
| 378 | 375 | box_size=6,
|
| ... | ... | @@ -380,9 +377,11 @@ def generate_qr_code(content: str) -> GdkPixbuf.Pixbuf | None: |
| 380 | 377 | qr.add_data(content)
|
| 381 | 378 | qr.make(fit=True)
|
| 382 | 379 | |
| 383 | - img = qr.make_image(fill_color='black', back_color='white')
|
|
| 384 | - img.save(image_path)
|
|
| 385 | - return GdkPixbuf.Pixbuf.new_from_file(image_path)
|
|
| 380 | + img = qr.make_image(image_factory=QrcPilImage).convert('RGB')
|
|
| 381 | + return GdkPixbuf.Pixbuf.new_from_bytes(
|
|
| 382 | + GLib.Bytes.new(img.tobytes()),
|
|
| 383 | + GdkPixbuf.Colorspace.RGB, False, 8,
|
|
| 384 | + img.width, img.height, img.width*3)
|
|
| 386 | 385 | |
| 387 | 386 | |
| 388 | 387 | def play_sound(sound_event: str,
|
| ... | ... | @@ -50,6 +50,7 @@ |
| 50 | 50 | from omemo_dr.exceptions import KeyExchangeMessage
|
| 51 | 51 | from omemo_dr.exceptions import MessageNotForDevice
|
| 52 | 52 | from omemo_dr.exceptions import SelfMessage
|
| 53 | +from omemo_dr.identitykey import IdentityKey
|
|
| 53 | 54 | from omemo_dr.session_manager import OMEMOSessionManager
|
| 54 | 55 | from omemo_dr.structs import OMEMOBundle
|
| 55 | 56 | from omemo_dr.structs import OMEMOConfig
|
| ... | ... | @@ -61,6 +62,7 @@ |
| 61 | 62 | from gajim.common.const import EncryptionData
|
| 62 | 63 | from gajim.common.const import EncryptionInfoMsg
|
| 63 | 64 | from gajim.common.const import Trust as GajimTrust
|
| 65 | +from gajim.common.const import XmppUriQuery
|
|
| 64 | 66 | from gajim.common.events import EncryptionInfo
|
| 65 | 67 | from gajim.common.events import MucAdded
|
| 66 | 68 | from gajim.common.events import MucDiscoUpdate
|
| ... | ... | @@ -92,6 +94,8 @@ |
| 92 | 94 | ('origin-id', Namespace.SID),
|
| 93 | 95 | ]
|
| 94 | 96 | |
| 97 | +DeviceIdT = int
|
|
| 98 | +IdentityT = tuple[DeviceIdT, IdentityKey]
|
|
| 95 | 99 | |
| 96 | 100 | class OMEMO(BaseModule):
|
| 97 | 101 | |
| ... | ... | @@ -646,6 +650,25 @@ def _debug_print_stanza(self, stanza: Any) -> None: |
| 646 | 650 | stanzastr = stanzastr[0:-1]
|
| 647 | 651 | self._log.debug(stanzastr)
|
| 648 | 652 | |
| 653 | + def compose_trust_uri(self, jid: JID) -> str:
|
|
| 654 | + verified_identities = [
|
|
| 655 | + (info.device_id, info.public_key)
|
|
| 656 | + for info in self._backend.get_identity_infos(
|
|
| 657 | + jid.bare, only_active=True, trust=OMEMOTrust.VERIFIED)
|
|
| 658 | + ]
|
|
| 659 | + if self._client.is_own_jid(jid):
|
|
| 660 | + verified_identities.insert(0, self._backend.get_our_identity())
|
|
| 661 | + return compose_trust_uri(jid, verified_identities)
|
|
| 662 | + |
|
| 649 | 663 | def cleanup(self) -> None:
|
| 650 | 664 | self._backend.destroy()
|
| 651 | 665 | del self._backend
|
| 666 | + |
|
| 667 | + |
|
| 668 | +def compose_trust_uri(jid: JID, devices: list[IdentityT]) -> str:
|
|
| 669 | + query = (
|
|
| 670 | + XmppUriQuery.MESSAGE.value,
|
|
| 671 | + [(f'omemo-sid-{sid}', ik.get_fingerprint()) for sid, ik in devices]
|
|
| 672 | + ) if devices else None
|
|
| 673 | + uri = jid.new_as_bare().to_iri(query)
|
|
| 674 | + return uri |
| ... | ... | @@ -334,13 +334,13 @@ def _update_share_box(self) -> None: |
| 334 | 334 | self._ui.jid_label.set_text(str(self._contact.jid))
|
| 335 | 335 | |
| 336 | 336 | def _get_share_uri(self) -> str:
|
| 337 | + assert self._client is not None
|
|
| 337 | 338 | assert self._contact is not None
|
| 338 | 339 | jid = self._contact.get_address()
|
| 339 | 340 | if self._contact.is_groupchat:
|
| 340 | 341 | return jid.to_iri(XmppUriQuery.JOIN.value)
|
| 341 | 342 | else:
|
| 342 | - # TODO: add verified OMEMO FPs
|
|
| 343 | - return jid.to_iri()
|
|
| 343 | + return self._client.get_module('OMEMO').compose_trust_uri(jid)
|
|
| 344 | 344 | |
| 345 | 345 | def _on_share_clicked(self, _button: Gtk.Button) -> None:
|
| 346 | 346 | # Generate QR code on demand (i.e. not when switching chats)
|
| ... | ... | @@ -25,22 +25,20 @@ |
| 25 | 25 | import logging
|
| 26 | 26 | import time
|
| 27 | 27 | |
| 28 | -from gi.repository import GdkPixbuf
|
|
| 29 | 28 | from gi.repository import Gtk
|
| 30 | -from nbxmpp.protocol import JID
|
|
| 31 | 29 | from omemo_dr.const import OMEMOTrust
|
| 32 | 30 | from omemo_dr.structs import IdentityInfo
|
| 33 | 31 | |
| 34 | 32 | from gajim.common import app
|
| 35 | 33 | from gajim.common import ged
|
| 36 | 34 | from gajim.common import types
|
| 37 | -from gajim.common.const import XmppUriQuery
|
|
| 38 | 35 | from gajim.common.events import AccountConnected
|
| 39 | 36 | from gajim.common.events import AccountDisconnected
|
| 40 | 37 | from gajim.common.ged import EventHelper
|
| 41 | 38 | from gajim.common.helpers import generate_qr_code
|
| 42 | 39 | from gajim.common.i18n import _
|
| 43 | 40 | from gajim.common.modules.contacts import BareContact
|
| 41 | +from gajim.common.modules.omemo import compose_trust_uri
|
|
| 44 | 42 | |
| 45 | 43 | from .builder import get_builder
|
| 46 | 44 | from .dialogs import ConfirmationDialog
|
| ... | ... | @@ -196,25 +194,12 @@ def _load_fingerprints(self, contact: types.ChatContactT) -> None: |
| 196 | 194 | str(contact.jid)):
|
| 197 | 195 | self._ui.list.add(KeyRow(contact, identity_info))
|
| 198 | 196 | |
| 199 | - @staticmethod
|
|
| 200 | - def _get_qrcode(jid: JID,
|
|
| 201 | - sid: int,
|
|
| 202 | - fingerprint: str
|
|
| 203 | - ) -> GdkPixbuf.Pixbuf | None:
|
|
| 204 | - |
|
| 205 | - qry = (XmppUriQuery.MESSAGE.value, [(f'omemo-sid-{sid}', fingerprint)])
|
|
| 206 | - ver_string = jid.new_as_bare().to_iri(qry)
|
|
| 207 | - log.debug('Verification String: %s', ver_string)
|
|
| 208 | - return generate_qr_code(ver_string)
|
|
| 209 | - |
|
| 210 | 197 | def _load_qrcode(self) -> None:
|
| 211 | - client = app.get_client(self._account)
|
|
| 212 | - our_device_id, our_identity_key =\
|
|
| 213 | - self._omemo.backend.get_our_identity()
|
|
| 214 | - pixbuf = self._get_qrcode(client.get_own_jid(),
|
|
| 215 | - our_device_id,
|
|
| 216 | - our_identity_key.get_fingerprint())
|
|
| 217 | - self._ui.qr_code_image.set_from_pixbuf(pixbuf)
|
|
| 198 | + uri = compose_trust_uri(
|
|
| 199 | + app.get_client(self._account).get_own_jid(),
|
|
| 200 | + [self._omemo.backend.get_our_identity()])
|
|
| 201 | + log.debug('Trust URI: %s', uri)
|
|
| 202 | + self._ui.qr_code_image.set_from_pixbuf(generate_qr_code(uri))
|
|
| 218 | 203 | |
| 219 | 204 | def _on_show_inactive(self, switch: Gtk.Switch, _param: Any) -> None:
|
| 220 | 205 | self._ui.list.invalidate_filter()
|