add key verification test
This commit is contained in:
parent
e2c358f319
commit
c4d09268a0
|
@ -99,16 +99,16 @@ class KeyVerificationManager {
|
||||||
|
|
||||||
if (_requests.containsKey(transactionId)) {
|
if (_requests.containsKey(transactionId)) {
|
||||||
final req = _requests[transactionId];
|
final req = _requests[transactionId];
|
||||||
|
final otherDeviceId = event['content']['from_device'];
|
||||||
if (event['sender'] != client.userID) {
|
if (event['sender'] != client.userID) {
|
||||||
await req.handlePayload(type, event['content'], event['event_id']);
|
await req.handlePayload(type, event['content'], event['event_id']);
|
||||||
} else if (req.userId == client.userID && req.deviceId == null) {
|
} else if (event['sender'] == client.userID &&
|
||||||
// okay, maybe another of our devices answered
|
otherDeviceId != null &&
|
||||||
await req.handlePayload(type, event['content'], event['event_id']);
|
otherDeviceId != client.deviceID) {
|
||||||
if (req.deviceId != client.deviceID) {
|
// okay, another of our devices answered
|
||||||
req.otherDeviceAccepted();
|
req.otherDeviceAccepted();
|
||||||
req.dispose();
|
req.dispose();
|
||||||
_requests.remove(transactionId);
|
_requests.remove(transactionId);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (event['sender'] != client.userID) {
|
} else if (event['sender'] != client.userID) {
|
||||||
final room = client.getRoomById(update.roomID) ??
|
final room = client.getRoomById(update.roomID) ??
|
||||||
|
|
|
@ -16,12 +16,47 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
import 'package:famedlysdk/encryption.dart';
|
import 'package:famedlysdk/encryption.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
import 'package:olm/olm.dart' as olm;
|
import 'package:olm/olm.dart' as olm;
|
||||||
|
|
||||||
import '../fake_client.dart';
|
import '../fake_client.dart';
|
||||||
|
import '../fake_matrix_api.dart';
|
||||||
|
|
||||||
|
class MockSSSS extends SSSS {
|
||||||
|
MockSSSS(Encryption encryption) : super(encryption);
|
||||||
|
|
||||||
|
bool requestedSecrets = false;
|
||||||
|
@override
|
||||||
|
Future<void> maybeRequestAll(List<DeviceKeys> devices) async {
|
||||||
|
requestedSecrets = true;
|
||||||
|
final handle = open();
|
||||||
|
handle.unlock(recoveryKey: SSSS_KEY);
|
||||||
|
await handle.maybeCacheAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EventUpdate getLastSentEvent(KeyVerification req) {
|
||||||
|
final entry = FakeMatrixApi.calledEndpoints.entries
|
||||||
|
.firstWhere((p) => p.key.contains('/send/'));
|
||||||
|
final type = entry.key.split('/')[6];
|
||||||
|
final content = json.decode(entry.value.first);
|
||||||
|
return EventUpdate(
|
||||||
|
content: {
|
||||||
|
'event_id': req.transactionId,
|
||||||
|
'type': type,
|
||||||
|
'content': content,
|
||||||
|
'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
|
||||||
|
'sender': req.client.userID,
|
||||||
|
},
|
||||||
|
eventType: type,
|
||||||
|
type: 'timeline',
|
||||||
|
roomID: req.room.id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
/// All Tests related to the ChatTime
|
/// All Tests related to the ChatTime
|
||||||
|
@ -38,70 +73,392 @@ void main() {
|
||||||
|
|
||||||
if (!olmEnabled) return;
|
if (!olmEnabled) return;
|
||||||
|
|
||||||
Client client;
|
// key @othertest:fakeServer.notExisting
|
||||||
Room room;
|
const otherPickledOlmAccount =
|
||||||
var updateCounter = 0;
|
'VWhVApbkcilKAEGppsPDf9nNVjaK8/IxT3asSR0sYg0S5KgbfE8vXEPwoiKBX2cEvwX3OessOBOkk+ZE7TTbjlrh/KEd31p8Wo+47qj0AP+Ky+pabnhi+/rTBvZy+gfzTqUfCxZrkzfXI9Op4JnP6gYmy7dVX2lMYIIs9WCO1jcmIXiXum5jnfXu1WLfc7PZtO2hH+k9CDKosOFaXRBmsu8k/BGXPSoWqUpvu6WpEG9t5STk4FeAzA';
|
||||||
KeyVerification keyVerification;
|
|
||||||
|
Client client1;
|
||||||
|
Client client2;
|
||||||
|
|
||||||
test('setupClient', () async {
|
test('setupClient', () async {
|
||||||
client = await getClient();
|
client1 = await getClient();
|
||||||
room = Room(id: '!localpart:server.abc', client: client);
|
client2 =
|
||||||
keyVerification = KeyVerification(
|
Client('othertestclient', debug: true, httpClient: FakeMatrixApi());
|
||||||
encryption: client.encryption,
|
client2.database = client1.database;
|
||||||
room: room,
|
await client2.checkServer('https://fakeServer.notExisting');
|
||||||
userId: '@alice:example.com',
|
client2.connect(
|
||||||
deviceId: 'ABCD',
|
newToken: 'abc',
|
||||||
onUpdate: () => updateCounter++,
|
newUserID: '@othertest:fakeServer.notExisting',
|
||||||
|
newHomeserver: client2.api.homeserver,
|
||||||
|
newDeviceName: 'Text Matrix Client',
|
||||||
|
newDeviceID: 'FOXDEVICE',
|
||||||
|
newOlmAccount: otherPickledOlmAccount,
|
||||||
);
|
);
|
||||||
|
await Future.delayed(Duration(milliseconds: 10));
|
||||||
|
client1.verificationMethods = {
|
||||||
|
KeyVerificationMethod.emoji,
|
||||||
|
KeyVerificationMethod.numbers
|
||||||
|
};
|
||||||
|
client2.verificationMethods = {
|
||||||
|
KeyVerificationMethod.emoji,
|
||||||
|
KeyVerificationMethod.numbers
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
test('acceptSas', () async {
|
test('Run emoji / number verification', () async {
|
||||||
await keyVerification.acceptSas();
|
// for a full run we test in-room verification in a cleartext room
|
||||||
});
|
// because then we can easily intercept the payloads and inject in the other client
|
||||||
test('acceptVerification', () async {
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
await keyVerification.acceptVerification();
|
// make sure our master key is *not* verified to not triger SSSS for now
|
||||||
});
|
client1.userDeviceKeys[client1.userID].masterKey.setDirectVerified(false);
|
||||||
test('cancel', () async {
|
final req1 =
|
||||||
await keyVerification.cancel('m.cancelcode');
|
await client1.userDeviceKeys[client2.userID].startVerification();
|
||||||
expect(keyVerification.canceled, true);
|
var evt = getLastSentEvent(req1);
|
||||||
expect(keyVerification.canceledCode, 'm.cancelcode');
|
expect(req1.state, KeyVerificationState.waitingAccept);
|
||||||
expect(keyVerification.canceledReason, null);
|
|
||||||
});
|
KeyVerification req2;
|
||||||
test('handlePayload', () async {
|
final sub = client2.onKeyVerificationRequest.stream.listen((req) {
|
||||||
await keyVerification.handlePayload('m.key.verification.request', {
|
req2 = req;
|
||||||
'from_device': 'AliceDevice2',
|
|
||||||
'methods': ['m.sas.v1'],
|
|
||||||
'timestamp': 1559598944869,
|
|
||||||
'transaction_id': 'S0meUniqueAndOpaqueString'
|
|
||||||
});
|
});
|
||||||
await keyVerification.handlePayload('m.key.verification.start', {
|
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
'from_device': 'BobDevice1',
|
await Future.delayed(Duration(milliseconds: 10));
|
||||||
'method': 'm.sas.v1',
|
await sub.cancel();
|
||||||
'transaction_id': 'S0meUniqueAndOpaqueString'
|
expect(req2 != null, true);
|
||||||
|
|
||||||
|
// send ready
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await req2.acceptVerification();
|
||||||
|
evt = getLastSentEvent(req2);
|
||||||
|
expect(req2.state, KeyVerificationState.waitingAccept);
|
||||||
|
|
||||||
|
// send start
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
evt = getLastSentEvent(req1);
|
||||||
|
|
||||||
|
// send accept
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
evt = getLastSentEvent(req2);
|
||||||
|
|
||||||
|
// send key
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
evt = getLastSentEvent(req1);
|
||||||
|
|
||||||
|
// send key
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
evt = getLastSentEvent(req2);
|
||||||
|
|
||||||
|
// receive last key
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
|
||||||
|
// compare emoji
|
||||||
|
expect(req1.state, KeyVerificationState.askSas);
|
||||||
|
expect(req2.state, KeyVerificationState.askSas);
|
||||||
|
expect(req1.sasTypes[0], 'emoji');
|
||||||
|
expect(req1.sasTypes[1], 'decimal');
|
||||||
|
expect(req2.sasTypes[0], 'emoji');
|
||||||
|
expect(req2.sasTypes[1], 'decimal');
|
||||||
|
// compare emoji
|
||||||
|
final emoji1 = req1.sasEmojis;
|
||||||
|
final emoji2 = req2.sasEmojis;
|
||||||
|
for (var i = 0; i < 7; i++) {
|
||||||
|
expect(emoji1[i].emoji, emoji2[i].emoji);
|
||||||
|
expect(emoji1[i].name, emoji2[i].name);
|
||||||
|
}
|
||||||
|
// compare numbers
|
||||||
|
final numbers1 = req1.sasNumbers;
|
||||||
|
final numbers2 = req2.sasNumbers;
|
||||||
|
for (var i = 0; i < 3; i++) {
|
||||||
|
expect(numbers1[i], numbers2[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// alright, they match
|
||||||
|
|
||||||
|
// send mac
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await req1.acceptSas();
|
||||||
|
evt = getLastSentEvent(req1);
|
||||||
|
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
expect(req1.state, KeyVerificationState.waitingSas);
|
||||||
|
|
||||||
|
// send mac
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await req2.acceptSas();
|
||||||
|
evt = getLastSentEvent(req2);
|
||||||
|
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
|
||||||
|
expect(req1.state, KeyVerificationState.done);
|
||||||
|
expect(req2.state, KeyVerificationState.done);
|
||||||
|
expect(
|
||||||
|
client1.userDeviceKeys[client2.userID].deviceKeys[client2.deviceID]
|
||||||
|
.directVerified,
|
||||||
|
true);
|
||||||
|
expect(
|
||||||
|
client2.userDeviceKeys[client1.userID].deviceKeys[client1.deviceID]
|
||||||
|
.directVerified,
|
||||||
|
true);
|
||||||
|
await client1.encryption.keyVerificationManager.cleanup();
|
||||||
|
await client2.encryption.keyVerificationManager.cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('ask SSSS start', () async {
|
||||||
|
client1.userDeviceKeys[client1.userID].masterKey.setDirectVerified(true);
|
||||||
|
await client1.database.clearSSSSCache(client1.id);
|
||||||
|
final req1 =
|
||||||
|
await client1.userDeviceKeys[client2.userID].startVerification();
|
||||||
|
expect(req1.state, KeyVerificationState.askSSSS);
|
||||||
|
await req1.openSSSS(recoveryKey: SSSS_KEY);
|
||||||
|
await Future.delayed(Duration(milliseconds: 10));
|
||||||
|
expect(req1.state, KeyVerificationState.waitingAccept);
|
||||||
|
|
||||||
|
await req1.cancel();
|
||||||
|
await client1.encryption.keyVerificationManager.cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('ask SSSS end', () async {
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
// make sure our master key is *not* verified to not triger SSSS for now
|
||||||
|
client1.userDeviceKeys[client1.userID].masterKey.setDirectVerified(false);
|
||||||
|
// the other one has to have their master key verified to trigger asking for ssss
|
||||||
|
client2.userDeviceKeys[client2.userID].masterKey.setDirectVerified(true);
|
||||||
|
final req1 =
|
||||||
|
await client1.userDeviceKeys[client2.userID].startVerification();
|
||||||
|
var evt = getLastSentEvent(req1);
|
||||||
|
expect(req1.state, KeyVerificationState.waitingAccept);
|
||||||
|
|
||||||
|
KeyVerification req2;
|
||||||
|
final sub = client2.onKeyVerificationRequest.stream.listen((req) {
|
||||||
|
req2 = req;
|
||||||
});
|
});
|
||||||
await keyVerification.handlePayload('m.key.verification.cancel', {
|
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
'code': 'm.user',
|
await Future.delayed(Duration(milliseconds: 10));
|
||||||
'reason': 'User rejected the key verification request',
|
await sub.cancel();
|
||||||
'transaction_id': 'S0meUniqueAndOpaqueString'
|
expect(req2 != null, true);
|
||||||
|
|
||||||
|
// send ready
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await req2.acceptVerification();
|
||||||
|
evt = getLastSentEvent(req2);
|
||||||
|
expect(req2.state, KeyVerificationState.waitingAccept);
|
||||||
|
|
||||||
|
// send start
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
evt = getLastSentEvent(req1);
|
||||||
|
|
||||||
|
// send accept
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
evt = getLastSentEvent(req2);
|
||||||
|
|
||||||
|
// send key
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
evt = getLastSentEvent(req1);
|
||||||
|
|
||||||
|
// send key
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
evt = getLastSentEvent(req2);
|
||||||
|
|
||||||
|
// receive last key
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
|
||||||
|
// compare emoji
|
||||||
|
expect(req1.state, KeyVerificationState.askSas);
|
||||||
|
expect(req2.state, KeyVerificationState.askSas);
|
||||||
|
// compare emoji
|
||||||
|
final emoji1 = req1.sasEmojis;
|
||||||
|
final emoji2 = req2.sasEmojis;
|
||||||
|
for (var i = 0; i < 7; i++) {
|
||||||
|
expect(emoji1[i].emoji, emoji2[i].emoji);
|
||||||
|
expect(emoji1[i].name, emoji2[i].name);
|
||||||
|
}
|
||||||
|
// compare numbers
|
||||||
|
final numbers1 = req1.sasNumbers;
|
||||||
|
final numbers2 = req2.sasNumbers;
|
||||||
|
for (var i = 0; i < 3; i++) {
|
||||||
|
expect(numbers1[i], numbers2[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// alright, they match
|
||||||
|
client1.userDeviceKeys[client1.userID].masterKey.setDirectVerified(true);
|
||||||
|
await client1.database.clearSSSSCache(client1.id);
|
||||||
|
|
||||||
|
// send mac
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await req1.acceptSas();
|
||||||
|
evt = getLastSentEvent(req1);
|
||||||
|
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
expect(req1.state, KeyVerificationState.waitingSas);
|
||||||
|
|
||||||
|
// send mac
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await req2.acceptSas();
|
||||||
|
evt = getLastSentEvent(req2);
|
||||||
|
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
|
||||||
|
expect(req1.state, KeyVerificationState.askSSSS);
|
||||||
|
expect(req2.state, KeyVerificationState.done);
|
||||||
|
|
||||||
|
await req1.openSSSS(recoveryKey: SSSS_KEY);
|
||||||
|
await Future.delayed(Duration(milliseconds: 10));
|
||||||
|
expect(req1.state, KeyVerificationState.done);
|
||||||
|
|
||||||
|
client1.encryption.ssss = MockSSSS(client1.encryption);
|
||||||
|
(client1.encryption.ssss as MockSSSS).requestedSecrets = false;
|
||||||
|
await client1.database.clearSSSSCache(client1.id);
|
||||||
|
await req1.maybeRequestSSSSSecrets();
|
||||||
|
await Future.delayed(Duration(milliseconds: 10));
|
||||||
|
expect((client1.encryption.ssss as MockSSSS).requestedSecrets, true);
|
||||||
|
// delay for 12 seconds to be sure no other tests clear the ssss cache
|
||||||
|
await Future.delayed(Duration(seconds: 12));
|
||||||
|
|
||||||
|
await client1.encryption.keyVerificationManager.cleanup();
|
||||||
|
await client2.encryption.keyVerificationManager.cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('reject verification', () async {
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
// make sure our master key is *not* verified to not triger SSSS for now
|
||||||
|
client1.userDeviceKeys[client1.userID].masterKey.setDirectVerified(false);
|
||||||
|
final req1 =
|
||||||
|
await client1.userDeviceKeys[client2.userID].startVerification();
|
||||||
|
var evt = getLastSentEvent(req1);
|
||||||
|
expect(req1.state, KeyVerificationState.waitingAccept);
|
||||||
|
|
||||||
|
KeyVerification req2;
|
||||||
|
final sub = client2.onKeyVerificationRequest.stream.listen((req) {
|
||||||
|
req2 = req;
|
||||||
});
|
});
|
||||||
|
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
await Future.delayed(Duration(milliseconds: 10));
|
||||||
|
await sub.cancel();
|
||||||
|
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await req2.rejectVerification();
|
||||||
|
evt = getLastSentEvent(req2);
|
||||||
|
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
expect(req1.state, KeyVerificationState.error);
|
||||||
|
expect(req2.state, KeyVerificationState.error);
|
||||||
|
|
||||||
|
await client1.encryption.keyVerificationManager.cleanup();
|
||||||
|
await client2.encryption.keyVerificationManager.cleanup();
|
||||||
});
|
});
|
||||||
test('rejectSas', () async {
|
|
||||||
await keyVerification.rejectSas();
|
test('reject sas', () async {
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
// make sure our master key is *not* verified to not triger SSSS for now
|
||||||
|
client1.userDeviceKeys[client1.userID].masterKey.setDirectVerified(false);
|
||||||
|
final req1 =
|
||||||
|
await client1.userDeviceKeys[client2.userID].startVerification();
|
||||||
|
var evt = getLastSentEvent(req1);
|
||||||
|
expect(req1.state, KeyVerificationState.waitingAccept);
|
||||||
|
|
||||||
|
KeyVerification req2;
|
||||||
|
final sub = client2.onKeyVerificationRequest.stream.listen((req) {
|
||||||
|
req2 = req;
|
||||||
|
});
|
||||||
|
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
await Future.delayed(Duration(milliseconds: 10));
|
||||||
|
await sub.cancel();
|
||||||
|
expect(req2 != null, true);
|
||||||
|
|
||||||
|
// send ready
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await req2.acceptVerification();
|
||||||
|
evt = getLastSentEvent(req2);
|
||||||
|
expect(req2.state, KeyVerificationState.waitingAccept);
|
||||||
|
|
||||||
|
// send start
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
evt = getLastSentEvent(req1);
|
||||||
|
|
||||||
|
// send accept
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
evt = getLastSentEvent(req2);
|
||||||
|
|
||||||
|
// send key
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
evt = getLastSentEvent(req1);
|
||||||
|
|
||||||
|
// send key
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
evt = getLastSentEvent(req2);
|
||||||
|
|
||||||
|
// receive last key
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
|
||||||
|
await req1.acceptSas();
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
await req2.rejectSas();
|
||||||
|
evt = getLastSentEvent(req2);
|
||||||
|
await client1.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
expect(req1.state, KeyVerificationState.error);
|
||||||
|
expect(req2.state, KeyVerificationState.error);
|
||||||
|
|
||||||
|
await client1.encryption.keyVerificationManager.cleanup();
|
||||||
|
await client2.encryption.keyVerificationManager.cleanup();
|
||||||
});
|
});
|
||||||
test('rejectVerification', () async {
|
|
||||||
await keyVerification.rejectVerification();
|
test('other device accepted', () async {
|
||||||
});
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
test('start', () async {
|
// make sure our master key is *not* verified to not triger SSSS for now
|
||||||
await keyVerification.start();
|
client1.userDeviceKeys[client1.userID].masterKey.setDirectVerified(false);
|
||||||
});
|
final req1 =
|
||||||
test('verifyActivity', () async {
|
await client1.userDeviceKeys[client2.userID].startVerification();
|
||||||
final verified = await keyVerification.verifyActivity();
|
var evt = getLastSentEvent(req1);
|
||||||
expect(verified, true);
|
expect(req1.state, KeyVerificationState.waitingAccept);
|
||||||
keyVerification?.dispose();
|
|
||||||
|
KeyVerification req2;
|
||||||
|
final sub = client2.onKeyVerificationRequest.stream.listen((req) {
|
||||||
|
req2 = req;
|
||||||
|
});
|
||||||
|
await client2.encryption.keyVerificationManager.handleEventUpdate(evt);
|
||||||
|
await Future.delayed(Duration(milliseconds: 10));
|
||||||
|
await sub.cancel();
|
||||||
|
expect(req2 != null, true);
|
||||||
|
|
||||||
|
await client2.encryption.keyVerificationManager
|
||||||
|
.handleEventUpdate(EventUpdate(
|
||||||
|
content: {
|
||||||
|
'event_id': req2.transactionId,
|
||||||
|
'type': 'm.key.verification.ready',
|
||||||
|
'content': {
|
||||||
|
'methods': ['m.sas.v1'],
|
||||||
|
'from_device': 'SOMEOTHERDEVICE',
|
||||||
|
'm.relates_to': {
|
||||||
|
'rel_type': 'm.reference',
|
||||||
|
'event_id': req2.transactionId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
|
||||||
|
'sender': client2.userID,
|
||||||
|
},
|
||||||
|
eventType: 'm.key.verification.ready',
|
||||||
|
type: 'timeline',
|
||||||
|
roomID: req2.room.id,
|
||||||
|
));
|
||||||
|
expect(req2.state, KeyVerificationState.error);
|
||||||
|
|
||||||
|
await req2.cancel();
|
||||||
|
await client1.encryption.keyVerificationManager.cleanup();
|
||||||
|
await client2.encryption.keyVerificationManager.cleanup();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('dispose client', () async {
|
test('dispose client', () async {
|
||||||
await client.dispose(closeDatabase: true);
|
await client1.dispose(closeDatabase: true);
|
||||||
|
await client2.dispose(closeDatabase: true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,11 @@ class FakeMatrixApi extends MockClient {
|
||||||
action.contains('/state/m.room.member/')) {
|
action.contains('/state/m.room.member/')) {
|
||||||
res = {'displayname': ''};
|
res = {'displayname': ''};
|
||||||
return Response(json.encode(res), 200);
|
return Response(json.encode(res), 200);
|
||||||
|
} else if (method == 'PUT' &&
|
||||||
|
action.contains(
|
||||||
|
'/client/r0/rooms/%211234%3AfakeServer.notExisting/send/')) {
|
||||||
|
res = {'event_id': '\$event${FakeMatrixApi.eventCounter++}'};
|
||||||
|
return Response(json.encode(res), 200);
|
||||||
} else {
|
} else {
|
||||||
res = {
|
res = {
|
||||||
'errcode': 'M_UNRECOGNIZED',
|
'errcode': 'M_UNRECOGNIZED',
|
||||||
|
@ -2008,6 +2013,10 @@ class FakeMatrixApi extends MockClient {
|
||||||
(var req) => {},
|
(var req) => {},
|
||||||
'/client/r0/user/%40alice%3Aexample.com/rooms/1234/account_data/test.account.data':
|
'/client/r0/user/%40alice%3Aexample.com/rooms/1234/account_data/test.account.data':
|
||||||
(var req) => {},
|
(var req) => {},
|
||||||
|
'/client/r0/user/%40test%3AfakeServer.notExisting/account_data/m.direct':
|
||||||
|
(var req) => {},
|
||||||
|
'/client/r0/user/%40othertest%3AfakeServer.notExisting/account_data/m.direct':
|
||||||
|
(var req) => {},
|
||||||
'/client/r0/profile/%40alice%3Aexample.com/displayname': (var reqI) => {},
|
'/client/r0/profile/%40alice%3Aexample.com/displayname': (var reqI) => {},
|
||||||
'/client/r0/profile/%40alice%3Aexample.com/avatar_url': (var reqI) => {},
|
'/client/r0/profile/%40alice%3Aexample.com/avatar_url': (var reqI) => {},
|
||||||
'/client/r0/profile/%40test%3AfakeServer.notExisting/avatar_url':
|
'/client/r0/profile/%40test%3AfakeServer.notExisting/avatar_url':
|
||||||
|
|
Loading…
Reference in a new issue