The general principle used by FileVault is the same as for any encryption scheme which allows more than one password to access the data (such as LUKS, which is commonly used in Linux environments). To summarise:
- A key called the MEK (media encryption key) is used to encrypt and decrypt the data.
- A key called the KEK (key encryption key) is used to generate a ciphertext version of the MEK, which we'll call X. The value of X is stored alongside the data, e.g. in a filesystem header.
- A series of passwords (such as your user password and a recovery password), e.g P₁ and P₂, are passed to a standardised key derivation function to generate corresponding encryption keys that are used to generate ciphertext versions of the KEK. Let's say that the ciphertext version of the KEK generated using P₁ is C₁, and likewise, P₂ yields C₂. The values C₁ and C₂ are stored alongside X.
Now, if you know one of the passwords, you can provide it to decrypt the data. For example, if you know P₂, you can decrypt C₂ to find out the KEK. Once you know the KEK, you can decrypt X to find out the MEK. Once you know the MEK, you can decrypt the data.
This scheme allows easy addition, removal, and alteration of passwords used to access the data, since this simply requires altering the set of stored Cᵢ values. No re-encrypting of the data itself is necessary, since the MEK being used doesn't change.
In LUKS, these places to store a Cᵢ value are called "keyslots", and LUKS provides eight such keyslots.
In APFS, all such Cᵢ values are stored together in a data block called a "keybag" — in principle, the size of this keybag is unbounded, but in current practice, it's typically large enough for 7 keys. When you set up authorised users and passwords in FileVault preferences, one of these slots is used to store a Cᵢ which can be decrypted using the recovery password that is displayed to you.