1 import type { PrivateKeyReferenceV4, PrivateKeyReferenceV6 } from '@proton/crypto';
2 import { CryptoProxy } from '@proton/crypto';
3 import { getDefaultKeyFlags } from '@proton/shared/lib/keys';
5 import { reactivateKeyRoute } from '../../api/keys';
7 type ActiveKeyWithVersion,
12 type KeyTransparencyVerify,
14 } from '../../interfaces';
18 getNormalizedActiveAddressKeys,
20 } from '../getActiveKeys';
21 import { getSignedKeyListWithDeferredPublish } from '../signedKeyList';
22 import type { KeyReactivationData, KeyReactivationRecord, OnKeyReactivationCallback } from './interface';
23 import { resetUserId } from './reactivateKeyHelper';
25 interface ReactivateKeysProcessArguments {
28 keysToReactivate: KeyReactivationData[];
30 onReactivation: OnKeyReactivationCallback;
33 keyTransparencyVerify: KeyTransparencyVerify;
36 export const reactivateKeysProcess = async ({
44 keyTransparencyVerify,
45 }: ReactivateKeysProcessArguments) => {
46 const activeKeys = await getActiveAddressKeys(address, address?.SignedKeyList, Keys, keys);
48 let mutableActiveKeys = activeKeys;
50 for (const keyToReactivate of keysToReactivate) {
51 const { id, Key, privateKey: reactivatedKey } = keyToReactivate;
54 if (!reactivatedKey) {
55 throw new Error('Missing key');
58 await resetUserId(Key, reactivatedKey);
60 const privateKeyArmored = await CryptoProxy.exportPrivateKey({
61 privateKey: reactivatedKey,
62 passphrase: keyPassword,
64 const newActiveKey = (await getActiveKeyObject(
65 reactivatedKey as PrivateKeyReferenceV4 | PrivateKeyReferenceV6,
68 // We do not mark the v6 as primary by default, because it will fail if forwarding is enabled
69 primary: reactivatedKey.isPrivateKeyV6() ? 0 : getPrimaryFlag(mutableActiveKeys.v4),
70 flags: getDefaultKeyFlags(address),
72 )) as ActiveKeyWithVersion;
73 const toNormalize = isActiveKeyV6(newActiveKey)
74 ? { v4: [...mutableActiveKeys.v4], v6: [...mutableActiveKeys.v6, newActiveKey] }
75 : { v4: [...mutableActiveKeys.v4, newActiveKey], v6: [...mutableActiveKeys.v6] };
76 const updatedActiveKeys = getNormalizedActiveAddressKeys(address, toNormalize);
77 const [SignedKeyList, onSKLPublishSuccess] = address
78 ? await getSignedKeyListWithDeferredPublish(updatedActiveKeys, address, keyTransparencyVerify)
79 : [undefined, undefined];
83 PrivateKey: privateKeyArmored,
87 if (onSKLPublishSuccess) {
88 await onSKLPublishSuccess();
91 mutableActiveKeys = updatedActiveKeys;
93 onReactivation(id, 'ok');
95 onReactivation(id, e);
100 export interface ReactivateKeysProcessLegacyArguments {
102 keyReactivationRecords: KeyReactivationRecord[];
103 onReactivation: OnKeyReactivationCallback;
104 addressesKeys: { address: Address; keys: DecryptedKey[] }[];
105 userKeys: DecryptedKey[];
107 keyTransparencyVerify: KeyTransparencyVerify;
110 const reactivateKeysProcessLegacy = async ({
111 keyReactivationRecords,
117 keyTransparencyVerify,
118 }: ReactivateKeysProcessLegacyArguments) => {
119 for (const keyReactivationRecord of keyReactivationRecords) {
120 const { user, address, keysToReactivate } = keyReactivationRecord;
122 const Keys = address ? address.Keys : user?.Keys || [];
124 ? addressesKeys.find((addressKeys) => addressKeys.address.ID === address.ID)?.keys
127 throw new Error('Missing keys');
129 await reactivateKeysProcess({
137 keyTransparencyVerify,
140 keysToReactivate.forEach(({ id }) => onReactivation(id, e));
145 export default reactivateKeysProcessLegacy;