Cleanup - unused files / unused exports / duplicate exports
[ProtonMail-WebClient.git] / packages / shared / lib / mail / autocrypt.ts
blobbbd4f981f085b2022232e220a4c725ac86bda058
1 import { binaryStringToArray, decodeBase64 } from '@proton/crypto/lib/utils';
3 const MANDATORY_FIELDS = ['keydata', 'addr'];
4 const OPTIONAL_FIELDS = ['prefer-encrypt'];
5 const CRITICAL_FIELDS = OPTIONAL_FIELDS.concat(MANDATORY_FIELDS);
7 export interface AutocryptHeader {
8     addr: string;
9     keydata: Uint8Array;
10     'prefer-encrypt'?: 'mutual';
11     // Non-critical optional fields
12     [_key: string]: undefined | string | Uint8Array;
15 // Parse according to https://autocrypt.org/level1.html#the-autocrypt-header
16 export const getParsedAutocryptHeader = (header = '', sender = ''): AutocryptHeader | undefined => {
17     let invalid = false;
19     const result: AutocryptHeader = Object.fromEntries(
20         header
21             .split(';')
22             .map((keyValue) => {
23                 const trimmedKeyValue = keyValue.trim();
25                 // For ease of parsing, the keydata attribute MUST be the last attribute in this header. Avoid splitting by = since it's base64
26                 if (trimmedKeyValue.startsWith('keydata=')) {
27                     try {
28                         const keydataStringValue = trimmedKeyValue.slice('keydata='.length);
29                         const keydataValue = binaryStringToArray(decodeBase64(keydataStringValue));
30                         return ['keydata', keydataValue];
31                     } catch (e: any) {
32                         return ['', ''];
33                     }
34                 }
36                 const [parsedKey = '', parsedValue = ''] = keyValue.split('=');
38                 const key = parsedKey.trim();
40                 // It MUST treat the entire Autocrypt header as invalid if it encounters a “critical” attribute that it doesn’t support.
41                 if (!CRITICAL_FIELDS.includes(key) && !key.startsWith('_')) {
42                     invalid = true;
43                     return ['', ''];
44                 }
46                 return [key, parsedValue.trim()];
47             })
48             .filter(([key, value]) => {
49                 return key && value;
50             })
51     );
53     // The mandatory fields must be present.
54     if (MANDATORY_FIELDS.some((field) => !result[field]) || invalid) {
55         return;
56     }
58     // If addr differs from the addr in the From header, the entire Autocrypt header MUST be treated as invalid.
59     if (result.addr.toLowerCase() !== sender.toLowerCase()) {
60         return;
61     }
63     // The prefer-encrypt attribute is optional and can only occur with the value mutual.
64     // Its presence in the Autocrypt header indicates an agreement to enable encryption by default.
65     if (result['prefer-encrypt'] !== 'mutual') {
66         return;
67     }
69     return result;