feat: Migrate to vodozemac
This commit is contained in:
parent
6cf6171b35
commit
31a32b0145
|
|
@ -18,6 +18,11 @@ jobs:
|
|||
- uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
|
||||
with:
|
||||
sdk: ${{ env.dart_version }}
|
||||
- uses: famedly/backend-build-workflows/.github/actions/rust-prepare@main
|
||||
with:
|
||||
gitlab_user: ${{ secrets.GITLAB_USER }}
|
||||
gitlab_pass: ${{ secrets.GITLAB_PASS }}
|
||||
gitlab_ssh: ${{ secrets.CI_SSH_PRIVATE_KEY}}
|
||||
- name: Run tests
|
||||
run: |
|
||||
export HOMESERVER_IMPLEMENTATION=${{matrix.homeserver}}
|
||||
|
|
@ -27,6 +32,7 @@ jobs:
|
|||
source scripts/integration-create-environment-variables.sh
|
||||
scripts/integration-prepare-homeserver.sh
|
||||
scripts/prepare.sh
|
||||
scripts/prepare_vodozemac.sh
|
||||
scripts/test_driver.sh
|
||||
|
||||
coverage_without_olm:
|
||||
|
|
@ -54,7 +60,7 @@ jobs:
|
|||
coverage:
|
||||
#runs-on: arm-ubuntu-latest-16core
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: cat .github/workflows/versions.env >> $GITHUB_ENV
|
||||
|
|
@ -62,9 +68,15 @@ jobs:
|
|||
with:
|
||||
sdk: ${{ env.dart_version }}
|
||||
#architecture: "arm64"
|
||||
- uses: famedly/backend-build-workflows/.github/actions/rust-prepare@main
|
||||
with:
|
||||
gitlab_user: ${{ secrets.GITLAB_USER }}
|
||||
gitlab_pass: ${{ secrets.GITLAB_PASS }}
|
||||
gitlab_ssh: ${{ secrets.CI_SSH_PRIVATE_KEY}}
|
||||
- name: Run tests
|
||||
run: |
|
||||
sudo apt-get update && sudo apt-get install --no-install-recommends --no-install-suggests -y lcov libsqlite3-0 libsqlite3-dev libolm3 libssl3
|
||||
./scripts/prepare_vodozemac.sh
|
||||
./scripts/test.sh
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ !cancelled() }}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ coverage/
|
|||
coverage_badge.svg
|
||||
coverage.xml
|
||||
TEST-report.*
|
||||
rust
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
|
|
|
|||
|
|
@ -16,9 +16,10 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:olm/olm.dart' as olm;
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/encryption/encryption.dart';
|
||||
import 'package:matrix/encryption/ssss.dart';
|
||||
|
|
@ -31,26 +32,22 @@ class CrossSigning {
|
|||
CrossSigning(this.encryption) {
|
||||
encryption.ssss.setValidator(EventTypes.CrossSigningSelfSigning,
|
||||
(String secret) async {
|
||||
final keyObj = olm.PkSigning();
|
||||
try {
|
||||
return keyObj.init_with_seed(base64decodeUnpadded(secret)) ==
|
||||
final keyObj = vod.PkSigning.fromSecretKey(secret);
|
||||
return keyObj.publicKey.toBase64() ==
|
||||
client.userDeviceKeys[client.userID]!.selfSigningKey!.ed25519Key;
|
||||
} catch (_) {
|
||||
return false;
|
||||
} finally {
|
||||
keyObj.free();
|
||||
}
|
||||
});
|
||||
encryption.ssss.setValidator(EventTypes.CrossSigningUserSigning,
|
||||
(String secret) async {
|
||||
final keyObj = olm.PkSigning();
|
||||
try {
|
||||
return keyObj.init_with_seed(base64decodeUnpadded(secret)) ==
|
||||
final keyObj = vod.PkSigning.fromSecretKey(secret);
|
||||
return keyObj.publicKey.toBase64() ==
|
||||
client.userDeviceKeys[client.userID]!.userSigningKey!.ed25519Key;
|
||||
} catch (_) {
|
||||
return false;
|
||||
} finally {
|
||||
keyObj.free();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -92,14 +89,13 @@ class CrossSigning {
|
|||
final masterPrivateKey = base64decodeUnpadded(
|
||||
await handle.getStored(EventTypes.CrossSigningMasterKey),
|
||||
);
|
||||
final keyObj = olm.PkSigning();
|
||||
String? masterPubkey;
|
||||
try {
|
||||
masterPubkey = keyObj.init_with_seed(masterPrivateKey);
|
||||
masterPubkey = vod.PkSigning.fromSecretKey(base64Encode(masterPrivateKey))
|
||||
.publicKey
|
||||
.toBase64();
|
||||
} catch (e) {
|
||||
masterPubkey = null;
|
||||
} finally {
|
||||
keyObj.free();
|
||||
}
|
||||
final userDeviceKeys =
|
||||
client.userDeviceKeys[client.userID]?.deviceKeys[client.deviceID];
|
||||
|
|
@ -210,12 +206,7 @@ class CrossSigning {
|
|||
}
|
||||
|
||||
String _sign(String canonicalJson, Uint8List key) {
|
||||
final keyObj = olm.PkSigning();
|
||||
try {
|
||||
keyObj.init_with_seed(key);
|
||||
return keyObj.sign(canonicalJson);
|
||||
} finally {
|
||||
keyObj.free();
|
||||
}
|
||||
final keyObj = vod.PkSigning.fromSecretKey(base64Encode(key));
|
||||
return keyObj.sign(canonicalJson).toBase64();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import 'dart:convert';
|
|||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:olm/olm.dart' as olm;
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/encryption/encryption.dart';
|
||||
import 'package:matrix/encryption/utils/base64_unpadded.dart';
|
||||
|
|
@ -45,19 +46,18 @@ class KeyManager {
|
|||
|
||||
KeyManager(this.encryption) {
|
||||
encryption.ssss.setValidator(megolmKey, (String secret) async {
|
||||
final keyObj = olm.PkDecryption();
|
||||
try {
|
||||
final keyObj = vod.PkDecryption.fromSecretKey(
|
||||
vod.Curve25519PublicKey.fromBase64(secret),
|
||||
);
|
||||
final info = await getRoomKeysBackupInfo(false);
|
||||
if (info.algorithm !=
|
||||
BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2) {
|
||||
return false;
|
||||
}
|
||||
return keyObj.init_with_private_key(base64decodeUnpadded(secret)) ==
|
||||
info.authData['public_key'];
|
||||
return keyObj.publicKey == info.authData['public_key'];
|
||||
} catch (_) {
|
||||
return false;
|
||||
} finally {
|
||||
keyObj.free();
|
||||
}
|
||||
});
|
||||
encryption.ssss.setCacheCallback(megolmKey, (String secret) {
|
||||
|
|
@ -669,54 +669,57 @@ class KeyManager {
|
|||
}
|
||||
final privateKey =
|
||||
base64decodeUnpadded((await encryption.ssss.getCached(megolmKey))!);
|
||||
final decryption = olm.PkDecryption();
|
||||
final info = await getRoomKeysBackupInfo();
|
||||
String backupPubKey;
|
||||
try {
|
||||
backupPubKey = decryption.init_with_private_key(privateKey);
|
||||
|
||||
if (info.algorithm != BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2 ||
|
||||
info.authData['public_key'] != backupPubKey) {
|
||||
return;
|
||||
}
|
||||
for (final roomEntry in keys.rooms.entries) {
|
||||
final roomId = roomEntry.key;
|
||||
for (final sessionEntry in roomEntry.value.sessions.entries) {
|
||||
final sessionId = sessionEntry.key;
|
||||
final session = sessionEntry.value;
|
||||
final sessionData = session.sessionData;
|
||||
Map<String, Object?>? decrypted;
|
||||
try {
|
||||
decrypted = json.decode(
|
||||
decryption.decrypt(
|
||||
sessionData['ephemeral'] as String,
|
||||
sessionData['mac'] as String,
|
||||
sessionData['ciphertext'] as String,
|
||||
final decryption = vod.PkDecryption.fromSecretKey(
|
||||
vod.Curve25519PublicKey.fromBytes(privateKey),
|
||||
);
|
||||
backupPubKey = decryption.publicKey;
|
||||
|
||||
if (info.algorithm != BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2 ||
|
||||
info.authData['public_key'] != backupPubKey) {
|
||||
return;
|
||||
}
|
||||
for (final roomEntry in keys.rooms.entries) {
|
||||
final roomId = roomEntry.key;
|
||||
for (final sessionEntry in roomEntry.value.sessions.entries) {
|
||||
final sessionId = sessionEntry.key;
|
||||
final session = sessionEntry.value;
|
||||
final sessionData = session.sessionData;
|
||||
Map<String, Object?>? decrypted;
|
||||
try {
|
||||
decrypted = json.decode(
|
||||
decryption.decrypt(
|
||||
vod.PkMessage(
|
||||
base64decodeUnpadded(sessionData['ciphertext'] as String),
|
||||
base64decodeUnpadded(sessionData['mac'] as String),
|
||||
vod.Curve25519PublicKey.fromBase64(
|
||||
sessionData['ephemeral'] as String,
|
||||
),
|
||||
),
|
||||
);
|
||||
} catch (e, s) {
|
||||
Logs().e('[LibOlm] Error decrypting room key', e, s);
|
||||
}
|
||||
final senderKey = decrypted?.tryGet<String>('sender_key');
|
||||
if (decrypted != null && senderKey != null) {
|
||||
decrypted['session_id'] = sessionId;
|
||||
decrypted['room_id'] = roomId;
|
||||
await setInboundGroupSession(
|
||||
roomId,
|
||||
sessionId,
|
||||
senderKey,
|
||||
decrypted,
|
||||
forwarded: true,
|
||||
senderClaimedKeys:
|
||||
decrypted.tryGetMap<String, String>('sender_claimed_keys') ??
|
||||
<String, String>{},
|
||||
uploaded: true,
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
} catch (e, s) {
|
||||
Logs().e('[LibOlm] Error decrypting room key', e, s);
|
||||
}
|
||||
final senderKey = decrypted?.tryGet<String>('sender_key');
|
||||
if (decrypted != null && senderKey != null) {
|
||||
decrypted['session_id'] = sessionId;
|
||||
decrypted['room_id'] = roomId;
|
||||
await setInboundGroupSession(
|
||||
roomId,
|
||||
sessionId,
|
||||
senderKey,
|
||||
decrypted,
|
||||
forwarded: true,
|
||||
senderClaimedKeys:
|
||||
decrypted.tryGetMap<String, String>('sender_claimed_keys') ??
|
||||
<String, String>{},
|
||||
uploaded: true,
|
||||
);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
decryption.free();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -875,57 +878,56 @@ class KeyManager {
|
|||
final privateKey =
|
||||
base64decodeUnpadded((await encryption.ssss.getCached(megolmKey))!);
|
||||
// decryption is needed to calculate the public key and thus see if the claimed information is in fact valid
|
||||
final decryption = olm.PkDecryption();
|
||||
|
||||
final info = await getRoomKeysBackupInfo(false);
|
||||
String backupPubKey;
|
||||
try {
|
||||
backupPubKey = decryption.init_with_private_key(privateKey);
|
||||
|
||||
if (info.algorithm !=
|
||||
BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2 ||
|
||||
info.authData['public_key'] != backupPubKey) {
|
||||
decryption.free();
|
||||
return;
|
||||
}
|
||||
final args = GenerateUploadKeysArgs(
|
||||
pubkey: backupPubKey,
|
||||
dbSessions: <DbInboundGroupSessionBundle>[],
|
||||
userId: userID,
|
||||
final decryption = vod.PkDecryption.fromSecretKey(
|
||||
vod.Curve25519PublicKey.fromBytes(privateKey),
|
||||
);
|
||||
backupPubKey = decryption.publicKey;
|
||||
|
||||
if (info.algorithm !=
|
||||
BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2 ||
|
||||
info.authData['public_key'] != backupPubKey) {
|
||||
return;
|
||||
}
|
||||
final args = GenerateUploadKeysArgs(
|
||||
pubkey: backupPubKey,
|
||||
dbSessions: <DbInboundGroupSessionBundle>[],
|
||||
userId: userID,
|
||||
);
|
||||
// we need to calculate verified beforehand, as else we pass a closure to an isolate
|
||||
// with 500 keys they do, however, noticably block the UI, which is why we give brief async suspentions in here
|
||||
// so that the event loop can progress
|
||||
var i = 0;
|
||||
for (final dbSession in dbSessions) {
|
||||
final device =
|
||||
client.getUserDeviceKeysByCurve25519Key(dbSession.senderKey);
|
||||
args.dbSessions.add(
|
||||
DbInboundGroupSessionBundle(
|
||||
dbSession: dbSession,
|
||||
verified: device?.verified ?? false,
|
||||
),
|
||||
);
|
||||
// we need to calculate verified beforehand, as else we pass a closure to an isolate
|
||||
// with 500 keys they do, however, noticably block the UI, which is why we give brief async suspentions in here
|
||||
// so that the event loop can progress
|
||||
var i = 0;
|
||||
for (final dbSession in dbSessions) {
|
||||
final device =
|
||||
client.getUserDeviceKeysByCurve25519Key(dbSession.senderKey);
|
||||
args.dbSessions.add(
|
||||
DbInboundGroupSessionBundle(
|
||||
dbSession: dbSession,
|
||||
verified: device?.verified ?? false,
|
||||
),
|
||||
);
|
||||
i++;
|
||||
if (i > 10) {
|
||||
await Future.delayed(Duration(milliseconds: 1));
|
||||
i = 0;
|
||||
}
|
||||
i++;
|
||||
if (i > 10) {
|
||||
await Future.delayed(Duration(milliseconds: 1));
|
||||
i = 0;
|
||||
}
|
||||
final roomKeys =
|
||||
await client.nativeImplementations.generateUploadKeys(args);
|
||||
Logs().i('[Key Manager] Uploading ${dbSessions.length} room keys...');
|
||||
// upload the payload...
|
||||
await client.putRoomKeys(info.version, roomKeys);
|
||||
// and now finally mark all the keys as uploaded
|
||||
// no need to optimze this, as we only run it so seldomly and almost never with many keys at once
|
||||
for (final dbSession in dbSessions) {
|
||||
await database.markInboundGroupSessionAsUploaded(
|
||||
dbSession.roomId,
|
||||
dbSession.sessionId,
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
decryption.free();
|
||||
}
|
||||
final roomKeys =
|
||||
await client.nativeImplementations.generateUploadKeys(args);
|
||||
Logs().i('[Key Manager] Uploading ${dbSessions.length} room keys...');
|
||||
// upload the payload...
|
||||
await client.putRoomKeys(info.version, roomKeys);
|
||||
// and now finally mark all the keys as uploaded
|
||||
// no need to optimze this, as we only run it so seldomly and almost never with many keys at once
|
||||
for (final dbSession in dbSessions) {
|
||||
await database.markInboundGroupSessionAsUploaded(
|
||||
dbSession.roomId,
|
||||
dbSession.sessionId,
|
||||
);
|
||||
}
|
||||
} catch (e, s) {
|
||||
Logs().e('[Key Manager] Error uploading room keys', e, s);
|
||||
|
|
@ -1247,9 +1249,10 @@ class RoomKeyRequest extends ToDeviceEvent {
|
|||
/// you would likely want to use [NativeImplementations] and
|
||||
/// [Client.nativeImplementations] instead
|
||||
RoomKeys generateUploadKeysImplementation(GenerateUploadKeysArgs args) {
|
||||
final enc = olm.PkEncryption();
|
||||
try {
|
||||
enc.set_recipient_key(args.pubkey);
|
||||
final enc = vod.PkEncryption.fromPublicKey(
|
||||
vod.Curve25519PublicKey.fromBase64(args.pubkey),
|
||||
);
|
||||
// first we generate the payload to upload all the session keys in this chunk
|
||||
final roomKeys = RoomKeys(rooms: {});
|
||||
for (final dbSession in args.dbSessions) {
|
||||
|
|
@ -1279,17 +1282,15 @@ RoomKeys generateUploadKeysImplementation(GenerateUploadKeysArgs args) {
|
|||
forwardedCount: sess.forwardingCurve25519KeyChain.length,
|
||||
isVerified: dbSession.verified, //device?.verified ?? false,
|
||||
sessionData: {
|
||||
'ephemeral': encrypted.ephemeral,
|
||||
'ciphertext': encrypted.ciphertext,
|
||||
'mac': encrypted.mac,
|
||||
'ephemeral': encrypted.ephemeralKey.toBase64(),
|
||||
'ciphertext': base64Encode(encrypted.ciphertext),
|
||||
'mac': base64Encode(encrypted.mac),
|
||||
},
|
||||
);
|
||||
}
|
||||
enc.free();
|
||||
return roomKeys;
|
||||
} catch (e, s) {
|
||||
Logs().e('[Key Manager] Error generating payload', e, s);
|
||||
enc.free();
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,12 +20,11 @@ import 'dart:convert';
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:canonical_json/canonical_json.dart';
|
||||
import 'package:olm/olm.dart' as olm;
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/encryption/encryption.dart';
|
||||
import 'package:matrix/encryption/key_manager.dart';
|
||||
import 'package:matrix/encryption/ssss.dart';
|
||||
import 'package:matrix/encryption/utils/base64_unpadded.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
enum BootstrapState {
|
||||
|
|
@ -371,106 +370,82 @@ class Bootstrap {
|
|||
}
|
||||
final userID = client.userID!;
|
||||
try {
|
||||
Uint8List masterSigningKey;
|
||||
String masterSigningKey;
|
||||
final secretsToStore = <String, String>{};
|
||||
MatrixCrossSigningKey? masterKey;
|
||||
MatrixCrossSigningKey? selfSigningKey;
|
||||
MatrixCrossSigningKey? userSigningKey;
|
||||
String? masterPub;
|
||||
if (setupMasterKey) {
|
||||
final master = olm.PkSigning();
|
||||
try {
|
||||
masterSigningKey = master.generate_seed();
|
||||
masterPub = master.init_with_seed(masterSigningKey);
|
||||
final json = <String, dynamic>{
|
||||
'user_id': userID,
|
||||
'usage': ['master'],
|
||||
'keys': <String, dynamic>{
|
||||
'ed25519:$masterPub': masterPub,
|
||||
},
|
||||
};
|
||||
masterKey = MatrixCrossSigningKey.fromJson(json);
|
||||
secretsToStore[EventTypes.CrossSigningMasterKey] =
|
||||
base64.encode(masterSigningKey);
|
||||
} finally {
|
||||
master.free();
|
||||
}
|
||||
final master = vod.PkSigning();
|
||||
masterSigningKey = master.secretKey;
|
||||
masterPub = master.publicKey.toBase64();
|
||||
final json = <String, dynamic>{
|
||||
'user_id': userID,
|
||||
'usage': ['master'],
|
||||
'keys': <String, dynamic>{
|
||||
'ed25519:$masterPub': masterPub,
|
||||
},
|
||||
};
|
||||
masterKey = MatrixCrossSigningKey.fromJson(json);
|
||||
secretsToStore[EventTypes.CrossSigningMasterKey] = masterSigningKey;
|
||||
} else {
|
||||
Logs().v('Get stored key...');
|
||||
masterSigningKey = base64decodeUnpadded(
|
||||
await newSsssKey?.getStored(EventTypes.CrossSigningMasterKey) ?? '',
|
||||
);
|
||||
masterSigningKey =
|
||||
await newSsssKey?.getStored(EventTypes.CrossSigningMasterKey) ?? '';
|
||||
if (masterSigningKey.isEmpty) {
|
||||
// no master signing key :(
|
||||
throw BootstrapBadStateException('No master key');
|
||||
}
|
||||
final master = olm.PkSigning();
|
||||
try {
|
||||
masterPub = master.init_with_seed(masterSigningKey);
|
||||
} finally {
|
||||
master.free();
|
||||
}
|
||||
final master = vod.PkSigning.fromSecretKey(masterSigningKey);
|
||||
masterPub = master.publicKey.toBase64();
|
||||
}
|
||||
String? sign(Map<String, dynamic> object) {
|
||||
final keyObj = olm.PkSigning();
|
||||
try {
|
||||
keyObj.init_with_seed(masterSigningKey);
|
||||
return keyObj
|
||||
.sign(String.fromCharCodes(canonicalJson.encode(object)));
|
||||
} finally {
|
||||
keyObj.free();
|
||||
}
|
||||
final keyObj = vod.PkSigning.fromSecretKey(masterSigningKey);
|
||||
return keyObj
|
||||
.sign(String.fromCharCodes(canonicalJson.encode(object)))
|
||||
.toBase64();
|
||||
}
|
||||
|
||||
if (setupSelfSigningKey) {
|
||||
final selfSigning = olm.PkSigning();
|
||||
try {
|
||||
final selfSigningPriv = selfSigning.generate_seed();
|
||||
final selfSigningPub = selfSigning.init_with_seed(selfSigningPriv);
|
||||
final json = <String, dynamic>{
|
||||
'user_id': userID,
|
||||
'usage': ['self_signing'],
|
||||
'keys': <String, dynamic>{
|
||||
'ed25519:$selfSigningPub': selfSigningPub,
|
||||
},
|
||||
};
|
||||
final signature = sign(json);
|
||||
json['signatures'] = <String, dynamic>{
|
||||
userID: <String, dynamic>{
|
||||
'ed25519:$masterPub': signature,
|
||||
},
|
||||
};
|
||||
selfSigningKey = MatrixCrossSigningKey.fromJson(json);
|
||||
secretsToStore[EventTypes.CrossSigningSelfSigning] =
|
||||
base64.encode(selfSigningPriv);
|
||||
} finally {
|
||||
selfSigning.free();
|
||||
}
|
||||
final selfSigning = vod.PkSigning();
|
||||
final selfSigningPriv = selfSigning.secretKey;
|
||||
final selfSigningPub = selfSigning.publicKey.toBase64();
|
||||
final json = <String, dynamic>{
|
||||
'user_id': userID,
|
||||
'usage': ['self_signing'],
|
||||
'keys': <String, dynamic>{
|
||||
'ed25519:$selfSigningPub': selfSigningPub,
|
||||
},
|
||||
};
|
||||
final signature = sign(json);
|
||||
json['signatures'] = <String, dynamic>{
|
||||
userID: <String, dynamic>{
|
||||
'ed25519:$masterPub': signature,
|
||||
},
|
||||
};
|
||||
selfSigningKey = MatrixCrossSigningKey.fromJson(json);
|
||||
secretsToStore[EventTypes.CrossSigningSelfSigning] = selfSigningPriv;
|
||||
}
|
||||
if (setupUserSigningKey) {
|
||||
final userSigning = olm.PkSigning();
|
||||
try {
|
||||
final userSigningPriv = userSigning.generate_seed();
|
||||
final userSigningPub = userSigning.init_with_seed(userSigningPriv);
|
||||
final json = <String, dynamic>{
|
||||
'user_id': userID,
|
||||
'usage': ['user_signing'],
|
||||
'keys': <String, dynamic>{
|
||||
'ed25519:$userSigningPub': userSigningPub,
|
||||
},
|
||||
};
|
||||
final signature = sign(json);
|
||||
json['signatures'] = <String, dynamic>{
|
||||
userID: <String, dynamic>{
|
||||
'ed25519:$masterPub': signature,
|
||||
},
|
||||
};
|
||||
userSigningKey = MatrixCrossSigningKey.fromJson(json);
|
||||
secretsToStore[EventTypes.CrossSigningUserSigning] =
|
||||
base64.encode(userSigningPriv);
|
||||
} finally {
|
||||
userSigning.free();
|
||||
}
|
||||
final userSigning = vod.PkSigning();
|
||||
final userSigningPriv = userSigning.secretKey;
|
||||
final userSigningPub = userSigning.publicKey.toBase64();
|
||||
final json = <String, dynamic>{
|
||||
'user_id': userID,
|
||||
'usage': ['user_signing'],
|
||||
'keys': <String, dynamic>{
|
||||
'ed25519:$userSigningPub': userSigningPub,
|
||||
},
|
||||
};
|
||||
final signature = sign(json);
|
||||
json['signatures'] = <String, dynamic>{
|
||||
userID: <String, dynamic>{
|
||||
'ed25519:$masterPub': signature,
|
||||
},
|
||||
};
|
||||
userSigningKey = MatrixCrossSigningKey.fromJson(json);
|
||||
secretsToStore[EventTypes.CrossSigningUserSigning] = userSigningPriv;
|
||||
}
|
||||
// upload the keys!
|
||||
state = BootstrapState.loading;
|
||||
|
|
@ -561,15 +536,13 @@ class Bootstrap {
|
|||
return;
|
||||
}
|
||||
try {
|
||||
final keyObj = olm.PkDecryption();
|
||||
final keyObj = vod.PkDecryption();
|
||||
String pubKey;
|
||||
Uint8List privKey;
|
||||
try {
|
||||
pubKey = keyObj.generate_key();
|
||||
privKey = keyObj.get_private_key();
|
||||
} finally {
|
||||
keyObj.free();
|
||||
}
|
||||
|
||||
pubKey = keyObj.publicKey;
|
||||
privKey = keyObj.privateKey;
|
||||
|
||||
Logs().v('Create the new backup version...');
|
||||
await client.postRoomKeysVersion(
|
||||
BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
|
||||
import 'package:canonical_json/canonical_json.dart';
|
||||
import 'package:olm/olm.dart' as olm;
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
|
|
@ -37,15 +37,15 @@ extension JsonSignatureCheckExtension on Map<String, dynamic> {
|
|||
final canonical = canonicalJson.encode(this);
|
||||
final message = String.fromCharCodes(canonical);
|
||||
var isValid = false;
|
||||
final olmutil = olm.Utility();
|
||||
try {
|
||||
olmutil.ed25519_verify(key, message, signature);
|
||||
vod.Ed25519PublicKey.fromBase64(key).verify(
|
||||
message: message,
|
||||
signature: vod.Ed25519Signature.fromBase64(signature),
|
||||
);
|
||||
isValid = true;
|
||||
} catch (e, s) {
|
||||
isValid = false;
|
||||
Logs().w('[LibOlm] Signature check failed', e, s);
|
||||
} finally {
|
||||
olmutil.free();
|
||||
}
|
||||
return isValid;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,9 @@ import 'dart:convert';
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:canonical_json/canonical_json.dart';
|
||||
import 'package:olm/olm.dart' as olm;
|
||||
import 'package:crypto/crypto.dart' as crypto;
|
||||
import 'package:typed_data/typed_data.dart';
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/encryption/encryption.dart';
|
||||
import 'package:matrix/encryption/utils/base64_unpadded.dart';
|
||||
|
|
@ -1258,12 +1259,8 @@ class _KeyVerificationMethodSas extends _KeyVerificationMethod {
|
|||
String? commitment;
|
||||
late String theirPublicKey;
|
||||
Map<String, dynamic>? macPayload;
|
||||
olm.SAS? sas;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
sas?.free();
|
||||
}
|
||||
vod.Sas? sas;
|
||||
vod.EstablishedSas? establishedSas;
|
||||
|
||||
List<String> get knownAuthentificationTypes {
|
||||
final types = <String>[];
|
||||
|
|
@ -1322,7 +1319,7 @@ class _KeyVerificationMethodSas extends _KeyVerificationMethod {
|
|||
await _sendKey();
|
||||
} else {
|
||||
// we already sent our key, time to verify the commitment being valid
|
||||
if (!_validateCommitment()) {
|
||||
if (await _validateCommitment() == false) {
|
||||
await request.cancel('m.mismatched_commitment');
|
||||
return;
|
||||
}
|
||||
|
|
@ -1415,8 +1412,8 @@ class _KeyVerificationMethodSas extends _KeyVerificationMethod {
|
|||
}
|
||||
|
||||
Future<void> _sendAccept() async {
|
||||
final sas = this.sas = olm.SAS();
|
||||
commitment = _makeCommitment(sas.get_pubkey(), startCanonicalJson);
|
||||
final sas = this.sas = vod.Sas();
|
||||
commitment = await _makeCommitment(sas.publicKey, startCanonicalJson);
|
||||
await request.send(EventTypes.KeyVerificationAccept, {
|
||||
'method': type,
|
||||
'key_agreement_protocol': keyAgreementProtocol,
|
||||
|
|
@ -1451,31 +1448,31 @@ class _KeyVerificationMethodSas extends _KeyVerificationMethod {
|
|||
}
|
||||
authenticationTypes = possibleAuthenticationTypes;
|
||||
commitment = payload['commitment'];
|
||||
sas = olm.SAS();
|
||||
sas = vod.Sas();
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<void> _sendKey() async {
|
||||
await request.send('m.key.verification.key', {
|
||||
'key': sas!.get_pubkey(),
|
||||
'key': sas!.publicKey,
|
||||
});
|
||||
}
|
||||
|
||||
void _handleKey(Map<String, dynamic> payload) {
|
||||
theirPublicKey = payload['key'];
|
||||
sas!.set_their_key(payload['key']);
|
||||
establishedSas = sas!.establishSasSecret(payload['key']);
|
||||
}
|
||||
|
||||
bool _validateCommitment() {
|
||||
final checkCommitment = _makeCommitment(theirPublicKey, startCanonicalJson);
|
||||
Future<bool> _validateCommitment() async {
|
||||
final checkCommitment =
|
||||
await _makeCommitment(theirPublicKey, startCanonicalJson);
|
||||
return commitment == checkCommitment;
|
||||
}
|
||||
|
||||
Uint8List makeSas(int bytes) {
|
||||
var sasInfo = '';
|
||||
if (keyAgreementProtocol == 'curve25519-hkdf-sha256') {
|
||||
final ourInfo =
|
||||
'${client.userID}|${client.deviceID}|${sas!.get_pubkey()}|';
|
||||
final ourInfo = '${client.userID}|${client.deviceID}|${sas!.publicKey}|';
|
||||
final theirInfo =
|
||||
'${request.userId}|${request.deviceId}|$theirPublicKey|';
|
||||
sasInfo =
|
||||
|
|
@ -1488,7 +1485,7 @@ class _KeyVerificationMethodSas extends _KeyVerificationMethod {
|
|||
} else {
|
||||
throw Exception('Unknown key agreement protocol');
|
||||
}
|
||||
return sas!.generate_bytes(sasInfo, bytes);
|
||||
return establishedSas!.generateBytes(sasInfo, bytes);
|
||||
}
|
||||
|
||||
Future<void> _sendMac() async {
|
||||
|
|
@ -1554,21 +1551,20 @@ class _KeyVerificationMethodSas extends _KeyVerificationMethod {
|
|||
});
|
||||
}
|
||||
|
||||
String _makeCommitment(String pubKey, String canonicalJson) {
|
||||
Future<String> _makeCommitment(String pubKey, String canonicalJson) async {
|
||||
if (hash == 'sha256') {
|
||||
final olmutil = olm.Utility();
|
||||
final ret = olmutil.sha256(pubKey + canonicalJson);
|
||||
olmutil.free();
|
||||
return ret;
|
||||
final bytes = utf8.encode(pubKey + canonicalJson);
|
||||
final digest = crypto.sha256.convert(bytes);
|
||||
return base64.encode(digest.bytes);
|
||||
}
|
||||
throw Exception('Unknown hash method');
|
||||
}
|
||||
|
||||
String _calculateMac(String input, String info) {
|
||||
if (messageAuthenticationCode == 'hkdf-hmac-sha256.v2') {
|
||||
return sas!.calculate_mac_fixed_base64(input, info);
|
||||
return establishedSas!.calculateMac(input, info);
|
||||
} else if (messageAuthenticationCode == 'hkdf-hmac-sha256') {
|
||||
return sas!.calculate_mac(input, info);
|
||||
return establishedSas!.calculateMacDeprecated(input, info);
|
||||
} else {
|
||||
throw Exception('Unknown message authentification code');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import 'dart:convert';
|
|||
|
||||
import 'package:canonical_json/canonical_json.dart';
|
||||
import 'package:collection/collection.dart' show IterableExtension;
|
||||
import 'package:olm/olm.dart' as olm;
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/encryption.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
|
@ -240,24 +240,17 @@ abstract class SignableKey extends MatrixSignableKey {
|
|||
String signature, {
|
||||
bool isSignatureWithoutLibolmValid = false,
|
||||
}) {
|
||||
olm.Utility olmutil;
|
||||
try {
|
||||
olmutil = olm.Utility();
|
||||
} catch (e) {
|
||||
// if no libolm is present we land in this catch block, and return the default
|
||||
// set if no libolm is there. Some signatures should be assumed-valid while others
|
||||
// should be assumed-invalid
|
||||
return isSignatureWithoutLibolmValid;
|
||||
}
|
||||
var valid = false;
|
||||
try {
|
||||
olmutil.ed25519_verify(pubKey, signingContent, signature);
|
||||
vod.Ed25519PublicKey.fromBase64(pubKey).verify(
|
||||
message: signingContent,
|
||||
signature: vod.Ed25519Signature.fromBase64(signature),
|
||||
);
|
||||
valid = true;
|
||||
} catch (_) {
|
||||
} catch (e) {
|
||||
Logs().d('Invalid Ed25519 signature', e);
|
||||
// bad signature
|
||||
valid = false;
|
||||
} finally {
|
||||
olmutil.free();
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,11 @@ dependencies:
|
|||
sqflite_common: ^2.4.5
|
||||
sqlite3: ^2.1.0
|
||||
typed_data: ^1.3.2
|
||||
vodozemac:
|
||||
git:
|
||||
url: https://github.com/famedly/dart-vodozemac.git
|
||||
path: dart
|
||||
ref: main
|
||||
webrtc_interface: ^1.2.0
|
||||
|
||||
dev_dependencies:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
git clone https://github.com/famedly/dart-vodozemac.git
|
||||
mv ./dart-vodozemac/rust ./
|
||||
rm -rf dart-vodozemac
|
||||
cd ./rust
|
||||
cargo build
|
||||
cd ..
|
||||
|
|
@ -26,6 +26,7 @@ import 'package:collection/collection.dart';
|
|||
import 'package:olm/olm.dart' as olm;
|
||||
import 'package:path/path.dart' show join;
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
import 'package:matrix/src/utils/client_init_exception.dart';
|
||||
|
|
@ -67,11 +68,15 @@ void main() {
|
|||
group('client mem', tags: 'olm', () {
|
||||
late Client matrix;
|
||||
|
||||
Logs().level = Level.error;
|
||||
Future? vodInit;
|
||||
|
||||
/// Check if all Elements get created
|
||||
|
||||
setUp(() async {
|
||||
vodInit ??= vod.init(
|
||||
wasmPath: './pkg/',
|
||||
libraryPath: './rust/target/debug/',
|
||||
);
|
||||
await vodInit;
|
||||
matrix = await getClient();
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -19,18 +19,26 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
import './fake_client.dart';
|
||||
|
||||
void main() {
|
||||
void main() async {
|
||||
/// All Tests related to device keys
|
||||
group('Device keys', tags: 'olm', () {
|
||||
Logs().level = Level.error;
|
||||
|
||||
late Client client;
|
||||
|
||||
Future? vodInit;
|
||||
|
||||
test('setupClient', () async {
|
||||
vodInit ??= vod.init(
|
||||
wasmPath: './pkg/',
|
||||
libraryPath: './rust/target/debug/',
|
||||
);
|
||||
await vodInit;
|
||||
client = await getClient();
|
||||
await client.abortSync();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import 'dart:convert';
|
|||
|
||||
import 'package:olm/olm.dart' as olm;
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/encryption.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
|
@ -35,6 +36,10 @@ void main() {
|
|||
late String origKeyId;
|
||||
|
||||
setUpAll(() async {
|
||||
await vod.init(
|
||||
wasmPath: './pkg/',
|
||||
libraryPath: './rust/target/debug/',
|
||||
);
|
||||
await olm.init();
|
||||
olm.get_library_version();
|
||||
client = await getClient();
|
||||
|
|
@ -75,20 +80,16 @@ void main() {
|
|||
|
||||
// test all the x-signing keys match up
|
||||
for (final keyType in {'master', 'user_signing', 'self_signing'}) {
|
||||
final privateKey = base64
|
||||
.decode(await defaultKey.getStored('m.cross_signing.$keyType'));
|
||||
final keyObj = olm.PkSigning();
|
||||
try {
|
||||
final pubKey = keyObj.init_with_seed(privateKey);
|
||||
expect(
|
||||
pubKey,
|
||||
client.userDeviceKeys[client.userID]
|
||||
?.getCrossSigningKey(keyType)
|
||||
?.publicKey,
|
||||
);
|
||||
} finally {
|
||||
keyObj.free();
|
||||
}
|
||||
final privateKey =
|
||||
await defaultKey.getStored('m.cross_signing.$keyType');
|
||||
final keyObj = vod.PkSigning.fromSecretKey(privateKey);
|
||||
final pubKey = keyObj.publicKey.toBase64();
|
||||
expect(
|
||||
pubKey,
|
||||
client.userDeviceKeys[client.userID]
|
||||
?.getCrossSigningKey(keyType)
|
||||
?.publicKey,
|
||||
);
|
||||
}
|
||||
|
||||
await defaultKey.store('foxes', 'floof');
|
||||
|
|
@ -133,20 +134,16 @@ void main() {
|
|||
|
||||
// test all the x-signing keys match up
|
||||
for (final keyType in {'master', 'user_signing', 'self_signing'}) {
|
||||
final privateKey = base64
|
||||
.decode(await defaultKey.getStored('m.cross_signing.$keyType'));
|
||||
final keyObj = olm.PkSigning();
|
||||
try {
|
||||
final pubKey = keyObj.init_with_seed(privateKey);
|
||||
expect(
|
||||
pubKey,
|
||||
client.userDeviceKeys[client.userID]
|
||||
?.getCrossSigningKey(keyType)
|
||||
?.publicKey,
|
||||
);
|
||||
} finally {
|
||||
keyObj.free();
|
||||
}
|
||||
final privateKey =
|
||||
await defaultKey.getStored('m.cross_signing.$keyType');
|
||||
final keyObj = vod.PkSigning.fromSecretKey(privateKey);
|
||||
final pubKey = keyObj.publicKey.toBase64();
|
||||
expect(
|
||||
pubKey,
|
||||
client.userDeviceKeys[client.userID]
|
||||
?.getCrossSigningKey(keyType)
|
||||
?.publicKey,
|
||||
);
|
||||
}
|
||||
|
||||
expect(await defaultKey.getStored('foxes'), 'floof');
|
||||
|
|
@ -192,20 +189,16 @@ void main() {
|
|||
|
||||
// test all the x-signing keys match up
|
||||
for (final keyType in {'master', 'user_signing', 'self_signing'}) {
|
||||
final privateKey = base64
|
||||
.decode(await defaultKey.getStored('m.cross_signing.$keyType'));
|
||||
final keyObj = olm.PkSigning();
|
||||
try {
|
||||
final pubKey = keyObj.init_with_seed(privateKey);
|
||||
expect(
|
||||
pubKey,
|
||||
client.userDeviceKeys[client.userID]
|
||||
?.getCrossSigningKey(keyType)
|
||||
?.publicKey,
|
||||
);
|
||||
} finally {
|
||||
keyObj.free();
|
||||
}
|
||||
final privateKey =
|
||||
await defaultKey.getStored('m.cross_signing.$keyType');
|
||||
final keyObj = vod.PkSigning.fromSecretKey(privateKey);
|
||||
final pubKey = keyObj.publicKey.toBase64();
|
||||
expect(
|
||||
pubKey,
|
||||
client.userDeviceKeys[client.userID]
|
||||
?.getCrossSigningKey(keyType)
|
||||
?.publicKey,
|
||||
);
|
||||
}
|
||||
|
||||
expect(await defaultKey.getStored('foxes'), 'floof');
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import 'dart:convert';
|
|||
|
||||
import 'package:olm/olm.dart' as olm;
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
import '../fake_client.dart';
|
||||
|
|
@ -31,6 +32,10 @@ void main() {
|
|||
late Client client;
|
||||
|
||||
setUpAll(() async {
|
||||
await vod.init(
|
||||
wasmPath: './pkg/',
|
||||
libraryPath: './rust/target/debug/',
|
||||
);
|
||||
await olm.init();
|
||||
olm.get_library_version();
|
||||
client = await getClient();
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
import 'package:olm/olm.dart' as olm;
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
import '../fake_client.dart';
|
||||
|
|
@ -33,6 +34,10 @@ void main() {
|
|||
final now = DateTime.now();
|
||||
|
||||
setUpAll(() async {
|
||||
await vod.init(
|
||||
wasmPath: './pkg/',
|
||||
libraryPath: './rust/target/debug/',
|
||||
);
|
||||
await olm.init();
|
||||
olm.get_library_version();
|
||||
client = await getClient();
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
import 'package:olm/olm.dart' as olm;
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
import '../fake_client.dart';
|
||||
|
|
@ -41,6 +42,10 @@ void main() async {
|
|||
late Map<String, dynamic> payload;
|
||||
|
||||
setUpAll(() async {
|
||||
await vod.init(
|
||||
wasmPath: './pkg/',
|
||||
libraryPath: './rust/target/debug/',
|
||||
);
|
||||
await olm.init();
|
||||
olm.get_library_version();
|
||||
client = await getClient();
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import 'dart:convert';
|
|||
|
||||
import 'package:olm/olm.dart' as olm;
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
import '../fake_client.dart';
|
||||
|
|
@ -30,6 +31,10 @@ void main() {
|
|||
late Client client;
|
||||
|
||||
setUpAll(() async {
|
||||
await vod.init(
|
||||
wasmPath: './pkg/',
|
||||
libraryPath: './rust/target/debug/',
|
||||
);
|
||||
await olm.init();
|
||||
olm.get_library_version();
|
||||
client = await getClient();
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import 'dart:convert';
|
|||
|
||||
import 'package:olm/olm.dart' as olm;
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
import '../fake_client.dart';
|
||||
|
|
@ -42,6 +43,10 @@ void main() {
|
|||
Logs().level = Level.error;
|
||||
|
||||
setUpAll(() async {
|
||||
await vod.init(
|
||||
wasmPath: './pkg/',
|
||||
libraryPath: './rust/target/debug/',
|
||||
);
|
||||
await olm.init();
|
||||
olm.get_library_version();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import 'dart:typed_data';
|
|||
|
||||
import 'package:olm/olm.dart' as olm;
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/encryption.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
|
@ -58,6 +59,10 @@ void main() async {
|
|||
late Client client2;
|
||||
|
||||
setUpAll(() async {
|
||||
await vod.init(
|
||||
wasmPath: './pkg/',
|
||||
libraryPath: './rust/target/debug/',
|
||||
);
|
||||
await olm.init();
|
||||
olm.get_library_version();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import 'dart:convert';
|
|||
|
||||
import 'package:olm/olm.dart' as olm;
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/encryption/utils/json_signature_check_extension.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
|
@ -32,6 +33,10 @@ void main() {
|
|||
late Client client;
|
||||
|
||||
setUpAll(() async {
|
||||
await vod.init(
|
||||
wasmPath: './pkg/',
|
||||
libraryPath: './rust/target/debug/',
|
||||
);
|
||||
await olm.init();
|
||||
olm.get_library_version();
|
||||
client = await getClient();
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import 'dart:convert';
|
|||
|
||||
import 'package:olm/olm.dart' as olm;
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
import '../fake_client.dart';
|
||||
|
|
@ -35,6 +36,10 @@ void main() {
|
|||
final senderKey = 'JBG7ZaPn54OBC7TuIEiylW3BZ+7WcGQhFBPB9pogbAg';
|
||||
|
||||
setUpAll(() async {
|
||||
await vod.init(
|
||||
wasmPath: './pkg/',
|
||||
libraryPath: './rust/target/debug/',
|
||||
);
|
||||
await olm.init();
|
||||
olm.get_library_version();
|
||||
client = await getClient();
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import 'dart:async';
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/encryption.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
|
@ -69,7 +70,14 @@ void main() async {
|
|||
|
||||
late Client client1;
|
||||
late Client client2;
|
||||
Future? vodInit;
|
||||
|
||||
setUp(() async {
|
||||
vodInit ??= vod.init(
|
||||
wasmPath: './pkg/',
|
||||
libraryPath: './rust/target/debug/',
|
||||
);
|
||||
await vodInit;
|
||||
client1 = await getClient();
|
||||
client2 = await getOtherClient();
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import 'dart:typed_data';
|
|||
|
||||
import 'package:olm/olm.dart' as olm;
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/encryption.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
|
@ -54,6 +55,10 @@ void main() {
|
|||
late Client client;
|
||||
|
||||
setUpAll(() async {
|
||||
await vod.init(
|
||||
wasmPath: './pkg/',
|
||||
libraryPath: './rust/target/debug/',
|
||||
);
|
||||
await olm.init();
|
||||
olm.get_library_version();
|
||||
client = await getClient();
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import 'dart:math';
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
import 'fake_client.dart';
|
||||
|
|
@ -671,12 +672,20 @@ void main() {
|
|||
expect(fetchedParticipants.length, newParticipants.length);
|
||||
});
|
||||
|
||||
test('calcEncryptionHealthState', () async {
|
||||
expect(
|
||||
await room.calcEncryptionHealthState(),
|
||||
EncryptionHealthState.unverifiedDevices,
|
||||
);
|
||||
});
|
||||
test(
|
||||
'calcEncryptionHealthState',
|
||||
() async {
|
||||
await vod.init(
|
||||
wasmPath: './pkg/',
|
||||
libraryPath: './rust/target/debug/',
|
||||
);
|
||||
expect(
|
||||
await room.calcEncryptionHealthState(),
|
||||
EncryptionHealthState.allVerified,
|
||||
);
|
||||
},
|
||||
tags: 'olm',
|
||||
);
|
||||
|
||||
test('getEventByID', () async {
|
||||
final event = await room.getEventById('1234');
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import 'dart:io';
|
|||
|
||||
import 'package:olm/olm.dart' as olm;
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vodozemac/vodozemac.dart' as vod;
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
import '../test/fake_database.dart';
|
||||
|
|
@ -39,6 +40,10 @@ void main() => group(
|
|||
Client? testClientA, testClientB;
|
||||
|
||||
try {
|
||||
await vod.init(
|
||||
wasmPath: './pkg/',
|
||||
libraryPath: './rust/target/debug/',
|
||||
);
|
||||
await olm.init();
|
||||
olm.Account();
|
||||
Logs().i('[LibOlm] Enabled');
|
||||
|
|
|
|||
Loading…
Reference in New Issue