add more tests

This commit is contained in:
Sorunome 2020-06-13 10:56:39 +02:00
parent 34619c065b
commit 7803dc4b93
No known key found for this signature in database
GPG key ID: B19471D07FC9BE9C
5 changed files with 330 additions and 4 deletions

View file

@ -405,8 +405,7 @@ class KeyManager {
try { try {
await loadSingleKey(room.id, sessionId); await loadSingleKey(room.id, sessionId);
} catch (err, stacktrace) { } catch (err, stacktrace) {
print('++++++++++++++++++'); print('[KeyManager] Failed to access online key backup: ' + err.toString());
print(err.toString());
print(stacktrace); print(stacktrace);
} }
if (!hadPreviously && if (!hadPreviously &&

View file

@ -127,7 +127,7 @@ void main() {
} }
expect(sync.nextBatch == matrix.prevBatch, true); expect(sync.nextBatch == matrix.prevBatch, true);
expect(matrix.accountData.length, 3); expect(matrix.accountData.length, 9);
expect(matrix.getDirectChatFromUserId('@bob:example.com'), expect(matrix.getDirectChatFromUserId('@bob:example.com'),
'!726s6s6q:example.com'); '!726s6s6q:example.com');
expect(matrix.rooms[1].directChatMatrixID, '@bob:example.com'); expect(matrix.rooms[1].directChatMatrixID, '@bob:example.com');
@ -157,7 +157,7 @@ void main() {
expect(matrix.presences['@alice:example.com'].presence.presence, expect(matrix.presences['@alice:example.com'].presence.presence,
PresenceType.online); PresenceType.online);
expect(presenceCounter, 1); expect(presenceCounter, 1);
expect(accountDataCounter, 3); expect(accountDataCounter, 9);
await Future.delayed(Duration(milliseconds: 50)); await Future.delayed(Duration(milliseconds: 50));
expect(matrix.userDeviceKeys.length, 4); expect(matrix.userDeviceKeys.length, 4);
expect(matrix.userDeviceKeys['@alice:example.com'].outdated, false); expect(matrix.userDeviceKeys['@alice:example.com'].outdated, false);

View file

@ -0,0 +1,207 @@
/*
* Ansible inventory script used at Famedly GmbH for managing many hosts
* Copyright (C) 2020 Famedly GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import 'dart:typed_data';
import 'dart:convert';
import 'package:famedlysdk/famedlysdk.dart';
import 'package:famedlysdk/matrix_api.dart';
import 'package:famedlysdk/encryption.dart';
import 'package:test/test.dart';
import 'package:encrypt/encrypt.dart';
import 'package:olm/olm.dart' as olm;
import '../fake_client.dart';
import '../fake_matrix_api.dart';
void main() {
group('SSSS', () {
var olmEnabled = true;
try {
olm.init();
olm.Account();
} catch (_) {
olmEnabled = false;
print('[LibOlm] Failed to load LibOlm: ' + _.toString());
}
print('[LibOlm] Enabled: $olmEnabled');
if (!olmEnabled) return;
Client client;
test('setupClient', () async {
client = await getClient();
});
test('basic things', () async {
expect(client.encryption.ssss.defaultKeyId, '0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3');
});
test('encrypt / decrypt', () {
final signing = olm.PkSigning();
final key = Uint8List.fromList(SecureRandom(32).bytes);
final enc = SSSS.encryptAes('secret foxies', key, 'name');
final dec = SSSS.decryptAes(enc, key, 'name');
expect(dec, 'secret foxies');
});
test('store', () async {
final handle = client.encryption.ssss.open();
var failed = false;
try {
handle.unlock(passphrase: 'invalid');
} catch (_) {
failed = true;
}
expect(failed, true);
expect(handle.isUnlocked, false);
failed = false;
try {
handle.unlock(recoveryKey: 'invalid');
} catch (_) {
failed = true;
}
expect(failed, true);
expect(handle.isUnlocked, false);
handle.unlock(passphrase: SSSS_PASSPHRASE);
handle.unlock(recoveryKey: SSSS_KEY);
expect(handle.isUnlocked, true);
FakeMatrixApi.calledEndpoints.clear();
await handle.store('best animal', 'foxies');
// alright, since we don't properly sync we will manually have to update
// account_data for this test
final content = FakeMatrixApi.calledEndpoints['/client/r0/user/%40test%3AfakeServer.notExisting/account_data/best+animal'].first;
client.accountData['best animal'] = BasicEvent.fromJson({
'type': 'best animal',
'content': json.decode(content),
});
expect(await handle.getStored('best animal'), 'foxies');
});
test('cache', () async {
final handle = client.encryption.ssss.open('m.cross_signing.self_signing');
handle.unlock(recoveryKey: SSSS_KEY);
expect((await client.encryption.ssss.getCached('m.cross_signing.self_signing')) != null, false);
expect((await client.encryption.ssss.getCached('m.cross_signing.user_signing')) != null, false);
await handle.getStored('m.cross_signing.self_signing');
expect((await client.encryption.ssss.getCached('m.cross_signing.self_signing')) != null, true);
await handle.maybeCacheAll();
expect((await client.encryption.ssss.getCached('m.cross_signing.user_signing')) != null, true);
expect((await client.encryption.ssss.getCached('m.megolm_backup.v1')) != null, true);
});
test('make share requests', () async {
final key = client.userDeviceKeys[client.userID].deviceKeys['OTHERDEVICE'];
key.setDirectVerified(true);
FakeMatrixApi.calledEndpoints.clear();
await client.encryption.ssss.request('some.type', [key]);
expect(FakeMatrixApi.calledEndpoints.keys.any((k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')), true);
});
test('answer to share requests', () async {
var event = ToDeviceEvent(
sender: client.userID,
type: 'm.secret.request',
content: {
'action': 'request',
'requesting_device_id': 'OTHERDEVICE',
'name': 'm.cross_signing.self_signing',
'request_id': '1',
},
);
FakeMatrixApi.calledEndpoints.clear();
await client.encryption.ssss.handleToDeviceEvent(event);
expect(FakeMatrixApi.calledEndpoints.keys.any((k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')), true);
// now test some fail scenarios
// not by us
event = ToDeviceEvent(
sender: '@someotheruser:example.org',
type: 'm.secret.request',
content: {
'action': 'request',
'requesting_device_id': 'OTHERDEVICE',
'name': 'm.cross_signing.self_signing',
'request_id': '1',
},
);
FakeMatrixApi.calledEndpoints.clear();
await client.encryption.ssss.handleToDeviceEvent(event);
expect(FakeMatrixApi.calledEndpoints.keys.any((k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')), false);
// secret not cached
event = ToDeviceEvent(
sender: client.userID,
type: 'm.secret.request',
content: {
'action': 'request',
'requesting_device_id': 'OTHERDEVICE',
'name': 'm.unknown.secret',
'request_id': '1',
},
);
FakeMatrixApi.calledEndpoints.clear();
await client.encryption.ssss.handleToDeviceEvent(event);
expect(FakeMatrixApi.calledEndpoints.keys.any((k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')), false);
// is a cancelation
event = ToDeviceEvent(
sender: client.userID,
type: 'm.secret.request',
content: {
'action': 'request_cancellation',
'requesting_device_id': 'OTHERDEVICE',
'name': 'm.cross_signing.self_signing',
'request_id': '1',
},
);
FakeMatrixApi.calledEndpoints.clear();
await client.encryption.ssss.handleToDeviceEvent(event);
expect(FakeMatrixApi.calledEndpoints.keys.any((k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')), false);
// device not verified
final key = client.userDeviceKeys[client.userID].deviceKeys['OTHERDEVICE'];
key.setDirectVerified(false);
event = ToDeviceEvent(
sender: client.userID,
type: 'm.secret.request',
content: {
'action': 'request',
'requesting_device_id': 'OTHERDEVICE',
'name': 'm.cross_signing.self_signing',
'request_id': '1',
},
);
FakeMatrixApi.calledEndpoints.clear();
await client.encryption.ssss.handleToDeviceEvent(event);
expect(FakeMatrixApi.calledEndpoints.keys.any((k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')), false);
key.setDirectVerified(true);
});
// test('fail', () {
// expect(true, false);
// });
test('dispose client', () async {
await client.dispose(closeDatabase: true);
});
});
}

View file

@ -21,6 +21,9 @@ import 'package:famedlysdk/famedlysdk.dart';
import 'fake_matrix_api.dart'; import 'fake_matrix_api.dart';
import 'fake_database.dart'; import 'fake_database.dart';
const SSSS_PASSPHRASE = 'nae7ahDiequ7ohniufah3ieS2je1thohX4xeeka7aixohsho9O';
const SSSS_KEY = 'EsT9 RzbW VhPW yqNp cC7j ViiW 5TZB LuY4 ryyv 9guN Ysmr WDPH';
// key @test:fakeServer.notExisting // key @test:fakeServer.notExisting
const pickledOlmAccount = const pickledOlmAccount =
'N2v1MkIFGcl0mQpo2OCwSopxPQJ0wnl7oe7PKiT4141AijfdTIhRu+ceXzXKy3Kr00nLqXtRv7kid6hU4a+V0rfJWLL0Y51+3Rp/ORDVnQy+SSeo6Fn4FHcXrxifJEJ0djla5u98fBcJ8BSkhIDmtXRPi5/oJAvpiYn+8zMjFHobOeZUAxYR0VfQ9JzSYBsSovoQ7uFkNks1M4EDUvHtuyg3RxViwdNxs3718fyAqQ/VSwbXsY0Nl+qQbF+nlVGHenGqk5SuNl1P6e1PzZxcR0IfXA94Xij1Ob5gDv5YH4UCn9wRMG0abZsQP0YzpDM0FLaHSCyo9i5JD/vMlhH+nZWrgAzPPCTNGYewNV8/h3c+VyJh8ZTx/fVi6Yq46Fv+27Ga2ETRZ3Qn+Oyx6dLBjnBZ9iUvIhqpe2XqaGA1PopOz8iDnaZitw'; 'N2v1MkIFGcl0mQpo2OCwSopxPQJ0wnl7oe7PKiT4141AijfdTIhRu+ceXzXKy3Kr00nLqXtRv7kid6hU4a+V0rfJWLL0Y51+3Rp/ORDVnQy+SSeo6Fn4FHcXrxifJEJ0djla5u98fBcJ8BSkhIDmtXRPi5/oJAvpiYn+8zMjFHobOeZUAxYR0VfQ9JzSYBsSovoQ7uFkNks1M4EDUvHtuyg3RxViwdNxs3718fyAqQ/VSwbXsY0Nl+qQbF+nlVGHenGqk5SuNl1P6e1PzZxcR0IfXA94Xij1Ob5gDv5YH4UCn9wRMG0abZsQP0YzpDM0FLaHSCyo9i5JD/vMlhH+nZWrgAzPPCTNGYewNV8/h3c+VyJh8ZTx/fVi6Yq46Fv+27Ga2ETRZ3Qn+Oyx6dLBjnBZ9iUvIhqpe2XqaGA1PopOz8iDnaZitw';

View file

@ -516,6 +516,71 @@ class FakeMatrixApi extends MockClient {
}, },
'type': 'm.direct' 'type': 'm.direct'
}, },
{
'type': 'm.secret_storage.default_key',
'content': {'key': '0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3'}
},
{
'type': 'm.secret_storage.key.0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3',
'content': {
'algorithm': 'm.secret_storage.v1.aes-hmac-sha2',
'passphrase': {
'algorithm': 'm.pbkdf2',
'iterations': 500000,
'salt': 'F4jJ80mr0Fc8mRwU9JgA3lQDyjPuZXQL'
},
'iv': 'HjbTgIoQH2pI7jQo19NUzA==',
'mac': 'QbJjQzDnAggU0cM4RBnDxw2XyarRGjdahcKukP9xVlk='
}
},
{
'type': 'm.cross_signing.master',
'content': {
'encrypted': {
'0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3': {
'iv': 'eIb2IITxtmcq+1TrT8D5eQ==',
'ciphertext': 'lWRTPo5qxf4LAVwVPzGHOyMcP181n7bb9/B0lvkLDC2Oy4DvAL0eLx2x3bY=',
'mac': 'Ynx89tIxPkx0o6ljMgxszww17JOgB4tg4etmNnMC9XI='
}
}
}
},
{
'type': 'm.cross_signing.self_signing',
'content': {
'encrypted': {
'0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3': {
'iv': 'YqU2XIjYulYZl+bkZtGgVw==',
'ciphertext': 'kM2TSoy/jR/4d357ZoRPbpPypxQl6XRLo3FsEXz+f7vIOp82GeRp28RYb3k=',
'mac': 'F+DZa5tAFmWsYSryw5EuEpzTmmABRab4GETkM85bGGo='
}
}
}
},
{
'type': 'm.cross_signing.user_signing',
'content': {
'encrypted': {
'0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3': {
'iv': 'D7AM3LXFu7ZlyGOkR+OeqQ==',
'ciphertext': 'bYA2+OMgsO6QB1E31aY+ESAWrT0fUBTXqajy4qmL7bVDSZY4Uj64EXNbHuA=',
'mac': 'j2UtyPo/UBSoiaQCWfzCiRZXp3IRt0ZZujuXgUMjnw4='
}
}
}
},
{
'type': 'm.megolm_backup.v1',
'content': {
'encrypted': {
'0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3': {
'iv': 'cL/0MJZaiEd3fNU+I9oJrw==',
'ciphertext': 'WL73Pzdk5wZdaaSpaeRH0uZYKcxkuV8IS6Qa2FEfA1+vMeRLuHcWlXbMX0w=',
'mac': '+xozp909S6oDX8KRV8D8ZFVRyh7eEYQpPP76f+DOsnw='
}
}
}
}
] ]
}, },
'to_device': { 'to_device': {
@ -1461,6 +1526,13 @@ class FakeMatrixApi extends MockClient {
'event_format': 'client', 'event_format': 'client',
'event_fields': ['type', 'content', 'sender'] 'event_fields': ['type', 'content', 'sender']
}, },
'/client/unstable/room_keys/version': (var req) => {
'algorithm': 'm.megolm_backup.v1.curve25519-aes-sha2',
'auth_data': {'public_key': 'GXYaxqhNhUK28zUdxOmEsFRguz+PzBsDlTLlF0O0RkM'},
'count': 0,
'etag': '0',
'version': '5',
},
}, },
'POST': { 'POST': {
'/client/r0/delete_devices': (var req) => {}, '/client/r0/delete_devices': (var req) => {},
@ -1673,6 +1745,19 @@ class FakeMatrixApi extends MockClient {
}, },
'signatures': {}, 'signatures': {},
}, },
'OTHERDEVICE': {
'user_id': '@test:fakeServer.notExisting',
'device_id': 'OTHERDEVICE',
'algorithms': [
'm.olm.v1.curve25519-aes-sha2',
'm.megolm.v1.aes-sha2'
],
'keys': {
'curve25519:OTHERDEVICE': 'blah',
'ed25519:OTHERDEVICE': 'blah'
},
'signatures': {},
},
}, },
'@othertest:fakeServer.notExisting': { '@othertest:fakeServer.notExisting': {
'FOXDEVICE': { 'FOXDEVICE': {
@ -1692,6 +1777,36 @@ class FakeMatrixApi extends MockClient {
}, },
}, },
}, },
'master_keys': {
'@test:fakeServer.notExisting': {
'user_id': '@test:fakeServer.notExisting',
'usage': ['master'],
'keys': {
'ed25519:82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8': '82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8',
},
'signatures': {},
},
},
'self_signing_keys': {
'@test:fakeServer.notExisting': {
'user_id': '@test:fakeServer.notExisting',
'usage': ['self_signing'],
'keys': {
'ed25519:F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY': 'F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY',
},
'signatures': {},
},
},
'user_signing_keys': {
'@test:fakeServer.notExisting': {
'user_id': '@test:fakeServer.notExisting',
'usage': ['user_signing'],
'keys': {
'ed25519:0PiwulzJ/RU86LlzSSZ8St80HUMN3dqjKa/orIJoA0g': '0PiwulzJ/RU86LlzSSZ8St80HUMN3dqjKa/orIJoA0g',
},
'signatures': {},
},
},
}, },
'/client/r0/register': (var req) => { '/client/r0/register': (var req) => {
'user_id': '@testuser:example.com', 'user_id': '@testuser:example.com',
@ -1783,6 +1898,8 @@ class FakeMatrixApi extends MockClient {
(var req) => {}, (var req) => {},
'/client/r0/user/%40alice%3Aexample.com/account_data/test.account.data': '/client/r0/user/%40alice%3Aexample.com/account_data/test.account.data':
(var req) => {}, (var req) => {},
'/client/r0/user/%40test%3AfakeServer.notExisting/account_data/best+animal':
(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/profile/%40alice%3Aexample.com/displayname': (var reqI) => {}, '/client/r0/profile/%40alice%3Aexample.com/displayname': (var reqI) => {},