better smoothen out keys
This commit is contained in:
parent
4154c7d0eb
commit
e1679d59be
|
@ -20,4 +20,5 @@ library encryption;
|
|||
|
||||
export './encryption/encryption.dart';
|
||||
export './encryption/key_manager.dart';
|
||||
export './encryption/ssss.dart';
|
||||
export './encryption/utils/key_verification.dart';
|
||||
|
|
|
@ -100,7 +100,7 @@ class CrossSigning {
|
|||
]);
|
||||
}
|
||||
|
||||
bool signable(List<SignedKey> keys) {
|
||||
bool signable(List<SignableKey> keys) {
|
||||
for (final key in keys) {
|
||||
if (key is CrossSigningKey && key.usage.contains('master')) {
|
||||
return true;
|
||||
|
@ -114,13 +114,13 @@ class CrossSigning {
|
|||
return false;
|
||||
}
|
||||
|
||||
Future<void> sign(List<SignedKey> keys) async {
|
||||
Future<void> sign(List<SignableKey> keys) async {
|
||||
Uint8List selfSigningKey;
|
||||
Uint8List userSigningKey;
|
||||
final signatures = <String, dynamic>{};
|
||||
var signedKey = false;
|
||||
final addSignature =
|
||||
(SignedKey key, SignedKey signedWith, String signature) {
|
||||
(SignableKey key, SignableKey signedWith, String signature) {
|
||||
if (key == null || signedWith == null || signature == null) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -221,11 +221,7 @@ class SSSS {
|
|||
'mac': encrypted.mac,
|
||||
};
|
||||
// store the thing in your account data
|
||||
await client.jsonRequest(
|
||||
type: RequestType.PUT,
|
||||
action: '/client/r0/user/${client.userID}/account_data/${type}',
|
||||
data: content,
|
||||
);
|
||||
await client.api.setAccountData(client.userID, type, content);
|
||||
if (CACHE_TYPES.contains(type) && client.database != null) {
|
||||
// cache the thing
|
||||
await client.database
|
||||
|
|
|
@ -128,7 +128,7 @@ class KeyVerification {
|
|||
List<String> possibleMethods;
|
||||
Map<String, dynamic> startPaylaod;
|
||||
String _nextAction;
|
||||
List<SignedKey> _verifiedDevices;
|
||||
List<SignableKey> _verifiedDevices;
|
||||
|
||||
DateTime lastActivity;
|
||||
String lastStep;
|
||||
|
@ -404,8 +404,8 @@ class KeyVerification {
|
|||
}
|
||||
|
||||
Future<void> verifyKeys(Map<String, String> keys,
|
||||
Future<bool> Function(String, SignedKey) verifier) async {
|
||||
_verifiedDevices = <SignedKey>[];
|
||||
Future<bool> Function(String, SignableKey) verifier) async {
|
||||
_verifiedDevices = <SignableKey>[];
|
||||
|
||||
if (!client.userDeviceKeys.containsKey(userId)) {
|
||||
await cancel('m.key_mismatch');
|
||||
|
@ -863,7 +863,7 @@ class _KeyVerificationMethodSas extends _KeyVerificationMethod {
|
|||
mac[entry.key] = entry.value;
|
||||
}
|
||||
}
|
||||
await request.verifyKeys(mac, (String mac, SignedKey key) async {
|
||||
await request.verifyKeys(mac, (String mac, SignableKey key) async {
|
||||
return mac ==
|
||||
_calculateMac(key.ed25519Key, baseInfo + 'ed25519:' + key.identifier);
|
||||
});
|
||||
|
|
|
@ -31,9 +31,8 @@ export 'package:famedlysdk/matrix_api/model/filter.dart';
|
|||
export 'package:famedlysdk/matrix_api/model/keys_query_response.dart';
|
||||
export 'package:famedlysdk/matrix_api/model/login_response.dart';
|
||||
export 'package:famedlysdk/matrix_api/model/login_types.dart';
|
||||
export 'package:famedlysdk/matrix_api/model/matrix_cross_signing_key.dart';
|
||||
export 'package:famedlysdk/matrix_api/model/matrix_device_keys.dart';
|
||||
export 'package:famedlysdk/matrix_api/model/matrix_exception.dart';
|
||||
export 'package:famedlysdk/matrix_api/model/matrix_keys.dart';
|
||||
export 'package:famedlysdk/matrix_api/model/message_types.dart';
|
||||
export 'package:famedlysdk/matrix_api/model/presence_content.dart';
|
||||
export 'package:famedlysdk/matrix_api/model/notifications_query_response.dart';
|
||||
|
|
|
@ -36,8 +36,8 @@ import 'package:mime_type/mime_type.dart';
|
|||
import 'package:moor/moor.dart';
|
||||
|
||||
import 'model/device.dart';
|
||||
import 'model/matrix_device_keys.dart';
|
||||
import 'model/matrix_event.dart';
|
||||
import 'model/matrix_keys.dart';
|
||||
import 'model/event_context.dart';
|
||||
import 'model/events_sync_update.dart';
|
||||
import 'model/login_response.dart';
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import 'matrix_device_keys.dart';
|
||||
import 'matrix_cross_signing_key.dart';
|
||||
import 'matrix_keys.dart';
|
||||
|
||||
class KeysQueryResponse {
|
||||
Map<String, dynamic> failures;
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
* Famedly Matrix SDK
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
class MatrixCrossSigningKey {
|
||||
String userId;
|
||||
List<String> usage;
|
||||
Map<String, String> keys;
|
||||
Map<String, Map<String, String>> signatures;
|
||||
Map<String, dynamic> unsigned;
|
||||
String get publicKey => keys?.values?.first;
|
||||
|
||||
MatrixCrossSigningKey(
|
||||
this.userId,
|
||||
this.usage,
|
||||
this.keys,
|
||||
this.signatures, {
|
||||
this.unsigned,
|
||||
});
|
||||
|
||||
// This object is used for signing so we need the raw json too
|
||||
Map<String, dynamic> _json;
|
||||
|
||||
MatrixCrossSigningKey.fromJson(Map<String, dynamic> json) {
|
||||
_json = json;
|
||||
userId = json['user_id'];
|
||||
usage = List<String>.from(json['usage']);
|
||||
keys = Map<String, String>.from(json['keys']);
|
||||
signatures = Map<String, Map<String, String>>.from(
|
||||
(json['signatures'] as Map)
|
||||
.map((k, v) => MapEntry(k, Map<String, String>.from(v))));
|
||||
unsigned = json['unsigned'] != null
|
||||
? Map<String, dynamic>.from(json['unsigned'])
|
||||
: null;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final data = _json ?? <String, dynamic>{};
|
||||
data['user_id'] = userId;
|
||||
data['usage'] = usage;
|
||||
data['keys'] = keys;
|
||||
|
||||
if (signatures != null) {
|
||||
data['signatures'] = signatures;
|
||||
}
|
||||
if (unsigned != null) {
|
||||
data['unsigned'] = unsigned;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
|
@ -16,38 +16,25 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
class MatrixDeviceKeys {
|
||||
class MatrixSignableKey {
|
||||
String userId;
|
||||
String deviceId;
|
||||
List<String> algorithms;
|
||||
Map<String, String> keys;
|
||||
Map<String, Map<String, String>> signatures;
|
||||
Map<String, dynamic> unsigned;
|
||||
String get deviceDisplayName =>
|
||||
unsigned != null ? unsigned['device_display_name'] : null;
|
||||
|
||||
MatrixSignableKey(this.userId, this.keys, this.signatures, {this.unsigned});
|
||||
|
||||
// This object is used for signing so we need the raw json too
|
||||
Map<String, dynamic> _json;
|
||||
|
||||
MatrixDeviceKeys(
|
||||
this.userId,
|
||||
this.deviceId,
|
||||
this.algorithms,
|
||||
this.keys,
|
||||
this.signatures, {
|
||||
this.unsigned,
|
||||
});
|
||||
|
||||
MatrixDeviceKeys.fromJson(Map<String, dynamic> json) {
|
||||
MatrixSignableKey.fromJson(Map<String, dynamic> json) {
|
||||
_json = json;
|
||||
userId = json['user_id'];
|
||||
deviceId = json['device_id'];
|
||||
algorithms = json['algorithms'].cast<String>();
|
||||
keys = Map<String, String>.from(json['keys']);
|
||||
signatures = Map<String, Map<String, String>>.from(
|
||||
signatures = json['signatures'] is Map ? Map<String, Map<String, String>>.from(
|
||||
(json['signatures'] as Map)
|
||||
.map((k, v) => MapEntry(k, Map<String, String>.from(v))));
|
||||
unsigned = json['unsigned'] != null
|
||||
.map((k, v) => MapEntry(k, Map<String, String>.from(v)))) : null;
|
||||
unsigned = json['unsigned'] is Map
|
||||
? Map<String, dynamic>.from(json['unsigned'])
|
||||
: null;
|
||||
}
|
||||
|
@ -55,8 +42,6 @@ class MatrixDeviceKeys {
|
|||
Map<String, dynamic> toJson() {
|
||||
final data = _json ?? <String, dynamic>{};
|
||||
data['user_id'] = userId;
|
||||
data['device_id'] = deviceId;
|
||||
data['algorithms'] = algorithms;
|
||||
data['keys'] = keys;
|
||||
|
||||
if (signatures != null) {
|
||||
|
@ -68,3 +53,59 @@ class MatrixDeviceKeys {
|
|||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class MatrixCrossSigningKey extends MatrixSignableKey {
|
||||
List<String> usage;
|
||||
String get publicKey => keys?.values?.first;
|
||||
|
||||
MatrixCrossSigningKey(
|
||||
String userId,
|
||||
this.usage,
|
||||
Map<String, String> keys,
|
||||
Map<String, Map<String, String>> signatures, {
|
||||
Map<String, dynamic> unsigned,
|
||||
}) : super(userId, keys, signatures, unsigned: unsigned);
|
||||
|
||||
@override
|
||||
MatrixCrossSigningKey.fromJson(Map<String, dynamic> json)
|
||||
: super.fromJson(json) {
|
||||
usage = List<String>.from(json['usage']);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
final data = super.toJson();
|
||||
data['usage'] = usage;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class MatrixDeviceKeys extends MatrixSignableKey {
|
||||
String deviceId;
|
||||
List<String> algorithms;
|
||||
String get deviceDisplayName =>
|
||||
unsigned != null ? unsigned['device_display_name'] : null;
|
||||
|
||||
MatrixDeviceKeys(
|
||||
String userId,
|
||||
this.deviceId,
|
||||
this.algorithms,
|
||||
Map<String, String> keys,
|
||||
Map<String, Map<String, String>> signatures, {
|
||||
Map<String, dynamic> unsigned,
|
||||
}) : super(userId, keys, signatures, unsigned: unsigned);
|
||||
|
||||
@override
|
||||
MatrixDeviceKeys.fromJson(Map<String, dynamic> json) : super.fromJson(json) {
|
||||
deviceId = json['device_id'];
|
||||
algorithms = json['algorithms'].cast<String>();
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
final data = super.toJson();
|
||||
data['device_id'] = deviceId;
|
||||
data['algorithms'] = algorithms;
|
||||
return data;
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ class DeviceKeysList {
|
|||
Map<String, DeviceKeys> deviceKeys = {};
|
||||
Map<String, CrossSigningKey> crossSigningKeys = {};
|
||||
|
||||
SignedKey getKey(String id) {
|
||||
SignableKey getKey(String id) {
|
||||
if (deviceKeys.containsKey(id)) {
|
||||
return deviceKeys[id];
|
||||
}
|
||||
|
@ -98,13 +98,9 @@ class DeviceKeysList {
|
|||
DeviceKeysList(this.userId);
|
||||
}
|
||||
|
||||
abstract class SignedKey {
|
||||
abstract class SignableKey extends MatrixSignableKey {
|
||||
Client client;
|
||||
String userId;
|
||||
String identifier;
|
||||
Map<String, dynamic> content;
|
||||
Map<String, String> keys;
|
||||
Map<String, dynamic> signatures;
|
||||
Map<String, dynamic> validSignatures;
|
||||
bool _verified;
|
||||
bool blocked;
|
||||
|
@ -120,8 +116,15 @@ abstract class SignedKey {
|
|||
bool get crossVerified => hasValidSignatureChain();
|
||||
bool get signed => hasValidSignatureChain(verifiedOnly: false);
|
||||
|
||||
SignableKey.fromJson(Map<String, dynamic> json, Client cl)
|
||||
: client = cl,
|
||||
super.fromJson(json) {
|
||||
_verified = false;
|
||||
blocked = false;
|
||||
}
|
||||
|
||||
String get signingContent {
|
||||
final data = Map<String, dynamic>.from(content);
|
||||
final data = Map<String, dynamic>.from(super.toJson());
|
||||
// some old data might have the custom verified and blocked keys
|
||||
data.remove('verified');
|
||||
data.remove('blocked');
|
||||
|
@ -166,7 +169,7 @@ abstract class SignedKey {
|
|||
continue;
|
||||
}
|
||||
final keyId = fullKeyId.substring('ed25519:'.length);
|
||||
SignedKey key;
|
||||
SignableKey key;
|
||||
if (client.userDeviceKeys[otherUserId].deviceKeys.containsKey(keyId)) {
|
||||
key = client.userDeviceKeys[otherUserId].deviceKeys[keyId];
|
||||
} else if (client.userDeviceKeys[otherUserId].crossSigningKeys
|
||||
|
@ -236,8 +239,9 @@ abstract class SignedKey {
|
|||
|
||||
Future<void> setBlocked(bool newBlocked);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
final data = Map<String, dynamic>.from(content);
|
||||
final data = Map<String, dynamic>.from(super.toJson());
|
||||
// some old data may have the verified and blocked keys which are unneeded now
|
||||
data.remove('verified');
|
||||
data.remove('blocked');
|
||||
|
@ -248,7 +252,7 @@ abstract class SignedKey {
|
|||
String toString() => json.encode(toJson());
|
||||
}
|
||||
|
||||
class CrossSigningKey extends SignedKey {
|
||||
class CrossSigningKey extends SignableKey {
|
||||
String get publicKey => identifier;
|
||||
List<String> usage;
|
||||
|
||||
|
@ -269,59 +273,35 @@ class CrossSigningKey extends SignedKey {
|
|||
newBlocked, client.id, userId, publicKey);
|
||||
}
|
||||
|
||||
CrossSigningKey.fromMatrixCrossSigningKey(
|
||||
MatrixCrossSigningKey k, Client cl) {
|
||||
client = cl;
|
||||
content = Map<String, dynamic>.from(k.toJson());
|
||||
userId = k.userId;
|
||||
CrossSigningKey.fromMatrixCrossSigningKey(MatrixCrossSigningKey k, Client cl)
|
||||
: super.fromJson(Map<String, dynamic>.from(k.toJson()), cl) {
|
||||
final json = toJson();
|
||||
identifier = k.publicKey;
|
||||
usage = content['usage'].cast<String>();
|
||||
keys = content['keys'] != null
|
||||
? Map<String, String>.from(content['keys'])
|
||||
: null;
|
||||
signatures = content['signatures'] != null
|
||||
? Map<String, dynamic>.from(content['signatures'])
|
||||
: null;
|
||||
_verified = false;
|
||||
blocked = false;
|
||||
usage = json['usage'].cast<String>();
|
||||
}
|
||||
|
||||
CrossSigningKey.fromDb(DbUserCrossSigningKey dbEntry, Client cl) {
|
||||
client = cl;
|
||||
final json = Event.getMapFromPayload(dbEntry.content);
|
||||
content = Map<String, dynamic>.from(json);
|
||||
userId = dbEntry.userId;
|
||||
CrossSigningKey.fromDb(DbUserCrossSigningKey dbEntry, Client cl)
|
||||
: super.fromJson(Event.getMapFromPayload(dbEntry.content), cl) {
|
||||
final json = toJson();
|
||||
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;
|
||||
_verified = dbEntry.verified;
|
||||
blocked = dbEntry.blocked;
|
||||
}
|
||||
|
||||
CrossSigningKey.fromJson(Map<String, dynamic> json, Client cl) {
|
||||
client = cl;
|
||||
content = Map<String, dynamic>.from(json);
|
||||
userId = json['user_id'];
|
||||
CrossSigningKey.fromJson(Map<String, dynamic> json, Client cl)
|
||||
: super.fromJson(Map<String, dynamic>.from(json), cl) {
|
||||
final json = toJson();
|
||||
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;
|
||||
_verified = json['verified'] ?? false;
|
||||
blocked = json['blocked'] ?? false;
|
||||
if (keys != null) {
|
||||
if (keys != null && keys.isNotEmpty) {
|
||||
identifier = keys.values.first;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DeviceKeys extends SignedKey {
|
||||
class DeviceKeys extends SignableKey {
|
||||
String get deviceId => identifier;
|
||||
List<String> algorithms;
|
||||
Map<String, dynamic> unsigned;
|
||||
|
||||
String get curve25519Key => keys['curve25519:$deviceId'];
|
||||
|
||||
|
@ -346,60 +326,27 @@ class DeviceKeys extends SignedKey {
|
|||
?.setBlockedUserDeviceKey(newBlocked, client.id, userId, deviceId);
|
||||
}
|
||||
|
||||
DeviceKeys.fromMatrixDeviceKeys(MatrixDeviceKeys k, Client cl) {
|
||||
client = cl;
|
||||
content = Map<String, dynamic>.from(k.toJson());
|
||||
userId = k.userId;
|
||||
DeviceKeys.fromMatrixDeviceKeys(MatrixDeviceKeys k, Client cl)
|
||||
: super.fromJson(Map<String, dynamic>.from(k.toJson()), cl) {
|
||||
final json = toJson();
|
||||
identifier = k.deviceId;
|
||||
algorithms = content['algorithms'].cast<String>();
|
||||
keys = content['keys'] != null
|
||||
? Map<String, String>.from(content['keys'])
|
||||
: null;
|
||||
signatures = content['signatures'] != null
|
||||
? Map<String, dynamic>.from(content['signatures'])
|
||||
: null;
|
||||
unsigned = content['unsigned'] != null
|
||||
? Map<String, dynamic>.from(content['unsigned'])
|
||||
: null;
|
||||
_verified = false;
|
||||
blocked = false;
|
||||
algorithms = json['algorithms'].cast<String>();
|
||||
}
|
||||
|
||||
DeviceKeys.fromDb(DbUserDeviceKeysKey dbEntry, Client cl) {
|
||||
client = cl;
|
||||
final json = Event.getMapFromPayload(dbEntry.content);
|
||||
content = Map<String, dynamic>.from(json);
|
||||
userId = dbEntry.userId;
|
||||
DeviceKeys.fromDb(DbUserDeviceKeysKey dbEntry, Client cl)
|
||||
: super.fromJson(Event.getMapFromPayload(dbEntry.content), cl) {
|
||||
final json = toJson();
|
||||
identifier = dbEntry.deviceId;
|
||||
algorithms = content['algorithms'].cast<String>();
|
||||
keys = content['keys'] != null
|
||||
? Map<String, String>.from(content['keys'])
|
||||
: null;
|
||||
signatures = content['signatures'] != null
|
||||
? Map<String, dynamic>.from(content['signatures'])
|
||||
: null;
|
||||
unsigned = json['unsigned'] != null
|
||||
? Map<String, dynamic>.from(json['unsigned'])
|
||||
: null;
|
||||
algorithms = json['algorithms'].cast<String>();
|
||||
_verified = dbEntry.verified;
|
||||
blocked = dbEntry.blocked;
|
||||
}
|
||||
|
||||
DeviceKeys.fromJson(Map<String, dynamic> json, Client cl) {
|
||||
client = cl;
|
||||
content = Map<String, dynamic>.from(json);
|
||||
userId = json['user_id'];
|
||||
DeviceKeys.fromJson(Map<String, dynamic> json, Client cl)
|
||||
: super.fromJson(Map<String, dynamic>.from(json), cl) {
|
||||
final json = toJson();
|
||||
identifier = json['device_id'];
|
||||
algorithms = json['algorithms'].cast<String>();
|
||||
keys = json['keys'] != null ? Map<String, String>.from(json['keys']) : null;
|
||||
signatures = json['signatures'] != null
|
||||
? Map<String, dynamic>.from(json['signatures'])
|
||||
: null;
|
||||
unsigned = json['unsigned'] != null
|
||||
? Map<String, dynamic>.from(json['unsigned'])
|
||||
: null;
|
||||
_verified = json['verified'] ?? false;
|
||||
blocked = json['blocked'] ?? false;
|
||||
}
|
||||
|
||||
KeyVerification startVerification() {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
import 'dart:typed_data';
|
||||
import 'package:famedlysdk/matrix_api.dart';
|
||||
import 'package:famedlysdk/matrix_api/model/matrix_device_keys.dart';
|
||||
import 'package:famedlysdk/matrix_api/model/matrix_keys.dart';
|
||||
import 'package:famedlysdk/matrix_api/model/filter.dart';
|
||||
import 'package:famedlysdk/matrix_api/model/matrix_exception.dart';
|
||||
import 'package:famedlysdk/matrix_api/model/presence_content.dart';
|
||||
|
|
Loading…
Reference in a new issue