Make CSFLE observable from the local Customer Master Key through the key vault, ciphertext BinData, deterministic/random algorithms, and driver decryption.

Client-Side Field Level Encryption: Key Vaults, KMS, Automatic Encryption, and Driver Responsibilities

AtlasMart wants the database server to store customer email and support notes as ciphertext while a trusted application can decrypt them. The Community-compatible learning path therefore uses explicit CSFLE with a disposable local master key.

Advanced120–200 minutesExplicit CSFLE labMongoDB 8.3.8 · mongosh 2.10.0 · PyMongo 4.17.0Last reviewed: September 2026

Learning objectives

01

Explain the CSFLE key hierarchy: Customer Master Key, Data Encryption Key, key vault, and encrypted BSON BinData.

02

Use Community-compatible explicit CSFLE with a generated local master key and PyMongo encryption support.

03

Compare deterministic and random CSFLE algorithms, including equality-pattern leakage and query consequences.

04

Inspect key-vault metadata and prove that an ordinary MongoDB client sees ciphertext while a configured client can decrypt.

05

Distinguish explicit encryption from automatic encryption and state the Enterprise/Atlas query-analysis boundary.

Reproducible lab baseline

This lesson pins MongoDB Community Server 8.3.8 with mongodb/mongodb-community-server:8.3.8-ubuntu2204-slim, mongosh 2.10.0, and PyMongo 4.17.0 where driver behavior is used. Topology: one disposable Community standalone named atlasmart-ch23-l3. Explicit CSFLE is supported on Community. The local master key is generated at runtime for learning only; production should use an appropriately protected remote KMS or another secure key-injection design. Host publication is loopback-only on port 27183. Authentication/TLS state is stated next to the experiment. Default read/write concern and primary read preference are used unless noted. FCV is observed and never changed. The local KMS examples generate disposable 96-byte master keys at runtime and never embed a real cloud/KMIP credential. Atlas, Enterprise Advanced, AWS KMS, Azure Key Vault, GCP KMS, KMIP, and HSMs are optional production paths. PyMongo CSFLE requires the encryption dependency; current PyMongo upgrade guidance requires pymongocrypt 1.10+ for supported CSFLE use. Product runtime labs were not executed in the generation environment; ciphertext values, key identifiers, timings, storage amplification, and recovery results must be measured locally rather than copied as invented output.

1. The key vault stores wrapped DEKs, not the plaintext master key

The Customer Master Key (CMK) lives in the configured Key Management System (KMS) boundary. The driver uses it to wrap a Data Encryption Key (DEK). MongoDB stores the wrapped DEK as a key-vault document. The application retrieves that wrapped material and asks the configured KMS provider to unwrap it. A key alternate name is convenient, but the key-vault namespace also needs a unique partial index on keyAltNames so two DEKs cannot claim the same name.

Object Stored where in this local lab? Production expectation
CMK ephemeral local file outside MongoDB remote KMS/HSM or hardened key injection
DEK document encryption.__keyVault back up key vault with database; protect access
encrypted field atlasmart.customers_csfle ciphertext remains in normal database/backups
plaintext trusted Python process only keep out of logs/crash dumps/telemetry

2. Build the explicit-CSFLE lab without committing a key

start MongoDB and prepare a local Python environment
docker rm -f atlasmart-ch23-l3 2>/dev/null || truedocker volume rm atlasmart-ch23-l3-db 2>/dev/null || truedocker run -d --name atlasmart-ch23-l3 \  -p 127.0.0.1:27183:27017 \  -v atlasmart-ch23-l3-db:/data/db \  mongodb/mongodb-community-server:8.3.8-ubuntu2204-slim \  --bind_ip_all --port 27017until mongosh "mongodb://127.0.0.1:27183/admin" --quiet --eval 'db.runCommand({ping:1}).ok' 2>/dev/null | grep -q 1; do sleep 1; donemongosh "mongodb://127.0.0.1:27183/admin" --quiet --eval '  printjson(db.adminCommand({buildInfo:1}));  printjson(db.adminCommand({getParameter:1,featureCompatibilityVersion:1}));' python -m venv /tmp/atlasmart-ch23-venv. /tmp/atlasmart-ch23-venv/bin/activatepython -m pip install --disable-pip-version-check "pymongo[encryption]==4.17.0"python - <<'PY'import os, pathlibpath=pathlib.Path('/tmp/atlasmart-ch23-master-key.bin')path.write_bytes(os.urandom(96))os.chmod(path,0o600)print('generated_bytes=',path.stat().st_size)PY
explicit CSFLE: create key, encrypt, store, query, and decrypt
from pathlib import Pathfrom bson.codec_options import CodecOptionsfrom pymongo import MongoClientfrom pymongo.encryption import ClientEncryptionURI = "mongodb://127.0.0.1:27183"KEY_VAULT = "encryption.__keyVault"client = MongoClient(URI)key_vault = client.encryption.__keyVaultkey_vault.create_index(    "keyAltNames", unique=True,    partialFilterExpression={"keyAltNames": {"$exists": True}},)local_master_key = Path('/tmp/atlasmart-ch23-master-key.bin').read_bytes()kms = {"local": {"key": local_master_key}}ce = ClientEncryption(kms, KEY_VAULT, client, CodecOptions())key_id = ce.create_data_key("local", key_alt_names=["atlasmart-customer-pii"])email = "alice@example.test"note = "customer requested a refund"email_ct = ce.encrypt(email, "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", key_id=key_id)note_ct = ce.encrypt(note, "AEAD_AES_256_CBC_HMAC_SHA_512-Random", key_id=key_id)coll = client.atlasmart.customers_csflecoll.delete_many({})coll.insert_one({"customerId":"C-2303", "email":email_ct, "supportNote":note_ct})raw = coll.find_one({"customerId":"C-2303"})print('raw_email_type=', type(raw['email']).__name__)print('raw_note_type=', type(raw['supportNote']).__name__)print('decrypted_email=', ce.decrypt(raw['email']))print('decrypted_note=', ce.decrypt(raw['supportNote']))query_ct = ce.encrypt(email, "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", key_id=key_id)print('deterministic_match=', coll.count_documents({"email": query_ct}))print('key_alt_names=', key_vault.find_one({"_id": key_id})["keyAltNames"])

3. Deterministic and random CSFLE make different leakage/query tradeoffs

Random encryption should produce different ciphertext for the same plaintext across encryptions and therefore does not support equality lookup by encrypting the query value. Deterministic encryption maps the same value under the same key/algorithm to the same ciphertext, which enables equality matching but leaks equality/frequency patterns. That leakage is one reason Queryable Encryption uses a different cryptographic design for searchable encrypted fields.

compare deterministic and random equality behavior
# Continue in the same script after creating ce/key_id.d1 = ce.encrypt("same", "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", key_id=key_id)d2 = ce.encrypt("same", "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", key_id=key_id)r1 = ce.encrypt("same", "AEAD_AES_256_CBC_HMAC_SHA_512-Random", key_id=key_id)r2 = ce.encrypt("same", "AEAD_AES_256_CBC_HMAC_SHA_512-Random", key_id=key_id)print('deterministic_equal=', d1 == d2)print('random_equal=', r1 == r2)

4. Automatic CSFLE is a different operational mode

With automatic encryption, a configured driver analyzes outgoing commands and encrypts/decrypts fields according to a schema. Current compatibility documentation keeps automatic CSFLE on Atlas/Enterprise while explicit CSFLE is available on Community. The Automatic Encryption Shared Library is the modern query-analysis component; older deployments can encounter mongocryptd. Do not make “the driver will encrypt it” an implicit assumption—record whether the application is explicit or automatic and fail closed if the encryption configuration cannot initialize.

Failure injection

Delete or replace the local master-key file only after copying the ciphertext/key-vault state into the disposable lab. A subsequent decrypt should fail. Restore the original 96-byte key and retry. This demonstrates the recoverability dependency without touching any real key or production data.

5. Production judgment

CSFLE moves selected plaintext out of the database trust boundary, but the trusted application becomes more sensitive: it holds or can obtain keys and plaintext. Protect application memory, logs, KMS credentials, deployment pipelines, and key-vault permissions. Deterministic CSFLE may be acceptable for equality-search needs when its leakage model is understood; random encryption is stronger against frequency observation but not directly queryable. The next lesson uses Queryable Encryption when the application needs server-assisted encrypted equality/range queries without deterministic ciphertext semantics.

Check your understanding

  1. What does the key vault store?
  2. Why is the keyAltNames index unique and partial?
  3. What leakage does deterministic CSFLE introduce?
  4. Can Community perform explicit CSFLE?
  5. Why is a local master-key file a lab-only choice?
Review the answers

1. Wrapped data-encryption key documents and metadata such as alternate names; it does not store the local/cloud Customer Master Key itself.

2. It prevents ambiguous alternate names while indexing only key documents that actually have alternate names.

3. Equal plaintext values encrypted with the same key/algorithm produce equal ciphertext, revealing equality/frequency patterns.

4. Yes. Current compatibility supports explicit CSFLE on Community; automatic encryption/query analysis has a different Enterprise/Atlas boundary.

5. It weakens key separation and can be lost or copied with the application; production should use a protected remote KMS/HSM or hardened injection design.

Authoritative references

Version-, edition-, driver-, topology-, and preview-sensitive encryption behavior was checked against current MongoDB documentation at generation time. Re-check these sources before applying the procedure to a later release.

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.