Cleanup - unused files / unused exports / duplicate exports
[ProtonMail-WebClient.git] / packages / shared / lib / keys / add / addKeysProcess.ts
blob5f089458b120b2ed811293e291db46a90ee743bd
1 import { CryptoProxy } from '@proton/crypto';
2 import { activatePasswordlessKey } from '@proton/shared/lib/api/members';
3 import {
4     getIsPasswordless,
5     getReplacedAddressKeyTokens,
6     reencryptOrganizationToken,
7     splitKeys,
8 } from '@proton/shared/lib/keys';
9 import noop from '@proton/utils/noop';
11 import { createUserKeyRoute, replaceAddressTokens } from '../../api/keys';
12 import { DEFAULT_KEYGEN_TYPE, KEYGEN_CONFIGS } from '../../constants';
13 import type {
14     Address,
15     Api,
16     CachedOrganizationKey,
17     DecryptedKey,
18     KeyGenConfig,
19     KeyTransparencyVerify,
20     UserModel,
21 } from '../../interfaces';
22 import { storeDeviceRecovery } from '../../recoveryFile/deviceRecovery';
23 import { getActiveKeys } from '../getActiveKeys';
24 import { getHasMigratedAddressKeys } from '../keyMigration';
25 import { generateUserKey } from '../userKeys';
26 import { createAddressKeyLegacy, createAddressKeyV2 } from './addAddressKeyHelper';
28 interface AddAddressKeysProcessArguments {
29     api: Api;
30     addressKeys: DecryptedKey[];
31     userKeys: DecryptedKey[];
32     address: Address;
33     addresses: Address[];
34     keyGenConfig: KeyGenConfig;
35     keyPassword: string;
36     keyTransparencyVerify: KeyTransparencyVerify;
39 export const addAddressKeysProcess = async ({
40     api,
41     keyGenConfig,
42     addresses,
43     address,
44     addressKeys,
45     userKeys,
46     keyPassword,
47     keyTransparencyVerify,
48 }: AddAddressKeysProcessArguments) => {
49     const hasMigratedAddressKeys = getHasMigratedAddressKeys(addresses);
51     const activeKeys = await getActiveKeys(address, address.SignedKeyList, address.Keys, addressKeys);
53     if (hasMigratedAddressKeys) {
54         return createAddressKeyV2({
55             api,
56             userKeys,
57             keyGenConfig,
58             activeKeys,
59             address,
60             keyTransparencyVerify,
61         });
62     }
64     return createAddressKeyLegacy({
65         api,
66         address,
67         keyGenConfig,
68         passphrase: keyPassword,
69         activeKeys,
70         keyTransparencyVerify,
71     });
74 interface AddUserKeysProcessArguments {
75     api: Api;
76     keyGenConfig?: KeyGenConfig;
77     user: UserModel;
78     userKeys: DecryptedKey[];
79     addresses: Address[];
80     passphrase: string;
81     isDeviceRecoveryAvailable?: boolean;
82     isDeviceRecoveryEnabled?: boolean;
83     organizationKey?: CachedOrganizationKey;
86 export const addUserKeysProcess = async ({
87     api,
88     keyGenConfig = KEYGEN_CONFIGS[DEFAULT_KEYGEN_TYPE],
89     user,
90     userKeys,
91     addresses,
92     passphrase,
93     organizationKey,
94     isDeviceRecoveryAvailable,
95     isDeviceRecoveryEnabled,
96 }: AddUserKeysProcessArguments) => {
97     const { privateKey, privateKeyArmored } = await generateUserKey({
98         passphrase,
99         keyGenConfig,
100     });
102     await api(
103         createUserKeyRoute({
104             Primary: 1,
105             PrivateKey: privateKeyArmored,
106         })
107     );
109     const splitUserKeys = splitKeys(userKeys);
111     if (getHasMigratedAddressKeys(addresses)) {
112         const replacedResult = await getReplacedAddressKeyTokens({
113             privateKeys: splitUserKeys.privateKeys,
114             addresses,
115             privateKey,
116         });
117         if (replacedResult.AddressKeyTokens.length) {
118             await api(replaceAddressTokens(replacedResult)).catch(/*ignore failures */ noop);
119         }
120     }
122     if (getIsPasswordless(organizationKey?.Key) && organizationKey?.privateKey) {
123         const result = await reencryptOrganizationToken({
124             Token: organizationKey.Key.Token,
125             encryptionKey: privateKey,
126             signingKey: privateKey,
127             decryptionKeys: splitUserKeys.privateKeys,
128         });
129         await api(
130             activatePasswordlessKey({
131                 TokenKeyPacket: result.keyPacket,
132                 Signature: result.signature,
133             })
134         ).catch(/*ignore failures */ noop);
135     }
137     // Store a new device recovery immediately to avoid having the storing trigger asynchronously which would cause red notification flashes
138     if (isDeviceRecoveryAvailable && isDeviceRecoveryEnabled) {
139         const publicKey = await CryptoProxy.importPublicKey({
140             binaryKey: await CryptoProxy.exportPublicKey({ key: privateKey, format: 'binary' }),
141         });
142         await storeDeviceRecovery({
143             api,
144             user,
145             userKeys: [{ ID: 'tmp-id', privateKey, publicKey }, ...userKeys],
146         });
147     }
149     return privateKey;