feat: Add events for commiting the device map and ratchet
This commit is contained in:
parent
859f25d867
commit
be239fdb43
@ -1,11 +1,28 @@
|
||||
import 'package:omemo_dart/src/double_ratchet/double_ratchet.dart';
|
||||
import 'package:omemo_dart/src/omemo/device.dart';
|
||||
|
||||
abstract class OmemoEvent {}
|
||||
|
||||
/// Triggered when a ratchet has been modified
|
||||
class RatchetModifiedEvent extends OmemoEvent {
|
||||
|
||||
RatchetModifiedEvent(this.jid, this.deviceId, this.ratchet);
|
||||
final String jid;
|
||||
final int deviceId;
|
||||
final OmemoDoubleRatchet ratchet;
|
||||
}
|
||||
|
||||
/// Triggered when the device map has been modified
|
||||
class DeviceMapModifiedEvent extends OmemoEvent {
|
||||
|
||||
DeviceMapModifiedEvent(this.map);
|
||||
final Map<String, List<int>> map;
|
||||
}
|
||||
|
||||
/// Triggered by the OmemoSessionManager when our own device bundle was modified
|
||||
/// and thus should be republished.
|
||||
class DeviceBundleModifiedEvent extends OmemoEvent {
|
||||
class DeviceModifiedEvent extends OmemoEvent {
|
||||
|
||||
DeviceBundleModifiedEvent(this.device);
|
||||
DeviceModifiedEvent(this.device);
|
||||
final Device device;
|
||||
}
|
||||
|
@ -130,6 +130,9 @@ class OmemoSessionManager {
|
||||
_deviceMap[jid]!.add(deviceId);
|
||||
}
|
||||
|
||||
// Commit the device map
|
||||
_eventStreamController.add(DeviceMapModifiedEvent(_deviceMap));
|
||||
|
||||
// Add the ratchet session
|
||||
final key = RatchetMapKey(jid, deviceId);
|
||||
if (!_ratchetMap.containsKey(key)) {
|
||||
@ -138,6 +141,9 @@ class OmemoSessionManager {
|
||||
// TODO(PapaTutuWawa): What do we do now?
|
||||
throw Exception();
|
||||
}
|
||||
|
||||
// Commit the ratchet
|
||||
_eventStreamController.add(RatchetModifiedEvent(jid, deviceId, ratchet));
|
||||
});
|
||||
}
|
||||
|
||||
@ -218,6 +224,9 @@ class OmemoSessionManager {
|
||||
final ratchet = _ratchetMap[ratchetKey]!;
|
||||
final ciphertext = (await ratchet.ratchetEncrypt(concatKey)).ciphertext;
|
||||
|
||||
// Commit the ratchet
|
||||
_eventStreamController.add(RatchetModifiedEvent(jid, deviceId, ratchet));
|
||||
|
||||
if (kex.isNotEmpty && kex.containsKey(deviceId)) {
|
||||
final k = kex[deviceId]!
|
||||
..message = OmemoAuthenticatedMessage.fromBuffer(ciphertext);
|
||||
@ -274,9 +283,9 @@ class OmemoSessionManager {
|
||||
// Replace the OPK
|
||||
await _deviceLock.synchronized(() async {
|
||||
device = await device.replaceOnetimePrekey(kex.pkId!);
|
||||
_eventStreamController.add(
|
||||
DeviceBundleModifiedEvent(device),
|
||||
);
|
||||
|
||||
// Commit the device
|
||||
_eventStreamController.add(DeviceModifiedEvent(device));
|
||||
});
|
||||
} else {
|
||||
authMessage = OmemoAuthenticatedMessage.fromBuffer(decodedRawKey);
|
||||
@ -291,17 +300,22 @@ class OmemoSessionManager {
|
||||
}
|
||||
|
||||
final message = OmemoMessage.fromBuffer(authMessage.message!);
|
||||
|
||||
final ratchetKey = RatchetMapKey(senderJid, senderDeviceId);
|
||||
final ratchet = _ratchetMap[ratchetKey]!;
|
||||
List<int> keyAndHmac;
|
||||
if (rawKey.kex) {
|
||||
keyAndHmac = await ratchet.ratchetDecrypt(message, authMessage.writeToBuffer());
|
||||
} else {
|
||||
keyAndHmac = await ratchet.ratchetDecrypt(message, decodedRawKey);
|
||||
}
|
||||
final key = keyAndHmac.sublist(0, 32);
|
||||
final hmac = keyAndHmac.sublist(32, 48);
|
||||
List<int>? keyAndHmac;
|
||||
await _lock.synchronized(() async {
|
||||
final ratchet = _ratchetMap[ratchetKey]!;
|
||||
if (rawKey.kex) {
|
||||
keyAndHmac = await ratchet.ratchetDecrypt(message, authMessage.writeToBuffer());
|
||||
} else {
|
||||
keyAndHmac = await ratchet.ratchetDecrypt(message, decodedRawKey);
|
||||
}
|
||||
|
||||
// Commit the ratchet
|
||||
_eventStreamController.add(RatchetModifiedEvent(senderJid, senderDeviceId, ratchet));
|
||||
});
|
||||
|
||||
final key = keyAndHmac!.sublist(0, 32);
|
||||
final hmac = keyAndHmac!.sublist(32, 48);
|
||||
final derivedKeys = await deriveEncryptionKeys(key, omemoPayloadInfoString);
|
||||
|
||||
final computedHmac = await truncatedHmac(ciphertext, derivedKeys.authenticationKey);
|
||||
|
@ -8,12 +8,18 @@ void main() {
|
||||
|
||||
// Alice and Bob generate their sessions
|
||||
var deviceModified = false;
|
||||
var ratchetModified = 0;
|
||||
var deviceMapModified = 0;
|
||||
final aliceSession = await OmemoSessionManager.generateNewIdentity(opkAmount: 1);
|
||||
final bobSession = await OmemoSessionManager.generateNewIdentity(opkAmount: 1);
|
||||
final bobOpks = (await bobSession.getDevice()).opks.values.toList();
|
||||
bobSession.eventStream.listen((event) {
|
||||
if (event is DeviceBundleModifiedEvent) {
|
||||
if (event is DeviceModifiedEvent) {
|
||||
deviceModified = true;
|
||||
} else if (event is RatchetModifiedEvent) {
|
||||
ratchetModified++;
|
||||
} else if (event is DeviceMapModifiedEvent) {
|
||||
deviceMapModified++;
|
||||
}
|
||||
});
|
||||
|
||||
@ -39,6 +45,11 @@ void main() {
|
||||
aliceMessage.encryptedKeys,
|
||||
);
|
||||
expect(messagePlaintext, bobMessage);
|
||||
// The ratchet should be modified two times: Once for when the ratchet is created and
|
||||
// other time for when the message is decrypted
|
||||
expect(ratchetModified, 2);
|
||||
// Bob's device map should be modified once
|
||||
expect(deviceMapModified, 1);
|
||||
// The event should be triggered
|
||||
expect(deviceModified, true);
|
||||
// Bob should have replaced his OPK
|
||||
|
Loading…
Reference in New Issue
Block a user