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';
10 CachedOrganizationKey,
14 KeyTransparencyVerify,
16 } from '../interfaces';
17 import { removePrimary } from './add/addAddressKeyHelper';
19 decryptAddressKeyUsingOrgKeyToken,
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 {
31 organizationKey: CachedOrganizationKey;
32 keyGenConfig?: KeyGenConfig;
34 keyTransparencyVerify: KeyTransparencyVerify;
37 export const createGroupAddressKey = async ({
40 keyGenConfig = KEYGEN_CONFIGS[DEFAULT_KEYGEN_TYPE],
42 keyTransparencyVerify,
43 }: CreateGroupAddressKeyArguments) => {
44 const { token, encryptedToken, signature } = await getNewAddressKeyTokenFromOrgKey({ address, organizationKey });
45 const { privateKey, privateKeyArmored } = await generateAddressKey({
50 const newActiveKey = await getActiveKeyObject(privateKey, {
53 flags: getDefaultKeyFlags(address),
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(
64 const { Key } = await api(
65 createGroupAddressKeyRoute({
66 AddressID: address.ID,
67 PrivateKey: privateKeyArmored,
69 OrgSignature: signature,
70 OrgToken: encryptedToken,
73 // Only once the SKL is successfully posted we add it to the KT commit state.
74 await onSKLPublishSuccess();
75 newActiveKey.ID = Key.ID;
80 export const getDecryptedGroupAddressKey = async (
81 addressKeys: AddressKey[],
82 organizationKey: PrivateKeyReference
83 ): Promise<DecryptedAddressKey | undefined> => {
84 const [primaryKey] = addressKeys;
85 const { Token, Signature } = primaryKey;
88 const primaryKeyResult = await decryptAddressKeyUsingOrgKeyToken({ Token, organizationKey, Signature })
89 .then((password) => getDecryptedAddressKey(primaryKey, password))
92 return Promise.resolve(primaryKeyResult);