fix: resolve tsc errors — logger import, Uint8Array generics, VoiceTokenPayload type, test assertion

This commit is contained in:
J3vb
2026-04-04 23:40:37 +02:00
parent 36e81ebec7
commit f841ba87d7
3 changed files with 16 additions and 7 deletions
+14 -6
View File
@@ -14,7 +14,9 @@
* - When a participant leaves, the key holder rotates the room key.
*/
import { log } from "@lib/logger";
import { createLogger } from "@lib/logger";
const log = createLogger("e2eeCrypto");
// ── WebCrypto availability check ───────────────────────────────────────────
if (typeof crypto === "undefined" || !crypto.subtle) {
@@ -27,9 +29,11 @@ const ECDH_CURVE = "P-256";
// UTF-8 bytes of "owncord-voice-e2ee-v1"
const HKDF_SALT = new Uint8Array([
111, 119, 110, 99, 111, 114, 100, 45, 118, 111, 105, 99, 101, 45, 101, 50, 101, 101, 45, 118, 49,
]);
]) as Uint8Array<ArrayBuffer>;
// UTF-8 bytes of "room-key-wrap"
const HKDF_INFO = new Uint8Array([114, 111, 111, 109, 45, 107, 101, 121, 45, 119, 114, 97, 112]);
const HKDF_INFO = new Uint8Array([
114, 111, 111, 109, 45, 107, 101, 121, 45, 119, 114, 97, 112,
]) as Uint8Array<ArrayBuffer>;
const ROOM_KEY_BYTES = 32; // 256-bit AES key for LiveKit SFrame
// ── Key pair generation ─────────────────────────────────────────────────────
@@ -100,7 +104,11 @@ export async function wrapRoomKey(
const wrapKey = await deriveWrappingKey(myPrivateKey, peerPublicKey);
const iv = crypto.getRandomValues(new Uint8Array(12)); // 96-bit GCM nonce
const ciphertext = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, wrapKey, roomKey);
const ciphertext = await crypto.subtle.encrypt(
{ name: "AES-GCM", iv },
wrapKey,
roomKey as Uint8Array<ArrayBuffer>,
);
return {
encryptedKey: uint8ToBase64(new Uint8Array(ciphertext)),
@@ -168,14 +176,14 @@ function uint8ToBase64(bytes: Uint8Array): string {
return btoa(Array.from(bytes, (b) => String.fromCharCode(b)).join(""));
}
function base64ToUint8(base64: string): Uint8Array {
function base64ToUint8(base64: string): Uint8Array<ArrayBuffer> {
let binary: string;
try {
binary = atob(base64);
} catch {
throw new Error("E2EE: invalid base64 input");
}
const bytes = new Uint8Array(binary.length);
const bytes = new Uint8Array(binary.length) as Uint8Array<ArrayBuffer>;
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i);
}
+1
View File
@@ -280,6 +280,7 @@ export interface VoiceTokenPayload {
readonly token: string;
readonly url: string;
readonly direct_url?: string;
readonly is_key_holder?: boolean;
}
// ── Voice E2EE (client-side ECDH key exchange) ─────────────────────────────
@@ -54,7 +54,7 @@ describe("e2eeCrypto", () => {
// Decode, flip the first byte, re-encode
const bytes = Uint8Array.from(atob(encryptedKey), (c) => c.charCodeAt(0));
bytes[0] ^= 0xff;
bytes[0] = bytes[0]! ^ 0xff;
const tampered = btoa(String.fromCharCode(...bytes));
await expect(unwrapRoomKey(bob.privateKey, alice.publicKey, tampered, iv)).rejects.toThrow();