feat: Add last features for use in moxxmpp

This commit is contained in:
PapaTutuWawa 2023-01-01 16:49:19 +01:00
parent 4085631804
commit 092ce36410
14 changed files with 216 additions and 88 deletions

View File

@ -1,5 +1,6 @@
import 'dart:convert'; import 'dart:convert';
import 'package:cryptography/cryptography.dart'; import 'package:cryptography/cryptography.dart';
import 'package:hex/hex.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:omemo_dart/src/crypto.dart'; import 'package:omemo_dart/src/crypto.dart';
import 'package:omemo_dart/src/double_ratchet/crypto.dart'; import 'package:omemo_dart/src/double_ratchet/crypto.dart';
@ -252,6 +253,12 @@ class OmemoDoubleRatchet {
}; };
} }
/// Returns the OMEMO compatible fingerprint of the ratchet session.
Future<String> getOmemoFingerprint() async {
final curveKey = await ik.toCurve25519();
return HEX.encode(await curveKey.getBytes());
}
Future<List<int>?> _trySkippedMessageKeys(OmemoMessage header, List<int> ciphertext) async { Future<List<int>?> _trySkippedMessageKeys(OmemoMessage header, List<int> ciphertext) async {
final key = SkippedKey( final key = SkippedKey(
OmemoPublicKey.fromBytes(header.dhPub!, KeyPairType.x25519), OmemoPublicKey.fromBytes(header.dhPub!, KeyPairType.x25519),

View File

@ -9,7 +9,6 @@ const privateKeyLength = 32;
const publicKeyLength = 32; const publicKeyLength = 32;
class OmemoPublicKey { class OmemoPublicKey {
const OmemoPublicKey(this._pubkey); const OmemoPublicKey(this._pubkey);
factory OmemoPublicKey.fromBytes(List<int> bytes, KeyPairType type) { factory OmemoPublicKey.fromBytes(List<int> bytes, KeyPairType type) {
@ -55,7 +54,6 @@ class OmemoPublicKey {
} }
class OmemoPrivateKey { class OmemoPrivateKey {
const OmemoPrivateKey(this._privkey, this.type); const OmemoPrivateKey(this._privkey, this.type);
final List<int> _privkey; final List<int> _privkey;
final KeyPairType type; final KeyPairType type;
@ -85,7 +83,6 @@ class OmemoPrivateKey {
/// A generic wrapper class for both Ed25519 and X25519 keypairs /// A generic wrapper class for both Ed25519 and X25519 keypairs
class OmemoKeyPair { class OmemoKeyPair {
const OmemoKeyPair(this.pk, this.sk, this.type); const OmemoKeyPair(this.pk, this.sk, this.type);
/// Create an OmemoKeyPair just from a [type] and the bytes of the private and public /// Create an OmemoKeyPair just from a [type] and the bytes of the private and public

View File

@ -1,5 +1,6 @@
import 'dart:convert'; import 'dart:convert';
import 'package:cryptography/cryptography.dart'; import 'package:cryptography/cryptography.dart';
import 'package:hex/hex.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:omemo_dart/src/helpers.dart'; import 'package:omemo_dart/src/helpers.dart';
import 'package:omemo_dart/src/keys.dart'; import 'package:omemo_dart/src/keys.dart';
@ -8,8 +9,8 @@ import 'package:omemo_dart/src/x3dh/x3dh.dart';
/// This class represents an OmemoBundle but with all keypairs belonging to the keys /// This class represents an OmemoBundle but with all keypairs belonging to the keys
@immutable @immutable
class Device { class OmemoDevice {
const Device( const OmemoDevice(
this.jid, this.jid,
this.id, this.id,
this.ik, this.ik,
@ -22,7 +23,7 @@ class Device {
); );
/// Deserialize the Device /// Deserialize the Device
factory Device.fromJson(Map<String, dynamic> data) { factory OmemoDevice.fromJson(Map<String, dynamic> data) {
// NOTE: We use the way OpenSSH names their keys, meaning that ik is the Identity // NOTE: We use the way OpenSSH names their keys, meaning that ik is the Identity
// Keypair's private key, while ik_pub refers to the Identity Keypair's public // Keypair's private key, while ik_pub refers to the Identity Keypair's public
// key. // key.
@ -66,7 +67,7 @@ class Device {
), ),
); );
return Device( return OmemoDevice(
data['jid']! as String, data['jid']! as String,
data['id']! as int, data['id']! as int,
OmemoKeyPair.fromBytes( OmemoKeyPair.fromBytes(
@ -92,7 +93,7 @@ class Device {
} }
/// Generate a completely new device, i.e. cryptographic identity. /// Generate a completely new device, i.e. cryptographic identity.
static Future<Device> generateNewDevice(String jid, { int opkAmount = 100 }) async { static Future<OmemoDevice> generateNewDevice(String jid, { int opkAmount = 100 }) async {
final id = generateRandom32BitNumber(); final id = generateRandom32BitNumber();
final ik = await OmemoKeyPair.generateNewPair(KeyPairType.ed25519); final ik = await OmemoKeyPair.generateNewPair(KeyPairType.ed25519);
final spk = await OmemoKeyPair.generateNewPair(KeyPairType.x25519); final spk = await OmemoKeyPair.generateNewPair(KeyPairType.x25519);
@ -104,7 +105,7 @@ class Device {
opks[i] = await OmemoKeyPair.generateNewPair(KeyPairType.x25519); opks[i] = await OmemoKeyPair.generateNewPair(KeyPairType.x25519);
} }
return Device(jid, id, ik, spk, spkId, signature, null, null, opks); return OmemoDevice(jid, id, ik, spk, spkId, signature, null, null, opks);
} }
/// Our bare Jid /// Our bare Jid
@ -134,10 +135,10 @@ class Device {
/// This replaces the Onetime-Prekey with id [id] with a completely new one. Returns /// This replaces the Onetime-Prekey with id [id] with a completely new one. Returns
/// a new Device object that copies over everything but replaces said key. /// a new Device object that copies over everything but replaces said key.
@internal @internal
Future<Device> replaceOnetimePrekey(int id) async { Future<OmemoDevice> replaceOnetimePrekey(int id) async {
opks[id] = await OmemoKeyPair.generateNewPair(KeyPairType.x25519); opks[id] = await OmemoKeyPair.generateNewPair(KeyPairType.x25519);
return Device( return OmemoDevice(
jid, jid,
this.id, this.id,
ik, ik,
@ -153,12 +154,12 @@ class Device {
/// This replaces the Signed-Prekey with a completely new one. Returns a new Device object /// This replaces the Signed-Prekey with a completely new one. Returns a new Device object
/// that copies over everything but replaces the Signed-Prekey and its signature. /// that copies over everything but replaces the Signed-Prekey and its signature.
@internal @internal
Future<Device> replaceSignedPrekey() async { Future<OmemoDevice> replaceSignedPrekey() async {
final newSpk = await OmemoKeyPair.generateNewPair(KeyPairType.x25519); final newSpk = await OmemoKeyPair.generateNewPair(KeyPairType.x25519);
final newSpkId = generateRandom32BitNumber(); final newSpkId = generateRandom32BitNumber();
final newSignature = await sig(ik, await newSpk.pk.getBytes()); final newSignature = await sig(ik, await newSpk.pk.getBytes());
return Device( return OmemoDevice(
jid, jid,
id, id,
ik, ik,
@ -174,8 +175,8 @@ class Device {
/// Returns a new device that is equal to this one with the exception that the new /// Returns a new device that is equal to this one with the exception that the new
/// device's id is a new number between 0 and 2**32 - 1. /// device's id is a new number between 0 and 2**32 - 1.
@internal @internal
Device withNewId() { OmemoDevice withNewId() {
return Device( return OmemoDevice(
jid, jid,
generateRandom32BitNumber(), generateRandom32BitNumber(),
ik, ik,
@ -207,6 +208,13 @@ class Device {
); );
} }
/// Returns the fingerprint of the current device
Future<String> getFingerprint() async {
// Since the local key is Ed25519, we must convert it to Curve25519 first
final curveKey = await ik.pk.toCurve25519();
return HEX.encode(await curveKey.getBytes());
}
/// Serialise the device information. /// Serialise the device information.
Future<Map<String, dynamic>> toJson() async { Future<Map<String, dynamic>> toJson() async {
/// Serialise the OPKs /// Serialise the OPKs
@ -236,7 +244,7 @@ class Device {
} }
@visibleForTesting @visibleForTesting
Future<bool> equals(Device other) async { Future<bool> equals(OmemoDevice other) async {
var opksMatch = true; var opksMatch = true;
if (opks.length != other.opks.length) { if (opks.length != other.opks.length) {
opksMatch = false; opksMatch = false;

View File

@ -31,5 +31,5 @@ class DeviceListModifiedEvent extends OmemoEvent {
/// and thus should be republished. /// and thus should be republished.
class DeviceModifiedEvent extends OmemoEvent { class DeviceModifiedEvent extends OmemoEvent {
DeviceModifiedEvent(this.device); DeviceModifiedEvent(this.device);
final Device device; final OmemoDevice device;
} }

View File

@ -38,9 +38,10 @@ class OmemoManager {
OmemoManager( OmemoManager(
this._device, this._device,
this._trustManager, this._trustManager,
this.sendEmptyOmemoMessage, this.sendEmptyOmemoMessageImpl,
this.fetchDeviceList, this.fetchDeviceListImpl,
this.fetchDeviceBundle, this.fetchDeviceBundleImpl,
this.subscribeToDeviceListNodeImpl,
); );
final Logger _log = Logger('OmemoManager'); final Logger _log = Logger('OmemoManager');
@ -49,14 +50,17 @@ class OmemoManager {
/// Send an empty OMEMO:2 message using the encrypted payload @result to /// Send an empty OMEMO:2 message using the encrypted payload @result to
/// @recipientJid. /// @recipientJid.
final Future<void> Function(EncryptionResult result, String recipientJid) sendEmptyOmemoMessage; final Future<void> Function(EncryptionResult result, String recipientJid) sendEmptyOmemoMessageImpl;
/// Fetch the list of device ids associated with @jid. If the device list cannot be /// Fetch the list of device ids associated with @jid. If the device list cannot be
/// fetched, return null. /// fetched, return null.
final Future<List<int>?> Function(String jid) fetchDeviceList; final Future<List<int>?> Function(String jid) fetchDeviceListImpl;
/// Fetch the device bundle for the device with id @id of jid. If it cannot be fetched, return null. /// Fetch the device bundle for the device with id @id of jid. If it cannot be fetched, return null.
final Future<OmemoBundle?> Function(String jid, int id) fetchDeviceBundle; final Future<OmemoBundle?> Function(String jid, int id) fetchDeviceBundleImpl;
/// Subscribe to the device list PEP node of @jid.
final Future<void> Function(String jid) subscribeToDeviceListNodeImpl;
/// Map bare JID to its known devices /// Map bare JID to its known devices
Map<String, List<int>> _deviceList = {}; Map<String, List<int>> _deviceList = {};
@ -65,6 +69,8 @@ class OmemoManager {
/// Map bare a ratchet key to its ratchet. Note that this is also locked by /// Map bare a ratchet key to its ratchet. Note that this is also locked by
/// _ratchetCriticalSectionLock. /// _ratchetCriticalSectionLock.
Map<RatchetMapKey, OmemoDoubleRatchet> _ratchetMap = {}; Map<RatchetMapKey, OmemoDoubleRatchet> _ratchetMap = {};
/// Map bare JID to whether we already tried to subscribe to the device list node.
final Map<String, bool> _subscriptionMap = {};
/// For preventing a race condition in encryption/decryption /// For preventing a race condition in encryption/decryption
final Map<String, Queue<Completer<void>>> _ratchetCriticalSectionQueue = {}; final Map<String, Queue<Completer<void>>> _ratchetCriticalSectionQueue = {};
final Lock _ratchetCriticalSectionLock = Lock(); final Lock _ratchetCriticalSectionLock = Lock();
@ -76,10 +82,11 @@ class OmemoManager {
/// Our own keys... /// Our own keys...
final Lock _deviceLock = Lock(); final Lock _deviceLock = Lock();
// ignore: prefer_final_fields // ignore: prefer_final_fields
Device _device; OmemoDevice _device;
/// The event bus of the session manager /// The event bus of the session manager
final StreamController<OmemoEvent> _eventStreamController = StreamController<OmemoEvent>.broadcast(); final StreamController<OmemoEvent> _eventStreamController = StreamController<OmemoEvent>.broadcast();
Stream<OmemoEvent> get eventStream => _eventStreamController.stream;
/// Enter the critical section for performing cryptographic operations on the ratchets /// Enter the critical section for performing cryptographic operations on the ratchets
Future<void> _enterRatchetCriticalSection(String jid) async { Future<void> _enterRatchetCriticalSection(String jid) async {
@ -379,7 +386,7 @@ class OmemoManager {
List<int> bundlesToFetch; List<int> bundlesToFetch;
if (!_deviceListRequested.containsKey(jid) || !_deviceList.containsKey(jid)) { if (!_deviceListRequested.containsKey(jid) || !_deviceList.containsKey(jid)) {
// We don't have an up-to-date version of the device list // We don't have an up-to-date version of the device list
final newDeviceList = await fetchDeviceList(jid); final newDeviceList = await fetchDeviceListImpl(jid);
if (newDeviceList == null) return []; if (newDeviceList == null) return [];
_deviceList[jid] = newDeviceList; _deviceList[jid] = newDeviceList;
@ -404,7 +411,7 @@ class OmemoManager {
final newBundles = List<OmemoBundle>.empty(growable: true); final newBundles = List<OmemoBundle>.empty(growable: true);
for (final id in bundlesToFetch) { for (final id in bundlesToFetch) {
final bundle = await fetchDeviceBundle(jid, id); final bundle = await fetchDeviceBundleImpl(jid, id);
if (bundle != null) newBundles.add(bundle); if (bundle != null) newBundles.add(bundle);
} }
@ -460,6 +467,11 @@ class OmemoManager {
continue; continue;
} }
if (!_subscriptionMap.containsKey(jid)) {
unawaited(subscribeToDeviceListNodeImpl(jid));
_subscriptionMap[jid] = true;
}
for (final deviceId in devices) { for (final deviceId in devices) {
// Empty OMEMO messages are allowed to bypass trust // Empty OMEMO messages are allowed to bypass trust
if (plaintext != null) { if (plaintext != null) {
@ -553,11 +565,18 @@ class OmemoManager {
Future<DecryptionResult> onIncomingStanza(OmemoIncomingStanza stanza) async { Future<DecryptionResult> onIncomingStanza(OmemoIncomingStanza stanza) async {
await _enterRatchetCriticalSection(stanza.bareSenderJid); await _enterRatchetCriticalSection(stanza.bareSenderJid);
if (!_subscriptionMap.containsKey(stanza.bareSenderJid)) {
unawaited(subscribeToDeviceListNodeImpl(stanza.bareSenderJid));
_subscriptionMap[stanza.bareSenderJid] = true;
}
final ratchetKey = RatchetMapKey(stanza.bareSenderJid, stanza.senderDeviceId); final ratchetKey = RatchetMapKey(stanza.bareSenderJid, stanza.senderDeviceId);
final _InternalDecryptionResult result; final _InternalDecryptionResult result;
try { try {
result = await _decryptMessage( result = await _decryptMessage(
base64.decode(stanza.payload), stanza.payload != null ?
base64.decode(stanza.payload!) :
null,
stanza.bareSenderJid, stanza.bareSenderJid,
stanza.senderDeviceId, stanza.senderDeviceId,
stanza.keys, stanza.keys,
@ -578,7 +597,7 @@ class OmemoManager {
if (ratchet!.acknowledged) { if (ratchet!.acknowledged) {
// Ratchet is acknowledged // Ratchet is acknowledged
if (ratchet.nr > 53 || result.ratchetCreated) { if (ratchet.nr > 53 || result.ratchetCreated) {
await sendEmptyOmemoMessage( await sendEmptyOmemoMessageImpl(
await _encryptToJids( await _encryptToJids(
[stanza.bareSenderJid], [stanza.bareSenderJid],
null, null,
@ -601,7 +620,7 @@ class OmemoManager {
stanza.senderDeviceId, stanza.senderDeviceId,
enterCriticalSection: false, enterCriticalSection: false,
); );
await sendEmptyOmemoMessage( await sendEmptyOmemoMessageImpl(
await _encryptToJids( await _encryptToJids(
[stanza.bareSenderJid], [stanza.bareSenderJid],
null, null,
@ -619,11 +638,29 @@ class OmemoManager {
/// Call when sending out an encrypted stanza. Will handle everything and /// Call when sending out an encrypted stanza. Will handle everything and
/// encrypt it. /// encrypt it.
Future<EncryptionResult?> onOutgoingStanza(OmemoOutgoingStanza stanza) async { Future<EncryptionResult> onOutgoingStanza(OmemoOutgoingStanza stanza) async {
return _encryptToJids( _log.finest('Waiting to enter critical section');
await _enterRatchetCriticalSection(stanza.recipientJids.first);
_log.finest('Entered critical section');
final result = _encryptToJids(
stanza.recipientJids, stanza.recipientJids,
stanza.payload, stanza.payload,
); );
await _leaveRatchetCriticalSection(stanza.recipientJids.first);
return result;
}
// Sends a hearbeat message as specified by XEP-0384 to [jid].
Future<void> sendOmemoHeartbeat(String jid) async {
// TODO(Unknown): Include some error handling
final result = await _encryptToJids(
[jid],
null,
);
await sendEmptyOmemoMessageImpl(result, jid);
} }
/// Mark the ratchet for device [deviceId] from [jid] as acked. /// Mark the ratchet for device [deviceId] from [jid] as acked.
@ -646,9 +683,9 @@ class OmemoManager {
/// Generates an entirely new device. May be useful when the user wants to reset their cryptographic /// Generates an entirely new device. May be useful when the user wants to reset their cryptographic
/// identity. Triggers an event to commit it to storage. /// identity. Triggers an event to commit it to storage.
Future<void> regenerateDevice({ int opkAmount = 100 }) async { Future<void> regenerateDevice() async {
await _deviceLock.synchronized(() async { await _deviceLock.synchronized(() async {
_device = await Device.generateNewDevice(_device.jid, opkAmount: opkAmount); _device = await OmemoDevice.generateNewDevice(_device.jid);
// Commit it // Commit it
_eventStreamController.add(DeviceModifiedEvent(_device)); _eventStreamController.add(DeviceModifiedEvent(_device));
@ -656,11 +693,17 @@ class OmemoManager {
} }
/// Returns the device used for encryption and decryption. /// Returns the device used for encryption and decryption.
Future<Device> getDevice() => _deviceLock.synchronized(() => _device); Future<OmemoDevice> getDevice() => _deviceLock.synchronized(() => _device);
/// Returns the id of the device used for encryption and decryption. /// Returns the id of the device used for encryption and decryption.
Future<int> getDeviceId() async => (await getDevice()).id; Future<int> getDeviceId() async => (await getDevice()).id;
/// Directly aquire the current device as a OMEMO device bundle.
Future<OmemoBundle> getDeviceBundle() async => (await getDevice()).toBundle();
/// Directly aquire the current device's fingerprint.
Future<String> getDeviceFingerprint() async => (await getDevice()).getFingerprint();
/// Returns the fingerprints for all devices of [jid] that we have a session with. /// Returns the fingerprints for all devices of [jid] that we have a session with.
/// If there are not sessions with [jid], then returns null. /// If there are not sessions with [jid], then returns null.
Future<List<DeviceFingerprint>?> getFingerprintsForJid(String jid) async { Future<List<DeviceFingerprint>?> getFingerprintsForJid(String jid) async {
@ -674,10 +717,11 @@ class OmemoManager {
final fingerprints = List<DeviceFingerprint>.empty(growable: true); final fingerprints = List<DeviceFingerprint>.empty(growable: true);
for (final key in fingerprintKeys) { for (final key in fingerprintKeys) {
final curveKey = await _ratchetMap[key]!.ik.toCurve25519();
fingerprints.add( fingerprints.add(
DeviceFingerprint( DeviceFingerprint(
key.deviceId, key.deviceId,
HEX.encode(await _ratchetMap[key]!.ik.getBytes()), HEX.encode(await curveKey.getBytes()),
), ),
); );
} }
@ -689,6 +733,7 @@ class OmemoManager {
/// Ensures that the device list is fetched again on the next message sending. /// Ensures that the device list is fetched again on the next message sending.
void onNewConnection() { void onNewConnection() {
_deviceListRequested.clear(); _deviceListRequested.clear();
_subscriptionMap.clear();
} }
/// Sets the device list for [jid] to [devices]. Triggers a DeviceListModifiedEvent. /// Sets the device list for [jid] to [devices]. Triggers a DeviceListModifiedEvent.
@ -704,4 +749,35 @@ class OmemoManager {
_deviceList = deviceList; _deviceList = deviceList;
_ratchetMap = ratchetMap; _ratchetMap = ratchetMap;
} }
/// Removes all ratchets for JID [jid]. This also removes all trust decisions for
/// [jid] from the trust manager. This function triggers a RatchetRemovedEvent for
/// every removed ratchet and a DeviceListModifiedEvent afterwards. Behaviour for
/// the trust manager is dependent on its implementation.
Future<void> removeAllRatchets(String jid) async {
await _enterRatchetCriticalSection(jid);
for (final deviceId in _deviceList[jid]!) {
// Remove the ratchet and commit it
_ratchetMap.remove(jid);
_eventStreamController.add(RatchetRemovedEvent(jid, deviceId));
}
// Remove the devices from the device list cache and commit it
_deviceList.remove(jid);
_deviceListRequested.remove(jid);
_eventStreamController.add(DeviceListModifiedEvent(_deviceList));
// Remove trust decisions
await _trustManager.removeTrustDecisionsForJid(jid);
await _leaveRatchetCriticalSection(jid);
}
/// Replaces the internal device with [newDevice]. Does not trigger an event.
Future<void> replaceDevice(OmemoDevice newDevice) async {
await _deviceLock.synchronized(() {
_device = newDevice;
});
}
} }

View File

@ -45,7 +45,7 @@ class OmemoSessionManager {
// NOTE: Dart has some issues with just casting a List<dynamic> to List<Map<...>>, as // NOTE: Dart has some issues with just casting a List<dynamic> to List<Map<...>>, as
// such we need to convert the items by hand. // such we need to convert the items by hand.
return OmemoSessionManager( return OmemoSessionManager(
Device.fromJson(data['device']! as Map<String, dynamic>), OmemoDevice.fromJson(data['device']! as Map<String, dynamic>),
(data['devices']! as Map<String, dynamic>).map<String, List<int>>( (data['devices']! as Map<String, dynamic>).map<String, List<int>>(
(key, value) { (key, value) {
return MapEntry( return MapEntry(
@ -62,7 +62,7 @@ class OmemoSessionManager {
/// Generate a new cryptographic identity. /// Generate a new cryptographic identity.
static Future<OmemoSessionManager> generateNewIdentity(String jid, TrustManager trustManager, { int opkAmount = 100 }) async { static Future<OmemoSessionManager> generateNewIdentity(String jid, TrustManager trustManager, { int opkAmount = 100 }) async {
assert(opkAmount > 0, 'opkAmount must be bigger than 0.'); assert(opkAmount > 0, 'opkAmount must be bigger than 0.');
final device = await Device.generateNewDevice(jid, opkAmount: opkAmount); final device = await OmemoDevice.generateNewDevice(jid, opkAmount: opkAmount);
return OmemoSessionManager(device, {}, {}, trustManager); return OmemoSessionManager(device, {}, {}, trustManager);
} }
@ -84,7 +84,7 @@ class OmemoSessionManager {
/// Our own keys... /// Our own keys...
// ignore: prefer_final_fields // ignore: prefer_final_fields
Device _device; OmemoDevice _device;
/// and its lock /// and its lock
final Lock _deviceLock; final Lock _deviceLock;
@ -96,7 +96,7 @@ class OmemoSessionManager {
Stream<OmemoEvent> get eventStream => _eventStreamController.stream; Stream<OmemoEvent> get eventStream => _eventStreamController.stream;
/// Returns our own device. /// Returns our own device.
Future<Device> getDevice() async { Future<OmemoDevice> getDevice() async {
return _deviceLock.synchronized(() => _device); return _deviceLock.synchronized(() => _device);
} }
@ -625,7 +625,7 @@ class OmemoSessionManager {
/// identity. Triggers an event to commit it to storage. /// identity. Triggers an event to commit it to storage.
Future<void> regenerateDevice({ int opkAmount = 100 }) async { Future<void> regenerateDevice({ int opkAmount = 100 }) async {
await _deviceLock.synchronized(() async { await _deviceLock.synchronized(() async {
_device = await Device.generateNewDevice(_device.jid, opkAmount: opkAmount); _device = await OmemoDevice.generateNewDevice(_device.jid, opkAmount: opkAmount);
// Commit it // Commit it
_eventStreamController.add(DeviceModifiedEvent(_device)); _eventStreamController.add(DeviceModifiedEvent(_device));

View File

@ -23,7 +23,7 @@ class OmemoIncomingStanza {
final List<EncryptedKey> keys; final List<EncryptedKey> keys;
/// The string payload included in the <encrypted /> element. /// The string payload included in the <encrypted /> element.
final String payload; final String? payload;
} }
/// Describes a stanza that is to be sent out /// Describes a stanza that is to be sent out

View File

@ -18,6 +18,9 @@ class AlwaysTrustingTrustManager extends TrustManager {
@override @override
Future<void> setEnabled(String jid, int deviceId, bool enabled) async {} Future<void> setEnabled(String jid, int deviceId, bool enabled) async {}
@override
Future<void> removeTrustDecisionsForJid(String jid) async {}
@override @override
Future<Map<String, dynamic>> toJson() async => <String, dynamic>{}; Future<Map<String, dynamic>> toJson() async => <String, dynamic>{};
} }

View File

@ -19,4 +19,7 @@ abstract class TrustManager {
/// Serialize the trust manager to JSON. /// Serialize the trust manager to JSON.
Future<Map<String, dynamic>> toJson(); Future<Map<String, dynamic>> toJson();
/// Removes all trust decisions for [jid].
Future<void> removeTrustDecisionsForJid(String jid);
} }

View File

@ -212,6 +212,14 @@ abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager {
); );
} }
@override
Future<void> removeTrustDecisionsForJid(String jid) async {
await _lock.synchronized(() async {
devices.remove(jid);
await commitState();
});
}
/// Called when the state of the trust manager has been changed. Allows the user to /// Called when the state of the trust manager has been changed. Allows the user to
/// commit the trust state to persistent storage. /// commit the trust state to persistent storage.
@visibleForOverriding @visibleForOverriding

View File

@ -18,6 +18,9 @@ class NeverTrustingTrustManager extends TrustManager {
@override @override
Future<void> setEnabled(String jid, int deviceId, bool enabled) async {} Future<void> setEnabled(String jid, int deviceId, bool enabled) async {}
@override
Future<void> removeTrustDecisionsForJid(String jid) async {}
@override @override
Future<Map<String, dynamic>> toJson() async => <String, dynamic>{}; Future<Map<String, dynamic>> toJson() async => <String, dynamic>{};
} }

View File

@ -14,7 +14,7 @@ void main() {
test('Test replacing a onetime prekey', () async { test('Test replacing a onetime prekey', () async {
const aliceJid = 'alice@server.example'; const aliceJid = 'alice@server.example';
final device = await Device.generateNewDevice(aliceJid, opkAmount: 1); final device = await OmemoDevice.generateNewDevice(aliceJid, opkAmount: 1);
final newDevice = await device.replaceOnetimePrekey(0); final newDevice = await device.replaceOnetimePrekey(0);
@ -327,7 +327,7 @@ void main() {
// Setup an event listener // Setup an event listener
final oldDevice = await aliceSession.getDevice(); final oldDevice = await aliceSession.getDevice();
Device? newDevice; OmemoDevice? newDevice;
aliceSession.eventStream.listen((event) { aliceSession.eventStream.listen((event) {
if (event is DeviceModifiedEvent) { if (event is DeviceModifiedEvent) {
newDevice = event.device; newDevice = event.device;

View File

@ -18,8 +18,8 @@ void main() {
var aliceEmptyMessageSent = 0; var aliceEmptyMessageSent = 0;
var bobEmptyMessageSent = 0; var bobEmptyMessageSent = 0;
final aliceDevice = await Device.generateNewDevice(aliceJid, opkAmount: 1); final aliceDevice = await OmemoDevice.generateNewDevice(aliceJid, opkAmount: 1);
final bobDevice = await Device.generateNewDevice(bobJid, opkAmount: 1); final bobDevice = await OmemoDevice.generateNewDevice(bobJid, opkAmount: 1);
final aliceManager = OmemoManager( final aliceManager = OmemoManager(
aliceDevice, aliceDevice,
@ -35,6 +35,7 @@ void main() {
expect(jid, bobJid); expect(jid, bobJid);
return bobDevice.toBundle(); return bobDevice.toBundle();
}, },
(jid) async {},
); );
final bobManager = OmemoManager( final bobManager = OmemoManager(
bobDevice, bobDevice,
@ -50,6 +51,7 @@ void main() {
expect(jid, aliceJid); expect(jid, aliceJid);
return aliceDevice.toBundle(); return aliceDevice.toBundle();
}, },
(jid) async {},
); );
// Alice sends a message // Alice sends a message
@ -66,7 +68,7 @@ void main() {
aliceJid, aliceJid,
aliceDevice.id, aliceDevice.id,
DateTime.now().millisecondsSinceEpoch, DateTime.now().millisecondsSinceEpoch,
aliceResult!.encryptedKeys, aliceResult.encryptedKeys,
base64.encode(aliceResult.ciphertext!), base64.encode(aliceResult.ciphertext!),
), ),
); );
@ -94,7 +96,7 @@ void main() {
bobJid, bobJid,
bobDevice.id, bobDevice.id,
DateTime.now().millisecondsSinceEpoch, DateTime.now().millisecondsSinceEpoch,
bobResult2!.encryptedKeys, bobResult2.encryptedKeys,
base64.encode(bobResult2.ciphertext!), base64.encode(bobResult2.ciphertext!),
), ),
); );
@ -111,8 +113,8 @@ void main() {
var aliceEmptyMessageSent = 0; var aliceEmptyMessageSent = 0;
var bobEmptyMessageSent = 0; var bobEmptyMessageSent = 0;
final aliceDevice = await Device.generateNewDevice(aliceJid, opkAmount: 1); final aliceDevice = await OmemoDevice.generateNewDevice(aliceJid, opkAmount: 1);
final bobDevice = await Device.generateNewDevice(bobJid, opkAmount: 1); final bobDevice = await OmemoDevice.generateNewDevice(bobJid, opkAmount: 1);
final aliceManager = OmemoManager( final aliceManager = OmemoManager(
aliceDevice, aliceDevice,
@ -128,6 +130,7 @@ void main() {
expect(jid, bobJid); expect(jid, bobJid);
return bobDevice.toBundle(); return bobDevice.toBundle();
}, },
(jid) async {},
); );
final bobManager = OmemoManager( final bobManager = OmemoManager(
bobDevice, bobDevice,
@ -143,6 +146,7 @@ void main() {
expect(jid, aliceJid); expect(jid, aliceJid);
return aliceDevice.toBundle(); return aliceDevice.toBundle();
}, },
(jid) async {},
); );
// Alice sends a message // Alice sends a message
@ -159,7 +163,7 @@ void main() {
aliceJid, aliceJid,
aliceDevice.id, aliceDevice.id,
DateTime.now().millisecondsSinceEpoch, DateTime.now().millisecondsSinceEpoch,
aliceResult!.encryptedKeys, aliceResult.encryptedKeys,
base64.encode(aliceResult.ciphertext!), base64.encode(aliceResult.ciphertext!),
), ),
); );
@ -185,7 +189,7 @@ void main() {
aliceJid, aliceJid,
aliceDevice.id, aliceDevice.id,
DateTime.now().millisecondsSinceEpoch, DateTime.now().millisecondsSinceEpoch,
aliceResultLoop!.encryptedKeys, aliceResultLoop.encryptedKeys,
base64.encode(aliceResultLoop.ciphertext!), base64.encode(aliceResultLoop.ciphertext!),
), ),
); );
@ -208,7 +212,7 @@ void main() {
aliceJid, aliceJid,
aliceDevice.id, aliceDevice.id,
DateTime.now().millisecondsSinceEpoch, DateTime.now().millisecondsSinceEpoch,
aliceResultFinal!.encryptedKeys, aliceResultFinal.encryptedKeys,
base64.encode(aliceResultFinal.ciphertext!), base64.encode(aliceResultFinal.ciphertext!),
), ),
); );
@ -221,7 +225,7 @@ void main() {
test('Test accessing data without it existing', () async { test('Test accessing data without it existing', () async {
const aliceJid = 'alice@server1'; const aliceJid = 'alice@server1';
const bobJid = 'bob@server2'; const bobJid = 'bob@server2';
final aliceDevice = await Device.generateNewDevice(aliceJid, opkAmount: 1); final aliceDevice = await OmemoDevice.generateNewDevice(aliceJid, opkAmount: 1);
final aliceManager = OmemoManager( final aliceManager = OmemoManager(
aliceDevice, aliceDevice,
@ -229,6 +233,7 @@ void main() {
(result, recipientJid) async {}, (result, recipientJid) async {},
(jid) async => [], (jid) async => [],
(jid, id) async => null, (jid, id) async => null,
(jid) async {},
); );
// Get non-existant fingerprints // Get non-existant fingerprints
@ -249,9 +254,9 @@ void main() {
const bobJid = 'bob@server2'; const bobJid = 'bob@server2';
var oldDevice = true; var oldDevice = true;
final aliceDevice = await Device.generateNewDevice(aliceJid, opkAmount: 1); final aliceDevice = await OmemoDevice.generateNewDevice(aliceJid, opkAmount: 1);
final bobOldDevice = await Device.generateNewDevice(bobJid, opkAmount: 1); final bobOldDevice = await OmemoDevice.generateNewDevice(bobJid, opkAmount: 1);
final bobCurrentDevice = await Device.generateNewDevice(bobJid, opkAmount: 1); final bobCurrentDevice = await OmemoDevice.generateNewDevice(bobJid, opkAmount: 1);
final aliceManager = OmemoManager( final aliceManager = OmemoManager(
aliceDevice, aliceDevice,
@ -270,6 +275,7 @@ void main() {
bobOldDevice.toBundle() : bobOldDevice.toBundle() :
bobCurrentDevice.toBundle(); bobCurrentDevice.toBundle();
}, },
(jid) async {},
); );
final bobManager = OmemoManager( final bobManager = OmemoManager(
bobCurrentDevice, bobCurrentDevice,
@ -277,6 +283,7 @@ void main() {
(result, recipientJid) async {}, (result, recipientJid) async {},
(jid) async => [], (jid) async => [],
(jid, id) async => null, (jid, id) async => null,
(jid) async {},
); );
// Alice encrypts a message to Bob // Alice encrypts a message to Bob
@ -293,7 +300,7 @@ void main() {
aliceJid, aliceJid,
aliceDevice.id, aliceDevice.id,
DateTime.now().millisecondsSinceEpoch, DateTime.now().millisecondsSinceEpoch,
aliceResult1!.encryptedKeys, aliceResult1.encryptedKeys,
base64.encode(aliceResult1.ciphertext!), base64.encode(aliceResult1.ciphertext!),
), ),
); );
@ -317,7 +324,7 @@ void main() {
aliceJid, aliceJid,
aliceDevice.id, aliceDevice.id,
DateTime.now().millisecondsSinceEpoch, DateTime.now().millisecondsSinceEpoch,
aliceResult2!.encryptedKeys, aliceResult2.encryptedKeys,
base64.encode(aliceResult2.ciphertext!), base64.encode(aliceResult2.ciphertext!),
), ),
); );
@ -331,9 +338,9 @@ void main() {
const bobJid = 'bob@server2'; const bobJid = 'bob@server2';
var bothDevices = false; var bothDevices = false;
final aliceDevice = await Device.generateNewDevice(aliceJid, opkAmount: 1); final aliceDevice = await OmemoDevice.generateNewDevice(aliceJid, opkAmount: 1);
final bobDevice1 = await Device.generateNewDevice(bobJid, opkAmount: 1); final bobDevice1 = await OmemoDevice.generateNewDevice(bobJid, opkAmount: 1);
final bobDevice2 = await Device.generateNewDevice(bobJid, opkAmount: 1); final bobDevice2 = await OmemoDevice.generateNewDevice(bobJid, opkAmount: 1);
final aliceManager = OmemoManager( final aliceManager = OmemoManager(
aliceDevice, aliceDevice,
@ -364,6 +371,7 @@ void main() {
return null; return null;
}, },
(jid) async {},
); );
final bobManager1 = OmemoManager( final bobManager1 = OmemoManager(
bobDevice1, bobDevice1,
@ -371,6 +379,7 @@ void main() {
(result, recipientJid) async {}, (result, recipientJid) async {},
(jid) async => [], (jid) async => [],
(jid, id) async => null, (jid, id) async => null,
(jid) async {},
); );
final bobManager2 = OmemoManager( final bobManager2 = OmemoManager(
bobDevice2, bobDevice2,
@ -384,6 +393,7 @@ void main() {
expect(jid, aliceJid); expect(jid, aliceJid);
return aliceDevice.toBundle(); return aliceDevice.toBundle();
}, },
(jid) async {},
); );
// Alice sends a message to Bob // Alice sends a message to Bob
@ -400,7 +410,7 @@ void main() {
aliceJid, aliceJid,
aliceDevice.id, aliceDevice.id,
DateTime.now().millisecondsSinceEpoch, DateTime.now().millisecondsSinceEpoch,
aliceResult1!.encryptedKeys, aliceResult1.encryptedKeys,
base64.encode(aliceResult1.ciphertext!), base64.encode(aliceResult1.ciphertext!),
), ),
); );
@ -423,7 +433,7 @@ void main() {
bobJid, bobJid,
bobDevice2.id, bobDevice2.id,
DateTime.now().millisecondsSinceEpoch, DateTime.now().millisecondsSinceEpoch,
bobResult2!.encryptedKeys, bobResult2.encryptedKeys,
base64.encode(bobResult2.ciphertext!), base64.encode(bobResult2.ciphertext!),
), ),
); );
@ -436,9 +446,9 @@ void main() {
const bobJid = 'bob@server2'; const bobJid = 'bob@server2';
var bothDevices = false; var bothDevices = false;
final aliceDevice = await Device.generateNewDevice(aliceJid, opkAmount: 1); final aliceDevice = await OmemoDevice.generateNewDevice(aliceJid, opkAmount: 1);
final bobDevice1 = await Device.generateNewDevice(bobJid, opkAmount: 1); final bobDevice1 = await OmemoDevice.generateNewDevice(bobJid, opkAmount: 1);
final bobDevice2 = await Device.generateNewDevice(bobJid, opkAmount: 1); final bobDevice2 = await OmemoDevice.generateNewDevice(bobJid, opkAmount: 1);
final aliceManager = OmemoManager( final aliceManager = OmemoManager(
aliceDevice, aliceDevice,
@ -469,6 +479,7 @@ void main() {
return null; return null;
}, },
(jid) async {},
); );
final bobManager1 = OmemoManager( final bobManager1 = OmemoManager(
bobDevice1, bobDevice1,
@ -476,6 +487,7 @@ void main() {
(result, recipientJid) async {}, (result, recipientJid) async {},
(jid) async => null, (jid) async => null,
(jid, id) async => null, (jid, id) async => null,
(jid) async {},
); );
final bobManager2 = OmemoManager( final bobManager2 = OmemoManager(
bobDevice2, bobDevice2,
@ -483,6 +495,7 @@ void main() {
(result, recipientJid) async {}, (result, recipientJid) async {},
(jid) async => null, (jid) async => null,
(jid, id) async => null, (jid, id) async => null,
(jid) async {},
); );
// Alice sends a message to Bob // Alice sends a message to Bob
@ -499,7 +512,7 @@ void main() {
aliceJid, aliceJid,
aliceDevice.id, aliceDevice.id,
DateTime.now().millisecondsSinceEpoch, DateTime.now().millisecondsSinceEpoch,
aliceResult1!.encryptedKeys, aliceResult1.encryptedKeys,
base64.encode(aliceResult1.ciphertext!), base64.encode(aliceResult1.ciphertext!),
), ),
); );
@ -528,7 +541,7 @@ void main() {
), ),
); );
expect(aliceResult2!.encryptedKeys.length, 2); expect(aliceResult2.encryptedKeys.length, 2);
// And Bob decrypts it // And Bob decrypts it
final bobResult21 = await bobManager1.onIncomingStanza( final bobResult21 = await bobManager1.onIncomingStanza(
@ -567,7 +580,7 @@ void main() {
bobJid, bobJid,
bobDevice2.id, bobDevice2.id,
DateTime.now().millisecondsSinceEpoch, DateTime.now().millisecondsSinceEpoch,
bobResult32!.encryptedKeys, bobResult32.encryptedKeys,
base64.encode(bobResult32.ciphertext!), base64.encode(bobResult32.ciphertext!),
), ),
); );
@ -580,9 +593,9 @@ void main() {
const bobJid = 'bob@server2'; const bobJid = 'bob@server2';
const cocoJid = 'coco@server3'; const cocoJid = 'coco@server3';
final aliceDevice = await Device.generateNewDevice(aliceJid, opkAmount: 1); final aliceDevice = await OmemoDevice.generateNewDevice(aliceJid, opkAmount: 1);
final bobDevice = await Device.generateNewDevice(bobJid, opkAmount: 1); final bobDevice = await OmemoDevice.generateNewDevice(bobJid, opkAmount: 1);
final cocoDevice = await Device.generateNewDevice(cocoJid, opkAmount: 1); final cocoDevice = await OmemoDevice.generateNewDevice(cocoJid, opkAmount: 1);
final aliceManager = OmemoManager( final aliceManager = OmemoManager(
aliceDevice, aliceDevice,
@ -606,6 +619,7 @@ void main() {
return null; return null;
}, },
(jid) async {},
); );
final bobManager = OmemoManager( final bobManager = OmemoManager(
bobDevice, bobDevice,
@ -613,6 +627,7 @@ void main() {
(result, recipientJid) async {}, (result, recipientJid) async {},
(jid) async => null, (jid) async => null,
(jid, id) async => null, (jid, id) async => null,
(jid) async {},
); );
final cocoManager = OmemoManager( final cocoManager = OmemoManager(
cocoDevice, cocoDevice,
@ -620,6 +635,7 @@ void main() {
(result, recipientJid) async {}, (result, recipientJid) async {},
(jid) async => null, (jid) async => null,
(jid, id) async => null, (jid, id) async => null,
(jid) async {},
); );
// Alice sends a message to Bob and Coco // Alice sends a message to Bob and Coco
@ -636,7 +652,7 @@ void main() {
aliceJid, aliceJid,
aliceDevice.id, aliceDevice.id,
DateTime.now().millisecondsSinceEpoch, DateTime.now().millisecondsSinceEpoch,
aliceResult!.encryptedKeys, aliceResult.encryptedKeys,
base64.encode(aliceResult.ciphertext!), base64.encode(aliceResult.ciphertext!),
), ),
); );
@ -661,8 +677,8 @@ void main() {
const bobJid = 'bob@server2'; const bobJid = 'bob@server2';
var failure = false; var failure = false;
final aliceDevice = await Device.generateNewDevice(aliceJid, opkAmount: 1); final aliceDevice = await OmemoDevice.generateNewDevice(aliceJid, opkAmount: 1);
final bobDevice = await Device.generateNewDevice(bobJid, opkAmount: 1); final bobDevice = await OmemoDevice.generateNewDevice(bobJid, opkAmount: 1);
final aliceManager = OmemoManager( final aliceManager = OmemoManager(
aliceDevice, aliceDevice,
@ -682,6 +698,7 @@ void main() {
null : null :
bobDevice.toBundle(); bobDevice.toBundle();
}, },
(jid) async {},
); );
final bobManager = OmemoManager( final bobManager = OmemoManager(
bobDevice, bobDevice,
@ -689,6 +706,7 @@ void main() {
(result, recipientJid) async {}, (result, recipientJid) async {},
(jid) async => null, (jid) async => null,
(jid, id) async => null, (jid, id) async => null,
(jid) async {},
); );
// Alice sends a message to Bob and Coco // Alice sends a message to Bob and Coco
@ -705,7 +723,7 @@ void main() {
aliceJid, aliceJid,
aliceDevice.id, aliceDevice.id,
DateTime.now().millisecondsSinceEpoch, DateTime.now().millisecondsSinceEpoch,
aliceResult1!.encryptedKeys, aliceResult1.encryptedKeys,
base64.encode(aliceResult1.ciphertext!), base64.encode(aliceResult1.ciphertext!),
), ),
); );
@ -737,7 +755,7 @@ void main() {
aliceJid, aliceJid,
aliceDevice.id, aliceDevice.id,
DateTime.now().millisecondsSinceEpoch, DateTime.now().millisecondsSinceEpoch,
aliceResult2!.encryptedKeys, aliceResult2.encryptedKeys,
base64.encode(aliceResult2.ciphertext!), base64.encode(aliceResult2.ciphertext!),
), ),
); );
@ -750,7 +768,7 @@ void main() {
const aliceJid = 'alice@server1'; const aliceJid = 'alice@server1';
const bobJid = 'bob@server2'; const bobJid = 'bob@server2';
final aliceDevice = await Device.generateNewDevice(aliceJid, opkAmount: 1); final aliceDevice = await OmemoDevice.generateNewDevice(aliceJid, opkAmount: 1);
final aliceManager = OmemoManager( final aliceManager = OmemoManager(
aliceDevice, aliceDevice,
@ -766,6 +784,7 @@ void main() {
return null; return null;
}, },
(jid) async {},
); );
// Alice sends a message to Bob // Alice sends a message to Bob
@ -776,7 +795,7 @@ void main() {
), ),
); );
expect(aliceResult!.isSuccess(1), false); expect(aliceResult.isSuccess(1), false);
expect(aliceResult.jidEncryptionErrors[bobJid] is NoKeyMaterialAvailableException, true); expect(aliceResult.jidEncryptionErrors[bobJid] is NoKeyMaterialAvailableException, true);
}); });
@ -785,8 +804,8 @@ void main() {
const bobJid = 'bob@server2'; const bobJid = 'bob@server2';
const cocoJid = 'coco@server3'; const cocoJid = 'coco@server3';
final aliceDevice = await Device.generateNewDevice(aliceJid, opkAmount: 1); final aliceDevice = await OmemoDevice.generateNewDevice(aliceJid, opkAmount: 1);
final bobDevice = await Device.generateNewDevice(bobJid, opkAmount: 1); final bobDevice = await OmemoDevice.generateNewDevice(bobJid, opkAmount: 1);
final aliceManager = OmemoManager( final aliceManager = OmemoManager(
aliceDevice, aliceDevice,
@ -806,6 +825,7 @@ void main() {
return null; return null;
}, },
(jid) async {},
); );
final bobManager = OmemoManager( final bobManager = OmemoManager(
bobDevice, bobDevice,
@ -813,6 +833,7 @@ void main() {
(result, recipientJid) async {}, (result, recipientJid) async {},
(jid) async => null, (jid) async => null,
(jid, id) async => null, (jid, id) async => null,
(jid) async {},
); );
// Alice sends a message to Bob and Coco // Alice sends a message to Bob and Coco
@ -823,7 +844,7 @@ void main() {
), ),
); );
expect(aliceResult!.isSuccess(2), true); expect(aliceResult.isSuccess(2), true);
expect(aliceResult.jidEncryptionErrors[cocoJid] is NoKeyMaterialAvailableException, true); expect(aliceResult.jidEncryptionErrors[cocoJid] is NoKeyMaterialAvailableException, true);
// Bob decrypts it // Bob decrypts it
@ -844,8 +865,8 @@ void main() {
const aliceJid = 'alice@server1'; const aliceJid = 'alice@server1';
const bobJid = 'bob@server2'; const bobJid = 'bob@server2';
final aliceDevice = await Device.generateNewDevice(aliceJid, opkAmount: 1); final aliceDevice = await OmemoDevice.generateNewDevice(aliceJid, opkAmount: 1);
final bobDevice = await Device.generateNewDevice(bobJid, opkAmount: 1); final bobDevice = await OmemoDevice.generateNewDevice(bobJid, opkAmount: 1);
final aliceManager = OmemoManager( final aliceManager = OmemoManager(
aliceDevice, aliceDevice,
@ -861,6 +882,7 @@ void main() {
return bobDevice.toBundle(); return bobDevice.toBundle();
}, },
(jid) async {},
); );
final bobManager = OmemoManager( final bobManager = OmemoManager(
bobDevice, bobDevice,
@ -868,6 +890,7 @@ void main() {
(result, recipientJid) async {}, (result, recipientJid) async {},
(jid) async => null, (jid) async => null,
(jid, id) async => null, (jid, id) async => null,
(jid) async {},
); );
// Alice encrypts a message for Bob // Alice encrypts a message for Bob
@ -884,7 +907,7 @@ void main() {
aliceJid, aliceJid,
aliceDevice.id, aliceDevice.id,
DateTime.now().millisecondsSinceEpoch, DateTime.now().millisecondsSinceEpoch,
aliceMessage!.encryptedKeys, aliceMessage.encryptedKeys,
base64.encode(aliceMessage.ciphertext!), base64.encode(aliceMessage.ciphertext!),
), ),
@ -905,7 +928,7 @@ void main() {
messageText, messageText,
), ),
); );
expect(bobResponseMessage!.isSuccess(1), true); expect(bobResponseMessage.isSuccess(1), true);
final aliceReceivedMessage = await aliceManager.onIncomingStanza( final aliceReceivedMessage = await aliceManager.onIncomingStanza(
OmemoIncomingStanza( OmemoIncomingStanza(

View File

@ -18,7 +18,7 @@ void main() {
final oldDevice = await oldSession.getDevice(); final oldDevice = await oldSession.getDevice();
final serialised = jsonify(await oldDevice.toJson()); final serialised = jsonify(await oldDevice.toJson());
final newDevice = Device.fromJson(serialised); final newDevice = OmemoDevice.fromJson(serialised);
expect(await oldDevice.equals(newDevice), true); expect(await oldDevice.equals(newDevice), true);
}); });
@ -32,7 +32,7 @@ void main() {
final oldDevice = await (await oldSession.getDevice()).replaceSignedPrekey(); final oldDevice = await (await oldSession.getDevice()).replaceSignedPrekey();
final serialised = jsonify(await oldDevice.toJson()); final serialised = jsonify(await oldDevice.toJson());
final newDevice = Device.fromJson(serialised); final newDevice = OmemoDevice.fromJson(serialised);
expect(await oldDevice.equals(newDevice), true); expect(await oldDevice.equals(newDevice), true);
}); });