110 lines
5.6 KiB
TypeScript
110 lines
5.6 KiB
TypeScript
import { type CallMembershipIdentityParts, type IEncryptionManager } from "./EncryptionManager.ts";
|
|
import { type EncryptionConfig, type MembershipConfig } from "./MatrixRTCSession.ts";
|
|
import type { CallMembership } from "./CallMembership.ts";
|
|
import { type IKeyTransport, type KeyTransportEventListener } from "./IKeyTransport.ts";
|
|
import { type Logger } from "../logger.ts";
|
|
import { type EncryptionKeyMapKey } from "./types.ts";
|
|
/**
|
|
* RTCEncryptionManager is used to manage the encryption keys for a call.
|
|
*
|
|
* It is responsible for distributing the keys to the other participants and rotating the keys if needed.
|
|
*
|
|
* This manager when used with to-device transport will share the existing key only to new joiners, and rotate
|
|
* if there is a leaver.
|
|
*
|
|
* XXX In the future we want to distribute a ratcheted key not the current one for new joiners.
|
|
*/
|
|
export declare class RTCEncryptionManager implements IEncryptionManager {
|
|
private readonly ownMembership;
|
|
private getMemberships;
|
|
private transport;
|
|
private onEncryptionKeysChanged;
|
|
private manageMediaKeys;
|
|
private useHashedRtcBackendIdentity;
|
|
private ownRtcBackendIdentityCache;
|
|
/**
|
|
* Store the key rings for each participant.
|
|
* The encryption manager stores the keys because the application layer might not be ready yet to handle the keys.
|
|
* The keys are stored and can be retrieved later when the application layer is ready {@link RTCEncryptionManager#getEncryptionKeys}.
|
|
*/
|
|
private readonly participantKeyRings;
|
|
private outboundSession;
|
|
/**
|
|
* Ensures that there is only one distribute operation at a time for that call.
|
|
*/
|
|
private currentKeyDistributionPromise;
|
|
/**
|
|
* The time to wait before using the outbound session after it has been distributed.
|
|
* This is to ensure that the key is delivered to all participants before it is used.
|
|
* When creating the first key, this is set to 0 so that the key can be used immediately.
|
|
*/
|
|
private useKeyDelay;
|
|
/**
|
|
* We want to avoid rolling out a new outbound key when the previous one was created less than `keyRotationGracePeriodMs` milliseconds ago.
|
|
* This is to avoid expensive key rotations when users quickly join the call in a row.
|
|
*
|
|
* This must be higher than `useKeyDelay` to have an effect.
|
|
* If it is lower, the current key will always be older than the grace period.
|
|
* @private
|
|
*/
|
|
private keyRotationGracePeriodMs;
|
|
/**
|
|
* If a new key distribution is being requested while one is going on, we will set this flag to true.
|
|
* This will ensure that a new round is started after the current one.
|
|
* @private
|
|
*/
|
|
private needToEnsureKeyAgain;
|
|
/**
|
|
* There is a possibility that keys arrive in the wrong order.
|
|
* For example, after a quick join/leave/join, there will be 2 keys of index 0 distributed, and
|
|
* if they are received in the wrong order, the stream won't be decryptable.
|
|
* For that reason we keep a small buffer of keys for a limited time to disambiguate.
|
|
* @private
|
|
*/
|
|
private keyBuffer;
|
|
private logger;
|
|
private readonly rtcIdentityProvider;
|
|
/**
|
|
*
|
|
* @param ownMembership - our own membership info
|
|
* @param getMemberships - function to get current memberships
|
|
* @param transport - key transport (room or to-device)
|
|
* @param statistics - statistics collector
|
|
* @param onEncryptionKeysChanged - callback to notify the media layer of new keys
|
|
* @param parentLogger - optional parent logger
|
|
* @param rtcBackendIdProvider - A function to compute the rtc backend identity, exposed for testing purposes
|
|
*/
|
|
constructor(ownMembership: CallMembershipIdentityParts, getMemberships: () => CallMembership[], transport: IKeyTransport, onEncryptionKeysChanged: (keyBin: Uint8Array<ArrayBuffer>, encryptionKeyIndex: number, membership: CallMembershipIdentityParts, rtcBackendIdentity: string) => void, parentLogger?: Logger, rtcBackendIdProvider?: (userId: string, deviceId: string, memberId: string) => Promise<string>);
|
|
private getOwnRtcBackendIdentity;
|
|
getEncryptionKeys(): ReadonlyMap<EncryptionKeyMapKey, ReadonlyArray<{
|
|
key: Uint8Array<ArrayBuffer>;
|
|
keyIndex: number;
|
|
membership: CallMembershipIdentityParts;
|
|
rtcBackendIdentity: string;
|
|
}>>;
|
|
private keysWithoutMatchingRTCMembership;
|
|
private checkKeysWithoutMatchingRTCMembership;
|
|
private addKeyToParticipant;
|
|
private addKeyToParticipantWithBackendIdentity;
|
|
join(joinConfig: (EncryptionConfig & MembershipConfig) | undefined): void;
|
|
leave(): void;
|
|
/**
|
|
* Will ensure that a new key is distributed and used to encrypt our media.
|
|
* If there is already a key distribution in progress, it will schedule a new distribution round just after the current one is completed.
|
|
* If this function is called repeatedly while a distribution is in progress,
|
|
* the calls will be coalesced to a single new distribution (that will start just after the current one has completed).
|
|
*/
|
|
private ensureKeyDistribution;
|
|
onNewKeyReceived: KeyTransportEventListener;
|
|
/**
|
|
* Called when the ownMembership of the call changes.
|
|
* This encryption manager is very basic, it will rotate the key everytime this is called.
|
|
* @param oldMemberships - This parameter is not used here, but it is kept for compatibility with the interface.
|
|
*/
|
|
onMembershipsUpdate(oldMemberships?: CallMembership[]): void;
|
|
private rolloutOutboundKey;
|
|
private createNewOutboundSession;
|
|
private nextKeyIndex;
|
|
private generateRandomKey;
|
|
}
|
|
//# sourceMappingURL=RTCEncryptionManager.d.ts.map
|