Update all non-major dependencies
[ProtonMail-WebClient.git] / applications / pass-desktop / src / lib / biometrics / biometrics.windows.ts
blobbcd368123e8f773e5c35658f3fd77227b5a28a25
1 import { KEY_LENGTH_BYTES } from '@proton/crypto/lib/subtle/aesGcm';
2 import { uint8ArrayToString } from '@proton/shared/lib/helpers/encoding';
4 import { biometric as winBiometrics } from '../../../native';
5 import type { BiometricsFactory, BiometricsPlatformHandler } from './types';
7 const factory: BiometricsFactory = (getWindow) => {
8     const checkPresence = async (reason = 'Proton Pass wants to unlock') => {
9         const handle = getWindow()?.getNativeWindowHandle();
10         if (!handle) return false;
11         return winBiometrics.checkPresence(handle, reason).catch(() => false);
12     };
14     const biometrics: BiometricsPlatformHandler = {
15         canCheckPresence: () => winBiometrics.canCheckPresence().catch(() => false),
16         checkPresence: (_, reason) => checkPresence(reason),
17         getDecryptionKey: (_, challenge) => winBiometrics.getDecryptionKey(challenge).catch(() => null),
18         getSecret: async (_, key, version) => {
19             if (!(await checkPresence())) throw new Error('Biometric authentication failed');
21             const secretBytes = await winBiometrics.getSecret(key).catch(() => null);
22             if (!secretBytes) return null;
24             /** Version 1 (Legacy): Secrets were stored as UTF-16 encoded strings in a Vec<u8>,
25              * retrieved via `U16String::from_ptr`. Now stored as `Uint8`. For retrocompatibility:
26              * 1. Reinterpret Uint8Array, extracting first byte of each UTF-16 pair
27              * 2. Slice to KEY_LENGTH_BYTES for correct secret length */
28             if (version === 1) {
29                 const secretBytesUint8 = (() => {
30                     const bytes = new Uint8Array(Math.floor(secretBytes.length / 2));
31                     for (let i = 0, j = 0; i < secretBytes.length; i += 2, j++) bytes[j] = secretBytes[i];
32                     return bytes.slice(0, KEY_LENGTH_BYTES);
33                 })();
35                 return uint8ArrayToString(secretBytesUint8);
36             }
38             /* Version 2+: Secrets are stored as raw byte arrays without
39              * any conversions to and from strings */
40             return uint8ArrayToString(secretBytes);
41         },
42         setSecret: (_, key, secret) => winBiometrics.setSecret(key, secret),
43         deleteSecret: (_, key) => winBiometrics.deleteSecret(key),
44     };
46     return biometrics;
49 export default factory;