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`
|
- 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
|
- 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
|
- 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:
|
dependencies:
|
||||||
omemo_dart:
|
omemo_dart:
|
||||||
hosted: https://git.polynom.me/api/packages/PapaTutuWawa/pub
|
hosted: https://git.polynom.me/api/packages/PapaTutuWawa/pub
|
||||||
version: ^0.1.0
|
version: ^0.2.0
|
||||||
# [...]
|
# [...]
|
||||||
|
|
||||||
# [...]
|
# [...]
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ class OmemoDoubleRatchet {
|
|||||||
ik,
|
ik,
|
||||||
ad,
|
ad,
|
||||||
{},
|
{},
|
||||||
true,
|
false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -254,6 +254,9 @@ class OmemoSessionManager {
|
|||||||
if (plaintext != null) {
|
if (plaintext != null) {
|
||||||
// Only encrypt to devices that are trusted
|
// Only encrypt to devices that are trusted
|
||||||
if (!(await _trustManager.isTrusted(jid, deviceId))) continue;
|
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);
|
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
|
/// Returns the device map, i.e. the mapping of bare Jid to its device identifiers
|
||||||
/// we have built sessions with.
|
/// we have built sessions with.
|
||||||
Future<Map<String, List<int>>> getDeviceMap() async {
|
Future<Map<String, List<int>>> getDeviceMap() async {
|
||||||
Map<String, List<int>>? map;
|
return _lock.synchronized(() => _deviceMap);
|
||||||
|
|
||||||
await _lock.synchronized(() async {
|
|
||||||
map = _deviceMap;
|
|
||||||
});
|
|
||||||
|
|
||||||
return map!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes the ratchet identified by [jid] and [deviceId] from the session manager.
|
/// 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.
|
/// 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.
|
/// we have not yet received an empty OMEMO message from.
|
||||||
Future<List<int>> getUnacknowledgedRatchets(String jid) async {
|
Future<List<int>?> getUnacknowledgedRatchets(String jid) async {
|
||||||
final ret = List<int>.empty(growable: true);
|
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) {
|
for (final device in devices) {
|
||||||
final ratchet = _ratchetMap[RatchetMapKey(jid, device)]!;
|
final ratchet = _ratchetMap[RatchetMapKey(jid, device)]!;
|
||||||
if (!ratchet.acknowledged) ret.add(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.
|
/// Mark the ratchet for device [deviceId] from [jid] as acked.
|
||||||
Future<void> ratchetAcknowledged(String jid, int deviceId) async {
|
Future<void> ratchetAcknowledged(String jid, int deviceId) async {
|
||||||
await _lock.synchronized(() async {
|
await _lock.synchronized(() async {
|
||||||
|
|||||||
@@ -11,4 +11,10 @@ class AlwaysTrustingTrustManager extends TrustManager {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> onNewSession(String jid, int deviceId) async {}
|
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
|
/// Called by the OmemoSessionManager when a new session has been built. Should set
|
||||||
/// a default trust state to [jid]'s device with identifier [deviceId].
|
/// a default trust state to [jid]'s device with identifier [deviceId].
|
||||||
Future<void> onNewSession(String jid, int 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 {
|
abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager {
|
||||||
BlindTrustBeforeVerificationTrustManager()
|
BlindTrustBeforeVerificationTrustManager()
|
||||||
: trustCache = {},
|
: trustCache = {},
|
||||||
|
enablementCache = {},
|
||||||
devices = {},
|
devices = {},
|
||||||
_lock = Lock();
|
_lock = Lock();
|
||||||
|
|
||||||
/// The cache for Mapping a RatchetMapKey to its trust state
|
/// The cache for mapping a RatchetMapKey to its trust state
|
||||||
@protected
|
@protected
|
||||||
final Map<RatchetMapKey, BTBVTrustState> trustCache;
|
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
|
/// Mapping of Jids to their device identifiers
|
||||||
@protected
|
@protected
|
||||||
final Map<String, List<int>> devices;
|
final Map<String, List<int>> devices;
|
||||||
@@ -74,10 +79,13 @@ abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager {
|
|||||||
@override
|
@override
|
||||||
Future<void> onNewSession(String jid, int deviceId) async {
|
Future<void> onNewSession(String jid, int deviceId) async {
|
||||||
await _lock.synchronized(() async {
|
await _lock.synchronized(() async {
|
||||||
|
final key = RatchetMapKey(jid, deviceId);
|
||||||
if (_hasAtLeastOneVerifiedDevice(jid)) {
|
if (_hasAtLeastOneVerifiedDevice(jid)) {
|
||||||
trustCache[RatchetMapKey(jid, deviceId)] = BTBVTrustState.notTrusted;
|
trustCache[key] = BTBVTrustState.notTrusted;
|
||||||
|
enablementCache[key] = false;
|
||||||
} else {
|
} else {
|
||||||
trustCache[RatchetMapKey(jid, deviceId)] = BTBVTrustState.blindTrust;
|
trustCache[key] = BTBVTrustState.blindTrust;
|
||||||
|
enablementCache[key] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (devices.containsKey(jid)) {
|
if (devices.containsKey(jid)) {
|
||||||
@@ -85,7 +93,7 @@ abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager {
|
|||||||
} else {
|
} else {
|
||||||
devices[jid] = List<int>.from([deviceId]);
|
devices[jid] = List<int>.from([deviceId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit the state
|
// Commit the state
|
||||||
await commitState();
|
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
|
/// 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
|
||||||
|
|||||||
@@ -11,4 +11,10 @@ class NeverTrustingTrustManager extends TrustManager {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> onNewSession(String jid, int deviceId) async {}
|
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
|
name: omemo_dart
|
||||||
description: An XMPP library independent OMEMO library
|
description: An XMPP library independent OMEMO library
|
||||||
version: 0.2.0
|
version: 0.2.1
|
||||||
homepage: https://github.com/PapaTutuWawa/omemo_dart
|
homepage: https://github.com/PapaTutuWawa/omemo_dart
|
||||||
publish_to: https://git.polynom.me/api/packages/PapaTutuWawa/pub
|
publish_to: https://git.polynom.me/api/packages/PapaTutuWawa/pub
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ dependencies:
|
|||||||
collection: ^1.16.0
|
collection: ^1.16.0
|
||||||
cryptography: ^2.0.5
|
cryptography: ^2.0.5
|
||||||
hex: ^0.2.0
|
hex: ^0.2.0
|
||||||
meta: ^1.8.0
|
meta: ^1.7.0
|
||||||
pinenacl: ^0.5.1
|
pinenacl: ^0.5.1
|
||||||
synchronized: ^3.0.0+2
|
synchronized: ^3.0.0+2
|
||||||
|
|
||||||
|
|||||||
@@ -539,7 +539,7 @@ void main() {
|
|||||||
// Alice marks the ratchet as acknowledged
|
// Alice marks the ratchet as acknowledged
|
||||||
await aliceSession.ratchetAcknowledged(bobJid, await bobSession.getDeviceId());
|
await aliceSession.ratchetAcknowledged(bobJid, await bobSession.getDeviceId());
|
||||||
expect(
|
expect(
|
||||||
(await aliceSession.getUnacknowledgedRatchets(bobJid)).isEmpty,
|
(await aliceSession.getUnacknowledgedRatchets(bobJid))!.isEmpty,
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ void main() {
|
|||||||
// Caroline starts a chat a device from Alice
|
// Caroline starts a chat a device from Alice
|
||||||
await btbv.onNewSession(aliceJid, 1);
|
await btbv.onNewSession(aliceJid, 1);
|
||||||
expect(await btbv.isTrusted(aliceJid, 1), true);
|
expect(await btbv.isTrusted(aliceJid, 1), true);
|
||||||
|
expect(await btbv.isEnabled(aliceJid, 1), true);
|
||||||
|
|
||||||
// Caroline meets with Alice and verifies her fingerprint
|
// Caroline meets with Alice and verifies her fingerprint
|
||||||
await btbv.setDeviceTrust(aliceJid, 1, BTBVTrustState.verified);
|
await btbv.setDeviceTrust(aliceJid, 1, BTBVTrustState.verified);
|
||||||
@@ -21,6 +22,7 @@ void main() {
|
|||||||
await btbv.onNewSession(aliceJid, 2);
|
await btbv.onNewSession(aliceJid, 2);
|
||||||
expect(await btbv.isTrusted(aliceJid, 2), false);
|
expect(await btbv.isTrusted(aliceJid, 2), false);
|
||||||
expect(btbv.getDeviceTrust(aliceJid, 2), BTBVTrustState.notTrusted);
|
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
|
// Caronline starts a chat with Bob but since they live far apart, Caroline cannot
|
||||||
// verify his fingerprint.
|
// verify his fingerprint.
|
||||||
@@ -32,5 +34,7 @@ void main() {
|
|||||||
expect(await btbv.isTrusted(bobJid, 4), true);
|
expect(await btbv.isTrusted(bobJid, 4), true);
|
||||||
expect(btbv.getDeviceTrust(bobJid, 3), BTBVTrustState.blindTrust);
|
expect(btbv.getDeviceTrust(bobJid, 3), BTBVTrustState.blindTrust);
|
||||||
expect(btbv.getDeviceTrust(bobJid, 4), 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