Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / packages / shared / lib / keys / groupKeys.ts
blob2027d158313e04227edb080af1dc7a2181616dd7
1 import type { PrivateKeyReference } from '@proton/crypto';
2 import { getDefaultKeyFlags } from '@proton/shared/lib/keys/keyFlags';
3 import noop from '@proton/utils/noop';
5 import { createGroupAddressKeyRoute } from '../api/keys';
6 import { DEFAULT_KEYGEN_TYPE, KEYGEN_CONFIGS } from '../constants';
7 import type {
8     Address,
9     Api,
10     CachedOrganizationKey,
11     DecryptedAddressKey,
12     Key,
13     KeyGenConfig,
14     KeyTransparencyVerify,
15     RequireSome,
16 } from '../interfaces';
17 import { removePrimary } from './add/addAddressKeyHelper';
18 import {
19     decryptAddressKeyUsingOrgKeyToken,
20     generateAddressKey,
21     getDecryptedAddressKey,
22     getNewAddressKeyTokenFromOrgKey,
23 } from './addressKeys';
24 import { getActiveAddressKeys, getActiveKeyObject, getNormalizedActiveAddressKeys } from './getActiveKeys';
25 import { getSignedKeyListWithDeferredPublish } from './signedKeyList';
27 type AddressKey = RequireSome<Key, 'Flags' | 'Signature' | 'AddressForwardingID'>;
29 interface CreateGroupAddressKeyArguments {
30     api: Api;
31     organizationKey: CachedOrganizationKey;
32     keyGenConfig?: KeyGenConfig; // v6 keys not supported for groups
33     address: Address;
34     keyTransparencyVerify: KeyTransparencyVerify;
37 export const createGroupAddressKey = async ({
38     api,
39     organizationKey,
40     keyGenConfig = KEYGEN_CONFIGS[DEFAULT_KEYGEN_TYPE],
41     address,
42     keyTransparencyVerify,
43 }: CreateGroupAddressKeyArguments) => {
44     const { token, encryptedToken, signature } = await getNewAddressKeyTokenFromOrgKey({ address, organizationKey });
45     const { privateKey, privateKeyArmored } = await generateAddressKey({
46         email: address.Email,
47         passphrase: token,
48         keyGenConfig,
49     });
50     const newActiveKey = await getActiveKeyObject(privateKey, {
51         ID: 'tmp',
52         primary: 1,
53         flags: getDefaultKeyFlags(address),
54     });
56     const activeKeys = await getActiveAddressKeys(address, address.SignedKeyList, address.Keys, []); // v6 keys should not be present for groups
58     const updatedActiveKeys = getNormalizedActiveAddressKeys(address, {
59         v4: [newActiveKey, ...activeKeys.v4.map(removePrimary)],
60         v6: activeKeys.v6,
61     });
62     const [SignedKeyList, onSKLPublishSuccess] = await getSignedKeyListWithDeferredPublish(
63         updatedActiveKeys,
64         address,
65         keyTransparencyVerify
66     );
67     const { Key } = await api(
68         createGroupAddressKeyRoute({
69             AddressID: address.ID,
70             PrivateKey: privateKeyArmored,
71             SignedKeyList,
72             OrgSignature: signature,
73             OrgToken: encryptedToken,
74         })
75     );
76     // Only once the SKL is successfully posted we add it to the KT commit state.
77     await onSKLPublishSuccess();
78     newActiveKey.ID = Key.ID;
80     return [Key];
83 export const getDecryptedGroupAddressKey = async (
84     addressKeys: AddressKey[],
85     organizationKey: PrivateKeyReference
86 ): Promise<DecryptedAddressKey | undefined> => {
87     const [primaryKey] = addressKeys;
88     const { Token, Signature } = primaryKey;
90     if (Token) {
91         const primaryKeyResult = await decryptAddressKeyUsingOrgKeyToken({ Token, organizationKey, Signature })
92             .then((password) => getDecryptedAddressKey(primaryKey, password))
93             .catch(noop);
95         return Promise.resolve(primaryKeyResult);
96     }
98     return undefined;