diff --git a/lib/encryption/olm_manager.dart b/lib/encryption/olm_manager.dart index 1c2cac7..9635939 100644 --- a/lib/encryption/olm_manager.dart +++ b/lib/encryption/olm_manager.dart @@ -24,6 +24,7 @@ import 'package:famedlysdk/matrix_api.dart'; import 'package:olm/olm.dart' as olm; import 'package:pedantic/pedantic.dart'; +import '../encryption/utils/json_signature_check_extension.dart'; import '../src/utils/logs.dart'; import 'encryption.dart'; import 'utils/olm_session.dart'; @@ -75,7 +76,8 @@ class OlmManager { } } - /// Adds a signature to this json from this olm account. + /// Adds a signature to this json from this olm account and returns the signed + /// json. Map signJson(Map payload) { if (!enabled) throw ('Encryption is disabled'); final Map unsigned = payload['unsigned']; @@ -105,6 +107,7 @@ class OlmManager { } /// Checks the signature of a signed json object. + @deprecated bool checkJsonSignature(String key, Map signedJson, String userId, String deviceId) { if (!enabled) throw ('Encryption is disabled'); @@ -406,8 +409,7 @@ class OlmManager { final identityKey = client.userDeviceKeys[userId].deviceKeys[deviceId].curve25519Key; for (Map deviceKey in deviceKeysEntry.value.values) { - if (!checkJsonSignature( - fingerprintKey, deviceKey, userId, deviceId)) { + if (!deviceKey.checkJsonSignature(fingerprintKey, userId, deviceId)) { continue; } var session = olm.Session(); diff --git a/lib/encryption/utils/json_signature_check_extension.dart b/lib/encryption/utils/json_signature_check_extension.dart new file mode 100644 index 0000000..8a2401f --- /dev/null +++ b/lib/encryption/utils/json_signature_check_extension.dart @@ -0,0 +1,29 @@ +import 'package:canonical_json/canonical_json.dart'; +import 'package:famedlysdk/src/utils/logs.dart'; +import 'package:olm/olm.dart' as olm; + +extension JsonSignatureCheckExtension on Map { + /// Checks the signature of a signed json object. + bool checkJsonSignature(String key, String userId, String deviceId) { + final Map signatures = this['signatures']; + if (signatures == null || !signatures.containsKey(userId)) return false; + remove('unsigned'); + remove('signatures'); + if (!signatures[userId].containsKey('ed25519:$deviceId')) return false; + final String signature = signatures[userId]['ed25519:$deviceId']; + final canonical = canonicalJson.encode(this); + final message = String.fromCharCodes(canonical); + var isValid = false; + final olmutil = olm.Utility(); + try { + olmutil.ed25519_verify(key, message, signature); + isValid = true; + } catch (e, s) { + isValid = false; + Logs.error('[LibOlm] Signature check failed: ' + e.toString(), s); + } finally { + olmutil.free(); + } + return isValid; + } +} diff --git a/test/encryption/olm_manager_test.dart b/test/encryption/olm_manager_test.dart index 78e7068..883171c 100644 --- a/test/encryption/olm_manager_test.dart +++ b/test/encryption/olm_manager_test.dart @@ -21,6 +21,7 @@ import 'package:famedlysdk/famedlysdk.dart'; import 'package:famedlysdk/src/utils/logs.dart'; import 'package:test/test.dart'; import 'package:olm/olm.dart' as olm; +import 'package:famedlysdk/encryption/utils/json_signature_check_extension.dart'; import '../fake_client.dart'; import '../fake_matrix_api.dart'; @@ -51,13 +52,9 @@ void main() { }; final signedPayload = client.encryption.olmManager.signJson(payload); expect( - client.encryption.olmManager.checkJsonSignature(client.fingerprintKey, - signedPayload, client.userID, client.deviceID), + signedPayload.checkJsonSignature( + client.fingerprintKey, client.userID, client.deviceID), true); - expect( - client.encryption.olmManager.checkJsonSignature( - client.fingerprintKey, payload, client.userID, client.deviceID), - false); }); test('uploadKeys', () async {