Update selected item color in Pass menu
[ProtonMail-WebClient.git] / packages / pass / lib / auth / password.ts
blobe467e3e246dbc2d1138035a2d0aa45c955ba1970
1 import { api } from '@proton/pass/lib/api/api';
2 import { type OfflineComponents, getOfflineKeyDerivation } from '@proton/pass/lib/cache/crypto';
3 import { decryptData, importSymmetricKey } from '@proton/pass/lib/crypto/utils/crypto-helpers';
4 import { PassEncryptionTag } from '@proton/pass/types';
5 import { queryUnlock } from '@proton/shared/lib/api/user';
6 import { stringToUint8Array } from '@proton/shared/lib/helpers/encoding';
7 import { srpAuth, srpGetVerify } from '@proton/shared/lib/srp';
8 import { getSrp } from '@proton/srp/lib';
9 import type { AuthInfo } from '@proton/srp/lib/interface';
11 import type { AuthStore } from './store';
13 export enum PasswordVerification {
14     LOCAL,
15     EXTRA_PASSWORD,
16     SRP,
19 export type PasswordCredentials = { password: string };
20 export type PasswordConfirmDTO = PasswordCredentials & { mode?: PasswordVerification };
21 export type ExtraPasswordDTO = PasswordCredentials & { enabled: boolean };
23 export const getPasswordVerification = (authStore: AuthStore) => {
24     const offlineConfig = authStore.getOfflineConfig();
25     const offlineVerifier = authStore.getOfflineVerifier();
26     const extraPassword = authStore.getExtraPassword();
27     const localVerification = offlineConfig && offlineVerifier;
29     if (localVerification) return PasswordVerification.LOCAL;
30     if (extraPassword) return PasswordVerification.EXTRA_PASSWORD;
31     return PasswordVerification.SRP;
34 export const registerExtraPassword = async (credentials: PasswordCredentials) => {
35     const { Auth } = await srpGetVerify({ api, credentials });
37     await api({
38         url: 'pass/v1/user/srp',
39         method: 'post',
40         data: {
41             SrpModulusID: Auth.ModulusID,
42             SrpVerifier: Auth.Verifier,
43             SrpSalt: Auth.Salt,
44         },
45     });
48 export const removeExtraPassword = async () => api({ url: 'pass/v1/user/srp', method: 'delete' });
50 /** Checks that the given password can be verified against the `offlineVerifier`.
51  * If we can successfully decrypt the `offlineVerifier`, then password is correct */
52 export const verifyOfflinePassword = async (
53     password: string,
54     { offlineVerifier, offlineConfig: { salt, params } }: Omit<OfflineComponents, 'offlineKD'>
55 ): Promise<boolean> => {
56     const offlineKD = await getOfflineKeyDerivation(password, stringToUint8Array(salt), params);
57     const offlineKey = await importSymmetricKey(offlineKD);
58     await decryptData(offlineKey, stringToUint8Array(offlineVerifier), PassEncryptionTag.Offline);
60     return true;
63 /** Verifies a proton user's encryption password via SRP */
64 export const verifyPassword = async (credentials: PasswordCredentials): Promise<boolean> => {
65     await srpAuth({ api, credentials, config: { ...queryUnlock(), silence: true } });
66     return true;
69 /** Verifies the pass specific extra-password via SRP */
70 export const verifyExtraPassword = async (credentials: PasswordCredentials): Promise<boolean> => {
71     const info = (await api({ url: 'pass/v1/user/srp/info', method: 'get' })).SRPData!;
73     const { Version, SrpSalt: Salt, Modulus, ServerEphemeral } = info;
74     const authInfo: AuthInfo = { ServerEphemeral, Modulus, Version, Salt };
76     const srp = await getSrp(authInfo, credentials, Version);
78     await api({
79         url: 'pass/v1/user/srp/auth',
80         method: 'post',
81         data: {
82             ClientEphemeral: srp.clientEphemeral,
83             ClientProof: srp.clientProof,
84             SrpSessionID: info.SrpSessionID,
85         },
86     });
88     return true;