KEK and FEK explained: why per-file encryption matters
KEK (Key Encryption Key) and FEK (File Encryption Key) form the two-layer key hierarchy used by serious encrypted apps — Signal, BitLocker, Apple's File Protection, Filarr. Here's what each one does, why one global key is dangerous, and what a correctly designed encryption layout looks like.
Mathis Belouar-Pruvot
· founder of Filarr · · 11 min read
Quick Answer. KEK (Key Encryption Key) and FEK (File Encryption Key) form a two-layer key hierarchy used by serious encrypted apps. The FEK, a random key, encrypts the data; the KEK, derived from your password, encrypts ("wraps") the FEK. This pattern, called envelope encryption, is used by Signal, BitLocker, AWS KMS and Apple's File Protection, and in its textbook form every file gets its own FEK. Filarr uses the two layers differently: one random FEK per account, under which your files and notes are encrypted, each with a fresh random value. Changing your password only re-wraps that FEK, and a stolen copy of the server's data opens nothing.
When an encrypted notes app says "your data is encrypted with AES-256," there's a hidden architectural choice that matters more than the cipher: how many keys are there, and how are they organized?
The naive design uses one key for everything — your password, stretched into a master key, encrypts every file. The better design uses two layers: a random data key that encrypts the content, wrapped by a key derived from your password. This is called envelope encryption, and the two layers have specific names: KEK (Key Encryption Key) and FEK (File Encryption Key). In the textbook layout, every file even gets its own FEK.
This article explains why the two-layer design exists, how it works step by step, what attacks it defends against, and how to recognize a correctly designed encrypted app.
What are KEK and FEK?
The terms come from key management systems and cloud KMS literature. The definitions:
- FEK (File Encryption Key): a random symmetric key (typically 256 bits) that encrypts file content. In the textbook layout, each file in the system has its own unique FEK; some designs, Filarr's among them, use a single FEK for a whole account.
- KEK (Key Encryption Key): a master key, typically derived from the user's password, that encrypts FEKs. The KEK itself never directly encrypts file content.
In the textbook layout, the arrangement is hierarchical: one KEK, many FEKs.
User password
│
▼
KDF (PBKDF2 / Argon2id)
│
▼
╔══════════╗
║ KEK ║ ← lives in memory only
╚══════════╝
│
│ encrypts each FEK
┌────────────┼────────────┐
▼ ▼ ▼
┌──────┐ ┌──────┐ ┌──────┐
│ FEK1 │ │ FEK2 │ │ FEK3 │
└──────┘ └──────┘ └──────┘
│ │ │
▼ ▼ ▼
┌──────┐ ┌──────┐ ┌──────┐
│file 1│ │file 2│ │file 3│
│encrypt│ │encrypt│ │encrypt│
└──────┘ └──────┘ └──────┘
When you save a file:
- Generate a fresh random FEK
- Encrypt the file with its FEK using AES-256-GCM
- Encrypt the FEK with the KEK using AES-256-GCM
- Store the encrypted file alongside the encrypted FEK on disk (or upload to cloud)
When you read a file:
- Use your password to re-derive the KEK
- Decrypt the FEK with the KEK
- Decrypt the file with the FEK
The KEK lives only in process memory and is wiped when you lock the app or close it. The FEKs live encrypted on disk. The original password is never stored anywhere.
Why not use one global key for everything?
The single-key design seems simpler. You stretch your password into a master key, encrypt every file with that master key, done. Why add a layer?
Three concrete problems with the single-key design.
1. Blast radius. If one ciphertext leaks the key (through a bug, a side-channel, or a nonce reuse), every file encrypted with that key is exposed. With per-file FEKs, leaking one file's encryption key only exposes that one file.
2. Key rotation is impossible. With a single global key, rotating the key (because of a suspected compromise) means re-encrypting every file. That's slow and risky. With KEK/FEK, you can rotate the KEK and re-wrap the FEKs without ever decrypting and re-encrypting the file content.
3. Selective sharing is impossible. If you want to share one file with another user, you'd have to share the global master key — which gives them access to all your files, forever. With per-file FEKs, you share a single FEK encrypted with the recipient's public key. They get exactly one file.
These problems aren't theoretical. The history of cryptographic disasters is largely a history of "one key for everything" designs failing badly.
What does envelope encryption mean?
"Envelope encryption" is the name of the KEK/FEK pattern in the cloud security industry. The metaphor: each file is sealed in an envelope with its own data key (FEK), and that envelope is then placed in another envelope sealed with a key encryption key (KEK).
AWS KMS, Google Cloud KMS, Azure Key Vault, and HashiCorp Vault all implement envelope encryption. The cloud-managed KEK never leaves a hardware security module; only the FEKs (encrypted under that KEK) are sent back to the application.
Filarr uses the same pattern on your device: your password derives the KEK, the KEK lives only in memory, and it wraps a single FEK, the key of your account, under which your files and notes are encrypted (details below).
How are the KEK and FEK actually generated?
The two halves use different generation methods because they have different requirements.
FEK generation: cryptographically secure random. A FEK is a 256-bit random value pulled from the operating system's secure random number generator (crypto.randomBytes in Node, getRandomValues in browsers, /dev/urandom on Linux, BCryptGenRandom on Windows). In the textbook layout, each new file gets a fresh FEK; in Filarr, each account does. Either way, the FEK is never derived from anything; it's pure randomness.
KEK generation: key derivation function. The KEK is derived from the user's password through a slow function designed to resist brute-force attacks. Two functions are commonly used:
- PBKDF2-SHA-512, salted per user, with at least the 210,000 iterations OWASP recommends for SHA-512 (600,000 is its figure for SHA-256).
- Argon2id with at least 64 MB of memory cost, 3 iterations, 4 parallelism lanes. The current best practice (RFC 9106).
Argon2id is preferred for new designs because it's memory-hard, which makes GPU and ASIC brute-forcing dramatically more expensive than PBKDF2. Many encrypted apps still use PBKDF2 for compatibility with existing libraries, sometimes alongside Argon2id for defense in depth.
What attacks does the KEK/FEK design defend against?
A good way to evaluate any cryptographic architecture is to walk through specific attack scenarios.
Attack 1: One file's key is exposed. A bug in the application briefly logs a FEK to disk. An attacker with disk access reads the log. What they get: the contents of one file. What they don't get: the master key, any other file. Single-key design fails this test catastrophically.
Attack 2: A user shares a file. With per-file FEKs, sharing means encrypting one FEK to the recipient's public key. The recipient gets access to one file, nothing more. With a single global key, you can't share anything without sharing everything.
Attack 3: User changes their password. With KEK/FEK, you re-derive a new KEK from the new password and re-wrap each FEK with the new KEK. No file content is touched. The operation is fast (milliseconds) and atomic. With a single key, you must re-encrypt every file from scratch — a destructive, slow, error-prone process.
Attack 4: Cloud server is compromised. The attacker reads all the encrypted blobs on disk. What they get: ciphertext + encrypted FEKs. What they don't get: the KEK (it's only in your device's memory) — so they cannot decrypt the FEKs, and therefore cannot decrypt anything.
Attack 5: Forensic recovery of a deleted file. With per-file FEKs, you can "shred" a file by deleting just its FEK. The encrypted file content becomes permanently unreadable, even if the bytes remain on disk. With a single key, deleting just one file's metadata still leaves it decryptable — secure deletion requires overwriting the bytes.
In every scenario, the two-layer design behaves better than the single-key design.
Are there other names for this pattern?
Yes. The same architectural pattern shows up in many places under different names:
- Envelope encryption — AWS, Google Cloud, Azure
- Key wrapping — NIST terminology
- DEK + KEK — "Data Encryption Key" instead of "File Encryption Key"
- Master key + file keys — Apple's File Protection in iOS / macOS
- Vault key + record keys — 1Password
- VMK + FVEK — Microsoft BitLocker (Volume Master Key + Full Volume Encryption Key)
These are all the same pattern: a master key that encrypts data keys, where the data keys actually touch the data. The naming differs but the structure is constant.
How can I tell if a notes app uses per-file encryption?
When evaluating an encrypted notes or file storage app, look for these signals:
-
Architecture documentation that mentions key wrapping, envelope encryption, or per-file keys. A serious app explains its encryption layout publicly. If the docs only say "AES-256," that's a marketing claim, not an architecture.
-
Independent audit reports. Auditors will explicitly note whether per-file keys are used. The presence of "KEK and FEK" in an audit report is a strong positive signal.
-
Selective sharing capability. If the app supports sharing individual files without giving the recipient access to your whole vault, it's almost certainly using per-file keys. Single-key designs cannot do selective sharing.
-
Fast password change. If changing your master password takes seconds and doesn't require re-encrypting your whole library, the design is using key wrapping (KEK is updated; FEKs and files are untouched).
-
Open source. With public source code, you can verify the architecture directly. Search for terms like
wrapKey,wrappedFek,unwrapKey,kekId,keyEncryptionKey.
How does Filarr implement KEK/FEK?
Filarr uses both layers, with one difference from the textbook layout: the FEK is the key of your account, not the key of a single file.
- KEK derivation. Your password is run through PBKDF2-SHA-512 (600,000 iterations, well above the 210,000 OWASP recommends for PBKDF2-SHA512) to produce a 256-bit KEK. The KEK lives in process memory only; it is never written to disk in plaintext.
- FEK generation. Each account, or each local profile, gets one 256-bit random FEK from the OS's secure RNG. The FEK is never derived from your password.
- File encryption. Your files and notes are encrypted with AES-256-GCM under the FEK, with a fresh random value (the nonce, or IV) for each file and each encryption. Two formats go one step further and derive a key of their own from the FEK, with HKDF and a random salt: large files imported on the desktop, and synced blocks. See what is AES-256-GCM for why this mode matters.
- FEK wrapping. The FEK is encrypted with the KEK using AES-256-GCM, and a second time under your recovery phrase (24 words for a cloud account). For a cloud account, the server keeps both wrapped copies, so a new device can open your data.
- Multi-profile isolation. Each local Filarr profile has its own FEK and its own KEK, derived from a different password. Profile A's KEK cannot decrypt Profile B's FEK — even though both belong to the same user.
- Cloud upload. When cloud sync is enabled, Filarr uploads the encrypted file blobs, and the server keeps the wrapped FEK. A stolen copy of the server's data opens nothing without your password or your recovery phrase. Signing in doesn't give away what it takes to rebuild the KEK either: since October 16, 2026, an up-to-date app sends a key derived from your password with a different salt, not the password itself. During a transition of about two months, an account that hasn't signed in again yet, or an older app version, still sends the password (over HTTPS), where a compromised server could capture it.
Measured against the attacks above, this layout gives you two things. A password change only re-wraps the FEK, so it is instantaneous and touches no file (attack 3). A stolen copy of the server's data yields ciphertext and wrapped keys, nothing readable (attack 4). What it does not give you is a per-file blast radius: the FEK opens the whole account, which is why it never leaves your device in plaintext and is only ever stored wrapped (attack 1). Sharing doesn't rely on per-file FEKs either: a share link carries a key of its own after the #, and a shared vault has its own key, sealed for each member (attack 2).
Read Filarr's full security architecture for the exact parameters and the threat model.
Further reading
- NIST SP 800-38F — Methods for Key Wrapping — the standard for envelope encryption
- RFC 9106 — Argon2 password hashing — the modern KDF
- OWASP Password Storage Cheat Sheet — current recommendations
- What is AES-256-GCM and why it matters
- Zero-knowledge encryption explained
- End-to-end vs zero-knowledge encryption
- What is local-first software?
- Filarr's security architecture