Compare commits
2 Commits
f15a3e6bf4
...
f723c43603
Author | SHA1 | Date | |
---|---|---|---|
f723c43603 | |||
d88876c928 |
@ -9,6 +9,7 @@ const omemoRatchetsTable = 'OmemoSessions';
|
|||||||
const omemoTrustCacheTable = 'OmemoTrustCacheList';
|
const omemoTrustCacheTable = 'OmemoTrustCacheList';
|
||||||
const omemoTrustDeviceListTable = 'OmemoTrustDeviceList';
|
const omemoTrustDeviceListTable = 'OmemoTrustDeviceList';
|
||||||
const omemoTrustEnableListTable = 'OmemoTrustEnableList';
|
const omemoTrustEnableListTable = 'OmemoTrustEnableList';
|
||||||
|
const omemoFingerprintCache = 'OmemoFingerprintCache';
|
||||||
const xmppStateTable = 'XmppState';
|
const xmppStateTable = 'XmppState';
|
||||||
|
|
||||||
const typeString = 0;
|
const typeString = 0;
|
||||||
|
@ -168,6 +168,15 @@ Future<void> createDatabase(Database db, int version) async {
|
|||||||
PRIMARY KEY (jid, id)
|
PRIMARY KEY (jid, id)
|
||||||
)''',
|
)''',
|
||||||
);
|
);
|
||||||
|
await db.execute(
|
||||||
|
'''
|
||||||
|
CREATE TABLE $omemoFingerprintCache (
|
||||||
|
jid TEXT NOT NULL,
|
||||||
|
id INTEGER NOT NULL,
|
||||||
|
fingerprint TEXT NOT NULL,
|
||||||
|
PRIMARY KEY (jid, id)
|
||||||
|
)''',
|
||||||
|
);
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
await db.execute(
|
await db.execute(
|
||||||
|
@ -13,6 +13,7 @@ import 'package:moxxyv2/service/database/migrations/0000_conversations2.dart';
|
|||||||
import 'package:moxxyv2/service/database/migrations/0000_conversations3.dart';
|
import 'package:moxxyv2/service/database/migrations/0000_conversations3.dart';
|
||||||
import 'package:moxxyv2/service/database/migrations/0000_language.dart';
|
import 'package:moxxyv2/service/database/migrations/0000_language.dart';
|
||||||
import 'package:moxxyv2/service/database/migrations/0000_lmc.dart';
|
import 'package:moxxyv2/service/database/migrations/0000_lmc.dart';
|
||||||
|
import 'package:moxxyv2/service/database/migrations/0000_omemo_fingerprint_cache.dart';
|
||||||
import 'package:moxxyv2/service/database/migrations/0000_reactions.dart';
|
import 'package:moxxyv2/service/database/migrations/0000_reactions.dart';
|
||||||
import 'package:moxxyv2/service/database/migrations/0000_reactions_store_hint.dart';
|
import 'package:moxxyv2/service/database/migrations/0000_reactions_store_hint.dart';
|
||||||
import 'package:moxxyv2/service/database/migrations/0000_retraction.dart';
|
import 'package:moxxyv2/service/database/migrations/0000_retraction.dart';
|
||||||
@ -21,6 +22,7 @@ import 'package:moxxyv2/service/database/migrations/0000_shared_media.dart';
|
|||||||
import 'package:moxxyv2/service/database/migrations/0000_xmpp_state.dart';
|
import 'package:moxxyv2/service/database/migrations/0000_xmpp_state.dart';
|
||||||
import 'package:moxxyv2/service/not_specified.dart';
|
import 'package:moxxyv2/service/not_specified.dart';
|
||||||
import 'package:moxxyv2/service/omemo/omemo.dart';
|
import 'package:moxxyv2/service/omemo/omemo.dart';
|
||||||
|
import 'package:moxxyv2/service/omemo/types.dart';
|
||||||
import 'package:moxxyv2/service/roster.dart';
|
import 'package:moxxyv2/service/roster.dart';
|
||||||
import 'package:moxxyv2/service/state.dart';
|
import 'package:moxxyv2/service/state.dart';
|
||||||
import 'package:moxxyv2/shared/models/conversation.dart';
|
import 'package:moxxyv2/shared/models/conversation.dart';
|
||||||
@ -65,7 +67,7 @@ class DatabaseService {
|
|||||||
_db = await openDatabase(
|
_db = await openDatabase(
|
||||||
dbPath,
|
dbPath,
|
||||||
password: key,
|
password: key,
|
||||||
version: 12,
|
version: 13,
|
||||||
onCreate: createDatabase,
|
onCreate: createDatabase,
|
||||||
onConfigure: (db) async {
|
onConfigure: (db) async {
|
||||||
// In order to do schema changes during database upgrades, we disable foreign
|
// In order to do schema changes during database upgrades, we disable foreign
|
||||||
@ -122,6 +124,10 @@ class DatabaseService {
|
|||||||
_log.finest('Running migration for database version 12');
|
_log.finest('Running migration for database version 12');
|
||||||
await upgradeFromV11ToV12(db);
|
await upgradeFromV11ToV12(db);
|
||||||
}
|
}
|
||||||
|
if (oldVersion < 13) {
|
||||||
|
_log.finest('Running migration for database version 13');
|
||||||
|
await upgradeFromV12ToV13(db);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1002,4 +1008,38 @@ class DatabaseService {
|
|||||||
|
|
||||||
await batch.commit();
|
await batch.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> addFingerprintsToCache(List<OmemoCacheTriple> items) async {
|
||||||
|
final batch = _db.batch();
|
||||||
|
for (final item in items) {
|
||||||
|
batch.insert(
|
||||||
|
omemoFingerprintCache,
|
||||||
|
<String, dynamic>{
|
||||||
|
'jid': item.jid,
|
||||||
|
'id': item.deviceId,
|
||||||
|
'fingerprint': item.fingerprint,
|
||||||
|
},
|
||||||
|
conflictAlgorithm: ConflictAlgorithm.replace,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await batch.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<OmemoCacheTriple>> getFingerprintsFromCache(String jid) async {
|
||||||
|
final rawItems = await _db.query(
|
||||||
|
omemoFingerprintCache,
|
||||||
|
where: 'jid = ?',
|
||||||
|
whereArgs: [jid],
|
||||||
|
);
|
||||||
|
|
||||||
|
return rawItems
|
||||||
|
.map((item) {
|
||||||
|
return OmemoCacheTriple(
|
||||||
|
jid,
|
||||||
|
item['id']! as int,
|
||||||
|
item['fingerprint']! as String,
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,5 +9,4 @@ Future<void> upgradeFromV6ToV7(Database db) async {
|
|||||||
await db.execute(
|
await db.execute(
|
||||||
"ALTER TABLE $conversationsTable ADD COLUMN lastMessageSender TEXT NOT NULL DEFAULT '';"
|
"ALTER TABLE $conversationsTable ADD COLUMN lastMessageSender TEXT NOT NULL DEFAULT '';"
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
import 'package:moxxyv2/service/database/constants.dart';
|
||||||
|
import 'package:sqflite_sqlcipher/sqflite.dart';
|
||||||
|
|
||||||
|
Future<void> upgradeFromV12ToV13(Database db) async {
|
||||||
|
await db.execute(
|
||||||
|
'''
|
||||||
|
CREATE TABLE $omemoFingerprintCache (
|
||||||
|
jid TEXT NOT NULL,
|
||||||
|
id INTEGER NOT NULL,
|
||||||
|
fingerprint TEXT NOT NULL,
|
||||||
|
PRIMARY KEY (jid, id)
|
||||||
|
)''',
|
||||||
|
);
|
||||||
|
}
|
@ -8,6 +8,7 @@ import 'package:moxxmpp/moxxmpp.dart';
|
|||||||
import 'package:moxxyv2/service/database/database.dart';
|
import 'package:moxxyv2/service/database/database.dart';
|
||||||
import 'package:moxxyv2/service/moxxmpp/omemo.dart';
|
import 'package:moxxyv2/service/moxxmpp/omemo.dart';
|
||||||
import 'package:moxxyv2/service/omemo/implementations.dart';
|
import 'package:moxxyv2/service/omemo/implementations.dart';
|
||||||
|
import 'package:moxxyv2/service/omemo/types.dart';
|
||||||
import 'package:moxxyv2/shared/models/omemo_device.dart';
|
import 'package:moxxyv2/shared/models/omemo_device.dart';
|
||||||
import 'package:omemo_dart/omemo_dart.dart';
|
import 'package:omemo_dart/omemo_dart.dart';
|
||||||
import 'package:synchronized/synchronized.dart';
|
import 'package:synchronized/synchronized.dart';
|
||||||
@ -25,6 +26,7 @@ class OmemoService {
|
|||||||
bool _initialized = false;
|
bool _initialized = false;
|
||||||
final Lock _lock = Lock();
|
final Lock _lock = Lock();
|
||||||
final Queue<Completer<void>> _waitingForInitialization = Queue<Completer<void>>();
|
final Queue<Completer<void>> _waitingForInitialization = Queue<Completer<void>>();
|
||||||
|
final Map<String, Map<int, String>> _fingerprintCache = {};
|
||||||
|
|
||||||
late OmemoSessionManager omemoState;
|
late OmemoSessionManager omemoState;
|
||||||
|
|
||||||
@ -64,6 +66,22 @@ class OmemoService {
|
|||||||
await GetIt.I.get<DatabaseService>().saveRatchet(
|
await GetIt.I.get<DatabaseService>().saveRatchet(
|
||||||
OmemoDoubleRatchetWrapper(event.ratchet, event.deviceId, event.jid),
|
OmemoDoubleRatchetWrapper(event.ratchet, event.deviceId, event.jid),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (event.added) {
|
||||||
|
// Cache the fingerprint
|
||||||
|
final fingerprint = HEX.encode(await event.ratchet.ik.getBytes());
|
||||||
|
await GetIt.I.get<DatabaseService>().addFingerprintsToCache([
|
||||||
|
OmemoCacheTriple(
|
||||||
|
event.jid,
|
||||||
|
event.deviceId,
|
||||||
|
fingerprint,
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (_fingerprintCache.containsKey(event.jid)) {
|
||||||
|
_fingerprintCache[event.jid]![event.deviceId] = fingerprint;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (event is DeviceMapModifiedEvent) {
|
} else if (event is DeviceMapModifiedEvent) {
|
||||||
await commitDeviceMap(event.map);
|
await commitDeviceMap(event.map);
|
||||||
} else if (event is DeviceModifiedEvent) {
|
} else if (event is DeviceModifiedEvent) {
|
||||||
@ -202,20 +220,70 @@ class OmemoService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _fetchFingerprintsAndCache(JID jid) async {
|
||||||
|
final bareJid = jid.toBare().toString();
|
||||||
|
final allDevicesRaw = await GetIt.I.get<XmppConnection>()
|
||||||
|
.getManagerById<OmemoManager>(omemoManager)!
|
||||||
|
.retrieveDeviceBundles(jid);
|
||||||
|
if (allDevicesRaw.isType<List<OmemoBundle>>()) {
|
||||||
|
final allDevices = allDevicesRaw.get<List<OmemoBundle>>();
|
||||||
|
final map = <int, String>{};
|
||||||
|
final items = List<OmemoCacheTriple>.empty(growable: true);
|
||||||
|
for (final device in allDevices) {
|
||||||
|
final curveIk = await device.ik.toCurve25519();
|
||||||
|
final fingerprint = HEX.encode(await curveIk.getBytes());
|
||||||
|
map[device.id] = fingerprint;
|
||||||
|
items.add(OmemoCacheTriple(bareJid, device.id, fingerprint));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache them in memory
|
||||||
|
_fingerprintCache[bareJid] = map;
|
||||||
|
|
||||||
|
// Cache them in the database
|
||||||
|
await GetIt.I.get<DatabaseService>().addFingerprintsToCache(items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _loadOrFetchFingerprints(JID jid) async {
|
||||||
|
final bareJid = jid.toBare().toString();
|
||||||
|
if (!_fingerprintCache.containsKey(bareJid)) {
|
||||||
|
// First try to load it from the database
|
||||||
|
final triples = await GetIt.I.get<DatabaseService>()
|
||||||
|
.getFingerprintsFromCache(bareJid);
|
||||||
|
if (triples.isEmpty) {
|
||||||
|
// We found no fingerprints in the database, so try to fetch them
|
||||||
|
await _fetchFingerprintsAndCache(jid);
|
||||||
|
} else {
|
||||||
|
// We have fetched fingerprints from the database
|
||||||
|
_fingerprintCache[bareJid] = Map<int, String>.fromEntries(
|
||||||
|
triples.map((triple) {
|
||||||
|
return MapEntry<int, String>(
|
||||||
|
triple.deviceId,
|
||||||
|
triple.fingerprint,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<List<OmemoDevice>> getOmemoKeysForJid(String jid) async {
|
Future<List<OmemoDevice>> getOmemoKeysForJid(String jid) async {
|
||||||
await ensureInitialized();
|
await ensureInitialized();
|
||||||
final fingerprints = await omemoState.getHexFingerprintsForJid(jid);
|
|
||||||
|
// Get finger prints if we have to
|
||||||
|
await _loadOrFetchFingerprints(JID.fromString(jid));
|
||||||
|
|
||||||
final keys = List<OmemoDevice>.empty(growable: true);
|
final keys = List<OmemoDevice>.empty(growable: true);
|
||||||
final tm = omemoState.trustManager as BlindTrustBeforeVerificationTrustManager;
|
final tm = omemoState.trustManager as BlindTrustBeforeVerificationTrustManager;
|
||||||
final trustMap = await tm.getDevicesTrust(jid);
|
final trustMap = await tm.getDevicesTrust(jid);
|
||||||
for (final fp in fingerprints) {
|
for (final deviceId in _fingerprintCache[jid]!.keys) {
|
||||||
keys.add(
|
keys.add(
|
||||||
OmemoDevice(
|
OmemoDevice(
|
||||||
fp.fingerprint,
|
_fingerprintCache[jid]![deviceId]!,
|
||||||
await tm.isTrusted(jid, fp.deviceId),
|
await tm.isTrusted(jid, deviceId),
|
||||||
trustMap[fp.deviceId] == BTBVTrustState.verified,
|
trustMap[deviceId] == BTBVTrustState.verified,
|
||||||
await tm.isEnabled(jid, fp.deviceId),
|
await tm.isEnabled(jid, deviceId),
|
||||||
fp.deviceId,
|
deviceId,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -267,36 +335,28 @@ class OmemoService {
|
|||||||
/// published on [ownJid]'s devices PubSub node.
|
/// published on [ownJid]'s devices PubSub node.
|
||||||
/// Note that the list is made so that the current device is excluded.
|
/// Note that the list is made so that the current device is excluded.
|
||||||
Future<List<OmemoDevice>> getOwnFingerprints(JID ownJid) async {
|
Future<List<OmemoDevice>> getOwnFingerprints(JID ownJid) async {
|
||||||
final conn = GetIt.I.get<XmppConnection>();
|
|
||||||
final ownId = await getDeviceId();
|
final ownId = await getDeviceId();
|
||||||
final keys = List<OmemoDevice>.from(
|
final keys = List<OmemoDevice>.from(
|
||||||
await getOmemoKeysForJid(ownJid.toString()),
|
await getOmemoKeysForJid(ownJid.toString()),
|
||||||
);
|
);
|
||||||
|
final bareJid = ownJid.toBare().toString();
|
||||||
|
|
||||||
// TODO(PapaTutuWawa): This should be cached in the database and only requested if
|
// Get finger prints if we have to
|
||||||
// it's not cached.
|
await _loadOrFetchFingerprints(ownJid);
|
||||||
final allDevicesRaw = await conn.getManagerById<OmemoManager>(omemoManager)!
|
|
||||||
.retrieveDeviceBundles(ownJid);
|
|
||||||
if (allDevicesRaw.isType<List<OmemoBundle>>()) {
|
|
||||||
final allDevices = allDevicesRaw.get<List<OmemoBundle>>();
|
|
||||||
|
|
||||||
for (final device in allDevices) {
|
|
||||||
// All devices that are publishes that is not the current device
|
|
||||||
if (device.id == ownId) continue;
|
|
||||||
final curveIk = await device.ik.toCurve25519();
|
|
||||||
|
|
||||||
|
_fingerprintCache[bareJid]!.forEach((deviceId, fingerprint) {
|
||||||
|
if (deviceId == ownId) return;
|
||||||
keys.add(
|
keys.add(
|
||||||
OmemoDevice(
|
OmemoDevice(
|
||||||
HEX.encode(await curveIk.getBytes()),
|
fingerprint,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
device.id,
|
deviceId,
|
||||||
hasSessionWith: false,
|
hasSessionWith: false,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
}
|
|
||||||
|
|
||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
6
lib/service/omemo/types.dart
Normal file
6
lib/service/omemo/types.dart
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
class OmemoCacheTriple {
|
||||||
|
const OmemoCacheTriple(this.jid, this.deviceId, this.fingerprint);
|
||||||
|
final String jid;
|
||||||
|
final int deviceId;
|
||||||
|
final String fingerprint;
|
||||||
|
}
|
@ -831,7 +831,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
path: "."
|
path: "."
|
||||||
ref: HEAD
|
ref: HEAD
|
||||||
resolved-ref: "797bf6985638f0fe5a6e12a7a8339cf7d9334f88"
|
resolved-ref: fe1ba99b14b516ecf6d147c57bd986d8afe7f3fc
|
||||||
url: "https://codeberg.org/PapaTutuWawa/omemo_dart.git"
|
url: "https://codeberg.org/PapaTutuWawa/omemo_dart.git"
|
||||||
source: git
|
source: git
|
||||||
version: "0.3.2"
|
version: "0.3.2"
|
||||||
|
@ -144,7 +144,7 @@ dependency_overrides:
|
|||||||
omemo_dart:
|
omemo_dart:
|
||||||
git:
|
git:
|
||||||
url: https://codeberg.org/PapaTutuWawa/omemo_dart.git
|
url: https://codeberg.org/PapaTutuWawa/omemo_dart.git
|
||||||
rev: 797bf6985638f0fe5a6e12a7a8339cf7d9334f88
|
rev: fe1ba99b14b516ecf6d147c57bd986d8afe7f3fc
|
||||||
|
|
||||||
extra_licenses:
|
extra_licenses:
|
||||||
- name: undraw.co
|
- name: undraw.co
|
||||||
|
Loading…
Reference in New Issue
Block a user