1 import type { PublicKeyReference } from '@proton/crypto';
2 import { PACKAGE_TYPE, SIGN } from '@proton/shared/lib/mail/mailSettings';
4 import type { CONTACT_MIME_TYPES } from '../../lib/constants';
5 import { MIME_TYPES, MIME_TYPES_MORE, PGP_SCHEMES, PGP_SCHEMES_MORE } from '../../lib/constants';
6 import type { MailSettings, SelfSend } from '../../lib/interfaces';
7 import { KT_VERIFICATION_STATUS } from '../../lib/interfaces';
8 import extractEncryptionPreferences, { ENCRYPTION_PREFERENCES_ERROR_TYPES } from '../../lib/mail/encryptionPreferences';
10 const fakeKey1: PublicKeyReference = {
14 getUserIDs: () => ['<user@pm.me>'],
16 const pinnedFakeKey1: PublicKeyReference = {
20 getUserIDs: () => ['<user@pm.me>'],
22 const fakeKey2: PublicKeyReference = {
26 getUserIDs: () => ['<user@tatoo.me>'],
28 const pinnedFakeKey2: PublicKeyReference = {
32 getUserIDs: () => ['<user@tatoo.me>'],
34 const fakeKey3: PublicKeyReference = {
39 const pinnedFakeKey3: PublicKeyReference = {
45 describe('extractEncryptionPreferences for an internal user', () => {
46 const ktVerificationResult = { status: KT_VERIFICATION_STATUS.VERIFIED_KEYS };
48 emailAddress: 'user@pm.me',
49 publicKeys: { apiKeys: [], pinnedKeys: [] },
50 scheme: PGP_SCHEMES_MORE.GLOBAL_DEFAULT,
51 mimeType: MIME_TYPES_MORE.AUTOMATIC,
52 isInternalWithDisabledE2EEForMail: false,
53 trustedFingerprints: new Set([]),
54 encryptionCapableFingerprints: new Set([]),
55 obsoleteFingerprints: new Set([]),
56 compromisedFingerprints: new Set([]),
59 isPGPExternalWithExternallyFetchedKeys: false,
60 isPGPExternalWithoutExternallyFetchedKeys: false,
61 pgpAddressDisabled: false,
63 isContactSignatureVerified: true,
64 contactSignatureTimestamp: new Date(0),
67 const mailSettings = {
69 PGPScheme: PACKAGE_TYPE.SEND_PGP_MIME,
70 DraftMIMEType: MIME_TYPES.DEFAULT,
73 it('should extract the primary API key when the email address does not belong to any contact', () => {
74 const apiKeys = [fakeKey1, fakeKey2, fakeKey3];
75 const pinnedKeys = [] as PublicKeyReference[];
76 const verifyingPinnedKeys = [] as PublicKeyReference[];
77 const publicKeyModel = {
80 isContactSignatureVerified: undefined,
81 contactSignatureTimestamp: undefined,
82 publicKeys: { apiKeys, pinnedKeys, verifyingPinnedKeys },
83 encryptionCapableFingerprints: new Set(['fakeKey1', 'fakeKey3']),
84 obsoleteFingerprints: new Set(['fakeKey3']),
86 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
88 expect(result).toEqual({
91 mimeType: MIME_TYPES_MORE.AUTOMATIC,
92 scheme: PGP_SCHEMES.PGP_MIME,
93 isInternalWithDisabledE2EEForMail: false,
95 isSendKeyPinned: false,
101 hasPinnedKeys: false,
104 isContactSignatureVerified: undefined,
105 contactSignatureTimestamp: undefined,
106 emailAddressWarnings: undefined,
107 ktVerificationResult,
111 it('should extract the primary API key when there are no pinned keys', () => {
112 const apiKeys = [fakeKey1, fakeKey2, fakeKey3];
113 const pinnedKeys = [] as PublicKeyReference[];
114 const verifyingPinnedKeys = [] as PublicKeyReference[];
115 const publicKeyModel = {
117 publicKeys: { apiKeys, pinnedKeys, verifyingPinnedKeys },
118 encryptionCapableFingerprints: new Set(['fakeKey1', 'fakeKey3']),
119 obsoleteFingerprints: new Set(['fakeKey3']),
121 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
123 expect(result).toEqual({
126 mimeType: MIME_TYPES_MORE.AUTOMATIC,
127 scheme: PGP_SCHEMES.PGP_MIME,
128 isInternalWithDisabledE2EEForMail: false,
130 isSendKeyPinned: false,
136 hasPinnedKeys: false,
139 isContactSignatureVerified: true,
140 contactSignatureTimestamp: new Date(0),
141 emailAddressWarnings: undefined,
142 ktVerificationResult,
146 it('should pick the pinned key (and not the API one)', () => {
147 const apiKeys = [fakeKey1, fakeKey2, fakeKey3];
148 const pinnedKeys = [pinnedFakeKey2, pinnedFakeKey1];
149 const verifyingPinnedKeys = [pinnedFakeKey2];
150 const publicKeyModel = {
152 publicKeys: { apiKeys, pinnedKeys, verifyingPinnedKeys },
153 trustedFingerprints: new Set(['fakeKey1', 'fakeKey2']),
154 encryptionCapableFingerprints: new Set(['fakeKey1', 'fakeKey3']),
155 obsoleteFingerprints: new Set(['fakeKey3']),
157 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
159 expect(result).toEqual({
162 mimeType: MIME_TYPES_MORE.AUTOMATIC,
163 scheme: PGP_SCHEMES.PGP_MIME,
164 isInternalWithDisabledE2EEForMail: false,
165 sendKey: pinnedFakeKey1,
166 isSendKeyPinned: true,
175 isContactSignatureVerified: true,
176 contactSignatureTimestamp: new Date(0),
177 emailAddressWarnings: undefined,
178 ktVerificationResult,
182 it('should give a warning for keyid mismatch', () => {
183 const apiKeys = [fakeKey2, fakeKey3];
184 const pinnedKeys = [pinnedFakeKey2];
185 const verifyingPinnedKeys = [] as PublicKeyReference[];
186 const publicKeyModel = {
188 publicKeys: { apiKeys, pinnedKeys, verifyingPinnedKeys },
189 trustedFingerprints: new Set(['fakeKey2']),
190 encryptionCapableFingerprints: new Set(['fakeKey2', 'fakeKey3']),
192 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
194 expect(result.warnings?.length).toEqual(1);
197 it('should give an error when the API gave emailAddress errors', () => {
198 const apiKeys = [fakeKey1, fakeKey2, fakeKey3];
199 const pinnedKeys = [pinnedFakeKey1];
200 const verifyingPinnedKeys = [pinnedFakeKey1] as PublicKeyReference[];
201 const publicKeyModel = {
203 publicKeys: { apiKeys, pinnedKeys, verifyingPinnedKeys },
204 encryptionCapableFingerprints: new Set(['fakeKey1', 'fakeKey2', 'fakeKey3']),
205 obsoleteFingerprints: new Set(['fakeKey1']),
206 emailAddressErrors: ['Recipient could not be found'],
208 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
210 expect(result?.error?.type).toEqual(ENCRYPTION_PREFERENCES_ERROR_TYPES.EMAIL_ADDRESS_ERROR);
213 it('should give an error when there are no pinned keys and the primary key is not valid for sending', () => {
214 const apiKeys = [fakeKey1, fakeKey2, fakeKey3];
215 const publicKeyModel = {
217 publicKeys: { apiKeys, pinnedKeys: [], verifyingPinnedKeys: [] },
218 encryptionCapableFingerprints: new Set(['fakeKey2', 'fakeKey3']),
219 compromisedFingerprints: new Set(['fakeKey1']),
221 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
223 expect(result?.error?.type).toEqual(ENCRYPTION_PREFERENCES_ERROR_TYPES.PRIMARY_CANNOT_SEND);
226 it('should give an error when the preferred pinned key is not valid for sending', () => {
227 const apiKeys = [fakeKey1, fakeKey2, fakeKey3];
228 const pinnedKeys = [pinnedFakeKey1];
229 const verifyingPinnedKeys = [pinnedFakeKey1];
230 const publicKeyModel = {
232 publicKeys: { apiKeys, pinnedKeys, verifyingPinnedKeys },
233 encryptionCapableFingerprints: new Set(['fakeKey2', 'fakeKey3']),
234 obsoleteFingerprints: new Set(['fakeKey1']),
236 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
238 expect(result?.error?.type).toEqual(ENCRYPTION_PREFERENCES_ERROR_TYPES.PRIMARY_CANNOT_SEND);
241 it('should give an error when the preferred pinned key is not among the keys returned by the API', () => {
242 const apiKeys = [fakeKey1, fakeKey2];
243 const pinnedKeys = [pinnedFakeKey3];
244 const verifyingPinnedKeys = [pinnedFakeKey3];
245 const publicKeyModel = {
247 publicKeys: { apiKeys, pinnedKeys, verifyingPinnedKeys },
248 encryptionCapableFingerprints: new Set(['fakeKey1', 'fakeKey2']),
249 trustedFingerprints: new Set(['fakeKey3']),
251 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
253 expect(result?.error?.type).toEqual(ENCRYPTION_PREFERENCES_ERROR_TYPES.PRIMARY_NOT_PINNED);
256 it('should give an error if the API returned no keys', () => {
257 const apiKeys = [] as PublicKeyReference[];
258 const pinnedKeys = [pinnedFakeKey1];
259 const verifyingPinnedKeys = [pinnedFakeKey1];
260 const publicKeyModel = {
262 publicKeys: { apiKeys, pinnedKeys, verifyingPinnedKeys },
263 trustedFingerprints: new Set(['fakeKey1']),
264 encryptionCapableFingerprints: new Set(['fakeKey1']),
266 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
268 expect(result?.error?.type).toEqual(ENCRYPTION_PREFERENCES_ERROR_TYPES.INTERNAL_USER_NO_API_KEY);
271 it('should give an error if the API returned no keys valid for sending', () => {
272 const apiKeys = [fakeKey1, fakeKey2, fakeKey3];
273 const pinnedKeys = [pinnedFakeKey1];
274 const verifyingPinnedKeys = [] as PublicKeyReference[];
275 const publicKeyModel = {
277 publicKeys: { apiKeys, pinnedKeys, verifyingPinnedKeys },
278 trustedFingerprints: new Set(['fakeKey1']),
279 encryptionCapableFingerprints: new Set(['fakeKey3']),
280 obsoleteFingerprints: new Set(['fakeKey3']),
282 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
284 expect(result?.error?.type).toEqual(ENCRYPTION_PREFERENCES_ERROR_TYPES.PRIMARY_CANNOT_SEND);
287 it('should give an error if there are pinned keys but the contact signature could not be verified', () => {
288 const apiKeys = [fakeKey1, fakeKey2, fakeKey3];
289 const pinnedKeys = [pinnedFakeKey1];
290 const verifyingPinnedKeys = [pinnedFakeKey1];
291 const publicKeyModel = {
293 isContactSignatureVerified: false,
294 publicKeys: { apiKeys, pinnedKeys, verifyingPinnedKeys },
295 encryptionCapableFingerprints: new Set(['fakeKey1', 'fakeKey2', 'fakeKey3']),
297 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
299 expect(result?.error?.type).toEqual(ENCRYPTION_PREFERENCES_ERROR_TYPES.CONTACT_SIGNATURE_NOT_VERIFIED);
302 it('should give an error if key transparency returned an error', () => {
303 const publicKeyModel = {
305 publicKeys: { apiKeys: [], pinnedKeys: [], verifyingPinnedKeys: [] },
306 emailAddressErrors: ['Key verification error'],
308 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
309 expect(result?.error?.type).toEqual(ENCRYPTION_PREFERENCES_ERROR_TYPES.EMAIL_ADDRESS_ERROR);
312 it('should give an error if key transparency returned an error, and ignore pinned keys', () => {
313 const pinnedKeys = [pinnedFakeKey2, pinnedFakeKey1];
314 const verifyingPinnedKeys = [pinnedFakeKey2];
315 const publicKeyModel = {
317 publicKeys: { apiKeys: [], pinnedKeys, verifyingPinnedKeys },
318 trustedFingerprints: new Set(['fakeKey1', 'fakeKey2']),
319 emailAddressErrors: ['Key verification error'],
321 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
322 expect(result?.error?.type).toEqual(ENCRYPTION_PREFERENCES_ERROR_TYPES.EMAIL_ADDRESS_ERROR);
326 const testExtractEncryptionPreferencesWithWKD = (encrypt: boolean) =>
327 describe(`extractEncryptionPreferences for an external user with WKD keys (encrypt: ${encrypt})`, () => {
328 const ktVerificationResult = { status: KT_VERIFICATION_STATUS.UNVERIFIED_KEYS };
331 emailAddress: 'user@pm.me',
332 publicKeys: { apiKeys: [], pinnedKeys: [], verifyingPinnedKeys: [] },
333 scheme: PGP_SCHEMES.PGP_INLINE,
334 mimeType: MIME_TYPES.PLAINTEXT as CONTACT_MIME_TYPES,
335 isInternalWithDisabledE2EEForMail: false,
336 trustedFingerprints: new Set([]),
337 encryptionCapableFingerprints: new Set([]),
338 obsoleteFingerprints: new Set([]),
339 compromisedFingerprints: new Set([]),
341 isPGPInternal: false,
342 isPGPExternalWithExternallyFetchedKeys: true,
343 isPGPExternalWithoutExternallyFetchedKeys: false,
344 pgpAddressDisabled: false,
346 isContactSignatureVerified: true,
347 contactSignatureTimestamp: new Date(0),
348 ktVerificationResult,
350 const mailSettings = {
352 PGPScheme: PACKAGE_TYPE.SEND_PGP_MIME,
353 DraftMIMEType: MIME_TYPES.DEFAULT,
356 it('should extract the primary API key when the email address does not belong to any contact', () => {
357 const apiKeys = [fakeKey1, fakeKey2, fakeKey3];
358 const pinnedKeys = [] as PublicKeyReference[];
359 const verifyingPinnedKeys = [] as PublicKeyReference[];
360 const publicKeyModel = {
363 isContactSignatureVerified: undefined,
364 contactSignatureTimestamp: undefined,
365 publicKeys: { apiKeys, pinnedKeys, verifyingPinnedKeys },
366 encryptionCapableFingerprints: new Set(['fakeKey1', 'fakeKey3']),
367 obsoleteFingerprints: new Set(['fakeKey3']),
369 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
371 expect(result).toEqual({
374 mimeType: MIME_TYPES.PLAINTEXT,
375 scheme: PGP_SCHEMES.PGP_INLINE,
376 isInternalWithDisabledE2EEForMail: false,
378 isSendKeyPinned: false,
384 hasPinnedKeys: false,
387 isContactSignatureVerified: undefined,
388 emailAddressWarnings: undefined,
389 contactSignatureTimestamp: undefined,
390 ktVerificationResult,
394 it('should extract the primary API key when there are no pinned keys', () => {
395 const apiKeys = [fakeKey1, fakeKey2, fakeKey3];
396 const pinnedKeys = [] as PublicKeyReference[];
397 const verifyingPinnedKeys = [] as PublicKeyReference[];
398 const publicKeyModel = {
400 publicKeys: { apiKeys, pinnedKeys, verifyingPinnedKeys },
401 encryptionCapableFingerprints: new Set(['fakeKey1', 'fakeKey3']),
402 obsoleteFingerprints: new Set(['fakeKey3']),
404 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
406 expect(result).toEqual({
409 mimeType: MIME_TYPES.PLAINTEXT,
410 scheme: PGP_SCHEMES.PGP_INLINE,
411 isInternalWithDisabledE2EEForMail: false,
413 isSendKeyPinned: false,
419 hasPinnedKeys: false,
422 isContactSignatureVerified: true,
423 contactSignatureTimestamp: new Date(0),
424 emailAddressWarnings: undefined,
425 ktVerificationResult,
429 it('should pick the pinned key (and not the API one)', () => {
430 const apiKeys = [fakeKey1, fakeKey2, fakeKey3];
431 const pinnedKeys = [pinnedFakeKey2, pinnedFakeKey1];
432 const verifyingPinnedKeys = [pinnedFakeKey1];
433 const publicKeyModel = {
435 publicKeys: { apiKeys, pinnedKeys, verifyingPinnedKeys },
436 trustedFingerprints: new Set(['fakeKey1', 'fakeKey2']),
437 encryptionCapableFingerprints: new Set(['fakeKey1', 'fakeKey3']),
438 obsoleteFingerprints: new Set(['fakeKey3']),
440 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
442 expect(result).toEqual({
445 mimeType: MIME_TYPES.PLAINTEXT,
446 scheme: PGP_SCHEMES.PGP_INLINE,
447 isInternalWithDisabledE2EEForMail: false,
448 sendKey: pinnedFakeKey1,
449 isSendKeyPinned: true,
458 isContactSignatureVerified: true,
459 contactSignatureTimestamp: new Date(0),
460 emailAddressWarnings: undefined,
461 ktVerificationResult,
465 it('should give a warning for keyid mismatch', () => {
466 const apiKeys = [fakeKey2, fakeKey3];
467 const pinnedKeys = [pinnedFakeKey2];
468 const verifyingPinnedKeys = [pinnedFakeKey2];
469 const publicKeyModel = {
471 publicKeys: { apiKeys, pinnedKeys, verifyingPinnedKeys },
472 trustedFingerprints: new Set(['fakeKey2']),
473 encryptionCapableFingerprints: new Set(['fakeKey2', 'fakeKey3']),
475 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
477 expect(result.warnings?.length).toEqual(1);
480 it('should give an error when the API gave emailAddress errors', () => {
481 const publicKeyModel = {
484 apiKeys: [fakeKey1, fakeKey2, fakeKey3],
485 pinnedKeys: [pinnedFakeKey1],
486 verifyingPinnedKeys: [],
488 encryptionCapableFingerprints: new Set(['fakeKey1', 'fakeKey2', 'fakeKey3']),
489 obsoleteFingerprints: new Set(['fakeKey1']),
490 emailAddressErrors: ['Recipient could not be found'],
492 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
494 expect(result?.error?.type).toEqual(ENCRYPTION_PREFERENCES_ERROR_TYPES.EMAIL_ADDRESS_ERROR);
497 it('should give an error when the preferred pinned key is not valid for sending', () => {
498 const publicKeyModel = {
501 apiKeys: [fakeKey1, fakeKey2, fakeKey3],
502 pinnedKeys: [pinnedFakeKey1],
503 verifyingPinnedKeys: [pinnedFakeKey1],
505 encryptionCapableFingerprints: new Set(['fakeKey1', 'fakeKey2', 'fakeKey3']),
506 obsoleteFingerprints: new Set(['fakeKey1']),
508 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
510 expect(result?.error?.type).toEqual(ENCRYPTION_PREFERENCES_ERROR_TYPES.PRIMARY_NOT_PINNED);
513 it('should give an error when the preferred pinned key is not among the keys returned by the API', () => {
514 const publicKeyModel = {
517 apiKeys: [fakeKey1, fakeKey2],
518 pinnedKeys: [pinnedFakeKey3],
519 verifyingPinnedKeys: [pinnedFakeKey3],
521 encryptionCapableFingerprints: new Set(['fakeKey1', 'fakeKey2', 'fakeKey3']),
522 trustedFingerprints: new Set(['fakeKey3']),
524 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
526 expect(result?.error?.type).toEqual(ENCRYPTION_PREFERENCES_ERROR_TYPES.PRIMARY_NOT_PINNED);
529 it('should give an error if the API returned no keys valid for sending', () => {
530 const publicKeyModel = {
533 apiKeys: [fakeKey1, fakeKey2, fakeKey3],
534 pinnedKeys: [pinnedFakeKey1],
535 verifyingPinnedKeys: [],
537 trustedFingerprints: new Set(['fakeKey1']),
538 encryptionCapableFingerprints: new Set(['fakeKey3']),
539 obsoleteFingerprints: new Set(['fakeKey3']),
541 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
543 expect(result?.error?.type).toEqual(
544 ENCRYPTION_PREFERENCES_ERROR_TYPES.EXTERNAL_USER_NO_VALID_EXTERNALLY_FETCHED_KEY
548 it('should give an error if there are pinned keys but the contact signature could not be verified', () => {
549 const apiKeys = [fakeKey1, fakeKey2, fakeKey3];
550 const pinnedKeys = [pinnedFakeKey1];
551 const verifyingPinnedKeys = [pinnedFakeKey1];
552 const publicKeyModel = {
554 isContactSignatureVerified: false,
555 publicKeys: { apiKeys, pinnedKeys, verifyingPinnedKeys },
556 encryptionCapableFingerprints: new Set(['fakeKey1', 'fakeKey2', 'fakeKey3']),
558 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
560 expect(result?.error?.type).toEqual(ENCRYPTION_PREFERENCES_ERROR_TYPES.CONTACT_SIGNATURE_NOT_VERIFIED);
564 testExtractEncryptionPreferencesWithWKD(true);
565 testExtractEncryptionPreferencesWithWKD(false);
567 describe('extractEncryptionPreferences for an external user without WKD keys', () => {
568 const ktVerificationResult = { status: KT_VERIFICATION_STATUS.UNVERIFIED_KEYS };
570 emailAddress: 'user@tatoo.me',
571 publicKeys: { apiKeys: [], pinnedKeys: [], verifyingPinnedKeys: [] },
574 scheme: PGP_SCHEMES_MORE.GLOBAL_DEFAULT,
575 mimeType: MIME_TYPES_MORE.AUTOMATIC,
576 isInternalWithDisabledE2EEForMail: false,
577 trustedFingerprints: new Set([]),
578 encryptionCapableFingerprints: new Set([]),
579 obsoleteFingerprints: new Set([]),
580 compromisedFingerprints: new Set([]),
582 isPGPInternal: false,
583 isPGPExternalWithExternallyFetchedKeys: false,
584 isPGPExternalWithoutExternallyFetchedKeys: true,
585 pgpAddressDisabled: false,
587 isContactSignatureVerified: true,
588 contactSignatureTimestamp: new Date(0),
589 ktVerificationResult,
591 const mailSettings = {
593 PGPScheme: PACKAGE_TYPE.SEND_PGP_MIME,
594 DraftMIMEType: MIME_TYPES.PLAINTEXT,
597 it('should take into account the mail Settings', () => {
598 const modelWithoutSign = { ...model, encrypt: undefined, sign: undefined };
599 const result = extractEncryptionPreferences(modelWithoutSign, mailSettings);
601 expect(result).toEqual({
604 mimeType: MIME_TYPES_MORE.AUTOMATIC,
605 scheme: PGP_SCHEMES.PGP_MIME,
606 isInternalWithDisabledE2EEForMail: false,
609 verifyingPinnedKeys: [],
612 hasPinnedKeys: false,
614 isContactSignatureVerified: true,
615 contactSignatureTimestamp: new Date(0),
616 emailAddressWarnings: undefined,
617 ktVerificationResult,
621 it('should pick no key when the email address does not belong to any contact', () => {
622 const result = extractEncryptionPreferences(
626 isContactSignatureVerified: undefined,
627 contactSignatureTimestamp: undefined,
632 expect(result).toEqual({
635 mimeType: MIME_TYPES_MORE.AUTOMATIC,
636 scheme: PGP_SCHEMES.PGP_MIME,
637 isInternalWithDisabledE2EEForMail: false,
640 verifyingPinnedKeys: [],
643 hasPinnedKeys: false,
645 isContactSignatureVerified: undefined,
646 contactSignatureTimestamp: undefined,
647 emailAddressWarnings: undefined,
648 ktVerificationResult,
652 it('should pick no key when there are no pinned keys', () => {
653 const result = extractEncryptionPreferences(model, mailSettings);
655 expect(result).toEqual({
658 mimeType: MIME_TYPES_MORE.AUTOMATIC,
659 scheme: PGP_SCHEMES.PGP_MIME,
660 isInternalWithDisabledE2EEForMail: false,
663 verifyingPinnedKeys: [],
666 hasPinnedKeys: false,
668 isContactSignatureVerified: true,
669 contactSignatureTimestamp: new Date(0),
670 emailAddressWarnings: undefined,
671 ktVerificationResult,
675 it('should pick the first pinned key', () => {
676 const apiKeys = [] as PublicKeyReference[];
677 const pinnedKeys = [pinnedFakeKey2, pinnedFakeKey3];
678 const verifyingPinnedKeys = [pinnedFakeKey2, pinnedFakeKey3];
679 const publicKeyModel = {
683 publicKeys: { apiKeys, pinnedKeys, verifyingPinnedKeys },
684 trustedFingerprints: new Set(['fakeKey2', 'fakeKey3']),
685 encryptionCapableFingerprints: new Set(['fakeKey2', 'fakeKey3']),
687 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
689 expect(result).toEqual({
692 mimeType: MIME_TYPES_MORE.AUTOMATIC,
693 scheme: PGP_SCHEMES.PGP_MIME,
694 isInternalWithDisabledE2EEForMail: false,
695 sendKey: pinnedFakeKey2,
696 isSendKeyPinned: true,
705 isContactSignatureVerified: true,
706 contactSignatureTimestamp: new Date(0),
707 emailAddressWarnings: undefined,
708 ktVerificationResult,
712 it('should give a warning for keyid mismatch', () => {
713 const publicKeyModel = {
717 publicKeys: { apiKeys: [], pinnedKeys: [pinnedFakeKey1], verifyingPinnedKeys: [] },
718 trustedFingerprints: new Set(['fakeKey1']),
719 encryptionCapableFingerprints: new Set(['fakeKey1']),
721 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
723 expect(result.warnings?.length).toEqual(1);
726 it('should give an error when the preferred pinned key is not valid for sending', () => {
727 const publicKeyModel = {
733 pinnedKeys: [pinnedFakeKey2, pinnedFakeKey1],
734 verifyingPinnedKeys: [pinnedFakeKey1],
736 encryptionCapableFingerprints: new Set([]),
738 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
740 expect(result?.error?.type).toEqual(ENCRYPTION_PREFERENCES_ERROR_TYPES.EXTERNAL_USER_NO_VALID_PINNED_KEY);
743 it('should give an error if there are pinned keys but the contact signature could not be verified', () => {
744 const publicKeyModel = {
746 isContactSignatureVerified: false,
749 pinnedKeys: [pinnedFakeKey2, pinnedFakeKey1],
750 verifyingPinnedKeys: [pinnedFakeKey2],
752 encryptionCapableFingerprints: new Set(['fakeKey1', 'fakeKey2']),
754 const result = extractEncryptionPreferences(publicKeyModel, mailSettings);
756 expect(result?.error?.type).toEqual(ENCRYPTION_PREFERENCES_ERROR_TYPES.CONTACT_SIGNATURE_NOT_VERIFIED);
760 describe('extractEncryptionPreferences for an own address', () => {
761 const apiKeys = [fakeKey1, fakeKey2];
762 const pinnedKeys = [] as PublicKeyReference[];
763 const verifyingPinnedKeys = [] as PublicKeyReference[];
764 const ktVerificationResult = { status: KT_VERIFICATION_STATUS.VERIFIED_KEYS };
766 emailAddress: 'user@pm.me',
767 publicKeys: { apiKeys, pinnedKeys, verifyingPinnedKeys },
768 mimeType: MIME_TYPES_MORE.AUTOMATIC,
769 scheme: PGP_SCHEMES_MORE.GLOBAL_DEFAULT,
770 isInternalWithDisabledE2EEForMail: false,
771 trustedFingerprints: new Set([]),
772 encryptionCapableFingerprints: new Set(['fakeKey1', 'fakeKey2']),
773 obsoleteFingerprints: new Set([]),
774 compromisedFingerprints: new Set([]),
775 isPGPExternal: false,
777 isPGPExternalWithExternallyFetchedKeys: false,
778 isPGPExternalWithoutExternallyFetchedKeys: false,
779 pgpAddressDisabled: false,
781 emailAddressWarnings: undefined,
782 ktVerificationResult,
784 const mailSettings = {
786 PGPScheme: PACKAGE_TYPE.SEND_PGP_MIME,
787 DraftMIMEType: MIME_TYPES.PLAINTEXT,
790 it('should not pick the public key from the keys in selfSend.address', () => {
791 const selfSend: SelfSend = {
796 publicKey: pinnedFakeKey1,
799 const result = extractEncryptionPreferences(model, mailSettings, selfSend);
801 expect(result).toEqual({
804 mimeType: MIME_TYPES_MORE.AUTOMATIC,
805 scheme: PGP_SCHEMES.PGP_MIME,
806 isInternalWithDisabledE2EEForMail: false,
807 sendKey: pinnedFakeKey1,
808 isSendKeyPinned: false,
814 hasPinnedKeys: false,
817 isContactSignatureVerified: undefined,
818 contactSignatureTimestamp: undefined,
819 emailAddressWarnings: undefined,
820 ktVerificationResult,
824 it('should give a warning for keyid mismatch', () => {
825 const selfSend: SelfSend = {
830 publicKey: pinnedFakeKey2,
833 const result = extractEncryptionPreferences(model, mailSettings, selfSend);
835 expect(result.warnings?.length).toEqual(1);
838 it('should give an error when the address is disabled', () => {
839 const selfSend: SelfSend = {
844 publicKey: pinnedFakeKey1,
847 const result = extractEncryptionPreferences(model, mailSettings, selfSend);
849 expect(result?.error?.type).toEqual(ENCRYPTION_PREFERENCES_ERROR_TYPES.INTERNAL_USER_DISABLED);
852 it('should give an error when the API returned no keys for the address', () => {
853 const selfSend: SelfSend = {
858 publicKey: pinnedFakeKey1,
861 const result = extractEncryptionPreferences(model, mailSettings, selfSend);
863 expect(result?.error?.type).toEqual(ENCRYPTION_PREFERENCES_ERROR_TYPES.INTERNAL_USER_NO_API_KEY);
866 it('should give an error if the primary key is compromised', () => {
867 const selfSend: SelfSend = {
872 publicKey: pinnedFakeKey1,
875 const result = extractEncryptionPreferences(model, mailSettings, selfSend);
877 expect(result?.error?.type).toEqual(ENCRYPTION_PREFERENCES_ERROR_TYPES.INTERNAL_USER_NO_API_KEY);
880 it('should give an error when no public key (from the decypted private key) was received', () => {
881 const selfSend: SelfSend = {
887 const result = extractEncryptionPreferences(model, mailSettings, selfSend);
889 expect(result?.error?.type).toEqual(ENCRYPTION_PREFERENCES_ERROR_TYPES.PRIMARY_CANNOT_SEND);