matrix-js-sdk 41.1.0 → 41.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/lib/@types/requests.d.ts +3 -1
- package/lib/@types/requests.d.ts.map +1 -1
- package/lib/@types/requests.js.map +1 -1
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +12 -7
- package/lib/client.js.map +1 -1
- package/lib/common-crypto/CryptoBackend.d.ts +6 -1
- package/lib/common-crypto/CryptoBackend.d.ts.map +1 -1
- package/lib/common-crypto/CryptoBackend.js.map +1 -1
- package/lib/crypto-api/index.d.ts +0 -7
- package/lib/crypto-api/index.d.ts.map +1 -1
- package/lib/crypto-api/index.js.map +1 -1
- package/lib/matrix.d.ts +1 -0
- package/lib/matrix.d.ts.map +1 -1
- package/lib/matrix.js +1 -0
- package/lib/matrix.js.map +1 -1
- package/lib/rendezvous/MSC4108SignInWithQR.d.ts.map +1 -1
- package/lib/rendezvous/MSC4108SignInWithQR.js +5 -5
- package/lib/rendezvous/MSC4108SignInWithQR.js.map +1 -1
- package/lib/rendezvous/channels/MSC4108SecureChannel.d.ts +3 -3
- package/lib/rendezvous/channels/MSC4108SecureChannel.d.ts.map +1 -1
- package/lib/rendezvous/channels/MSC4108SecureChannel.js +2 -2
- package/lib/rendezvous/channels/MSC4108SecureChannel.js.map +1 -1
- package/lib/rust-crypto/index.d.ts.map +1 -1
- package/lib/rust-crypto/index.js +13 -1
- package/lib/rust-crypto/index.js.map +1 -1
- package/lib/rust-crypto/rust-crypto.d.ts +3 -3
- package/lib/rust-crypto/rust-crypto.d.ts.map +1 -1
- package/lib/rust-crypto/rust-crypto.js +306 -281
- package/lib/rust-crypto/rust-crypto.js.map +1 -1
- package/package.json +3 -3
- package/src/@types/requests.ts +3 -1
- package/src/client.ts +10 -6
- package/src/common-crypto/CryptoBackend.ts +13 -1
- package/src/crypto-api/index.ts +0 -14
- package/src/matrix.ts +1 -0
- package/src/rendezvous/MSC4108SignInWithQR.ts +6 -6
- package/src/rendezvous/channels/MSC4108SecureChannel.ts +5 -5
- package/src/rust-crypto/index.ts +17 -1
- package/src/rust-crypto/rust-crypto.ts +70 -46
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "matrix-js-sdk",
|
|
3
|
-
"version": "41.
|
|
3
|
+
"version": "41.2.0",
|
|
4
4
|
"description": "Matrix Client-Server SDK for Javascript",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22.0.0"
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
],
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@babel/runtime": "^7.12.5",
|
|
51
|
-
"@matrix-org/matrix-sdk-crypto-wasm": "^
|
|
51
|
+
"@matrix-org/matrix-sdk-crypto-wasm": "^18.0.0",
|
|
52
52
|
"another-json": "^0.2.0",
|
|
53
53
|
"bs58": "^6.0.0",
|
|
54
54
|
"content-type": "^1.0.4",
|
|
@@ -131,5 +131,5 @@
|
|
|
131
131
|
"eslint": "8"
|
|
132
132
|
}
|
|
133
133
|
},
|
|
134
|
-
"packageManager": "pnpm@10.
|
|
134
|
+
"packageManager": "pnpm@10.30.3+sha512.c961d1e0a2d8e354ecaa5166b822516668b7f44cb5bd95122d590dd81922f606f5473b6d23ec4a5be05e7fcd18e8488d47d978bbe981872f1145d06e9a740017"
|
|
135
135
|
}
|
package/src/@types/requests.ts
CHANGED
|
@@ -58,7 +58,9 @@ export interface InviteOpts {
|
|
|
58
58
|
/**
|
|
59
59
|
* Before sending the invite, if the room is encrypted, share the keys for any messages sent while the history
|
|
60
60
|
* visibility was `shared`, via the experimental
|
|
61
|
-
* support for [MSC4268](https://github.com/matrix-org/matrix-spec-proposals/pull/4268).
|
|
61
|
+
* support for [MSC4268](https://github.com/matrix-org/matrix-spec-proposals/pull/4268). If the room's current
|
|
62
|
+
* history visibility setting is neither `shared` nor `world_readable`, history sharing will be disabled to prevent
|
|
63
|
+
* exposing keys for messages sent prior to the visibility restriction.
|
|
62
64
|
*
|
|
63
65
|
* @experimental
|
|
64
66
|
*/
|
package/src/client.ts
CHANGED
|
@@ -2428,12 +2428,10 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
2428
2428
|
|
|
2429
2429
|
const roomId = res.room_id;
|
|
2430
2430
|
if (opts.acceptSharedHistory && inviter && this.cryptoBackend) {
|
|
2431
|
+
// Flag upfront that we are waiting for a key bundle, so that if we crash mid-import, we can try again.
|
|
2432
|
+
await this.cryptoBackend.markRoomAsPendingKeyBundle(roomId, inviter);
|
|
2431
2433
|
// Try to accept the room key bundle specified in a `m.room_key_bundle` to-device message we (might have) already received.
|
|
2432
|
-
|
|
2433
|
-
// If this fails, i.e. we haven't received this message yet, we need to wait until the to-device message arrives.
|
|
2434
|
-
if (!bundleDownloaded) {
|
|
2435
|
-
this.cryptoBackend.markRoomAsPendingKeyBundle(roomId, inviter);
|
|
2436
|
-
}
|
|
2434
|
+
await this.cryptoBackend.maybeAcceptKeyBundle(roomId, inviter);
|
|
2437
2435
|
}
|
|
2438
2436
|
|
|
2439
2437
|
// In case we were originally given an alias, check the room cache again
|
|
@@ -4088,7 +4086,13 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|
|
4088
4086
|
}
|
|
4089
4087
|
|
|
4090
4088
|
if (opts.shareEncryptedHistory) {
|
|
4091
|
-
|
|
4089
|
+
const historyVisibility = this.getRoom(roomId)?.getHistoryVisibility() ?? HistoryVisibility.Shared;
|
|
4090
|
+
// We should only share room history if the *current* visibility allows it.
|
|
4091
|
+
if ([HistoryVisibility.Invited, HistoryVisibility.Joined].includes(historyVisibility)) {
|
|
4092
|
+
this.logger.debug("Not sharing message history as the room history visibility is currently unshared");
|
|
4093
|
+
} else {
|
|
4094
|
+
await this.cryptoBackend?.shareRoomHistoryWithUser(roomId, userId);
|
|
4095
|
+
}
|
|
4092
4096
|
}
|
|
4093
4097
|
|
|
4094
4098
|
return await this.membershipChange(roomId, userId, KnownMembership.Invite, opts.reason);
|
|
@@ -80,6 +80,18 @@ export interface CryptoBackend extends SyncCryptoCallbacks, CryptoApi {
|
|
|
80
80
|
*/
|
|
81
81
|
importBackedUpRoomKeys(keys: IMegolmSessionData[], backupVersion: string, opts?: ImportRoomKeysOpts): Promise<void>;
|
|
82
82
|
|
|
83
|
+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
84
|
+
//
|
|
85
|
+
// Room key history sharing (MSC4268)
|
|
86
|
+
//
|
|
87
|
+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Share any shareable E2EE history in the given room with the given recipient,
|
|
91
|
+
* as per [MSC4268](https://github.com/matrix-org/matrix-spec-proposals/pull/4268)
|
|
92
|
+
*/
|
|
93
|
+
shareRoomHistoryWithUser(roomId: string, userId: string): Promise<void>;
|
|
94
|
+
|
|
83
95
|
/**
|
|
84
96
|
* Having accepted an invite for the given room from the given user, attempt to
|
|
85
97
|
* find information about a room key bundle and, if found, download the
|
|
@@ -103,7 +115,7 @@ export interface CryptoBackend extends SyncCryptoCallbacks, CryptoApi {
|
|
|
103
115
|
* @param roomId - The room we were invited to, for which we did not receive a key bundle before accepting the invite.
|
|
104
116
|
* @param inviterId - The user who invited us to the room and is expected to send the room key bundle.
|
|
105
117
|
*/
|
|
106
|
-
markRoomAsPendingKeyBundle(roomId: string, inviterId: string): void
|
|
118
|
+
markRoomAsPendingKeyBundle(roomId: string, inviterId: string): Promise<void>;
|
|
107
119
|
}
|
|
108
120
|
|
|
109
121
|
/** The methods which crypto implementations should expose to the Sync api
|
package/src/crypto-api/index.ts
CHANGED
|
@@ -720,20 +720,6 @@ export interface CryptoApi {
|
|
|
720
720
|
* @param secrets - The secrets bundle received from the other device
|
|
721
721
|
*/
|
|
722
722
|
importSecretsBundle?(secrets: Awaited<ReturnType<SecretsBundle["to_json"]>>): Promise<void>;
|
|
723
|
-
|
|
724
|
-
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
725
|
-
//
|
|
726
|
-
// Room key history sharing (MSC4268)
|
|
727
|
-
//
|
|
728
|
-
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
729
|
-
|
|
730
|
-
/**
|
|
731
|
-
* Share any shareable E2EE history in the given room with the given recipient,
|
|
732
|
-
* as per [MSC4268](https://github.com/matrix-org/matrix-spec-proposals/pull/4268)
|
|
733
|
-
*
|
|
734
|
-
* @experimental
|
|
735
|
-
*/
|
|
736
|
-
shareRoomHistoryWithUser(roomId: string, userId: string): Promise<void>;
|
|
737
723
|
}
|
|
738
724
|
|
|
739
725
|
/** A reason code for a failure to decrypt an event. */
|
package/src/matrix.ts
CHANGED
|
@@ -82,6 +82,7 @@ export * from "./models/room-summary.ts";
|
|
|
82
82
|
export * from "./models/event-status.ts";
|
|
83
83
|
export * from "./models/profile-keys.ts";
|
|
84
84
|
export * from "./models/related-relations.ts";
|
|
85
|
+
export { type StickyMatrixEvent, RoomStickyEventsEvent } from "./models/room-sticky-events.ts";
|
|
85
86
|
export type { RoomSummary } from "./client.ts";
|
|
86
87
|
export * as ContentHelpers from "./content-helpers.ts";
|
|
87
88
|
export * as SecretStorage from "./secret-storage.ts";
|
|
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import {
|
|
17
|
+
import { QrCodeIntent } from "@matrix-org/matrix-sdk-crypto-wasm";
|
|
18
18
|
|
|
19
19
|
import {
|
|
20
20
|
ClientRendezvousFailureReason,
|
|
@@ -108,7 +108,7 @@ interface SecretsPayload extends MSC4108Payload, Awaited<ReturnType<NonNullable<
|
|
|
108
108
|
* @experimental Note that this is UNSTABLE and may have breaking changes without notice.
|
|
109
109
|
*/
|
|
110
110
|
export class MSC4108SignInWithQR {
|
|
111
|
-
private readonly ourIntent:
|
|
111
|
+
private readonly ourIntent: QrCodeIntent;
|
|
112
112
|
private _code?: Uint8Array;
|
|
113
113
|
private expectingNewDeviceId?: string;
|
|
114
114
|
|
|
@@ -131,7 +131,7 @@ export class MSC4108SignInWithQR {
|
|
|
131
131
|
private readonly client?: MatrixClient,
|
|
132
132
|
public onFailure?: RendezvousFailureListener,
|
|
133
133
|
) {
|
|
134
|
-
this.ourIntent = client ?
|
|
134
|
+
this.ourIntent = client ? QrCodeIntent.Reciprocate : QrCodeIntent.Login;
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
/**
|
|
@@ -149,9 +149,9 @@ export class MSC4108SignInWithQR {
|
|
|
149
149
|
return;
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
if (this.ourIntent ===
|
|
152
|
+
if (this.ourIntent === QrCodeIntent.Reciprocate && this.client) {
|
|
153
153
|
this._code = await this.channel.generateCode(this.ourIntent, this.client.getDomain()!);
|
|
154
|
-
} else if (this.ourIntent ===
|
|
154
|
+
} else if (this.ourIntent === QrCodeIntent.Login) {
|
|
155
155
|
this._code = await this.channel.generateCode(this.ourIntent);
|
|
156
156
|
}
|
|
157
157
|
}
|
|
@@ -160,7 +160,7 @@ export class MSC4108SignInWithQR {
|
|
|
160
160
|
* Returns true if the device is the already logged in device reciprocating a new login on the other side of the channel.
|
|
161
161
|
*/
|
|
162
162
|
public get isExistingDevice(): boolean {
|
|
163
|
-
return this.ourIntent ===
|
|
163
|
+
return this.ourIntent === QrCodeIntent.Reciprocate;
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
/**
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
Ecies,
|
|
20
20
|
type EstablishedEcies,
|
|
21
21
|
QrCodeData,
|
|
22
|
-
|
|
22
|
+
QrCodeIntent,
|
|
23
23
|
} from "@matrix-org/matrix-sdk-crypto-wasm";
|
|
24
24
|
|
|
25
25
|
import {
|
|
@@ -56,9 +56,9 @@ export class MSC4108SecureChannel {
|
|
|
56
56
|
* @param mode the mode to generate the QR code in, either `Login` or `Reciprocate`.
|
|
57
57
|
* @param serverName the name of the homeserver to connect to, as defined by server discovery in the spec, required for `Reciprocate` mode.
|
|
58
58
|
*/
|
|
59
|
-
public async generateCode(mode:
|
|
60
|
-
public async generateCode(mode:
|
|
61
|
-
public async generateCode(mode:
|
|
59
|
+
public async generateCode(mode: QrCodeIntent.Login): Promise<Uint8Array>;
|
|
60
|
+
public async generateCode(mode: QrCodeIntent.Reciprocate, serverName: string): Promise<Uint8Array>;
|
|
61
|
+
public async generateCode(mode: QrCodeIntent, serverName?: string): Promise<Uint8Array> {
|
|
62
62
|
const { url } = this.rendezvousSession;
|
|
63
63
|
|
|
64
64
|
if (!url) {
|
|
@@ -68,7 +68,7 @@ export class MSC4108SecureChannel {
|
|
|
68
68
|
return new QrCodeData(
|
|
69
69
|
this.secureChannel.public_key(),
|
|
70
70
|
url,
|
|
71
|
-
mode ===
|
|
71
|
+
mode === QrCodeIntent.Reciprocate ? serverName : undefined,
|
|
72
72
|
).toBytes();
|
|
73
73
|
}
|
|
74
74
|
|
package/src/rust-crypto/index.ts
CHANGED
|
@@ -17,7 +17,7 @@ limitations under the License.
|
|
|
17
17
|
import * as RustSdkCryptoJs from "@matrix-org/matrix-sdk-crypto-wasm";
|
|
18
18
|
import { StoreHandle } from "@matrix-org/matrix-sdk-crypto-wasm";
|
|
19
19
|
|
|
20
|
-
import { RustCrypto } from "./rust-crypto.ts";
|
|
20
|
+
import { MAX_INVITE_ACCEPTANCE_MS_FOR_KEY_BUNDLE, RustCrypto } from "./rust-crypto.ts";
|
|
21
21
|
import { type IHttpOpts, type MatrixHttpApi } from "../http-api/index.ts";
|
|
22
22
|
import { type ServerSideSecretStorage } from "../secret-storage.ts";
|
|
23
23
|
import { type Logger } from "../logger.ts";
|
|
@@ -247,5 +247,21 @@ async function initOlmMachine(
|
|
|
247
247
|
}
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
+
// If we have any recently-joined rooms, see if we have a pending key bundle for them.
|
|
251
|
+
for (const pendingDetails of await olmMachine.getAllRoomsPendingKeyBundles()) {
|
|
252
|
+
const roomId = pendingDetails.roomId.toString();
|
|
253
|
+
if (Date.now() - pendingDetails.inviteAcceptedAtMillis <= MAX_INVITE_ACCEPTANCE_MS_FOR_KEY_BUNDLE) {
|
|
254
|
+
logger.info(
|
|
255
|
+
`Checking for pending key bundle for recently-joined room ${roomId} (joined ${new Date(pendingDetails.inviteAcceptedAtMillis).toISOString()})`,
|
|
256
|
+
);
|
|
257
|
+
await rustCrypto.maybeAcceptKeyBundle(roomId, pendingDetails.inviterId.toString());
|
|
258
|
+
} else {
|
|
259
|
+
logger.info(
|
|
260
|
+
`Clearing pending-key-bundle flag for room ${roomId} (too old: joined ${new Date(pendingDetails.inviteAcceptedAtMillis).toISOString()})`,
|
|
261
|
+
);
|
|
262
|
+
await olmMachine.clearRoomPendingKeyBundle(new RustSdkCryptoJs.RoomId(roomId));
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
250
266
|
return rustCrypto;
|
|
251
267
|
}
|
|
@@ -111,6 +111,9 @@ interface ISignableObject {
|
|
|
111
111
|
unsigned?: object;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
/** The maximum time, in milliseconds, since we accepted an invite, that we should accept a key bundle. */
|
|
115
|
+
export const MAX_INVITE_ACCEPTANCE_MS_FOR_KEY_BUNDLE = 24 * 60 * 60 * 1000; // 24 hours
|
|
116
|
+
|
|
114
117
|
/**
|
|
115
118
|
* An implementation of {@link CryptoBackend} using the Rust matrix-sdk-crypto.
|
|
116
119
|
*
|
|
@@ -131,9 +134,6 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
|
|
|
131
134
|
/** mapping of roomId → encryptor class */
|
|
132
135
|
private roomEncryptors: Record<string, RoomEncryptor> = {};
|
|
133
136
|
|
|
134
|
-
/** mapping of room ID -> inviter ID for rooms pending MSC4268 key bundles */
|
|
135
|
-
private readonly roomsPendingKeyBundles: Map<string, string> = new Map();
|
|
136
|
-
|
|
137
137
|
private eventDecryptor: EventDecryptor;
|
|
138
138
|
private keyClaimManager: KeyClaimManager;
|
|
139
139
|
private outgoingRequestProcessor: OutgoingRequestProcessor;
|
|
@@ -370,10 +370,10 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
|
|
|
370
370
|
/* allowRedirects */ true,
|
|
371
371
|
/* useAuthentication */ true,
|
|
372
372
|
);
|
|
373
|
-
let encryptedBundle:
|
|
373
|
+
let encryptedBundle: Uint8Array;
|
|
374
374
|
try {
|
|
375
375
|
const bundleUrl = new URL(url);
|
|
376
|
-
|
|
376
|
+
const encryptedBundleBlob = await this.http.authedRequest<Blob>(
|
|
377
377
|
Method.Get,
|
|
378
378
|
bundleUrl.pathname + bundleUrl.search,
|
|
379
379
|
{},
|
|
@@ -383,17 +383,24 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
|
|
|
383
383
|
prefix: "",
|
|
384
384
|
},
|
|
385
385
|
);
|
|
386
|
+
logger.info(`Received blob of length ${encryptedBundleBlob.size}`);
|
|
387
|
+
encryptedBundle = new Uint8Array(await encryptedBundleBlob.arrayBuffer());
|
|
386
388
|
} catch (err) {
|
|
387
389
|
logger.warn(`Error downloading encrypted bundle from ${url}:`, err);
|
|
388
390
|
throw err;
|
|
389
391
|
}
|
|
390
392
|
|
|
391
|
-
logger.info(`Received blob of length ${encryptedBundle.size}`);
|
|
392
393
|
try {
|
|
393
|
-
await this.olmMachine.receiveRoomKeyBundle(bundleData,
|
|
394
|
+
await this.olmMachine.receiveRoomKeyBundle(bundleData, encryptedBundle);
|
|
394
395
|
} catch (err) {
|
|
395
396
|
logger.warn(`Error receiving encrypted bundle:`, err);
|
|
397
|
+
|
|
396
398
|
throw err;
|
|
399
|
+
} finally {
|
|
400
|
+
// Even if we were unable to import the bundle, we still clear the flag that indicates that we
|
|
401
|
+
// are waiting for the bundle to be received. The only reason this can happen is that the bundle was
|
|
402
|
+
// malformed somehow, so we don't want to keep retrying it.
|
|
403
|
+
await this.olmMachine.clearRoomPendingKeyBundle(new RustSdkCryptoJs.RoomId(roomId));
|
|
397
404
|
}
|
|
398
405
|
|
|
399
406
|
return true;
|
|
@@ -402,8 +409,11 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
|
|
|
402
409
|
/**
|
|
403
410
|
* Implementation of {@link CryptoBackend.markRoomAsPendingKeyBundle}.
|
|
404
411
|
*/
|
|
405
|
-
public markRoomAsPendingKeyBundle(roomId: string, inviter: string): void {
|
|
406
|
-
this.
|
|
412
|
+
public async markRoomAsPendingKeyBundle(roomId: string, inviter: string): Promise<void> {
|
|
413
|
+
await this.olmMachine.storeRoomPendingKeyBundle(
|
|
414
|
+
new RustSdkCryptoJs.RoomId(roomId),
|
|
415
|
+
new RustSdkCryptoJs.UserId(inviter),
|
|
416
|
+
);
|
|
407
417
|
}
|
|
408
418
|
|
|
409
419
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
@@ -781,9 +791,7 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
|
|
|
781
791
|
* Implementation of {@link CryptoApi#getCrossSigningKeyId}
|
|
782
792
|
*/
|
|
783
793
|
public async getCrossSigningKeyId(type: CrossSigningKey = CrossSigningKey.Master): Promise<string | null> {
|
|
784
|
-
const userIdentity
|
|
785
|
-
new RustSdkCryptoJs.UserId(this.userId),
|
|
786
|
-
);
|
|
794
|
+
const userIdentity = await this.getOwnIdentity();
|
|
787
795
|
if (!userIdentity) {
|
|
788
796
|
// The public keys are not available on this device
|
|
789
797
|
return null;
|
|
@@ -1012,9 +1020,7 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
|
|
|
1012
1020
|
* Implementation of {@link CryptoApi#getCrossSigningStatus}
|
|
1013
1021
|
*/
|
|
1014
1022
|
public async getCrossSigningStatus(): Promise<CrossSigningStatus> {
|
|
1015
|
-
const userIdentity
|
|
1016
|
-
new RustSdkCryptoJs.UserId(this.userId),
|
|
1017
|
-
);
|
|
1023
|
+
const userIdentity = await this.getOwnIdentity();
|
|
1018
1024
|
|
|
1019
1025
|
const publicKeysOnDevice =
|
|
1020
1026
|
Boolean(userIdentity?.masterKey) &&
|
|
@@ -1128,9 +1134,9 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
|
|
|
1128
1134
|
* Implementation of {@link CryptoApi#requestVerificationDM}
|
|
1129
1135
|
*/
|
|
1130
1136
|
public async requestVerificationDM(userId: string, roomId: string): Promise<VerificationRequest> {
|
|
1131
|
-
const userIdentity
|
|
1132
|
-
|
|
1133
|
-
|
|
1137
|
+
const userIdentity = (await this.olmMachine.getIdentity(new RustSdkCryptoJs.UserId(userId))) as
|
|
1138
|
+
| RustSdkCryptoJs.OtherUserIdentity
|
|
1139
|
+
| undefined;
|
|
1134
1140
|
|
|
1135
1141
|
if (!userIdentity) throw new Error(`unknown userId ${userId}`);
|
|
1136
1142
|
|
|
@@ -1214,9 +1220,7 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
|
|
|
1214
1220
|
* @returns a VerificationRequest when the request has been sent to the other party.
|
|
1215
1221
|
*/
|
|
1216
1222
|
public async requestOwnUserVerification(): Promise<VerificationRequest> {
|
|
1217
|
-
const userIdentity
|
|
1218
|
-
new RustSdkCryptoJs.UserId(this.userId),
|
|
1219
|
-
);
|
|
1223
|
+
const userIdentity = await this.getOwnIdentity();
|
|
1220
1224
|
if (userIdentity === undefined) {
|
|
1221
1225
|
throw new Error("cannot request verification for this device when there is no existing cross-signing key");
|
|
1222
1226
|
}
|
|
@@ -1726,34 +1730,37 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
|
|
|
1726
1730
|
},
|
|
1727
1731
|
});
|
|
1728
1732
|
|
|
1729
|
-
// If we have received a room key bundle message, and have
|
|
1730
|
-
//
|
|
1731
|
-
// just in case it was received after invite.
|
|
1733
|
+
// If we have received a room key bundle message, and have recently joined the room in question,
|
|
1734
|
+
// tell the Rust SDK to try and accept the key bundle.
|
|
1732
1735
|
//
|
|
1733
1736
|
// We don't actually need to validate the contents of the bundle message, or do
|
|
1734
1737
|
// anything with its contents at all. We simply want to inform the Rust SDK we have
|
|
1735
1738
|
// received a new room key bundle that we might be able to download.
|
|
1736
|
-
if (
|
|
1737
|
-
|
|
1738
|
-
this.
|
|
1739
|
-
|
|
1740
|
-
// No `await`-ing here, as this is called from inside the `/sync` loop.
|
|
1741
|
-
this.maybeAcceptKeyBundle(
|
|
1742
|
-
parsedMessage.content.room_id,
|
|
1743
|
-
this.roomsPendingKeyBundles.get(parsedMessage.content.room_id)!,
|
|
1744
|
-
).then(
|
|
1745
|
-
(success) => {
|
|
1746
|
-
if (success) {
|
|
1747
|
-
this.roomsPendingKeyBundles.delete(parsedMessage.content.room_id);
|
|
1748
|
-
}
|
|
1749
|
-
},
|
|
1750
|
-
(err) => {
|
|
1751
|
-
this.logger.error(
|
|
1752
|
-
`Error attempting to download key bundle for room ${parsedMessage.content.room_id}`,
|
|
1753
|
-
);
|
|
1754
|
-
this.logger.error(err);
|
|
1755
|
-
},
|
|
1739
|
+
if (isRoomKeyBundleMessage(parsedMessage)) {
|
|
1740
|
+
const roomId = parsedMessage.content.room_id;
|
|
1741
|
+
const pendingDetails = await this.olmMachine.getPendingKeyBundleDetailsForRoom(
|
|
1742
|
+
new RustSdkCryptoJs.RoomId(roomId),
|
|
1756
1743
|
);
|
|
1744
|
+
// Only accept the key bundle if we joined the room less than 24 hours ago.
|
|
1745
|
+
if (!pendingDetails) {
|
|
1746
|
+
this.logger.debug(
|
|
1747
|
+
`Not yet accepting key bundle for room where we are not awaiting a bundle: ${roomId}`,
|
|
1748
|
+
);
|
|
1749
|
+
} else if (
|
|
1750
|
+
Date.now() - pendingDetails.inviteAcceptedAtMillis >
|
|
1751
|
+
MAX_INVITE_ACCEPTANCE_MS_FOR_KEY_BUNDLE
|
|
1752
|
+
) {
|
|
1753
|
+
this.logger.info(
|
|
1754
|
+
`Ignoring key bundle for room we joined too long ago: ${roomId}, joining time: ${new Date(pendingDetails.inviteAcceptedAtMillis).toISOString()}`,
|
|
1755
|
+
);
|
|
1756
|
+
} else {
|
|
1757
|
+
this.logger.info(`Considering key bundle for recently-joined room ${roomId}`);
|
|
1758
|
+
// Don't block for the import to happen, here, as this is called from inside the `/sync` loop.
|
|
1759
|
+
this.maybeAcceptKeyBundle(roomId, pendingDetails.inviterId.toString()).catch((err) => {
|
|
1760
|
+
this.logger.error(`Error attempting to download key bundle for room ${roomId}`);
|
|
1761
|
+
this.logger.error(err);
|
|
1762
|
+
});
|
|
1763
|
+
}
|
|
1757
1764
|
}
|
|
1758
1765
|
|
|
1759
1766
|
break;
|
|
@@ -1926,7 +1933,21 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
|
|
|
1926
1933
|
* @param oldMembership - The previous membership state. Null if it's a new member.
|
|
1927
1934
|
*/
|
|
1928
1935
|
public onRoomMembership(event: MatrixEvent, member: RoomMember, oldMembership?: string): void {
|
|
1929
|
-
const
|
|
1936
|
+
const roomId = event.getRoomId()!;
|
|
1937
|
+
|
|
1938
|
+
// If it's our own membership, and we are no longer joined, clear any indication that we are waiting for a key
|
|
1939
|
+
// bundle.
|
|
1940
|
+
if (
|
|
1941
|
+
oldMembership === KnownMembership.Join &&
|
|
1942
|
+
member.membership !== KnownMembership.Join &&
|
|
1943
|
+
member.userId === this.olmMachine.userId.toString()
|
|
1944
|
+
) {
|
|
1945
|
+
this.olmMachine.clearRoomPendingKeyBundle(new RustSdkCryptoJs.RoomId(roomId)).catch((e) => {
|
|
1946
|
+
this.logger.error(`Error clearing room pending key bundle indicator for ${roomId}: ${e}`);
|
|
1947
|
+
});
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1950
|
+
const enc = this.roomEncryptors[roomId];
|
|
1930
1951
|
if (!enc) {
|
|
1931
1952
|
// not encrypting in this room
|
|
1932
1953
|
return;
|
|
@@ -2189,7 +2210,10 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
|
|
|
2189
2210
|
* Used during migration from legacy js-crypto to update local trust if needed.
|
|
2190
2211
|
*/
|
|
2191
2212
|
public async getOwnIdentity(): Promise<RustSdkCryptoJs.OwnUserIdentity | undefined> {
|
|
2192
|
-
|
|
2213
|
+
const identity = (await this.getOlmMachineOrThrow().getIdentity(new RustSdkCryptoJs.UserId(this.userId))) as
|
|
2214
|
+
| RustSdkCryptoJs.OwnUserIdentity
|
|
2215
|
+
| undefined;
|
|
2216
|
+
return identity;
|
|
2193
2217
|
}
|
|
2194
2218
|
}
|
|
2195
2219
|
|