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 { getActiveAddressKeys, getActiveKeyObject, getNormalizedActiveAddressKeys } from './getActiveKeys';
25 import { getSignedKeyListWithDeferredPublish } from './signedKeyList';
27 type AddressKey = RequireSome<Key, 'Flags' | 'Signature' | 'AddressForwardingID'>;
29 interface CreateGroupAddressKeyArguments {
31 organizationKey: CachedOrganizationKey;
32 keyGenConfig?: KeyGenConfig; // v6 keys not supported for groups
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 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)],
62 const [SignedKeyList, onSKLPublishSuccess] = await getSignedKeyListWithDeferredPublish(
67 const { Key } = await api(
68 createGroupAddressKeyRoute({
69 AddressID: address.ID,
70 PrivateKey: privateKeyArmored,
72 OrgSignature: signature,
73 OrgToken: encryptedToken,
76 // Only once the SKL is successfully posted we add it to the KT commit state.
77 await onSKLPublishSuccess();
78 newActiveKey.ID = Key.ID;
83 export const getDecryptedGroupAddressKey = async (
84 addressKeys: AddressKey[],
85 organizationKey: PrivateKeyReference
86 ): Promise<DecryptedAddressKey | undefined> => {
87 const [primaryKey] = addressKeys;
88 const { Token, Signature } = primaryKey;
91 const primaryKeyResult = await decryptAddressKeyUsingOrgKeyToken({ Token, organizationKey, Signature })
92 .then((password) => getDecryptedAddressKey(primaryKey, password))
95 return Promise.resolve(primaryKeyResult);