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