refactor: Make signableJson type safe with type safe class

This commit is contained in:
Christian Kußowski 2025-08-22 14:01:28 +02:00
parent a6fc1a004d
commit 7d0a4dc3bc
No known key found for this signature in database
GPG Key ID: E067ECD60F1A0652
2 changed files with 38 additions and 27 deletions

View File

@ -102,28 +102,17 @@ class OlmManager {
/// Adds a signature to this json from this olm account and returns the signed
/// json.
Map<String, dynamic> signJson(Map<String, dynamic> payload) {
Map<String, Object?> signJson(Map<String, Object?> payload) {
if (!enabled) throw ('Encryption is disabled');
final Map<String, dynamic>? unsigned = payload['unsigned'];
final Map<String, dynamic>? signatures = payload['signatures'];
payload.remove('unsigned');
payload.remove('signatures');
final canonical = canonicalJson.encode(payload);
final signableJson = SignableJsonMap(payload);
final canonical = canonicalJson.encode(signableJson.jsonMap);
final signature = _olmAccount!.sign(String.fromCharCodes(canonical));
if (signatures != null) {
payload['signatures'] = signatures;
} else {
payload['signatures'] = <String, dynamic>{};
}
if (!payload['signatures'].containsKey(client.userID)) {
payload['signatures'][client.userID] = <String, dynamic>{};
}
payload['signatures'][client.userID]['ed25519:$ourDeviceId'] =
signature.toBase64();
if (unsigned != null) {
payload['unsigned'] = unsigned;
}
return payload;
final userSignatures = signableJson.signatures[client.userID!] ??= {};
userSignatures['ed25519:$ourDeviceId'] = signature.toBase64();
return signableJson.toJson();
}
String signString(String s) {
@ -811,3 +800,24 @@ class NoOlmSessionFoundException implements Exception {
String toString() =>
'No olm session found for ${device.userId}:${device.deviceId}';
}
class SignableJsonMap {
final Map<String, Object?> jsonMap;
final Map<String, Map<String, String>> signatures;
final Map<String, Object?>? unsigned;
SignableJsonMap(Map<String, Object?> json)
: jsonMap = json,
signatures =
json.tryGetMap<String, Map<String, String>>('signatures') ?? {},
unsigned = json.tryGetMap<String, Object?>('unsigned') {
jsonMap.remove('signatures');
jsonMap.remove('unsigned');
}
Map<String, Object?> toJson() => {
...jsonMap,
'signatures': signatures,
if (unsigned != null) 'unsigned': unsigned,
};
}

View File

@ -41,24 +41,25 @@ class OlmSession {
required this.lastReceived,
});
OlmSession.fromJson(Map<String, dynamic> dbEntry, this.key)
: identityKey = dbEntry['identity_key'] ?? '' {
OlmSession.fromJson(Map<String, Object?> dbEntry, this.key)
: identityKey = dbEntry.tryGet<String>('identity_key') ?? '' {
try {
try {
session = vod.Session.fromPickleEncrypted(
pickleKey: key.toPickleKey(),
pickle: dbEntry['pickle'],
pickle: dbEntry['pickle'] as String,
);
} catch (_) {
Logs().d('Unable to unpickle Olm session. Try LibOlm format.');
session = vod.Session.fromOlmPickleEncrypted(
pickleKey: utf8.encode(key),
pickle: dbEntry['pickle'],
pickle: dbEntry['pickle'] as String,
);
}
sessionId = dbEntry['session_id'];
lastReceived =
DateTime.fromMillisecondsSinceEpoch(dbEntry['last_received'] ?? 0);
sessionId = dbEntry['session_id'] as String;
lastReceived = DateTime.fromMillisecondsSinceEpoch(
dbEntry.tryGet<int>('last_received') ?? 0,
);
assert(sessionId == session!.sessionId);
} catch (e, s) {
Logs().e('[Vodozemac] Could not unpickle olm session', e, s);