Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / packages / shared / lib / contacts / keyVerifications.ts
blob78b796229c1d8e4f54eea9a1ab5af15ee2ae2185
1 import type { KeyID } from '@proton/crypto';
2 import { CryptoProxy } from '@proton/crypto';
4 import { CONTACT_CARD_TYPE } from '../constants';
5 import type { Key } from '../interfaces';
6 import type { Contact } from '../interfaces/contacts';
8 export interface KeyWithIds {
9     key: Key;
10     ids: KeyID[];
13 /**
14  * Get all the key ids of each user keys
15  */
16 export const getUserKeyIds = async (userKeys: Key[]) => {
17     return Promise.all(
18         userKeys.map(async (userKey) => {
19             const keyInfo = await CryptoProxy.getKeyInfo({ armoredKey: userKey.PrivateKey });
20             return { key: userKey, ids: keyInfo.keyIDs } as KeyWithIds;
21         })
22     );
25 /**
26  * Get all key ids of the encryption keys of the cards of a contact
27  * Technically each cards could be encrypted with different keys but it should never happen
28  * So we simplify by returning a flatten array of keys
29  */
30 export const getContactKeyIds = async (contact: Contact, fromEncryption: boolean) => {
31     const selectedCards =
32         contact?.Cards.filter((card) =>
33             fromEncryption
34                 ? card.Type === CONTACT_CARD_TYPE.ENCRYPTED_AND_SIGNED || card.Type === CONTACT_CARD_TYPE.ENCRYPTED
35                 : card.Type === CONTACT_CARD_TYPE.ENCRYPTED_AND_SIGNED || card.Type === CONTACT_CARD_TYPE.SIGNED
36         ) || [];
38     return (
39         await Promise.all(
40             selectedCards.map(async (card) => {
41                 const keyIDs = fromEncryption
42                     ? await CryptoProxy.getMessageInfo({ armoredMessage: card.Data }).then(
43                           ({ encryptionKeyIDs }) => encryptionKeyIDs
44                       )
45                     : await CryptoProxy.getSignatureInfo({ armoredSignature: card.Signature as string }).then(
46                           ({ signingKeyIDs }) => signingKeyIDs
47                       );
49                 return keyIDs;
50             })
51         )
52     ).flat();
55 /**
56  * Return first match of the keyWithIds in the keyIds list
57  */
58 export const matchKeys = (keysWithIds: KeyWithIds[], keyIdsToFind: KeyID[]) => {
59     const result = keysWithIds.find(({ ids }) => ids.some((idFromKey) => keyIdsToFind.includes(idFromKey)));
61     return result?.key;
64 /**
65  * Get user key used to encrypt this contact considering there is only one
66  */
67 export const getKeyUsedForContact = async (contact: Contact, userKeys: Key[], fromEncryption: boolean) => {
68     const userKeysIds = await getUserKeyIds(userKeys);
69     const contactKeyIds = await getContactKeyIds(contact, fromEncryption);
70     return matchKeys(userKeysIds, contactKeyIds);