{"version":3,"sources":["../src/e2ee.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type {\n  E2eeManagerGetFrameCryptorsResponse,\n  E2eeResponse,\n  GetKeyResponse,\n  GetSharedKeyResponse,\n  RatchetKeyResponse,\n  RatchetSharedKeyResponse,\n} from '@livekit/rtc-ffi-bindings';\nimport {\n  E2eeManagerSetEnabledRequest,\n  E2eeRequest,\n  EncryptionType,\n  FrameCryptorSetEnabledRequest,\n  FrameCryptorSetKeyIndexRequest,\n  GetKeyRequest,\n  GetSharedKeyRequest,\n  RatchetKeyRequest,\n  RatchetSharedKeyRequest,\n  SetKeyRequest,\n  SetSharedKeyRequest,\n} from '@livekit/rtc-ffi-bindings';\nimport { FfiClient } from './ffi_client.js';\n\nconst DEFAULT_RATCHET_SALT = new TextEncoder().encode('LKFrameEncryptionKey');\nconst DEFAULT_RATCHET_WINDOW_SIZE = 16;\nconst DEFAULT_FAILURE_TOLERANCE = -1;\n\nexport interface KeyProviderOptions {\n  sharedKey?: Uint8Array;\n  ratchetSalt?: Uint8Array;\n  ratchetWindowSize?: number;\n  failureTolerance?: number;\n}\n\nexport const defaultKeyProviderOptions: KeyProviderOptions = {\n  ratchetSalt: DEFAULT_RATCHET_SALT,\n  ratchetWindowSize: DEFAULT_RATCHET_WINDOW_SIZE,\n  failureTolerance: DEFAULT_FAILURE_TOLERANCE,\n};\n\nexport interface E2EEOptions {\n  keyProviderOptions: KeyProviderOptions;\n  encryptionType?: EncryptionType;\n}\n\nexport const defaultE2EEOptions: E2EEOptions = {\n  keyProviderOptions: defaultKeyProviderOptions,\n  encryptionType: EncryptionType.GCM,\n};\n\nexport class KeyProvider {\n  private roomHandle: bigint;\n  options: KeyProviderOptions;\n\n  /** internal */\n  constructor(roomHandle: bigint, opts: KeyProviderOptions) {\n    this.roomHandle = roomHandle;\n    this.options = opts;\n  }\n\n  setSharedKey(sharedKey: Uint8Array, keyIndex: number) {\n    const req = new E2eeRequest({\n      roomHandle: this.roomHandle,\n      message: {\n        case: 'setSharedKey',\n        value: new SetSharedKeyRequest({\n          keyIndex: keyIndex,\n          sharedKey: sharedKey,\n        }),\n      },\n    });\n\n    FfiClient.instance.request({\n      message: {\n        case: 'e2ee',\n        value: req,\n      },\n    });\n  }\n\n  exportSharedKey(keyIndex: number): Uint8Array {\n    const req = new E2eeRequest({\n      roomHandle: this.roomHandle,\n      message: {\n        case: 'getSharedKey',\n        value: new GetSharedKeyRequest({\n          keyIndex: keyIndex,\n        }),\n      },\n    });\n\n    const res = FfiClient.instance.request<E2eeResponse>({\n      message: {\n        case: 'e2ee',\n        value: req,\n      },\n    });\n\n    return (res.message.value as GetSharedKeyResponse).key!;\n  }\n\n  ratchetSharedKey(keyIndex: number): Uint8Array {\n    const req = new E2eeRequest({\n      roomHandle: this.roomHandle,\n      message: {\n        case: 'ratchetSharedKey',\n        value: new RatchetSharedKeyRequest({\n          keyIndex: keyIndex,\n        }),\n      },\n    });\n\n    const res = FfiClient.instance.request<E2eeResponse>({\n      message: {\n        case: 'e2ee',\n        value: req,\n      },\n    });\n\n    return (res.message.value as RatchetSharedKeyResponse).newKey!;\n  }\n\n  setKey(participantIdentity: string, keyIndex: number) {\n    const req = new E2eeRequest({\n      roomHandle: this.roomHandle,\n      message: {\n        case: 'setKey',\n        value: new SetKeyRequest({\n          keyIndex: keyIndex,\n          participantIdentity: participantIdentity,\n        }),\n      },\n    });\n\n    FfiClient.instance.request({\n      message: {\n        case: 'e2ee',\n        value: req,\n      },\n    });\n  }\n\n  exportKey(participantIdentity: string, keyIndex: number): Uint8Array {\n    const req = new E2eeRequest({\n      roomHandle: this.roomHandle,\n      message: {\n        case: 'getKey',\n        value: new GetKeyRequest({\n          keyIndex: keyIndex,\n          participantIdentity: participantIdentity,\n        }),\n      },\n    });\n\n    const res = FfiClient.instance.request<E2eeResponse>({\n      message: {\n        case: 'e2ee',\n        value: req,\n      },\n    });\n\n    return (res.message.value as GetKeyResponse).key!;\n  }\n\n  ratchetKey(participantIdentity: string, keyIndex: number): Uint8Array {\n    const req = new E2eeRequest({\n      roomHandle: this.roomHandle,\n      message: {\n        case: 'ratchetKey',\n        value: new RatchetKeyRequest({\n          keyIndex: keyIndex,\n          participantIdentity: participantIdentity,\n        }),\n      },\n    });\n\n    const res = FfiClient.instance.request<E2eeResponse>({\n      message: {\n        case: 'e2ee',\n        value: req,\n      },\n    });\n\n    return (res.message.value as RatchetKeyResponse).newKey!;\n  }\n}\n\nexport class FrameCryptor {\n  private roomHandle = BigInt(0);\n  participantIdentity: string;\n  keyIndex: number;\n  enabled: boolean;\n\n  constructor(roomHandle: bigint, participantIdentity: string, keyIndex: number, enabled: boolean) {\n    this.roomHandle = roomHandle;\n    this.participantIdentity = participantIdentity;\n    this.keyIndex = keyIndex;\n    this.enabled = enabled;\n  }\n\n  setEnabled(enabled: boolean) {\n    this.enabled = enabled;\n    const req = new E2eeRequest({\n      roomHandle: this.roomHandle,\n      message: {\n        case: 'cryptorSetEnabled',\n        value: new FrameCryptorSetEnabledRequest({\n          participantIdentity: this.participantIdentity,\n          enabled: this.enabled,\n        }),\n      },\n    });\n\n    FfiClient.instance.request({\n      message: {\n        case: 'e2ee',\n        value: req,\n      },\n    });\n  }\n\n  setKeyIndex(keyIndex: number) {\n    this.keyIndex = keyIndex;\n    const req = new E2eeRequest({\n      roomHandle: this.roomHandle,\n      message: {\n        case: 'cryptorSetKeyIndex',\n        value: new FrameCryptorSetKeyIndexRequest({\n          participantIdentity: this.participantIdentity,\n          keyIndex: this.keyIndex,\n        }),\n      },\n    });\n\n    FfiClient.instance.request({\n      message: {\n        case: 'e2ee',\n        value: req,\n      },\n    });\n  }\n}\n\nexport class E2EEManager {\n  private roomHandle = BigInt(0);\n  private options: E2EEOptions;\n  private keyProvider: KeyProvider;\n\n  enabled: boolean;\n\n  constructor(roomHandle: bigint, opts?: E2EEOptions) {\n    this.roomHandle = roomHandle;\n    this.enabled = opts !== undefined;\n\n    opts ??= defaultE2EEOptions;\n    const options = { ...defaultE2EEOptions, ...opts };\n\n    this.options = options;\n    this.keyProvider = new KeyProvider(roomHandle, options.keyProviderOptions);\n  }\n\n  setEnabled(enabled: boolean) {\n    this.enabled = enabled;\n    const req = new E2eeRequest({\n      roomHandle: this.roomHandle,\n      message: {\n        case: 'managerSetEnabled',\n        value: new E2eeManagerSetEnabledRequest({\n          enabled: this.enabled,\n        }),\n      },\n    });\n\n    FfiClient.instance.request({\n      message: {\n        case: 'e2ee',\n        value: req,\n      },\n    });\n  }\n\n  frameCryptors(): FrameCryptor[] {\n    const req = new E2eeRequest({\n      roomHandle: this.roomHandle,\n      message: {\n        case: 'managerGetFrameCryptors',\n        value: {},\n      },\n    });\n\n    const res = FfiClient.instance.request<E2eeResponse>({\n      message: {\n        case: 'e2ee',\n        value: req,\n      },\n    });\n\n    const frameCryptors = (\n      res.message.value as E2eeManagerGetFrameCryptorsResponse\n    ).frameCryptors.map(\n      (cryptor) =>\n        new FrameCryptor(\n          this.roomHandle,\n          cryptor.participantIdentity!,\n          cryptor.keyIndex!,\n          cryptor.enabled!,\n        ),\n    );\n\n    return frameCryptors;\n  }\n}\n"],"mappings":"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","names":[]}