format
This commit is contained in:
parent
29721f00a8
commit
c9a0c5302a
|
@ -1664,7 +1664,8 @@ class Client {
|
|||
if (entry.isValid) {
|
||||
// is this a new key or the same one as an old one?
|
||||
// better store an update - the signatures might have changed!
|
||||
if (!oldKeys.containsKey(deviceId) || oldKeys[deviceId].ed25519Key == entry.ed25519Key) {
|
||||
if (!oldKeys.containsKey(deviceId) ||
|
||||
oldKeys[deviceId].ed25519Key == entry.ed25519Key) {
|
||||
if (oldKeys.containsKey(deviceId)) {
|
||||
// be sure to save the verified status
|
||||
entry.setDirectVerified(oldKeys[deviceId].directVerified);
|
||||
|
@ -1681,7 +1682,8 @@ class Client {
|
|||
// This shouldn't ever happen. The same device ID has gotten
|
||||
// a new public key. So we ignore the update. TODO: ask krille
|
||||
// if we should instead use the new key with unknown verified / blocked status
|
||||
_userDeviceKeys[userId].deviceKeys[deviceId] = oldKeys[deviceId];
|
||||
_userDeviceKeys[userId].deviceKeys[deviceId] =
|
||||
oldKeys[deviceId];
|
||||
}
|
||||
if (database != null) {
|
||||
dbActions.add(() => database.storeUserDeviceKey(
|
||||
|
@ -1713,24 +1715,33 @@ class Client {
|
|||
}
|
||||
}
|
||||
// next we parse and persist the cross signing keys
|
||||
for (final keyType in ['master_keys', 'self_signing_keys', 'user_signing_keys']) {
|
||||
for (final keyType in [
|
||||
'master_keys',
|
||||
'self_signing_keys',
|
||||
'user_signing_keys'
|
||||
]) {
|
||||
if (!(response[keyType] is Map)) {
|
||||
continue;
|
||||
}
|
||||
for (final rawDeviceKeyListEntry in response[keyType].entries) {
|
||||
final String userId = rawDeviceKeyListEntry.key;
|
||||
final oldKeys = Map<String, CrossSigningKey>.from(_userDeviceKeys[userId].crossSigningKeys);
|
||||
final oldKeys = Map<String, CrossSigningKey>.from(
|
||||
_userDeviceKeys[userId].crossSigningKeys);
|
||||
_userDeviceKeys[userId].crossSigningKeys = {};
|
||||
// add the types we arne't handling atm back
|
||||
for (final oldEntry in oldKeys.entries) {
|
||||
if (!oldEntry.value.usage.contains(keyType.substring(0, keyType.length - '_keys'.length))) {
|
||||
_userDeviceKeys[userId].crossSigningKeys[oldEntry.key] = oldEntry.value;
|
||||
if (!oldEntry.value.usage.contains(
|
||||
keyType.substring(0, keyType.length - '_keys'.length))) {
|
||||
_userDeviceKeys[userId].crossSigningKeys[oldEntry.key] =
|
||||
oldEntry.value;
|
||||
}
|
||||
}
|
||||
final entry = CrossSigningKey.fromJson(rawDeviceKeyListEntry.value, this);
|
||||
final entry =
|
||||
CrossSigningKey.fromJson(rawDeviceKeyListEntry.value, this);
|
||||
if (entry.isValid) {
|
||||
final publicKey = entry.publicKey;
|
||||
if (!oldKeys.containsKey(publicKey) || oldKeys[publicKey].ed25519Key == entry.ed25519Key) {
|
||||
if (!oldKeys.containsKey(publicKey) ||
|
||||
oldKeys[publicKey].ed25519Key == entry.ed25519Key) {
|
||||
if (oldKeys.containsKey(publicKey)) {
|
||||
// be sure to save the verification status
|
||||
entry.setDirectVerified(oldKeys[publicKey].directVerified);
|
||||
|
@ -1742,34 +1753,37 @@ class Client {
|
|||
// This shouldn't ever happen. The same device ID has gotten
|
||||
// a new public key. So we ignore the update. TODO: ask krille
|
||||
// if we should instead use the new key with unknown verified / blocked status
|
||||
_userDeviceKeys[userId].crossSigningKeys[publicKey] = oldKeys[publicKey];
|
||||
_userDeviceKeys[userId].crossSigningKeys[publicKey] =
|
||||
oldKeys[publicKey];
|
||||
}
|
||||
if (database != null) {
|
||||
dbActions.add(() => database.storeUserCrossSigningKey(
|
||||
id,
|
||||
userId,
|
||||
publicKey,
|
||||
json.encode(entry.toJson()),
|
||||
entry.directVerified,
|
||||
entry.blocked,
|
||||
));
|
||||
id,
|
||||
userId,
|
||||
publicKey,
|
||||
json.encode(entry.toJson()),
|
||||
entry.directVerified,
|
||||
entry.blocked,
|
||||
));
|
||||
}
|
||||
}
|
||||
// delete old/unused entries
|
||||
if (database != null) {
|
||||
for (final oldCrossSigningKeyEntry in oldKeys.entries) {
|
||||
final publicKey = oldCrossSigningKeyEntry.key;
|
||||
if (!_userDeviceKeys[userId].crossSigningKeys.containsKey(publicKey)) {
|
||||
if (!_userDeviceKeys[userId]
|
||||
.crossSigningKeys
|
||||
.containsKey(publicKey)) {
|
||||
// we need to remove an old key
|
||||
dbActions.add(
|
||||
() => database.removeUserCrossSigningKey(id, userId, publicKey));
|
||||
dbActions.add(() => database.removeUserCrossSigningKey(
|
||||
id, userId, publicKey));
|
||||
}
|
||||
}
|
||||
}
|
||||
_userDeviceKeys[userId].outdated = false;
|
||||
if (database != null) {
|
||||
dbActions
|
||||
.add(() => database.storeUserDeviceKeysInfo(id, userId, false));
|
||||
dbActions.add(
|
||||
() => database.storeUserDeviceKeysInfo(id, userId, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,8 @@ class Database extends _$Database {
|
|||
await m.createTable(userCrossSigningKeys);
|
||||
await m.createIndex(userCrossSigningKeysIndex);
|
||||
// mark all keys as outdated so that the cross signing keys will be fetched
|
||||
await m.issueCustomQuery('UPDATE user_device_keys SET outdated = true');
|
||||
await m.issueCustomQuery(
|
||||
'UPDATE user_device_keys SET outdated = true');
|
||||
from++;
|
||||
}
|
||||
},
|
||||
|
@ -59,7 +60,8 @@ class Database extends _$Database {
|
|||
return res.first;
|
||||
}
|
||||
|
||||
Future<Map<String, sdk.DeviceKeysList>> getUserDeviceKeys(sdk.Client client) async {
|
||||
Future<Map<String, sdk.DeviceKeysList>> getUserDeviceKeys(
|
||||
sdk.Client client) async {
|
||||
final deviceKeys = await getAllUserDeviceKeys(client.id).get();
|
||||
if (deviceKeys.isEmpty) {
|
||||
return {};
|
||||
|
@ -68,10 +70,11 @@ class Database extends _$Database {
|
|||
final crossSigningKeys = await getAllUserCrossSigningKeys(client.id).get();
|
||||
final res = <String, sdk.DeviceKeysList>{};
|
||||
for (final entry in deviceKeys) {
|
||||
res[entry.userId] = sdk.DeviceKeysList.fromDb(entry,
|
||||
deviceKeysKeys.where((k) => k.userId == entry.userId).toList(),
|
||||
crossSigningKeys.where((k) => k.userId == entry.userId).toList(),
|
||||
client);
|
||||
res[entry.userId] = sdk.DeviceKeysList.fromDb(
|
||||
entry,
|
||||
deviceKeysKeys.where((k) => k.userId == entry.userId).toList(),
|
||||
crossSigningKeys.where((k) => k.userId == entry.userId).toList(),
|
||||
client);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,8 @@ import 'package:canonical_json/canonical_json.dart';
|
|||
import 'package:olm/olm.dart' as olm;
|
||||
|
||||
import '../client.dart';
|
||||
import '../database/database.dart' show DbUserDeviceKey, DbUserDeviceKeysKey, DbUserCrossSigningKey;
|
||||
import '../database/database.dart'
|
||||
show DbUserDeviceKey, DbUserDeviceKeysKey, DbUserCrossSigningKey;
|
||||
import '../event.dart';
|
||||
import 'key_verification.dart';
|
||||
|
||||
|
@ -14,7 +15,11 @@ class DeviceKeysList {
|
|||
Map<String, DeviceKeys> deviceKeys = {};
|
||||
Map<String, CrossSigningKey> crossSigningKeys = {};
|
||||
|
||||
DeviceKeysList.fromDb(DbUserDeviceKey dbEntry, List<DbUserDeviceKeysKey> childEntries, List<DbUserCrossSigningKey> crossSigningEntries, Client cl) {
|
||||
DeviceKeysList.fromDb(
|
||||
DbUserDeviceKey dbEntry,
|
||||
List<DbUserDeviceKeysKey> childEntries,
|
||||
List<DbUserCrossSigningKey> crossSigningEntries,
|
||||
Client cl) {
|
||||
client = cl;
|
||||
userId = dbEntry.userId;
|
||||
outdated = dbEntry.outdated;
|
||||
|
@ -93,7 +98,9 @@ abstract class _SignedKey {
|
|||
try {
|
||||
return hasValidSignatureChain();
|
||||
} catch (err, stacktrace) {
|
||||
print('[Cross Signing] Error during trying to determine signature chain: ' + err.toString());
|
||||
print(
|
||||
'[Cross Signing] Error during trying to determine signature chain: ' +
|
||||
err.toString());
|
||||
print(stacktrace);
|
||||
return false;
|
||||
}
|
||||
|
@ -134,7 +141,8 @@ abstract class _SignedKey {
|
|||
visited.add(setKey);
|
||||
for (final signatureEntries in signatures.entries) {
|
||||
final otherUserId = signatureEntries.key;
|
||||
if (!(signatureEntries.value is Map) || !client.userDeviceKeys.containsKey(otherUserId)) {
|
||||
if (!(signatureEntries.value is Map) ||
|
||||
!client.userDeviceKeys.containsKey(otherUserId)) {
|
||||
continue;
|
||||
}
|
||||
for (final signatureEntry in signatureEntries.value.entries) {
|
||||
|
@ -147,7 +155,8 @@ abstract class _SignedKey {
|
|||
_SignedKey key;
|
||||
if (client.userDeviceKeys[otherUserId].deviceKeys.containsKey(keyId)) {
|
||||
key = client.userDeviceKeys[otherUserId].deviceKeys[keyId];
|
||||
} else if (client.userDeviceKeys[otherUserId].crossSigningKeys.containsKey(keyId)) {
|
||||
} else if (client.userDeviceKeys[otherUserId].crossSigningKeys
|
||||
.containsKey(keyId)) {
|
||||
key = client.userDeviceKeys[otherUserId].crossSigningKeys[keyId];
|
||||
} else {
|
||||
continue;
|
||||
|
@ -157,7 +166,9 @@ abstract class _SignedKey {
|
|||
}
|
||||
var haveValidSignature = false;
|
||||
var gotSignatureFromCache = false;
|
||||
if (validSignatures != null && validSignatures.containsKey(otherUserId) && validSignatures[otherUserId].containsKey(fullKeyId)) {
|
||||
if (validSignatures != null &&
|
||||
validSignatures.containsKey(otherUserId) &&
|
||||
validSignatures[otherUserId].containsKey(fullKeyId)) {
|
||||
if (validSignatures[otherUserId][fullKeyId] == true) {
|
||||
haveValidSignature = true;
|
||||
gotSignatureFromCache = true;
|
||||
|
@ -209,16 +220,19 @@ class CrossSigningKey extends _SignedKey {
|
|||
String get publicKey => identifier;
|
||||
List<String> usage;
|
||||
|
||||
bool get isValid => userId != null && publicKey != null && keys != null && ed25519Key != null;
|
||||
bool get isValid =>
|
||||
userId != null && publicKey != null && keys != null && ed25519Key != null;
|
||||
|
||||
Future<void> setVerified(bool newVerified) {
|
||||
_verified = newVerified;
|
||||
return client.database?.setVerifiedUserCrossSigningKey(newVerified, client.id, userId, publicKey);
|
||||
return client.database?.setVerifiedUserCrossSigningKey(
|
||||
newVerified, client.id, userId, publicKey);
|
||||
}
|
||||
|
||||
Future<void> setBlocked(bool newBlocked) {
|
||||
blocked = newBlocked;
|
||||
return client.database?.setBlockedUserCrossSigningKey(newBlocked, client.id, userId, publicKey);
|
||||
return client.database?.setBlockedUserCrossSigningKey(
|
||||
newBlocked, client.id, userId, publicKey);
|
||||
}
|
||||
|
||||
CrossSigningKey.fromDb(DbUserCrossSigningKey dbEntry, Client cl) {
|
||||
|
@ -229,7 +243,9 @@ class CrossSigningKey extends _SignedKey {
|
|||
identifier = dbEntry.publicKey;
|
||||
usage = json['usage'].cast<String>();
|
||||
keys = json['keys'] != null ? Map<String, String>.from(json['keys']) : null;
|
||||
signatures = json['signatures'] != null ? Map<String, dynamic>.from(json['signatures']) : null;
|
||||
signatures = json['signatures'] != null
|
||||
? Map<String, dynamic>.from(json['signatures'])
|
||||
: null;
|
||||
_verified = dbEntry.verified;
|
||||
blocked = dbEntry.blocked;
|
||||
}
|
||||
|
|
|
@ -291,7 +291,8 @@ class KeyVerification {
|
|||
return [];
|
||||
}
|
||||
|
||||
Future<void> verifyKeys(Map<String, String> keys, Future<bool> Function(String, dynamic) verifier) async {
|
||||
Future<void> verifyKeys(Map<String, String> keys,
|
||||
Future<bool> Function(String, dynamic) verifier) async {
|
||||
final verifiedDevices = <String>[];
|
||||
|
||||
if (!client.userDeviceKeys.containsKey(userId)) {
|
||||
|
@ -310,9 +311,11 @@ class KeyVerification {
|
|||
return;
|
||||
}
|
||||
verifiedDevices.add(verifyDeviceId);
|
||||
} else if (client.userDeviceKeys[userId].crossSigningKeys.containsKey(verifyDeviceId)) {
|
||||
} else if (client.userDeviceKeys[userId].crossSigningKeys
|
||||
.containsKey(verifyDeviceId)) {
|
||||
// this is a cross signing key!
|
||||
if (!(await verifier(keyInfo, client.userDeviceKeys[userId].crossSigningKeys[verifyDeviceId]))) {
|
||||
if (!(await verifier(keyInfo,
|
||||
client.userDeviceKeys[userId].crossSigningKeys[verifyDeviceId]))) {
|
||||
await cancel('m.key_mismatch');
|
||||
return;
|
||||
}
|
||||
|
@ -321,10 +324,14 @@ class KeyVerification {
|
|||
}
|
||||
// okay, we reached this far, so all the devices are verified!
|
||||
for (final verifyDeviceId in verifiedDevices) {
|
||||
if (client.userDeviceKeys[userId].deviceKeys.containsKey(verifyDeviceId)) {
|
||||
await client.userDeviceKeys[userId].deviceKeys[verifyDeviceId].setVerified(true);
|
||||
} else if (client.userDeviceKeys[userId].crossSigningKeys.containsKey(verifyDeviceId)) {
|
||||
await client.userDeviceKeys[userId].crossSigningKeys[verifyDeviceId].setVerified(true);
|
||||
if (client.userDeviceKeys[userId].deviceKeys
|
||||
.containsKey(verifyDeviceId)) {
|
||||
await client.userDeviceKeys[userId].deviceKeys[verifyDeviceId]
|
||||
.setVerified(true);
|
||||
} else if (client.userDeviceKeys[userId].crossSigningKeys
|
||||
.containsKey(verifyDeviceId)) {
|
||||
await client.userDeviceKeys[userId].crossSigningKeys[verifyDeviceId]
|
||||
.setVerified(true);
|
||||
// TODO: sign the other persons master key
|
||||
}
|
||||
}
|
||||
|
@ -708,9 +715,13 @@ class _KeyVerificationMethodSas extends _KeyVerificationMethod {
|
|||
}
|
||||
await request.verifyKeys(mac, (String mac, dynamic device) async {
|
||||
if (device is DeviceKeys) {
|
||||
return mac == _calculateMac(device.ed25519Key, baseInfo + 'ed25519:' + device.deviceId);
|
||||
return mac ==
|
||||
_calculateMac(
|
||||
device.ed25519Key, baseInfo + 'ed25519:' + device.deviceId);
|
||||
} else if (device is CrossSigningKey) {
|
||||
return mac == _calculateMac(device.ed25519Key, baseInfo + 'ed25519:' + device.publicKey);
|
||||
return mac ==
|
||||
_calculateMac(
|
||||
device.ed25519Key, baseInfo + 'ed25519:' + device.publicKey);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
|
|
@ -65,8 +65,7 @@ void main() {
|
|||
final key = DeviceKeys.fromJson(rawJson, null);
|
||||
rawJson.remove('verified');
|
||||
rawJson.remove('blocked');
|
||||
expect(json.encode(key.toJson()),
|
||||
json.encode(rawJson));
|
||||
expect(json.encode(key.toJson()), json.encode(rawJson));
|
||||
expect(key.verified, false);
|
||||
expect(key.blocked, true);
|
||||
expect(json.encode(DeviceKeysList.fromJson(rawListJson, null).toJson()),
|
||||
|
|
Loading…
Reference in a new issue