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