Use same lock values as mobile clients
[ProtonMail-WebClient.git] / packages / shared / lib / keys / groupKeys.ts
blob140e97c8c487009c3d85907a3393091129f3658c
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 { getActiveKeyObject, getActiveKeys, getNormalizedActiveKeys } 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;
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 getActiveKeys(address, address.SignedKeyList, address.Keys, []);
58     const updatedActiveKeys = getNormalizedActiveKeys(address, [newActiveKey, ...activeKeys.map(removePrimary)]);
59     const [SignedKeyList, onSKLPublishSuccess] = await getSignedKeyListWithDeferredPublish(
60         updatedActiveKeys,
61         address,
62         keyTransparencyVerify
63     );
64     const { Key } = await api(
65         createGroupAddressKeyRoute({
66             AddressID: address.ID,
67             PrivateKey: privateKeyArmored,
68             SignedKeyList,
69             OrgSignature: signature,
70             OrgToken: encryptedToken,
71         })
72     );
73     // Only once the SKL is successfully posted we add it to the KT commit state.
74     await onSKLPublishSuccess();
75     newActiveKey.ID = Key.ID;
77     return [Key];
80 export const getDecryptedGroupAddressKey = async (
81     addressKeys: AddressKey[],
82     organizationKey: PrivateKeyReference
83 ): Promise<DecryptedAddressKey | undefined> => {
84     const [primaryKey] = addressKeys;
85     const { Token, Signature } = primaryKey;
87     if (Token) {
88         const primaryKeyResult = await decryptAddressKeyUsingOrgKeyToken({ Token, organizationKey, Signature })
89             .then((password) => getDecryptedAddressKey(primaryKey, password))
90             .catch(noop);
92         return Promise.resolve(primaryKeyResult);
93     }
95     return undefined;