finish ssss tests

This commit is contained in:
Sorunome 2020-06-13 18:10:24 +02:00
parent 7803dc4b93
commit e0251eda55
No known key found for this signature in database
GPG key ID: B19471D07FC9BE9C
5 changed files with 373 additions and 162 deletions

View file

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

View file

@ -5850,6 +5850,15 @@ abstract class _$Database extends GeneratedDatabase {
readsFrom: {ssssCache}).map(_rowToDbSSSSCache); readsFrom: {ssssCache}).map(_rowToDbSSSSCache);
} }
Future<int> clearSSSSCache(int client_id) {
return customUpdate(
'DELETE FROM ssss_cache WHERE client_id = :client_id',
variables: [Variable.withInt(client_id)],
updates: {ssssCache},
updateKind: UpdateKind.delete,
);
}
Future<int> insertClient( Future<int> insertClient(
String name, String name,
String homeserver_url, String homeserver_url,

View file

@ -198,6 +198,7 @@ storeUserCrossSigningKey: INSERT OR REPLACE INTO user_cross_signing_keys (client
removeUserCrossSigningKey: DELETE FROM user_cross_signing_keys WHERE client_id = :client_id AND user_id = :user_id AND public_key = :public_key; removeUserCrossSigningKey: DELETE FROM user_cross_signing_keys WHERE client_id = :client_id AND user_id = :user_id AND public_key = :public_key;
storeSSSSCache: INSERT OR REPLACE INTO ssss_cache (client_id, type, key_id, ciphertext, content) VALUES (:client_id, :type, :key_id, :ciphertext, :content); storeSSSSCache: INSERT OR REPLACE INTO ssss_cache (client_id, type, key_id, ciphertext, content) VALUES (:client_id, :type, :key_id, :ciphertext, :content);
dbGetSSSSCache: SELECT * FROM ssss_cache WHERE client_id = :client_id AND type = :type; dbGetSSSSCache: SELECT * FROM ssss_cache WHERE client_id = :client_id AND type = :type;
clearSSSSCache: DELETE FROM ssss_cache WHERE client_id = :client_id;
insertClient: INSERT INTO clients (name, homeserver_url, token, user_id, device_id, device_name, prev_batch, olm_account) VALUES (:name, :homeserver_url, :token, :user_id, :device_id, :device_name, :prev_batch, :olm_account); insertClient: INSERT INTO clients (name, homeserver_url, token, user_id, device_id, device_name, prev_batch, olm_account) VALUES (:name, :homeserver_url, :token, :user_id, :device_id, :device_name, :prev_batch, :olm_account);
ensureRoomExists: INSERT OR IGNORE INTO rooms (client_id, room_id, membership) VALUES (:client_id, :room_id, :membership); ensureRoomExists: INSERT OR IGNORE INTO rooms (client_id, room_id, membership) VALUES (:client_id, :room_id, :membership);
setRoomPrevBatch: UPDATE rooms SET prev_batch = :prev_batch WHERE client_id = :client_id AND room_id = :room_id; setRoomPrevBatch: UPDATE rooms SET prev_batch = :prev_batch WHERE client_id = :client_id AND room_id = :room_id;

View file

@ -32,176 +32,367 @@ import '../fake_matrix_api.dart';
void main() { void main() {
group('SSSS', () { group('SSSS', () {
var olmEnabled = true; 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 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 { try {
olm.init(); handle.unlock(passphrase: 'invalid');
olm.Account();
} catch (_) { } catch (_) {
olmEnabled = false; failed = true;
print('[LibOlm] Failed to load LibOlm: ' + _.toString());
} }
print('[LibOlm] Enabled: $olmEnabled'); expect(failed, true);
expect(handle.isUnlocked, false);
if (!olmEnabled) return; failed = false;
try {
Client client; handle.unlock(recoveryKey: 'invalid');
} catch (_) {
test('setupClient', () async { failed = true;
client = await getClient(); }
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('basic things', () async { test('cache', () async {
expect(client.encryption.ssss.defaultKeyId, '0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3'); 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('encrypt / decrypt', () { test('make share requests', () async {
final signing = olm.PkSigning(); final key =
final key = Uint8List.fromList(SecureRandom(32).bytes); 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);
});
final enc = SSSS.encryptAes('secret foxies', key, 'name'); test('answer to share requests', () async {
final dec = SSSS.decryptAes(enc, key, 'name'); var event = ToDeviceEvent(
expect(dec, 'secret foxies'); 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);
test('store', () async { // now test some fail scenarios
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 { // not by us
final handle = client.encryption.ssss.open('m.cross_signing.self_signing'); event = ToDeviceEvent(
handle.unlock(recoveryKey: SSSS_KEY); sender: '@someotheruser:example.org',
expect((await client.encryption.ssss.getCached('m.cross_signing.self_signing')) != null, false); type: 'm.secret.request',
expect((await client.encryption.ssss.getCached('m.cross_signing.user_signing')) != null, false); content: {
await handle.getStored('m.cross_signing.self_signing'); 'action': 'request',
expect((await client.encryption.ssss.getCached('m.cross_signing.self_signing')) != null, true); 'requesting_device_id': 'OTHERDEVICE',
await handle.maybeCacheAll(); 'name': 'm.cross_signing.self_signing',
expect((await client.encryption.ssss.getCached('m.cross_signing.user_signing')) != null, true); 'request_id': '1',
expect((await client.encryption.ssss.getCached('m.megolm_backup.v1')) != null, true); },
}); );
FakeMatrixApi.calledEndpoints.clear();
await client.encryption.ssss.handleToDeviceEvent(event);
expect(
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),
false);
test('make share requests', () async { // secret not cached
final key = client.userDeviceKeys[client.userID].deviceKeys['OTHERDEVICE']; event = ToDeviceEvent(
key.setDirectVerified(true); sender: client.userID,
FakeMatrixApi.calledEndpoints.clear(); type: 'm.secret.request',
await client.encryption.ssss.request('some.type', [key]); content: {
expect(FakeMatrixApi.calledEndpoints.keys.any((k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')), true); '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);
test('answer to share requests', () async { // is a cancelation
var event = ToDeviceEvent( event = ToDeviceEvent(
sender: client.userID, sender: client.userID,
type: 'm.secret.request', type: 'm.secret.request',
content: { content: {
'action': 'request', 'action': 'request_cancellation',
'requesting_device_id': 'OTHERDEVICE', 'requesting_device_id': 'OTHERDEVICE',
'name': 'm.cross_signing.self_signing', 'name': 'm.cross_signing.self_signing',
'request_id': '1', 'request_id': '1',
}, },
); );
FakeMatrixApi.calledEndpoints.clear(); FakeMatrixApi.calledEndpoints.clear();
await client.encryption.ssss.handleToDeviceEvent(event); await client.encryption.ssss.handleToDeviceEvent(event);
expect(FakeMatrixApi.calledEndpoints.keys.any((k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')), true); expect(
FakeMatrixApi.calledEndpoints.keys.any(
(k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')),
false);
// now test some fail scenarios // 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);
});
// not by us test('receive share requests', () async {
event = ToDeviceEvent( final key =
sender: '@someotheruser:example.org', client.userDeviceKeys[client.userID].deviceKeys['OTHERDEVICE'];
type: 'm.secret.request', key.setDirectVerified(true);
content: { final handle =
'action': 'request', client.encryption.ssss.open('m.cross_signing.self_signing');
'requesting_device_id': 'OTHERDEVICE', handle.unlock(recoveryKey: SSSS_KEY);
'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 await client.database.clearSSSSCache(client.id);
client.encryption.ssss.pendingShareRequests.clear();
await client.encryption.ssss.request('best animal', [key]);
var event = ToDeviceEvent(
sender: client.userID,
type: 'm.secret.send',
content: {
'request_id': client.encryption.ssss.pendingShareRequests.keys.first,
'secret': 'foxies!',
},
encryptedContent: {
'sender_key': key.curve25519Key,
},
);
await client.encryption.ssss.handleToDeviceEvent(event);
expect(await client.encryption.ssss.getCached('best animal'), 'foxies!');
// test the different validators
for (final type in [
'm.cross_signing.self_signing',
'm.cross_signing.user_signing',
'm.megolm_backup.v1'
]) {
final secret = await handle.getStored(type);
await client.database.clearSSSSCache(client.id);
client.encryption.ssss.pendingShareRequests.clear();
await client.encryption.ssss.request(type, [key]);
event = ToDeviceEvent( event = ToDeviceEvent(
sender: client.userID, sender: client.userID,
type: 'm.secret.request', type: 'm.secret.send',
content: { content: {
'action': 'request', 'request_id':
'requesting_device_id': 'OTHERDEVICE', client.encryption.ssss.pendingShareRequests.keys.first,
'name': 'm.unknown.secret', 'secret': secret,
'request_id': '1', },
encryptedContent: {
'sender_key': key.curve25519Key,
}, },
); );
FakeMatrixApi.calledEndpoints.clear();
await client.encryption.ssss.handleToDeviceEvent(event); await client.encryption.ssss.handleToDeviceEvent(event);
expect(FakeMatrixApi.calledEndpoints.keys.any((k) => k.startsWith('/client/r0/sendToDevice/m.room.encrypted')), false); expect(await client.encryption.ssss.getCached(type), secret);
}
// is a cancelation // test different fail scenarios
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 // not encrypted
final key = client.userDeviceKeys[client.userID].deviceKeys['OTHERDEVICE']; await client.database.clearSSSSCache(client.id);
key.setDirectVerified(false); client.encryption.ssss.pendingShareRequests.clear();
event = ToDeviceEvent( await client.encryption.ssss.request('best animal', [key]);
sender: client.userID, event = ToDeviceEvent(
type: 'm.secret.request', sender: client.userID,
content: { type: 'm.secret.send',
'action': 'request', content: {
'requesting_device_id': 'OTHERDEVICE', 'request_id': client.encryption.ssss.pendingShareRequests.keys.first,
'name': 'm.cross_signing.self_signing', 'secret': 'foxies!',
'request_id': '1', },
}, );
); await client.encryption.ssss.handleToDeviceEvent(event);
FakeMatrixApi.calledEndpoints.clear(); expect(await client.encryption.ssss.getCached('best animal'), null);
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', () { // unknown request id
// expect(true, false); await client.database.clearSSSSCache(client.id);
// }); client.encryption.ssss.pendingShareRequests.clear();
await client.encryption.ssss.request('best animal', [key]);
event = ToDeviceEvent(
sender: client.userID,
type: 'm.secret.send',
content: {
'request_id': 'invalid',
'secret': 'foxies!',
},
encryptedContent: {
'sender_key': key.curve25519Key,
},
);
await client.encryption.ssss.handleToDeviceEvent(event);
expect(await client.encryption.ssss.getCached('best animal'), null);
test('dispose client', () async { // not from a device we sent the request to
await client.dispose(closeDatabase: true); await client.database.clearSSSSCache(client.id);
}); client.encryption.ssss.pendingShareRequests.clear();
await client.encryption.ssss.request('best animal', [key]);
event = ToDeviceEvent(
sender: client.userID,
type: 'm.secret.send',
content: {
'request_id': client.encryption.ssss.pendingShareRequests.keys.first,
'secret': 'foxies!',
},
encryptedContent: {
'sender_key': 'invalid',
},
);
await client.encryption.ssss.handleToDeviceEvent(event);
expect(await client.encryption.ssss.getCached('best animal'), null);
// secret not a string
await client.database.clearSSSSCache(client.id);
client.encryption.ssss.pendingShareRequests.clear();
await client.encryption.ssss.request('best animal', [key]);
event = ToDeviceEvent(
sender: client.userID,
type: 'm.secret.send',
content: {
'request_id': client.encryption.ssss.pendingShareRequests.keys.first,
'secret': 42,
},
encryptedContent: {
'sender_key': key.curve25519Key,
},
);
await client.encryption.ssss.handleToDeviceEvent(event);
expect(await client.encryption.ssss.getCached('best animal'), null);
// validator doesn't check out
await client.database.clearSSSSCache(client.id);
client.encryption.ssss.pendingShareRequests.clear();
await client.encryption.ssss.request('m.megolm_backup.v1', [key]);
event = ToDeviceEvent(
sender: client.userID,
type: 'm.secret.send',
content: {
'request_id': client.encryption.ssss.pendingShareRequests.keys.first,
'secret': 'foxies!',
},
encryptedContent: {
'sender_key': key.curve25519Key,
},
);
await client.encryption.ssss.handleToDeviceEvent(event);
expect(
await client.encryption.ssss.getCached('m.megolm_backup.v1'), null);
});
test('request all', () async {
final key =
client.userDeviceKeys[client.userID].deviceKeys['OTHERDEVICE'];
key.setDirectVerified(true);
await client.database.clearSSSSCache(client.id);
client.encryption.ssss.pendingShareRequests.clear();
await client.encryption.ssss.maybeRequestAll([key]);
expect(client.encryption.ssss.pendingShareRequests.length, 3);
});
test('dispose client', () async {
await client.dispose(closeDatabase: true);
});
}); });
} }

View file

@ -539,7 +539,8 @@ class FakeMatrixApi extends MockClient {
'encrypted': { 'encrypted': {
'0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3': { '0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3': {
'iv': 'eIb2IITxtmcq+1TrT8D5eQ==', 'iv': 'eIb2IITxtmcq+1TrT8D5eQ==',
'ciphertext': 'lWRTPo5qxf4LAVwVPzGHOyMcP181n7bb9/B0lvkLDC2Oy4DvAL0eLx2x3bY=', 'ciphertext':
'lWRTPo5qxf4LAVwVPzGHOyMcP181n7bb9/B0lvkLDC2Oy4DvAL0eLx2x3bY=',
'mac': 'Ynx89tIxPkx0o6ljMgxszww17JOgB4tg4etmNnMC9XI=' 'mac': 'Ynx89tIxPkx0o6ljMgxszww17JOgB4tg4etmNnMC9XI='
} }
} }
@ -551,7 +552,8 @@ class FakeMatrixApi extends MockClient {
'encrypted': { 'encrypted': {
'0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3': { '0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3': {
'iv': 'YqU2XIjYulYZl+bkZtGgVw==', 'iv': 'YqU2XIjYulYZl+bkZtGgVw==',
'ciphertext': 'kM2TSoy/jR/4d357ZoRPbpPypxQl6XRLo3FsEXz+f7vIOp82GeRp28RYb3k=', 'ciphertext':
'kM2TSoy/jR/4d357ZoRPbpPypxQl6XRLo3FsEXz+f7vIOp82GeRp28RYb3k=',
'mac': 'F+DZa5tAFmWsYSryw5EuEpzTmmABRab4GETkM85bGGo=' 'mac': 'F+DZa5tAFmWsYSryw5EuEpzTmmABRab4GETkM85bGGo='
} }
} }
@ -563,7 +565,8 @@ class FakeMatrixApi extends MockClient {
'encrypted': { 'encrypted': {
'0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3': { '0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3': {
'iv': 'D7AM3LXFu7ZlyGOkR+OeqQ==', 'iv': 'D7AM3LXFu7ZlyGOkR+OeqQ==',
'ciphertext': 'bYA2+OMgsO6QB1E31aY+ESAWrT0fUBTXqajy4qmL7bVDSZY4Uj64EXNbHuA=', 'ciphertext':
'bYA2+OMgsO6QB1E31aY+ESAWrT0fUBTXqajy4qmL7bVDSZY4Uj64EXNbHuA=',
'mac': 'j2UtyPo/UBSoiaQCWfzCiRZXp3IRt0ZZujuXgUMjnw4=' 'mac': 'j2UtyPo/UBSoiaQCWfzCiRZXp3IRt0ZZujuXgUMjnw4='
} }
} }
@ -575,7 +578,8 @@ class FakeMatrixApi extends MockClient {
'encrypted': { 'encrypted': {
'0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3': { '0FajDWYaM6wQ4O60OZnLvwZfsBNu4Bu3': {
'iv': 'cL/0MJZaiEd3fNU+I9oJrw==', 'iv': 'cL/0MJZaiEd3fNU+I9oJrw==',
'ciphertext': 'WL73Pzdk5wZdaaSpaeRH0uZYKcxkuV8IS6Qa2FEfA1+vMeRLuHcWlXbMX0w=', 'ciphertext':
'WL73Pzdk5wZdaaSpaeRH0uZYKcxkuV8IS6Qa2FEfA1+vMeRLuHcWlXbMX0w=',
'mac': '+xozp909S6oDX8KRV8D8ZFVRyh7eEYQpPP76f+DOsnw=' 'mac': '+xozp909S6oDX8KRV8D8ZFVRyh7eEYQpPP76f+DOsnw='
} }
} }
@ -1527,12 +1531,14 @@ class FakeMatrixApi extends MockClient {
'event_fields': ['type', 'content', 'sender'] 'event_fields': ['type', 'content', 'sender']
}, },
'/client/unstable/room_keys/version': (var req) => { '/client/unstable/room_keys/version': (var req) => {
'algorithm': 'm.megolm_backup.v1.curve25519-aes-sha2', 'algorithm': 'm.megolm_backup.v1.curve25519-aes-sha2',
'auth_data': {'public_key': 'GXYaxqhNhUK28zUdxOmEsFRguz+PzBsDlTLlF0O0RkM'}, 'auth_data': {
'count': 0, 'public_key': 'GXYaxqhNhUK28zUdxOmEsFRguz+PzBsDlTLlF0O0RkM'
'etag': '0', },
'version': '5', 'count': 0,
}, 'etag': '0',
'version': '5',
},
}, },
'POST': { 'POST': {
'/client/r0/delete_devices': (var req) => {}, '/client/r0/delete_devices': (var req) => {},
@ -1782,7 +1788,8 @@ class FakeMatrixApi extends MockClient {
'user_id': '@test:fakeServer.notExisting', 'user_id': '@test:fakeServer.notExisting',
'usage': ['master'], 'usage': ['master'],
'keys': { 'keys': {
'ed25519:82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8': '82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8', 'ed25519:82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8':
'82mAXjsmbTbrE6zyShpR869jnrANO75H8nYY0nDLoJ8',
}, },
'signatures': {}, 'signatures': {},
}, },
@ -1792,7 +1799,8 @@ class FakeMatrixApi extends MockClient {
'user_id': '@test:fakeServer.notExisting', 'user_id': '@test:fakeServer.notExisting',
'usage': ['self_signing'], 'usage': ['self_signing'],
'keys': { 'keys': {
'ed25519:F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY': 'F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY', 'ed25519:F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY':
'F9ypFzgbISXCzxQhhSnXMkc1vq12Luna3Nw5rqViOJY',
}, },
'signatures': {}, 'signatures': {},
}, },
@ -1802,7 +1810,8 @@ class FakeMatrixApi extends MockClient {
'user_id': '@test:fakeServer.notExisting', 'user_id': '@test:fakeServer.notExisting',
'usage': ['user_signing'], 'usage': ['user_signing'],
'keys': { 'keys': {
'ed25519:0PiwulzJ/RU86LlzSSZ8St80HUMN3dqjKa/orIJoA0g': '0PiwulzJ/RU86LlzSSZ8St80HUMN3dqjKa/orIJoA0g', 'ed25519:0PiwulzJ/RU86LlzSSZ8St80HUMN3dqjKa/orIJoA0g':
'0PiwulzJ/RU86LlzSSZ8St80HUMN3dqjKa/orIJoA0g',
}, },
'signatures': {}, 'signatures': {},
}, },