1 import type { PrivateKeyReference, PublicKeyReference } from '@proton/crypto';
2 import { toPublicKeyReference } from '@proton/crypto';
3 import { ADDRESS_STATUS } from '@proton/shared/lib/constants';
4 import { canonicalizeInternalEmail } from '@proton/shared/lib/helpers/email';
5 import type { Address } from '@proton/shared/lib/interfaces/Address';
6 import type { GetAddressKeys } from '@proton/shared/lib/interfaces/hooks/GetAddressKeys';
7 import { getPrimaryKey } from '@proton/shared/lib/keys';
8 import { decryptPassphrase } from '@proton/shared/lib/keys/drivePassphrase';
9 import { splitKeys } from '@proton/shared/lib/keys/keys';
11 import type { ShareWithKey } from '../_shares';
13 // Special case for drive to allow users with just an external address
14 export const getActiveAddresses = (addresses: Address[]): Address[] => {
15 return addresses.filter(({ Status }) => Status === ADDRESS_STATUS.STATUS_ENABLED);
18 export const getPrimaryAddressAsync = async (getAddresses: () => Promise<Address[]>) => {
19 const addresses = await getAddresses();
20 const [activeAddress] = getActiveAddresses(addresses);
23 throw new Error('User has no active address');
29 export const getPrimaryAddressKeyAsync = async (
30 getPrimaryAddress: () => Promise<Address>,
31 getAddressKeys: GetAddressKeys
33 const activeAddress = await getPrimaryAddress();
34 const addressKeys = await getAddressKeys(activeAddress.ID);
35 const { privateKey, publicKey: maybePublicKey, ID: addressKeyID } = getPrimaryKey(addressKeys) || {};
37 if (!privateKey || !addressKeyID) {
38 // Should never happen
39 throw new Error('Primary private key is not available');
42 const publicKey = maybePublicKey || (await toPublicKeyReference(privateKey));
44 return { addressKeyID, privateKey, publicKey, address: activeAddress };
47 const getOwnAddressWithEmail = async (email: string, getAddresses: () => Promise<Address[]>) => {
48 // Some characters can be changed but still be the same email.
49 return (await getAddresses()).find(
50 ({ Email }) => canonicalizeInternalEmail(Email) === canonicalizeInternalEmail(email)
54 const getOwnAddress = async (addressId: string, getAddresses: () => Promise<Address[]>) => {
55 return (await getAddresses()).find(({ ID }) => ID === addressId);
58 const getOwnAddressAndKeys = async (
60 getAddresses: () => Promise<Address[]>,
61 getAddressKeys: GetAddressKeys
63 const address = await getOwnAddress(addressId, getAddresses);
67 const addressKeys = await getAddressKeys(address.ID);
69 return { address, addressKeys };
72 export const getOwnAddressAndPrimaryKeysAsync = async (
74 getAddresses: () => Promise<Address[]>,
75 getAddressKeys: GetAddressKeys
77 const { address, addressKeys } = await getOwnAddressAndKeys(addressId, getAddresses, getAddressKeys);
78 const { privateKey, publicKey, ID: addressKeyID } = getPrimaryKey(addressKeys) || {};
80 if (!privateKey || !addressKeyID) {
81 // Should never happen
82 throw new Error('Primary private key is not available');
85 // Should never happen
86 throw new Error('Address is not available');
89 return { addressKeyID, address, privateKey, publicKey: publicKey || (await toPublicKeyReference(privateKey)) };
92 const getOwnAddressAndKeysWithEmail = async (
94 getAddresses: () => Promise<Address[]>,
95 getAddressKeys: GetAddressKeys
97 const address = await getOwnAddressWithEmail(email, getAddresses);
101 const addressKeys = await getAddressKeys(address.ID);
103 return { address, addressKeys };
106 export const getOwnAddressKeysAsync = async (
108 getAddresses: () => Promise<Address[]>,
109 getAddressKeys: GetAddressKeys
111 const { addressKeys } = await getOwnAddressAndKeys(addressId, getAddresses, getAddressKeys);
112 return addressKeys ? splitKeys(addressKeys) : undefined;
115 export const getOwnAddressKeysWithEmailAsync = async (
117 getAddresses: () => Promise<Address[]>,
118 getAddressKeys: GetAddressKeys
120 const { addressKeys } = await getOwnAddressAndKeysWithEmail(email, getAddresses, getAddressKeys);
121 return addressKeys ? splitKeys(addressKeys) : undefined;
124 export const decryptSharePassphraseAsync = async (
126 privateKeys: PrivateKeyReference[],
127 getVerificationKey: (email: string) => Promise<PublicKeyReference[]>
129 const publicKeys = await getVerificationKey(meta.creator);
130 return decryptPassphrase({
131 armoredPassphrase: meta.passphrase,
132 armoredSignature: meta.passphraseSignature,