Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / packages / shared / lib / keys / changePassword.ts
blob49c876813878dd524c80f41c817ddfe597f00d86
1 import type { PrivateKeyReference } from '@proton/crypto';
2 import { CryptoProxy } from '@proton/crypto';
3 import isTruthy from '@proton/utils/isTruthy';
4 import noop from '@proton/utils/noop';
6 import type { DecryptedKey, Address as tsAddress } from '../interfaces';
7 import { getEncryptedArmoredAddressKey } from './addressKeys';
8 import { getHasMigratedAddressKeys } from './keyMigration';
10 const getEncryptedArmoredUserKey = async ({ ID, privateKey }: DecryptedKey, newKeyPassword: string) => {
11     const privateKeyArmored = await CryptoProxy.exportPrivateKey({
12         privateKey,
13         passphrase: newKeyPassword,
14     });
15     return {
16         ID,
17         PrivateKey: privateKeyArmored,
18     };
21 export const getEncryptedArmoredOrganizationKey = async (
22     organizationKey: PrivateKeyReference | undefined,
23     newKeyPassword: string
24 ) => {
25     if (!organizationKey) {
26         return;
27     }
28     return CryptoProxy.exportPrivateKey({ privateKey: organizationKey, passphrase: newKeyPassword });
31 export const getArmoredPrivateUserKeys = async (keys: DecryptedKey[], keyPassword: string) => {
32     if (keys.length === 0) {
33         return [];
34     }
35     const armoredKeys = await Promise.all(
36         keys.map((key) => {
37             return getEncryptedArmoredUserKey(key, keyPassword).catch(noop);
38         })
39     );
40     const result = armoredKeys.filter(isTruthy);
42     if (result.length === 0) {
43         const decryptedError = new Error('No decrypted keys exist');
44         decryptedError.name = 'NoDecryptedKeys';
45         throw decryptedError;
46     }
48     return result;
51 export const getArmoredPrivateAddressKeys = async (keys: DecryptedKey[], address: tsAddress, keyPassword: string) => {
52     const armoredKeys = await Promise.all(
53         keys.map(async ({ ID, privateKey }) => {
54             const PrivateKey = await getEncryptedArmoredAddressKey(privateKey, address.Email, keyPassword).catch(noop);
55             if (!PrivateKey) {
56                 return;
57             }
58             return {
59                 ID,
60                 PrivateKey,
61             };
62         })
63     );
65     const result = armoredKeys.filter(isTruthy);
67     if (result.length === 0) {
68         const decryptedError = new Error('No decrypted keys exist');
69         decryptedError.name = 'NoDecryptedKeys';
70         throw decryptedError;
71     }
73     return result;
76 interface AddressesKeys {
77     address: tsAddress;
78     keys: DecryptedKey[];
81 export const getArmoredPrivateAddressesKeys = async (addressesWithKeysList: AddressesKeys[], keyPassword: string) => {
82     const result = await Promise.all(
83         addressesWithKeysList.map(({ address, keys }) => {
84             if (!keys.length) {
85                 return;
86             }
87             return getArmoredPrivateAddressKeys(keys, address, keyPassword);
88         })
89     );
90     return result.flat().filter(isTruthy);
93 export const getUpdateKeysPayload = async ({
94     addressesKeys,
95     userKeys,
96     keyPassword,
97     organizationKey,
98     keySalt,
99     forceMigratedAddressKeys,
100 }: {
101     addressesKeys: AddressesKeys[];
102     userKeys: DecryptedKey[];
103     organizationKey: PrivateKeyReference | undefined;
104     keyPassword: string;
105     keySalt: string;
106     forceMigratedAddressKeys?: boolean;
107 }) => {
108     const hasMigratedAddressKeys = forceMigratedAddressKeys
109         ? true
110         : getHasMigratedAddressKeys(addressesKeys.map(({ address }) => address));
112     const [armoredUserKeys, armoredAddressesKeys, armoredOrganizationKey] = await Promise.all([
113         getArmoredPrivateUserKeys(userKeys, keyPassword),
114         hasMigratedAddressKeys ? [] : getArmoredPrivateAddressesKeys(addressesKeys, keyPassword),
115         getEncryptedArmoredOrganizationKey(organizationKey, keyPassword),
116     ]);
118     return hasMigratedAddressKeys
119         ? {
120               UserKeys: armoredUserKeys,
121               KeySalt: keySalt,
122               OrganizationKey: armoredOrganizationKey,
123           }
124         : {
125               Keys: [...armoredUserKeys, ...armoredAddressesKeys],
126               KeySalt: keySalt,
127               OrganizationKey: armoredOrganizationKey,
128           };