Compare commits
2 Commits
f15a3e6bf4
...
f723c43603
Author | SHA1 | Date | |
---|---|---|---|
f723c43603 | |||
d88876c928 |
@ -9,6 +9,7 @@ const omemoRatchetsTable = 'OmemoSessions';
|
||||
const omemoTrustCacheTable = 'OmemoTrustCacheList';
|
||||
const omemoTrustDeviceListTable = 'OmemoTrustDeviceList';
|
||||
const omemoTrustEnableListTable = 'OmemoTrustEnableList';
|
||||
const omemoFingerprintCache = 'OmemoFingerprintCache';
|
||||
const xmppStateTable = 'XmppState';
|
||||
|
||||
const typeString = 0;
|
||||
|
@ -160,7 +160,7 @@ Future<void> createDatabase(Database db, int version) async {
|
||||
PRIMARY KEY (jid, id)
|
||||
)''',
|
||||
);
|
||||
await db.execute(
|
||||
await db.execute(
|
||||
'''
|
||||
CREATE TABLE $omemoDeviceListTable (
|
||||
jid TEXT NOT NULL,
|
||||
@ -168,6 +168,15 @@ Future<void> createDatabase(Database db, int version) async {
|
||||
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
|
||||
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_language.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_store_hint.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/not_specified.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/state.dart';
|
||||
import 'package:moxxyv2/shared/models/conversation.dart';
|
||||
@ -65,7 +67,7 @@ class DatabaseService {
|
||||
_db = await openDatabase(
|
||||
dbPath,
|
||||
password: key,
|
||||
version: 12,
|
||||
version: 13,
|
||||
onCreate: createDatabase,
|
||||
onConfigure: (db) async {
|
||||
// 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');
|
||||
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();
|
||||
}
|
||||
|
||||
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(
|
||||
"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/moxxmpp/omemo.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:omemo_dart/omemo_dart.dart';
|
||||
import 'package:synchronized/synchronized.dart';
|
||||
@ -25,6 +26,7 @@ class OmemoService {
|
||||
bool _initialized = false;
|
||||
final Lock _lock = Lock();
|
||||
final Queue<Completer<void>> _waitingForInitialization = Queue<Completer<void>>();
|
||||
final Map<String, Map<int, String>> _fingerprintCache = {};
|
||||
|
||||
late OmemoSessionManager omemoState;
|
||||
|
||||
@ -64,6 +66,22 @@ class OmemoService {
|
||||
await GetIt.I.get<DatabaseService>().saveRatchet(
|
||||
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) {
|
||||
await commitDeviceMap(event.map);
|
||||
} else if (event is DeviceModifiedEvent) {
|
||||
@ -202,20 +220,70 @@ class OmemoService {
|
||||
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 {
|
||||
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 tm = omemoState.trustManager as BlindTrustBeforeVerificationTrustManager;
|
||||
final trustMap = await tm.getDevicesTrust(jid);
|
||||
for (final fp in fingerprints) {
|
||||
for (final deviceId in _fingerprintCache[jid]!.keys) {
|
||||
keys.add(
|
||||
OmemoDevice(
|
||||
fp.fingerprint,
|
||||
await tm.isTrusted(jid, fp.deviceId),
|
||||
trustMap[fp.deviceId] == BTBVTrustState.verified,
|
||||
await tm.isEnabled(jid, fp.deviceId),
|
||||
fp.deviceId,
|
||||
_fingerprintCache[jid]![deviceId]!,
|
||||
await tm.isTrusted(jid, deviceId),
|
||||
trustMap[deviceId] == BTBVTrustState.verified,
|
||||
await tm.isEnabled(jid, deviceId),
|
||||
deviceId,
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -267,36 +335,28 @@ class OmemoService {
|
||||
/// published on [ownJid]'s devices PubSub node.
|
||||
/// Note that the list is made so that the current device is excluded.
|
||||
Future<List<OmemoDevice>> getOwnFingerprints(JID ownJid) async {
|
||||
final conn = GetIt.I.get<XmppConnection>();
|
||||
final ownId = await getDeviceId();
|
||||
final keys = List<OmemoDevice>.from(
|
||||
await getOmemoKeysForJid(ownJid.toString()),
|
||||
);
|
||||
final bareJid = ownJid.toBare().toString();
|
||||
|
||||
// TODO(PapaTutuWawa): This should be cached in the database and only requested if
|
||||
// it's not cached.
|
||||
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();
|
||||
|
||||
keys.add(
|
||||
OmemoDevice(
|
||||
HEX.encode(await curveIk.getBytes()),
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
device.id,
|
||||
hasSessionWith: false,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
// Get finger prints if we have to
|
||||
await _loadOrFetchFingerprints(ownJid);
|
||||
|
||||
_fingerprintCache[bareJid]!.forEach((deviceId, fingerprint) {
|
||||
if (deviceId == ownId) return;
|
||||
keys.add(
|
||||
OmemoDevice(
|
||||
fingerprint,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
deviceId,
|
||||
hasSessionWith: false,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
@ -16,7 +16,7 @@ class OmemoDevice with _$OmemoDevice {
|
||||
@Default(true) bool hasSessionWith,
|
||||
}
|
||||
) = _OmemoDevice;
|
||||
|
||||
|
||||
/// JSON
|
||||
factory OmemoDevice.fromJson(Map<String, dynamic> json) => _$OmemoDeviceFromJson(json);
|
||||
}
|
||||
|
@ -831,7 +831,7 @@ packages:
|
||||
description:
|
||||
path: "."
|
||||
ref: HEAD
|
||||
resolved-ref: "797bf6985638f0fe5a6e12a7a8339cf7d9334f88"
|
||||
resolved-ref: fe1ba99b14b516ecf6d147c57bd986d8afe7f3fc
|
||||
url: "https://codeberg.org/PapaTutuWawa/omemo_dart.git"
|
||||
source: git
|
||||
version: "0.3.2"
|
||||
|
@ -144,7 +144,7 @@ dependency_overrides:
|
||||
omemo_dart:
|
||||
git:
|
||||
url: https://codeberg.org/PapaTutuWawa/omemo_dart.git
|
||||
rev: 797bf6985638f0fe5a6e12a7a8339cf7d9334f88
|
||||
rev: fe1ba99b14b516ecf6d147c57bd986d8afe7f3fc
|
||||
|
||||
extra_licenses:
|
||||
- name: undraw.co
|
||||
|
Loading…
Reference in New Issue
Block a user