1 import type { PrivateKeyReference } from '@proton/crypto';
2 import { CryptoProxy } from '@proton/crypto';
3 import type { ShareMapLink } from '@proton/shared/lib/interfaces/drive/link';
4 import { LinkType } from '@proton/shared/lib/interfaces/drive/link';
5 import { decryptUnsigned } from '@proton/shared/lib/keys/driveKeys';
6 import { decryptPassphrase } from '@proton/shared/lib/keys/drivePassphrase';
8 type DecryptAndCacheLink = (linkMeta: ShareMapLink, parentPrivateKey: PrivateKeyReference) => Promise<{ name: string }>;
9 type GetCachedParentPrivateKey = (linkId: string | null) => PrivateKeyReference | undefined;
11 export const LINK_KEYS_NOT_FOUND_MESSAGE = "ES Indexing: parent link key wasn't not found.";
13 export interface KeyCache {
14 getCachedPrivateKey: GetCachedParentPrivateKey;
15 decryptAndCacheLink: DecryptAndCacheLink;
18 export const createKeysCache = (rootKey: PrivateKeyReference): KeyCache => {
19 const keyCache = new Map<string | null, PrivateKeyReference>();
20 keyCache.set(null, rootKey);
22 const getCachedPrivateKey: GetCachedParentPrivateKey = (linkId) => {
23 return keyCache.get(linkId);
26 // XXX: move to a worker some time in the future
27 const decryptAndCacheLink: DecryptAndCacheLink = async (linkMeta, parentPrivateKey) => {
29 * If link is a folder, we need to decrypt its NodeKey in order to be able
30 * to decrypt its children names later on
32 if (linkMeta.Type === LinkType.FOLDER) {
33 const { decryptedPassphrase } = await decryptPassphrase({
34 armoredPassphrase: linkMeta.NodePassphrase!,
35 armoredSignature: linkMeta.NodePassphraseSignature!,
36 privateKeys: [parentPrivateKey],
38 validateSignature: false,
41 const linkPrivateKey = await CryptoProxy.importPrivateKey({
42 armoredKey: linkMeta.NodeKey!,
43 passphrase: decryptedPassphrase,
45 keyCache.set(linkMeta.LinkID, linkPrivateKey);
48 const name = await decryptUnsigned({ armoredMessage: linkMeta.Name, privateKey: parentPrivateKey });