Welcome to mirror list, hosted at ThFree Co, Russian Federation.

dev.gajim.org/gajim/gajim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Hörist <philipp@hoerist.com>2023-05-01 23:05:36 +0300
committerPhilipp Hörist <philipp@hoerist.com>2023-05-03 23:19:54 +0300
commit9b8b1839d1a5398c46925b1b299ad04177f82de7 (patch)
tree7270ec2a1698e960a500010b63405bd66d74bb9b
parentf8ba3f06ec9d4b695403ecd0c5a0f5fc48d888c2 (diff)
refactor: Adapt to omemo-dr changes
- Rename method and variables to snake case - Let omemo-dr generate the keys - Add needs_init() - Fix return types for some storage methods - Remove obsolete database methods
-rw-r--r--debian/control4
-rw-r--r--gajim/common/modules/omemo.py61
-rw-r--r--gajim/common/storage/omemo.py357
-rw-r--r--gajim/gtk/omemo_trust_manager.py44
-rw-r--r--pyproject.toml2
5 files changed, 236 insertions, 232 deletions
diff --git a/debian/control b/debian/control
index d27066e1f..c5cec30c3 100644
--- a/debian/control
+++ b/debian/control
@@ -13,7 +13,7 @@ Build-Depends:
python3-gi,
python3-gi-cairo,
python3-nbxmpp-nightly (>=20230405),
- python3-omemo-dr (>=20230407),
+ python3-omemo-dr (>=20230503),
python3-setuptools,
python3-packaging,
python3-cryptography (>=3.4.8),
@@ -36,7 +36,7 @@ Depends:
python3-gi (>= 3.42.0),
python3-gi-cairo (>= 1.14.0~),
python3-nbxmpp-nightly (>=20230405),
- python3-omemo-dr (>=20230407),
+ python3-omemo-dr (>=20230503),
gir1.2-pango-1.0 (>= 1.50.0),
gir1.2-gtk-3.0 (>= 3.24.30),
gir1.2-gtksource-4,
diff --git a/gajim/common/modules/omemo.py b/gajim/common/modules/omemo.py
index 1cf0ffd2c..7c6778ed1 100644
--- a/gajim/common/modules/omemo.py
+++ b/gajim/common/modules/omemo.py
@@ -51,6 +51,8 @@ from omemo_dr.exceptions import KeyExchangeMessage
from omemo_dr.exceptions import MessageNotForDevice
from omemo_dr.exceptions import SelfMessage
from omemo_dr.session import OMEMOSession
+from omemo_dr.structs import OMEMOBundle
+from omemo_dr.structs import OMEMOConfig
from gajim.common import app
from gajim.common import configpaths
@@ -130,7 +132,15 @@ class OMEMO(BaseModule):
db_path = data_dir / f'omemo_{self._own_jid}.db'
storage = OMEMOStorage(self._account, db_path, self._log)
- self._backend = OMEMOSession(self._own_jid, storage, self)
+ omemo_config = OMEMOConfig(default_prekey_amount=100,
+ min_prekey_amount=80,
+ spk_archive_seconds=86400 * 15,
+ spk_cycle_seconds=86400,
+ unacknowledged_count=2000)
+
+ self._backend = OMEMOSession(self._own_jid, storage, omemo_config)
+ self._backend.register_signal('republish-bundle',
+ self._on_republish_bundle)
self._omemo_groupchats: set[str] = set()
self._muc_temp_store: dict[bytes, str] = {}
@@ -168,6 +178,14 @@ class OMEMO(BaseModule):
if self.is_omemo_groupchat(jid):
self.get_affiliation_list(jid)
+ def _on_republish_bundle(self,
+ _session: OMEMOSession,
+ _signal_name: str,
+ bundle: OMEMOBundle
+ ) -> None:
+
+ self.set_bundle(bundle=bundle)
+
@property
def backend(self) -> OMEMOSession:
return self._backend
@@ -183,7 +201,7 @@ class OMEMO(BaseModule):
return False
missing = True
- for member_jid in self.backend.get_muc_members(jid):
+ for member_jid in self.backend.get_group_members(jid):
if not self.are_keys_missing(member_jid):
missing = False
if missing:
@@ -205,7 +223,7 @@ class OMEMO(BaseModule):
return False
# check if bundles are missing for some devices
- if self.backend.storage.hasUndecidedFingerprints(jid):
+ if self.backend.storage.has_undecided_fingerprints(jid):
self._log.info('%s => Undecided Fingerprints for %s',
contact.account, jid)
app.ged.raise_event(EncryptionInfo(
@@ -225,15 +243,15 @@ class OMEMO(BaseModule):
def _new_fingerprints_available(self, contact: types.ChatContactT) -> bool:
fingerprints: list[int] = []
if contact.is_groupchat:
- for member_jid in self.backend.get_muc_members(str(contact.jid),
+ for member_jid in self.backend.get_group_members(str(contact.jid),
without_self=False):
- fingerprints = self.backend.storage.getNewFingerprints(
+ fingerprints = self.backend.storage.get_new_fingerprints(
member_jid)
if fingerprints:
break
else:
- fingerprints = self.backend.storage.getNewFingerprints(
+ fingerprints = self.backend.storage.get_new_fingerprints(
str(contact.jid))
if not fingerprints:
@@ -359,7 +377,7 @@ class OMEMO(BaseModule):
return
plaintext = self._muc_temp_store[properties.omemo.payload]
- fingerprint = self.backend.own_fingerprint
+ fingerprint = self.backend.get_own_fingerprint()
trust = OMEMOTrust.VERIFIED
del self._muc_temp_store[properties.omemo.payload]
@@ -401,7 +419,8 @@ class OMEMO(BaseModule):
assert isinstance(properties.omemo, OMEMOMessage)
self._log.info('Groupchat: Last resort trying to find SID in DB')
- from_jid = self.backend.storage.getJidFromDevice(properties.omemo.sid)
+ from_jid = self.backend.storage.get_jid_from_device(
+ properties.omemo.sid)
if not from_jid:
self._log.error(
"Can't decrypt GroupChat Message from %s", resource)
@@ -443,9 +462,9 @@ class OMEMO(BaseModule):
jid = properties.muc_user.jid.bare
if properties.muc_user.affiliation in (Affiliation.OUTCAST,
Affiliation.NONE):
- self.backend.remove_muc_member(room, jid)
+ self.backend.remove_group_member(room, jid)
else:
- self.backend.add_muc_member(room, jid)
+ self.backend.add_group_member(room, jid)
if self.is_omemo_groupchat(room):
if not self.is_contact_in_roster(jid):
@@ -471,7 +490,7 @@ class OMEMO(BaseModule):
for user_jid in result.users:
jid = str(user_jid)
- self.backend.add_muc_member(room_jid, jid)
+ self.backend.add_group_member(room_jid, jid)
if not self.is_contact_in_roster(jid):
# Query Devicelists from JIDs not in our Roster
@@ -499,7 +518,7 @@ class OMEMO(BaseModule):
self._omemo_groupchats.discard(jid)
def _check_for_missing_sessions(self, jid: str) -> None:
- devices_without_session = self.backend.devices_without_sessions(jid)
+ devices_without_session = self.backend.get_devices_without_sessions(jid)
for device_id in devices_without_session:
if device_id in self._device_bundle_querys:
continue
@@ -524,7 +543,7 @@ class OMEMO(BaseModule):
# Fetch Bundles of own other Devices
if self._own_jid not in self._query_for_bundles:
- devices_without_session = self.backend.devices_without_sessions(
+ devices_without_session = self.backend.get_devices_without_sessions(
self._own_jid)
self._query_for_bundles.append(self._own_jid)
@@ -536,7 +555,7 @@ class OMEMO(BaseModule):
# Fetch Bundles of contacts devices
if contact_jid not in self._query_for_bundles:
- devices_without_session = self.backend.devices_without_sessions(
+ devices_without_session = self.backend.get_devices_without_sessions(
contact_jid)
self._query_for_bundles.append(contact_jid)
@@ -549,9 +568,11 @@ class OMEMO(BaseModule):
return False
return True
- def set_bundle(self) -> None:
- self._nbxmpp('OMEMO').set_bundle(self.backend.bundle,
- self.backend.own_device)
+ def set_bundle(self, bundle: OMEMOBundle | None = None) -> None:
+ if bundle is None:
+ bundle = self.backend.get_bundle()
+ self._nbxmpp('OMEMO').set_bundle(bundle,
+ self.backend.get_own_device())
@as_task
def request_bundle(self, jid: str, device_id: int):
@@ -579,7 +600,7 @@ class OMEMO(BaseModule):
message=EncryptionInfoMsg.UNDECIDED_FINGERPRINTS))
def set_devicelist(self, devicelist: Optional[list[int]] = None) -> None:
- devicelist_: set[int] = {self.backend.own_device}
+ devicelist_: set[int] = {self.backend.get_own_device()}
if devicelist is not None:
devicelist_.update(devicelist)
self._log.info('Publishing own devicelist: %s', devicelist_)
@@ -587,7 +608,7 @@ class OMEMO(BaseModule):
def clear_devicelist(self) -> None:
self.backend.update_devicelist(
- self._own_jid, [self.backend.own_device])
+ self._own_jid, [self.backend.get_own_device()])
self.set_devicelist()
@as_task
@@ -640,7 +661,7 @@ class OMEMO(BaseModule):
self._query_for_bundles.remove(jid)
if own_devices:
- if not self.backend.is_own_device_published:
+ if not self.backend.is_own_device_published():
# Our own device_id is not in the list, it could be
# overwritten by some other client
self.set_devicelist(devicelist)
diff --git a/gajim/common/storage/omemo.py b/gajim/common/storage/omemo.py
index adae07ae4..9ace1f028 100644
--- a/gajim/common/storage/omemo.py
+++ b/gajim/common/storage/omemo.py
@@ -26,29 +26,26 @@ import time
from collections import namedtuple
from pathlib import Path
-from omemo_dr.const import DEFAULT_PREKEY_AMOUNT
from omemo_dr.const import OMEMOTrust
from omemo_dr.ecc.djbec import CurvePublicKey
from omemo_dr.ecc.djbec import DjbECPrivateKey
from omemo_dr.exceptions import InvalidKeyIdException
from omemo_dr.identitykey import IdentityKey
from omemo_dr.identitykeypair import IdentityKeyPair
-from omemo_dr.state.axolotlstore import AxolotlStore
from omemo_dr.state.prekeyrecord import PreKeyRecord
from omemo_dr.state.sessionrecord import SessionRecord
from omemo_dr.state.signedprekeyrecord import SignedPreKeyRecord
-from omemo_dr.util.keyhelper import IdentityKeyExtended
-from omemo_dr.util.keyhelper import KeyHelper
+from omemo_dr.state.store import Store
from omemo_dr.util.medium import Medium
from gajim.common import app
from gajim.common.modules.util import LogAdapter
-def _convert_identity_key(key: bytes) -> Optional[IdentityKeyExtended]:
+def _convert_identity_key(key: bytes) -> Optional[IdentityKey]:
if not key:
return
- return IdentityKeyExtended(CurvePublicKey(key[1:]))
+ return IdentityKey(CurvePublicKey(key[1:]))
def _convert_record(record: bytes) -> SessionRecord:
@@ -59,15 +56,15 @@ sqlite3.register_converter('pk', _convert_identity_key)
sqlite3.register_converter('session_record', _convert_record)
-class OMEMOStorage(AxolotlStore):
+class OMEMOStorage(Store):
def __init__(self, account: str, db_path: Path, log: LogAdapter) -> None:
self._log = log
self._account = account
self._con = sqlite3.connect(db_path,
detect_types=sqlite3.PARSE_COLNAMES)
self._con.row_factory = self._namedtuple_factory
- self.createDb()
- self.migrateDb()
+ self.create_db()
+ self.migrate_db()
self._con.execute('PRAGMA secure_delete=1')
self._con.execute('PRAGMA synchronous=NORMAL;')
@@ -78,10 +75,6 @@ class OMEMOStorage(AxolotlStore):
self._con.execute('PRAGMA journal_mode=MEMORY;')
self._con.commit()
- if not self.getLocalRegistrationId():
- self._log.info('Generating OMEMO keys')
- self._generate_axolotl_keys()
-
def _is_blind_trust_enabled(self) -> bool:
return app.settings.get_account_setting(self._account,
'omemo_blind_trust')
@@ -105,26 +98,10 @@ class OMEMOStorage(AxolotlStore):
fields.append(col[0])
return namedtuple('Row', fields)(*row) # pyright: ignore
- def _generate_axolotl_keys(self) -> None:
- identity_key_pair = KeyHelper.generateIdentityKeyPair()
- registration_id = KeyHelper.getRandomSequence(2147483647)
- pre_keys = KeyHelper.generatePreKeys(
- KeyHelper.getRandomSequence(4294967296),
- DEFAULT_PREKEY_AMOUNT)
- self.storeLocalData(registration_id, identity_key_pair)
-
- signed_pre_key = KeyHelper.generateSignedPreKey(
- identity_key_pair, KeyHelper.getRandomSequence(65536))
-
- self.storeSignedPreKey(signed_pre_key.getId(), signed_pre_key)
-
- for pre_key in pre_keys:
- self.storePreKey(pre_key.getId(), pre_key)
-
def user_version(self) -> int:
return self._con.execute('PRAGMA user_version').fetchone()[0]
- def createDb(self) -> None:
+ def create_db(self) -> None:
if self.user_version() == 0:
create_tables = '''
@@ -166,7 +143,7 @@ class OMEMOStorage(AxolotlStore):
''' % (create_tables)
self._con.executescript(create_db_sql)
- def migrateDb(self) -> None:
+ def migrate_db(self) -> None:
''' Migrates the DB
'''
@@ -384,131 +361,130 @@ class OMEMOStorage(AxolotlStore):
self._con.execute('PRAGMA user_version=12')
self._con.commit()
- def loadSignedPreKey(self, signedPreKeyId: int) -> SignedPreKeyRecord:
+ def load_signed_pre_key(self, signed_pre_key_id: int) -> SignedPreKeyRecord:
query = 'SELECT record FROM signed_prekeys WHERE prekey_id = ?'
- result = self._con.execute(query, (signedPreKeyId, )).fetchone()
+ result = self._con.execute(query, (signed_pre_key_id, )).fetchone()
if result is None:
raise InvalidKeyIdException('No such signedprekeyrecord! %s ' %
- signedPreKeyId)
+ signed_pre_key_id)
return SignedPreKeyRecord.from_bytes(result.record)
- def loadSignedPreKeys(self) -> list[SignedPreKeyRecord]:
+ def load_signed_pre_keys(self) -> list[SignedPreKeyRecord]:
query = 'SELECT record FROM signed_prekeys'
results = self._con.execute(query).fetchall()
return [SignedPreKeyRecord.from_bytes(row.record) for row in results]
- def storeSignedPreKey(self,
- signedPreKeyId: int,
- signedPreKeyRecord: SignedPreKeyRecord
- ) -> None:
+ def store_signed_pre_key(self,
+ signed_pre_key_id: int,
+ signed_pre_key_record: SignedPreKeyRecord
+ ) -> None:
query = 'INSERT INTO signed_prekeys (prekey_id, record) VALUES(?,?)'
- self._con.execute(query, (signedPreKeyId,
- signedPreKeyRecord.serialize()))
+ self._con.execute(query, (signed_pre_key_id,
+ signed_pre_key_record.serialize()))
self._con.commit()
- def containsSignedPreKey(self, signedPreKeyId: int) -> bool:
+ def contains_signed_pre_key(self, signed_pre_key_id: int) -> bool:
query = 'SELECT record FROM signed_prekeys WHERE prekey_id = ?'
- result = self._con.execute(query, (signedPreKeyId,)).fetchone()
+ result = self._con.execute(query, (signed_pre_key_id,)).fetchone()
return result is not None
- def removeSignedPreKey(self, signedPreKeyId: int) -> None:
+ def remove_signed_pre_key(self, signed_pre_key_id: int) -> None:
query = 'DELETE FROM signed_prekeys WHERE prekey_id = ?'
- self._con.execute(query, (signedPreKeyId,))
+ self._con.execute(query, (signed_pre_key_id,))
self._con.commit()
- def getNextSignedPreKeyId(self) -> int:
- result = self.getCurrentSignedPreKeyId()
- if result is None:
- return 1 # StartId if no SignedPreKeys exist
+ def get_next_signed_pre_key_id(self) -> int:
+ result = self.get_current_signed_pre_key_id()
return (result % (Medium.MAX_VALUE - 1)) + 1
- def getCurrentSignedPreKeyId(self) -> Optional[int]:
+ def get_current_signed_pre_key_id(self) -> int:
query = 'SELECT MAX(prekey_id) FROM signed_prekeys'
result = self._con.execute(query).fetchone()
- return result.max_prekey_id if result is not None else None
+ assert result is not None
+ return result.max_prekey_id
- def getSignedPreKeyTimestamp(self, signedPreKeyId: int) -> int:
+ def get_signed_pre_key_timestamp(self, signed_pre_key_id: int) -> int:
query = '''SELECT strftime('%s', timestamp) FROM
signed_prekeys WHERE prekey_id = ?'''
- result = self._con.execute(query, (signedPreKeyId,)).fetchone()
+ result = self._con.execute(query, (signed_pre_key_id,)).fetchone()
if result is None:
raise InvalidKeyIdException('No such signedprekeyrecord! %s' %
- signedPreKeyId)
+ signed_pre_key_id)
return result.formated_time
- def removeOldSignedPreKeys(self, timestamp: int) -> None:
+ def remove_old_signed_pre_keys(self, timestamp: int) -> None:
query = '''DELETE FROM signed_prekeys
WHERE timestamp < datetime(?, "unixepoch")'''
self._con.execute(query, (timestamp,))
self._con.commit()
- def loadSession(self, recipientId: str, deviceId: int) -> SessionRecord:
+ def load_session(self, recipient_id: str, device_id: int) -> SessionRecord:
query = '''SELECT record as "record [session_record]"
FROM sessions WHERE recipient_id = ? AND device_id = ?'''
- result = self._con.execute(query, (recipientId, deviceId)).fetchone()
+ result = self._con.execute(query, (recipient_id, device_id)).fetchone()
return result.record if result is not None else SessionRecord()
- def getJidFromDevice(self, device_id: int) -> Optional[str]:
+ def get_jid_from_device(self, device_id: int) -> Optional[str]:
query = '''SELECT recipient_id
FROM sessions WHERE device_id = ?'''
result = self._con.execute(query, (device_id, )).fetchone()
return result.recipient_id if result is not None else None
- def getActiveDeviceTuples(self):
+ def get_active_device_tuples(self):
query = '''SELECT recipient_id, device_id
FROM sessions WHERE active = 1'''
return self._con.execute(query).fetchall()
- def storeSession(self,
- recipientId: str,
- deviceId: int,
- sessionRecord: SessionRecord
- ) -> None:
+ def store_session(self,
+ recipient_id: str,
+ device_id: int,
+ session_record: SessionRecord
+ ) -> None:
query = '''INSERT INTO sessions(recipient_id, device_id, record)
VALUES(?,?,?)'''
try:
- self._con.execute(query, (recipientId,
- deviceId,
- sessionRecord.serialize()))
+ self._con.execute(query, (recipient_id,
+ device_id,
+ session_record.serialize()))
except sqlite3.IntegrityError:
query = '''UPDATE sessions SET record = ?
WHERE recipient_id = ? AND device_id = ?'''
- self._con.execute(query, (sessionRecord.serialize(),
- recipientId,
- deviceId))
+ self._con.execute(query, (session_record.serialize(),
+ recipient_id,
+ device_id))
self._con.commit()
- def containsSession(self, recipientId: str, deviceId: int) -> bool:
+ def contains_session(self, recipient_id: str, device_id: int) -> bool:
query = '''SELECT record FROM sessions
WHERE recipient_id = ? AND device_id = ?'''
- result = self._con.execute(query, (recipientId, deviceId)).fetchone()
+ result = self._con.execute(query, (recipient_id, device_id)).fetchone()
return result is not None
- def deleteSession(self, recipientId: str, deviceId: int) -> None:
- self._log.info('Delete session for %s %s', recipientId, deviceId)
+ def delete_session(self, recipient_id: str, device_id: int) -> None:
+ self._log.info('Delete session for %s %s', recipient_id, device_id)
query = 'DELETE FROM sessions WHERE recipient_id = ? AND device_id = ?'
- self._con.execute(query, (recipientId, deviceId))
+ self._con.execute(query, (recipient_id, device_id))
self._con.commit()
- def deleteAllSessions(self, recipientId: str) -> None:
+ def delete_all_sessions(self, recipient_id: str) -> None:
query = 'DELETE FROM sessions WHERE recipient_id = ?'
- self._con.execute(query, (recipientId,))
+ self._con.execute(query, (recipient_id,))
self._con.commit()
- def getSessionsFromJid(self, recipientId: str):
+ def get_sessions_from_jid(self, recipient_id: str):
query = '''SELECT recipient_id,
device_id,
record as "record [session_record]",
active
FROM sessions WHERE recipient_id = ?'''
- return self._con.execute(query, (recipientId,)).fetchall()
+ return self._con.execute(query, (recipient_id,)).fetchall()
- def getSessionsFromJids(self, recipientIds: list[str]):
+ def get_sessions_from_jids(self, recipient_ids: list[str]):
query = '''
SELECT recipient_id,
device_id,
@@ -516,86 +492,84 @@ class OMEMOStorage(AxolotlStore):
active
FROM sessions
WHERE recipient_id IN ({})'''.format(
- ', '.join(['?'] * len(recipientIds)))
- return self._con.execute(query, recipientIds).fetchall()
+ ', '.join(['?'] * len(recipient_ids)))
+ return self._con.execute(query, recipient_ids).fetchall()
- def setActiveState(self, jid: str, devicelist: list[int]) -> None:
+ def set_active_state(self, address: str, devicelist: list[int]) -> None:
query = '''
UPDATE sessions SET active = 1
WHERE recipient_id = ? AND device_id IN ({})'''.format(
', '.join(['?'] * len(devicelist)))
- self._con.execute(query, (jid,) + tuple(devicelist))
+ self._con.execute(query, (address,) + tuple(devicelist))
query = '''
UPDATE sessions SET active = 0
WHERE recipient_id = ? AND device_id NOT IN ({})'''.format(
', '.join(['?'] * len(devicelist)))
- self._con.execute(query, (jid,) + tuple(devicelist))
+ self._con.execute(query, (address,) + tuple(devicelist))
self._con.commit()
- def setInactive(self, jid: str, device_id: int) -> None:
+ def set_inactive(self, address: str, device_id: int) -> None:
query = '''UPDATE sessions SET active = 0
WHERE recipient_id = ? AND device_id = ?'''
- self._con.execute(query, (jid, device_id))
+ self._con.execute(query, (address, device_id))
self._con.commit()
- def getInactiveSessionsKeys(self,
- recipientId: str
- ) -> list[IdentityKeyExtended]:
+ def get_inactive_sessions_keys(self,
+ recipient_id: str
+ ) -> list[IdentityKey]:
query = '''SELECT record as "record [session_record]" FROM sessions
WHERE active = 0 AND recipient_id = ?'''
- results = self._con.execute(query, (recipientId,)).fetchall()
+ results = self._con.execute(query, (recipient_id,)).fetchall()
- keys: list[IdentityKeyExtended] = []
+ keys: list[IdentityKey] = []
for result in results:
- key = result.record.getSessionState().getRemoteIdentityKey()
- keys.append(IdentityKeyExtended(key.getPublicKey()))
+ key = result.record.get_session_state().get_remote_identity_key()
+ keys.append(IdentityKey(key.get_public_key()))
return keys
- def loadPreKey(self, preKeyId: int) -> PreKeyRecord:
+ def load_pre_key(self, pre_key_id: int) -> PreKeyRecord:
query = '''SELECT record FROM prekeys WHERE prekey_id = ?'''
- result = self._con.execute(query, (preKeyId,)).fetchone()
+ result = self._con.execute(query, (pre_key_id,)).fetchone()
if result is None:
raise Exception('No such prekeyRecord!')
return PreKeyRecord.from_bytes(result.record)
- def loadPendingPreKeys(self) -> list[PreKeyRecord]:
+ def load_pending_pre_keys(self) -> list[PreKeyRecord]:
query = '''SELECT record FROM prekeys'''
result = self._con.execute(query).fetchall()
return [PreKeyRecord.from_bytes(row.record) for row in result]
- def storePreKey(self, preKeyId: int, preKeyRecord: PreKeyRecord) -> None:
+ def store_pre_key(self,
+ pre_key_id: int,
+ pre_key_record: PreKeyRecord
+ ) -> None:
query = 'INSERT INTO prekeys (prekey_id, record) VALUES(?,?)'
- self._con.execute(query, (preKeyId, preKeyRecord.serialize()))
+ self._con.execute(query, (pre_key_id, pre_key_record.serialize()))
self._con.commit()
- def containsPreKey(self, preKeyId: int) -> bool:
+ def contains_pre_key(self, pre_key_id: int) -> bool:
query = 'SELECT record FROM prekeys WHERE prekey_id = ?'
- result = self._con.execute(query, (preKeyId,)).fetchone()
+ result = self._con.execute(query, (pre_key_id,)).fetchone()
return result is not None
- def removePreKey(self, preKeyId: int) -> None:
+ def remove_pre_key(self, pre_key_id: int) -> None:
query = 'DELETE FROM prekeys WHERE prekey_id = ?'
- self._con.execute(query, (preKeyId,))
+ self._con.execute(query, (pre_key_id,))
self._con.commit()
- def getCurrentPreKeyId(self) -> int:
+ def get_current_pre_key_id(self) -> Optional[int]:
query = 'SELECT MAX(prekey_id) FROM prekeys'
- return self._con.execute(query).fetchone().max_prekey_id
+ result = self._con.execute(query).fetchone()
+ return result.max_prekey_id if result is not None else None
- def getPreKeyCount(self) -> int:
+ def get_pre_key_count(self) -> int:
query = 'SELECT COUNT(prekey_id) FROM prekeys'
return self._con.execute(query).fetchone().count_prekey_id
- def generateNewPreKeys(self, count: int) -> None:
- prekey_id = self.getCurrentPreKeyId() or 0
- pre_keys = KeyHelper.generatePreKeys(prekey_id + 1, count)
- for pre_key in pre_keys:
- self.storePreKey(pre_key.getId(), pre_key)
-
- def getIdentityKeyPair(self) -> IdentityKeyPair:
+ def get_identity_key_pair(self) -> IdentityKeyPair:
query = '''SELECT public_key as "public_key [pk]", private_key
FROM secret LIMIT 1'''
result = self._con.execute(query).fetchone()
@@ -603,15 +577,16 @@ class OMEMOStorage(AxolotlStore):
return IdentityKeyPair.new(result.public_key,
DjbECPrivateKey(result.private_key))
- def getLocalRegistrationId(self) -> Optional[int]: # pyright: ignore
+ def get_local_registration_id(self) -> int:
query = 'SELECT device_id FROM secret LIMIT 1'
result = self._con.execute(query).fetchone()
- return result.device_id if result is not None else None
+ assert result is not None
+ return result.device_id
- def storeLocalData(self,
- device_id: int,
- identityKeyPair: IdentityKeyPair
- ) -> None:
+ def store_own_identity(self,
+ device_id: int,
+ identity_key_pair: IdentityKeyPair
+ ) -> None:
query = 'SELECT * FROM secret'
result = self._con.execute(query).fetchone()
@@ -623,67 +598,71 @@ class OMEMOStorage(AxolotlStore):
query = '''INSERT INTO secret(device_id, public_key, private_key)
VALUES(?, ?, ?)'''
- public_key = identityKeyPair.getPublicKey().getPublicKey().serialize()
- private_key = identityKeyPair.getPrivateKey().serialize()
+ public_key = identity_key_pair.get_public_key().get_public_key().\
+ serialize()
+ private_key = identity_key_pair.get_private_key().serialize()
self._con.execute(query, (device_id, public_key, private_key))
self._con.commit()
- def saveIdentity(self, recipientId: str, identityKey: IdentityKey) -> None:
+ def save_identity(self,
+ recipient_id: str,
+ identity_key: IdentityKey
+ ) -> None:
query = '''INSERT INTO identities
(recipient_id, public_key, trust, shown)
VALUES(?, ?, ?, ?)'''
- if not self.containsIdentity(recipientId, identityKey):
- trust = self.getDefaultTrust(recipientId)
- self._con.execute(query, (recipientId,
- identityKey.getPublicKey().serialize(),
+ if not self.contains_identity(recipient_id, identity_key):
+ trust = self.get_default_trust(recipient_id)
+ self._con.execute(query, (recipient_id,
+ identity_key.get_public_key().serialize(),
trust,
1 if trust == OMEMOTrust.BLIND else 0))
self._con.commit()
- def containsIdentity(self,
- recipientId: str,
- identityKey: IdentityKey
- ) -> bool:
+ def contains_identity(self,
+ recipient_id: str,
+ identity_key: IdentityKey
+ ) -> bool:
query = '''SELECT * FROM identities WHERE recipient_id = ?
AND public_key = ?'''
- public_key = identityKey.getPublicKey().serialize()
- result = self._con.execute(query, (recipientId,
+ public_key = identity_key.get_public_key().serialize()
+ result = self._con.execute(query, (recipient_id,
public_key)).fetchone()
return result is not None
- def deleteIdentity(self,
- recipientId: str,
- identityKey: IdentityKey
- ) -> None:
+ def delete_identity(self,
+ recipient_id: str,
+ identity_key: IdentityKey
+ ) -> None:
query = '''DELETE FROM identities
WHERE recipient_id = ? AND public_key = ?'''
- public_key = identityKey.getPublicKey().serialize()
- self._con.execute(query, (recipientId, public_key))
+ public_key = identity_key.get_public_key().serialize()
+ self._con.execute(query, (recipient_id, public_key))
self._con.commit()
- def isTrustedIdentity(self,
- recipientId: str,
- identityKey: IdentityKey
- ) -> bool:
+ def is_trusted_identity(self,
+ recipient_id: str,
+ identity_key: IdentityKey
+ ) -> bool:
return True
- def getTrustForIdentity(self,
- recipientId: str,
- identityKey: IdentityKey
- ) -> Optional[OMEMOTrust]:
+ def get_trust_for_identity(self,
+ recipient_id: str,
+ identity_key: IdentityKey
+ ) -> Optional[OMEMOTrust]:
query = '''SELECT trust FROM identities WHERE recipient_id = ?
AND public_key = ?'''
- public_key = identityKey.getPublicKey().serialize()
- result = self._con.execute(query, (recipientId, public_key)).fetchone()
+ public_key = identity_key.get_public_key().serialize()
+ result = self._con.execute(query, (recipient_id, public_key)).fetchone()
return result.trust if result is not None else None
- def getFingerprints(self, jid: str):
+ def get_fingerprints(self, jid: str):
query = '''SELECT recipient_id,
public_key as "public_key [pk]",
trust,
@@ -692,7 +671,7 @@ class OMEMOStorage(AxolotlStore):
WHERE recipient_id = ? ORDER BY trust ASC'''
return self._con.execute(query, (jid,)).fetchall()
- def getMucFingerprints(self, jids: list[str]):
+ def get_muc_fingerprints(self, jids: list[str]):
query = '''
SELECT recipient_id,
public_key as "public_key [pk]",
@@ -704,18 +683,18 @@ class OMEMOStorage(AxolotlStore):
return self._con.execute(query, jids).fetchall()
- def hasUndecidedFingerprints(self, jid: str) -> bool:
+ def has_undecided_fingerprints(self, jid: str) -> bool:
query = '''SELECT public_key as "public_key [pk]" FROM identities
WHERE recipient_id = ? AND trust = ?'''
result = self._con.execute(query,
(jid, OMEMOTrust.UNDECIDED)).fetchall()
undecided = [row.public_key for row in result]
- inactive = self.getInactiveSessionsKeys(jid)
+ inactive = self.get_inactive_sessions_keys(jid)
undecided = set(undecided) - set(inactive)
return bool(undecided)
- def getDefaultTrust(self, jid: str) -> OMEMOTrust:
+ def get_default_trust(self, jid: str) -> OMEMOTrust:
if not self._is_blind_trust_enabled():
return OMEMOTrust.UNDECIDED
@@ -726,78 +705,84 @@ class OMEMOStorage(AxolotlStore):
return OMEMOTrust.BLIND
return OMEMOTrust.UNDECIDED
- def getTrustedFingerprints(self, jid: str) -> list[IdentityKeyExtended]:
+ def get_trusted_fingerprints(self, address: str) -> list[IdentityKey]:
query = '''SELECT public_key as "public_key [pk]" FROM identities
WHERE recipient_id = ? AND trust IN(1, 3)'''
- result = self._con.execute(query, (jid,)).fetchall()
+ result = self._con.execute(query, (address,)).fetchall()
return [row.public_key for row in result]
- def getNewFingerprints(self, jid: str) -> list[int]:
+ def get_new_fingerprints(self, jid: str) -> list[int]:
query = '''SELECT _id FROM identities WHERE shown = 0
AND recipient_id = ?'''
result = self._con.execute(query, (jid,)).fetchall()
return [row.id for row in result]
- def setShownFingerprints(self, fingerprints: list[int]) -> None:
+ def set_shown_fingerprints(self, fingerprints: list[int]) -> None:
query = 'UPDATE identities SET shown = 1 WHERE _id IN ({})'.format(
', '.join(['?'] * len(fingerprints)))
self._con.execute(query, fingerprints)
self._con.commit()
- def setTrust(self,
- recipient_id: str,
- identityKey: IdentityKey,
- trust: OMEMOTrust
- ) -> None:
+ def set_trust(self,
+ recipient_id: str,
+ identity_key: IdentityKey,
+ trust: OMEMOTrust
+ ) -> None:
query = '''UPDATE identities SET trust = ? WHERE public_key = ?
AND recipient_id = ?'''
- public_key = identityKey.getPublicKey().serialize()
+ public_key = identity_key.get_public_key().serialize()
self._con.execute(query, (trust, public_key, recipient_id))
self._con.commit()
- def isTrusted(self, recipient_id: str, device_id: int) -> bool:
- record = self.loadSession(recipient_id, device_id)
- if record.isFresh():
+ def is_trusted(self, recipient_id: str, device_id: int) -> bool:
+ record = self.load_session(recipient_id, device_id)
+ if record.is_fresh():
return False
- identity_key = record.getSessionState().getRemoteIdentityKey()
- return self.getTrustForIdentity(
+ identity_key = record.get_session_state().get_remote_identity_key()
+ return self.get_trust_for_identity(
recipient_id, identity_key) in (OMEMOTrust.VERIFIED,
OMEMOTrust.BLIND)
- def getIdentityLastSeen(self,
- recipient_id: str,
- identity_key: IdentityKey
- ) -> Optional[int]:
+ def get_identity_last_seen(self,
+ recipient_id: str,
+ identity_key: IdentityKey
+ ) -> Optional[int]:
- serialized = identity_key.getPublicKey().serialize()
+ serialized = identity_key.get_public_key().serialize()
query = '''SELECT timestamp FROM identities
WHERE recipient_id = ? AND public_key = ?'''
result = self._con.execute(query, (recipient_id,
serialized)).fetchone()
return result.timestamp if result is not None else None
- def setIdentityLastSeen(self,
- recipient_id: str,
- identity_key: IdentityKey
- ) -> None:
+ def set_identity_last_seen(self,
+ recipient_id: str,
+ identity_key: IdentityKey
+ ) -> None:
timestamp = int(time.time())
- serialized = identity_key.getPublicKey().serialize()
+ serialized = identity_key.get_public_key().serialize()
self._log.info('Set last seen for %s %s', recipient_id, timestamp)
query = '''UPDATE identities SET timestamp = ?
WHERE recipient_id = ? AND public_key = ?'''
self._con.execute(query, (timestamp, recipient_id, serialized))
self._con.commit()
- def getUnacknowledgedCount(self, recipient_id: str, device_id: int) -> int:
- record = self.loadSession(recipient_id, device_id)
- if record.isFresh():
+ def get_unacknowledged_count(self,
+ recipient_id: str,
+ device_id: int
+ ) -> int:
+ record = self.load_session(recipient_id, device_id)
+ if record.is_fresh():
return 0
- state = record.getSessionState()
- return state.getSenderChainKey().getIndex()
+ state = record.get_session_state()
+ return state.get_sender_chain_key().get_index()
- def getSubDeviceSessions(self, recipientId: str) -> list[int]:
- # Not used
- return []
+ def needs_init(self) -> bool:
+ try:
+ self.get_local_registration_id()
+ except AssertionError:
+ return True
+ return False
diff --git a/gajim/gtk/omemo_trust_manager.py b/gajim/gtk/omemo_trust_manager.py
index 6623829f3..acd749231 100644
--- a/gajim/gtk/omemo_trust_manager.py
+++ b/gajim/gtk/omemo_trust_manager.py
@@ -29,9 +29,7 @@ from gi.repository import GdkPixbuf
from gi.repository import Gtk
from nbxmpp.protocol import JID
from omemo_dr.const import OMEMOTrust
-from omemo_dr.identitykeypair import IdentityKeyPair
-from omemo_dr.util.keyhelper import get_fingerprint
-from omemo_dr.util.keyhelper import IdentityKeyExtended
+from omemo_dr.identitykey import IdentityKey
from gajim.common import app
from gajim.common import ged
@@ -125,9 +123,8 @@ class OMEMOTrustManager(Gtk.Box, EventHelper):
self._omemo = client.get_module('OMEMO')
- self._identity_key = cast(
- IdentityKeyPair, self._omemo.backend.storage.getIdentityKeyPair())
- our_fpr_formatted = get_fingerprint(self._identity_key, formatted=True)
+ our_fpr_formatted = self._omemo.backend.get_own_fingerprint(
+ formatted=True)
self._ui.our_fingerprint_1.set_text(our_fpr_formatted)
self._ui.our_fingerprint_2.set_text(our_fpr_formatted)
@@ -198,15 +195,16 @@ class OMEMOTrustManager(Gtk.Box, EventHelper):
if contact.is_groupchat:
members = list(self._omemo.backend.get_muc_members(
str(contact.jid)))
- sessions = self._omemo.backend.storage.getSessionsFromJids(members)
- results = self._omemo.backend.storage.getMucFingerprints(members)
+ sessions = self._omemo.backend.storage.get_sessions_from_jids(
+ members)
+ results = self._omemo.backend.storage.get_muc_fingerprints(members)
else:
- sessions = self._omemo.backend.storage.getSessionsFromJid(
+ sessions = self._omemo.backend.storage.get_sessions_from_jid(
str(contact.jid))
- results = self._omemo.backend.storage.getFingerprints(
+ results = self._omemo.backend.storage.get_fingerprints(
str(contact.jid))
- rows: dict[IdentityKeyExtended, KeyRow] = {}
+ rows: dict[IdentityKey, KeyRow] = {}
for result in results:
rows[result.public_key] = KeyRow(contact,
result.recipient_id,
@@ -215,16 +213,17 @@ class OMEMOTrustManager(Gtk.Box, EventHelper):
result.timestamp)
for item in sessions:
- if item.record.isFresh():
+ if item.record.is_fresh():
return
- identity_key = item.record.getSessionState().getRemoteIdentityKey()
- identity_key = IdentityKeyExtended(identity_key.getPublicKey())
+ identity_key = item.record.get_session_state().\
+ get_remote_identity_key()
+ identity_key = IdentityKey(identity_key.get_public_key())
try:
key_row = rows[identity_key]
except KeyError:
log.warning('Could not find session identitykey %s',
item.device_id)
- self._omemo.backend.storage.deleteSession(item.recipient_id,
+ self._omemo.backend.storage.delete_session(item.recipient_id,
item.device_id)
continue
@@ -237,10 +236,9 @@ class OMEMOTrustManager(Gtk.Box, EventHelper):
@staticmethod
def _get_qrcode(jid: JID,
sid: int,
- identity_key: IdentityKeyPair
+ fingerprint: str
) -> GdkPixbuf.Pixbuf | None:
- fingerprint = get_fingerprint(identity_key)
qry = (XmppUriQuery.MESSAGE.value, [(f'omemo-sid-{sid}', fingerprint)])
ver_string = jid.new_as_bare().to_iri(qry)
log.debug('Verification String: %s', ver_string)
@@ -249,8 +247,8 @@ class OMEMOTrustManager(Gtk.Box, EventHelper):
def _load_qrcode(self) -> None:
client = app.get_client(self._account)
pixbuf = self._get_qrcode(client.get_own_jid(),
- self._omemo.backend.own_device,
- self._identity_key)
+ self._omemo.backend.get_own_device(),
+ self._omemo.backend.get_own_fingerprint())
self._ui.qr_code_image.set_from_pixbuf(pixbuf)
def _on_show_inactive(self, switch: Gtk.Switch, _param: Any) -> None:
@@ -280,7 +278,7 @@ class KeyRow(Gtk.ListBoxRow):
def __init__(self,
contact: types.ChatContactT,
jid: JID,
- identity_key: IdentityKeyExtended,
+ identity_key: IdentityKey,
trust: OMEMOTrust,
last_seen: Optional[float]
) -> None:
@@ -347,9 +345,9 @@ class KeyRow(Gtk.ListBoxRow):
def _remove():
self._omemo.backend.remove_device(str(self.jid), self.device_id)
- self._omemo.backend.storage.deleteSession(
+ self._omemo.backend.storage.delete_session(
str(self.jid), self.device_id)
- self._omemo.backend.storage.deleteIdentity(
+ self._omemo.backend.storage.delete_identity(
str(self.jid), self._identity_key)
listbox = cast(Gtk.ListBox, self.get_parent())
@@ -373,7 +371,7 @@ class KeyRow(Gtk.ListBoxRow):
image.get_style_context().add_class(css_class)
image.set_tooltip_text(tooltip)
- self._omemo.backend.storage.setTrust(
+ self._omemo.backend.storage.set_trust(
str(self.jid), self._identity_key, self.trust)
@property
diff --git a/pyproject.toml b/pyproject.toml
index 4545e450b..0efb16b34 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -35,7 +35,7 @@ dependencies = [
"pycairo>=1.16.0",
"PyGObject>=3.42.0",
"qrcode>=7.3.1",
- "omemo-dr>=0.99.0,<2.0.0",
+ "omemo-dr>=0.99.1,<2.0.0",
"winsdk ; platform_system == 'Windows'",
]
dynamic = ["version"]