From 1fe08bef55977712ab13cc391661942088a19dd1 Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Wed, 11 Jun 2025 13:38:46 +0200 Subject: [PATCH] Add tests --- .../os-biometrics-windows.service.spec.ts | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/apps/desktop/src/key-management/biometrics/os-biometrics-windows.service.spec.ts b/apps/desktop/src/key-management/biometrics/os-biometrics-windows.service.spec.ts index fd2431d83ae..d0fd8682f2a 100644 --- a/apps/desktop/src/key-management/biometrics/os-biometrics-windows.service.spec.ts +++ b/apps/desktop/src/key-management/biometrics/os-biometrics-windows.service.spec.ts @@ -73,10 +73,71 @@ describe("OsBiometricsServiceWindows", () => { describe("getOrCreateBiometricEncryptionClientKeyHalf", () => { const userId = "test-user-id" as UserId; const key = new SymmetricCryptoKey(new Uint8Array(64)); + let encryptionService: EncryptService; + let cryptoFunctionService: CryptoFunctionService; + + beforeEach(() => { + encryptionService = mock(); + cryptoFunctionService = mock(); + service = new OsBiometricsServiceWindows( + mock(), + null, + mock(), + biometricStateService, + encryptionService, + cryptoFunctionService, + ); + }); + it("should return null if getRequirePasswordOnRestart is false", async () => { biometricStateService.getRequirePasswordOnStart = jest.fn().mockResolvedValue(false); const result = await service.getOrCreateBiometricEncryptionClientKeyHalf(userId, key); expect(result).toBeNull(); }); + + it("should return cached key half if already present", async () => { + biometricStateService.getRequirePasswordOnStart = jest.fn().mockResolvedValue(true); + const cachedKeyHalf = new Uint8Array([10, 20, 30]); + (service as any).clientKeyHalves.set(userId.toString(), cachedKeyHalf); + const result = await service.getOrCreateBiometricEncryptionClientKeyHalf(userId, key); + expect(result).toBe(cachedKeyHalf); + }); + + it("should decrypt and return existing encrypted client key half", async () => { + biometricStateService.getRequirePasswordOnStart = jest.fn().mockResolvedValue(true); + biometricStateService.getEncryptedClientKeyHalf = jest + .fn() + .mockResolvedValue(new Uint8Array([1, 2, 3])); + const decrypted = new Uint8Array([4, 5, 6]); + encryptionService.decryptBytes = jest.fn().mockResolvedValue(decrypted); + + const result = await service.getOrCreateBiometricEncryptionClientKeyHalf(userId, key); + + expect(biometricStateService.getEncryptedClientKeyHalf).toHaveBeenCalledWith(userId); + expect(encryptionService.decryptBytes).toHaveBeenCalledWith(new Uint8Array([1, 2, 3]), key); + expect(result).toEqual(decrypted); + expect((service as any).clientKeyHalves.get(userId.toString())).toEqual(decrypted); + }); + + it("should generate, encrypt, store, and cache a new key half if none exists", async () => { + biometricStateService.getRequirePasswordOnStart = jest.fn().mockResolvedValue(true); + biometricStateService.getEncryptedClientKeyHalf = jest.fn().mockResolvedValue(null); + const randomBytes = new Uint8Array([7, 8, 9]); + cryptoFunctionService.randomBytes = jest.fn().mockResolvedValue(randomBytes); + const encrypted = new Uint8Array([10, 11, 12]); + encryptionService.encryptBytes = jest.fn().mockResolvedValue(encrypted); + biometricStateService.setEncryptedClientKeyHalf = jest.fn().mockResolvedValue(undefined); + + const result = await service.getOrCreateBiometricEncryptionClientKeyHalf(userId, key); + + expect(cryptoFunctionService.randomBytes).toHaveBeenCalledWith(32); + expect(encryptionService.encryptBytes).toHaveBeenCalledWith(randomBytes, key); + expect(biometricStateService.setEncryptedClientKeyHalf).toHaveBeenCalledWith( + encrypted, + userId, + ); + expect(result).toBeNull(); + expect((service as any).clientKeyHalves.get(userId.toString())).toBeNull(); + }); }); });