Compare commits
8 Commits
v0.2.0
...
12e09947f6
| Author | SHA1 | Date | |
|---|---|---|---|
| 12e09947f6 | |||
| d530358359 | |||
| 0e370a8e19 | |||
| b6aa28e1ee | |||
| 2e10842c54 | |||
| 0e2af1f2a3 | |||
| 80e1b20f27 | |||
| f68e45af26 |
@@ -15,3 +15,8 @@
|
||||
- Add convenience functions `getDeviceId` and `getDeviceBundle`
|
||||
- Creating a new ratchet with an id for which we already have a ratchet will now overwrite the old ratchet
|
||||
- Ratchet now carry an "acknowledged" attribute
|
||||
|
||||
## 0.2.1
|
||||
|
||||
- Add `isRatchetAcknowledged`
|
||||
- Ratchets that are created due to accepting a kex are now unacknowledged
|
||||
|
||||
@@ -28,7 +28,7 @@ Include `omemo_dart` in your `pubspec.yaml` like this:
|
||||
dependencies:
|
||||
omemo_dart:
|
||||
hosted: https://git.polynom.me/api/packages/PapaTutuWawa/pub
|
||||
version: ^0.1.0
|
||||
version: ^0.2.0
|
||||
# [...]
|
||||
|
||||
# [...]
|
||||
|
||||
@@ -197,7 +197,7 @@ class OmemoDoubleRatchet {
|
||||
ik,
|
||||
ad,
|
||||
{},
|
||||
true,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -254,6 +254,9 @@ class OmemoSessionManager {
|
||||
if (plaintext != null) {
|
||||
// Only encrypt to devices that are trusted
|
||||
if (!(await _trustManager.isTrusted(jid, deviceId))) continue;
|
||||
|
||||
// Onyl encrypt to devices that are enabled
|
||||
if (!(await _trustManager.isEnabled(jid, deviceId))) continue;
|
||||
}
|
||||
|
||||
final ratchetKey = RatchetMapKey(jid, deviceId);
|
||||
@@ -415,13 +418,7 @@ class OmemoSessionManager {
|
||||
/// Returns the device map, i.e. the mapping of bare Jid to its device identifiers
|
||||
/// we have built sessions with.
|
||||
Future<Map<String, List<int>>> getDeviceMap() async {
|
||||
Map<String, List<int>>? map;
|
||||
|
||||
await _lock.synchronized(() async {
|
||||
map = _deviceMap;
|
||||
});
|
||||
|
||||
return map!;
|
||||
return _lock.synchronized(() => _deviceMap);
|
||||
}
|
||||
|
||||
/// Removes the ratchet identified by [jid] and [deviceId] from the session manager.
|
||||
@@ -446,20 +443,27 @@ class OmemoSessionManager {
|
||||
|
||||
/// Returns the list of device identifiers belonging to [jid] that are yet unacked, i.e.
|
||||
/// we have not yet received an empty OMEMO message from.
|
||||
Future<List<int>> getUnacknowledgedRatchets(String jid) async {
|
||||
final ret = List<int>.empty(growable: true);
|
||||
Future<List<int>?> getUnacknowledgedRatchets(String jid) async {
|
||||
return _lock.synchronized(() async {
|
||||
final ret = List<int>.empty(growable: true);
|
||||
final devices = _deviceMap[jid];
|
||||
if (devices == null) return null;
|
||||
|
||||
await _lock.synchronized(() async {
|
||||
final devices = _deviceMap[jid]!;
|
||||
for (final device in devices) {
|
||||
final ratchet = _ratchetMap[RatchetMapKey(jid, device)]!;
|
||||
if (!ratchet.acknowledged) ret.add(device);
|
||||
}
|
||||
});
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
});
|
||||
}
|
||||
|
||||
/// Returns true if the ratchet for [jid] with device identifier [deviceId] is
|
||||
/// acknowledged. Returns false if not.
|
||||
Future<bool> isRatchetAcknowledged(String jid, int deviceId) async {
|
||||
return _lock.synchronized(() => _ratchetMap[RatchetMapKey(jid, deviceId)]!.acknowledged);
|
||||
}
|
||||
|
||||
/// Mark the ratchet for device [deviceId] from [jid] as acked.
|
||||
Future<void> ratchetAcknowledged(String jid, int deviceId) async {
|
||||
await _lock.synchronized(() async {
|
||||
|
||||
@@ -11,4 +11,10 @@ class AlwaysTrustingTrustManager extends TrustManager {
|
||||
|
||||
@override
|
||||
Future<void> onNewSession(String jid, int deviceId) async {}
|
||||
|
||||
@override
|
||||
Future<bool> isEnabled(String jid, int deviceId) async => true;
|
||||
|
||||
@override
|
||||
Future<void> setEnabled(String jid, int deviceId, bool enabled) async {}
|
||||
}
|
||||
|
||||
@@ -8,4 +8,12 @@ abstract class TrustManager {
|
||||
/// Called by the OmemoSessionManager when a new session has been built. Should set
|
||||
/// a default trust state to [jid]'s device with identifier [deviceId].
|
||||
Future<void> onNewSession(String jid, int deviceId);
|
||||
|
||||
/// Return true if the device with id [deviceId] of Jid [jid] should be used for encryption.
|
||||
/// If not, return false.
|
||||
Future<bool> isEnabled(String jid, int deviceId);
|
||||
|
||||
/// Mark the device with id [deviceId] of Jid [jid] as enabled if [enabled] is true or as disabled
|
||||
/// if [enabled] is false.
|
||||
Future<void> setEnabled(String jid, int deviceId, bool enabled);
|
||||
}
|
||||
|
||||
@@ -18,13 +18,18 @@ enum BTBVTrustState {
|
||||
abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager {
|
||||
BlindTrustBeforeVerificationTrustManager()
|
||||
: trustCache = {},
|
||||
enablementCache = {},
|
||||
devices = {},
|
||||
_lock = Lock();
|
||||
|
||||
/// The cache for Mapping a RatchetMapKey to its trust state
|
||||
/// The cache for mapping a RatchetMapKey to its trust state
|
||||
@protected
|
||||
final Map<RatchetMapKey, BTBVTrustState> trustCache;
|
||||
|
||||
/// The cache for mapping a RatchetMapKey to whether it is enabled or not
|
||||
@protected
|
||||
final Map<RatchetMapKey, bool> enablementCache;
|
||||
|
||||
/// Mapping of Jids to their device identifiers
|
||||
@protected
|
||||
final Map<String, List<int>> devices;
|
||||
@@ -74,10 +79,13 @@ abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager {
|
||||
@override
|
||||
Future<void> onNewSession(String jid, int deviceId) async {
|
||||
await _lock.synchronized(() async {
|
||||
final key = RatchetMapKey(jid, deviceId);
|
||||
if (_hasAtLeastOneVerifiedDevice(jid)) {
|
||||
trustCache[RatchetMapKey(jid, deviceId)] = BTBVTrustState.notTrusted;
|
||||
trustCache[key] = BTBVTrustState.notTrusted;
|
||||
enablementCache[key] = false;
|
||||
} else {
|
||||
trustCache[RatchetMapKey(jid, deviceId)] = BTBVTrustState.blindTrust;
|
||||
trustCache[key] = BTBVTrustState.blindTrust;
|
||||
enablementCache[key] = true;
|
||||
}
|
||||
|
||||
if (devices.containsKey(jid)) {
|
||||
@@ -85,7 +93,7 @@ abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager {
|
||||
} else {
|
||||
devices[jid] = List<int>.from([deviceId]);
|
||||
}
|
||||
|
||||
|
||||
// Commit the state
|
||||
await commitState();
|
||||
});
|
||||
@@ -114,6 +122,26 @@ abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager {
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> isEnabled(String jid, int deviceId) async {
|
||||
return _lock.synchronized(() async {
|
||||
final value = enablementCache[RatchetMapKey(jid, deviceId)];
|
||||
|
||||
if (value == null) return false;
|
||||
return value;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setEnabled(String jid, int deviceId, bool enabled) async {
|
||||
await _lock.synchronized(() async {
|
||||
enablementCache[RatchetMapKey(jid, deviceId)] = enabled;
|
||||
});
|
||||
|
||||
// Commit the state
|
||||
await commitState();
|
||||
}
|
||||
|
||||
/// Called when the state of the trust manager has been changed. Allows the user to
|
||||
/// commit the trust state to persistent storage.
|
||||
@visibleForOverriding
|
||||
|
||||
@@ -11,4 +11,10 @@ class NeverTrustingTrustManager extends TrustManager {
|
||||
|
||||
@override
|
||||
Future<void> onNewSession(String jid, int deviceId) async {}
|
||||
|
||||
@override
|
||||
Future<bool> isEnabled(String jid, int deviceId) async => true;
|
||||
|
||||
@override
|
||||
Future<void> setEnabled(String jid, int deviceId, bool enabled) async {}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: omemo_dart
|
||||
description: An XMPP library independent OMEMO library
|
||||
version: 0.2.0
|
||||
version: 0.2.1
|
||||
homepage: https://github.com/PapaTutuWawa/omemo_dart
|
||||
publish_to: https://git.polynom.me/api/packages/PapaTutuWawa/pub
|
||||
|
||||
@@ -11,7 +11,7 @@ dependencies:
|
||||
collection: ^1.16.0
|
||||
cryptography: ^2.0.5
|
||||
hex: ^0.2.0
|
||||
meta: ^1.8.0
|
||||
meta: ^1.7.0
|
||||
pinenacl: ^0.5.1
|
||||
synchronized: ^3.0.0+2
|
||||
|
||||
|
||||
@@ -539,7 +539,7 @@ void main() {
|
||||
// Alice marks the ratchet as acknowledged
|
||||
await aliceSession.ratchetAcknowledged(bobJid, await bobSession.getDeviceId());
|
||||
expect(
|
||||
(await aliceSession.getUnacknowledgedRatchets(bobJid)).isEmpty,
|
||||
(await aliceSession.getUnacknowledgedRatchets(bobJid))!.isEmpty,
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -12,6 +12,7 @@ void main() {
|
||||
// Caroline starts a chat a device from Alice
|
||||
await btbv.onNewSession(aliceJid, 1);
|
||||
expect(await btbv.isTrusted(aliceJid, 1), true);
|
||||
expect(await btbv.isEnabled(aliceJid, 1), true);
|
||||
|
||||
// Caroline meets with Alice and verifies her fingerprint
|
||||
await btbv.setDeviceTrust(aliceJid, 1, BTBVTrustState.verified);
|
||||
@@ -21,6 +22,7 @@ void main() {
|
||||
await btbv.onNewSession(aliceJid, 2);
|
||||
expect(await btbv.isTrusted(aliceJid, 2), false);
|
||||
expect(btbv.getDeviceTrust(aliceJid, 2), BTBVTrustState.notTrusted);
|
||||
expect(await btbv.isEnabled(aliceJid, 2), false);
|
||||
|
||||
// Caronline starts a chat with Bob but since they live far apart, Caroline cannot
|
||||
// verify his fingerprint.
|
||||
@@ -32,5 +34,7 @@ void main() {
|
||||
expect(await btbv.isTrusted(bobJid, 4), true);
|
||||
expect(btbv.getDeviceTrust(bobJid, 3), BTBVTrustState.blindTrust);
|
||||
expect(btbv.getDeviceTrust(bobJid, 4), BTBVTrustState.blindTrust);
|
||||
expect(await btbv.isEnabled(bobJid, 3), true);
|
||||
expect(await btbv.isEnabled(bobJid, 4), true);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user