The Mirror That Doesn't See.
Follow, in nine steps, how a consumer can receive fully personalized skincare recommendations — without the brand ever seeing her selfie, skin profile, or the resulting scores.
The Scenario
A consumer generates 8 skin features locally from a selfie. Encrypts on her own phone. Sends to the server.
The Server
Computes affinity scores for 5 catalog products by applying a linear model — over the ciphertext, without decrypting.
The Guarantee
At no point does the server see the profile in cleartext. The guarantee is mathematical (RLWE), not political.
Define the parameters.
CKKS operates over vectors of real numbers with approximate arithmetic — the standard scheme for machine learning under FHE. The parameters define security, computational depth and cost.
Chosen Parameters
What This Means
Mathematical base: RLWE in Zq[x]/(xN+1) — the same problem behind post-quantum cryptography standardized by NIST (ML-KEM, ML-DSA).
Generate the key pair.
The private key is born on the consumer's phone and never leaves it. The public key is what travels to the brand's server.
Key Flow
The relinearization key rlk also goes to the server — it enables multiplications under encryption but does not reveal sk.
What Was Generated
sk := kgen.GenSecretKey()
pk := kgen.GenPublicKey(sk)
rlk := kgen.GenRelinKey(sk)
Generate the profile and encrypt.
In production, the 8 features would come from a vision model running locally on the selfie. Here we simulate the vector directly — and encryption happens before any byte leaves the phone.
Skin Profile · Cleartext (only the consumer sees)
CKKS Encryption
This overhead is the price of mathematical privacy. In exchange, the server can compute over the ciphertext without ever knowing the content.
What the server receives.
These are the exact bytes that leave the phone for the brand's server. To any observer without the sk key, it is indistinguishable noise.
Real Ciphertext Sample (first 32 bytes)
74 65 78 74 4d 65 74 61
44 61 74 61 22 3a 7b 22
53 63 61 6c 65 22 3a 7b
...
The full ciphertext has ~1 MB of pseudo-random bytes. Without the secret key, recovering any individual feature would require solving Ring-LWE at dimension 16 384 — ~2128 operations.
What Travels
Compute scores under encryption.
For each of the 5 catalog products, the server computes score = bias + Σ(weighti × featurei) — entirely over the ciphertext, without ever decrypting.
The Algorithm (per product)
Everything happens on ct — the server never has access to the real numbers.
Real Measured Performance
Decrypt and recommend.
The 5 ciphertexts travel back to the phone. Only there, with the secret key sk, do they become readable numbers. The consumer finally sees her recommendation.
Recommendation Ranking
- iSensitive Soothing Lotion+1.4470
- iiPureté Mattifying Toner+1.2980
- iiiLumière Spot Brightener+0.7250
- ivAbsolu Anti-Aging Cream+0.6350
- vQuotidien Hydrating Serum+0.2990
Why It Makes Sense
The consumer has high sensitivity (0.65) and moderate redness (0.48) → the algorithm correctly picked the Soothing Lotion.
She also has high oiliness (0.78) and visible pores (0.71) → the Mattifying Toner shows up second.
Mathematical validation.
To prove that the encrypted computation is equivalent to the cleartext one, we recompute the scores directly in plaintext (for checking only) and compare.
FHE vs Plaintext
| Product | FHE | Cleartext | Error |
|---|---|---|---|
| Sensitive Soothing Lotion | +1.447000 | +1.447000 | 2.3e-10 |
| Pureté Mattifying Toner | +1.298000 | +1.298000 | 2.7e-10 |
| Lumière Spot Brightener | +0.725000 | +0.725000 | 2.6e-10 |
| Absolu Anti-Aging Cream | +0.635000 | +0.635000 | 1.3e-10 |
| Quotidien Hydrating Serum | +0.299000 | +0.299000 | 4.0e-10 |
Result
CKKS is approximate by design — the error comes from the controlled noise added during encryption. For recommendation scoring, 9 decimal places of precision is more than enough.
For exact counts (database, fraud scoring), we would use BFV/BGV which have zero error.
What an attacker can do.
Imagine a dishonest brand employee, or an intruder, captures the ct_features ciphertext. What can they extract without the secret key?
Attack Attempts
- Attempt 1 — Read bytes directly Result: pseudo-random bytes. Nothing extracted.
- Attempt 2 — Recover sk from pk Requires solving Ring-LWE at dimension 16 384 with a ~280-bit modulus. Best known attack (BKZ): ~2128 operations. Infeasible on classical or foreseeable quantum hardware.
- Attempt 3 — Brute force the features Even guessing them, verification would require decryption — which collides with the barrier in Attempt 2.
Why this is different
In traditional architectures (TLS + AES + server processing), the data exists in cleartext at some point — during processing. That moment is the Achilles heel of the entire history of cryptography so far.
FHE eliminates that moment. The data never exists in cleartext outside the consumer's device.
What just happened.
In under half a second total, we ran a complete personalized recommendation pipeline with verifiable mathematical privacy. All factual, all measured.
The Complete Flow
- The consumer generated 8 skin features locally
- Encrypted on her own device with her private key
- Sent only the ciphertext to the server
- The server computed 5 scores under encryption (131 ms)
- Returned 5 score ciphertexts
- The consumer decrypted on her phone and saw the recommendation