This project demonstrates practical homomorphic encryption (HE) using a real-world analytics scenario: a cloud server performs statistical queries on encrypted employee burnout data — without ever seeing the raw values. It is a course project for Applied Cryptography (CS6903/4783).
The core idea is a three-party privacy model:
Alice (data owner)
│ encrypts employee columns with CKKS
▼
Carol (cloud server)
│ evaluates queries on ciphertext only — sees no plaintext
▼
Alice
│ decrypts Carol's result ciphertext with her secret key
▼
Final answer (e.g., average burn_rate = 0.4891)
Carol computes aggregates (averages, dot products, element-wise operations) entirely inside the encryption. The result she hands back is still encrypted — only Alice can read it. This proves that HE is practically viable for real analytics with negligible approximation error (<10⁻⁷) while maintaining 128-bit cryptographic security.
Developer Burnout Prediction Dataset — 7,000 synthetic employee records modeled after a Kaggle dataset.
Source: kaggle.com/datasets/asifxzaman/developer-burnout-prediction-dataset7000-samples
Generated by he_burnout/generate_dataset.py. Key columns:
| Column | Type | Description |
|---|---|---|
| employee_id | string | Unique ID |
| gender | categorical | Male / Female / Non-binary |
| company_type | categorical | Product / Service |
| designation | int (1–5) | Seniority level |
| resource_allocation | float (1–10) | Workload intensity |
| mental_fatigue_score | float (0–10) | Self-reported fatigue |
| hours_per_week | int (30–70) | Weekly work hours |
| years_experience | int (1–20) | Experience |
| team_size | int (3–30) | Team headcount |
| burn_rate | float (0–1) | Target variable |
Why CKKS?
- Approximate arithmetic over real-valued vectors — ideal for floating-point analytics
- Supports encrypted addition, multiplication, dot products, and rotations
- 128-bit security via the Ring Learning With Errors (RLWE) problem
- Implemented using TenSEAL (Python bindings for Microsoft SEAL)
Parameters:
Scheme : CKKS
poly_degree : 8192 → 128-bit security
coeff_moduli : [60, 40, 40, 60] bits
global_scale : 2^40
Galois keys : yes (required for sum/rotation)
Relin keys : yes (required after multiplication)
Optional BFV comparison is available via Pyfhel (see benchmark.py). BFV supports exact integer arithmetic but is ~3.5× slower than CKKS for rotation-heavy queries.
| ID | Query | HE Operation |
|---|---|---|
| Q1 | Average burn_rate | sum() then divide |
| Q2 | Average mental_fatigue | sum() then divide |
| Q3 | Weighted burn-risk score | dot(weights) |
| Q4 | Normalised hours (÷ 40) | scalar_multiply |
| Q5 | Stress index per employee | vector_add (two columns) |
| Q6 | Average resource_allocation | sum() then divide |
| Q7 | Average hours_per_week | sum() then divide |
AppliedCryptographyProject3/
├── README.md # Project README
└── he_burnout/
├── app.py # Flask web dashboard (main entry point)
├── he_engine.py # CKKS HE engine — Alice, Carol, plaintext baseline
├── benchmark.py # Full benchmark suite across N and query types
├── demo.py # Interactive CLI demo
├── generate_dataset.py # Synthetic dataset generator (7,000 rows)
├── plot_results.py # Matplotlib static chart generator
├── plot_compare.py # CKKS vs BFV comparison charts
├── requirements.txt # Python dependencies
├── developer_burnout_dataset.csv # Dataset (auto-generated on first run)
├── benchmark_results.json # Benchmark output (auto-generated)
├── benchmark_plots.png # 4-panel performance chart (auto-generated)
└── dashboard.html # Static fallback dashboard
- Python 3.12 is recommended. TenSEAL has platform-specific wheels that may not build on newer Python versions.
From the project root:
cd he_burnout
pip install -r requirements.txtOr using a specific Python version:
py -3.12 -m pip install -r requirements.txtDependencies (requirements.txt):
tenseal # CKKS homomorphic encryption via Microsoft SEAL
pandas # Dataset loading and manipulation
numpy # Numeric computation and plaintext baseline
matplotlib # Static performance charts
flask # Web server for the interactive dashboard
pyfhel # BFV scheme (optional, for comparison in benchmark)
Note:
pyfhelcan be tricky to install on Windows. If it fails, the core CKKS functionality and web app still work — only the BFV comparison tab in the charts will be unavailable.
cd he_burnout
python app.pyThen open http://localhost:5000 in your browser.
In GitHub Codespaces, go to the Ports tab and open port 5000.
The dashboard has two tabs:
Live Query tab
- Choose dataset size: N ∈ {100, 500, 1000, 3000, 7000}
- Choose a query type (avg, stress index, weighted risk, etc.)
- Click Run Encrypted Query
- Watch the Alice → Carol → Alice pipeline animate step by step
- Side-by-side: HE result vs plaintext result, execution time, CKKS approximation error, slowdown factor
- Query history table builds automatically
Performance Charts tab
- Upload / Encrypt Time — HE vs plaintext overhead across all N
- Query Execution Time — all query types across dataset sizes
- Slowdown Factor — log-scale HE/plaintext ratio by query type
- CKKS Approximation Error — log-scale noise (all values < 10⁻⁷)
- CKKS vs BFV Comparison — scheme-level performance comparison
Sweeps all dataset sizes and query types, outputs a JSON results file and a terminal summary table.
cd he_burnout
python benchmark.pyOutputs:
benchmark_results.json— all timings, results, and errors- Terminal table summary
Runtime: approximately 10–15 minutes (5 sizes × 5 queries × 2 schemes).
cd he_burnout
python plot_results.pyOutputs benchmark_plots.png — a 4-panel Matplotlib figure showing upload times, query times, slowdown factors, and CKKS error distribution.
cd he_burnout
python demo.pyMenu-driven terminal interface. Run any of the 7 queries on 7,000 rows and see HE vs plaintext results with timing and error.
cd he_burnout
python generate_dataset.pyRecreates developer_burnout_dataset.csv with 7,000 fresh synthetic records.
| N | HE Upload | Plain Upload | Q1 HE Time | Q1 Plain Time | Q1 Error | Slowdown |
|---|---|---|---|---|---|---|
| 100 | 0.046s | <0.001s | 0.038s | ~0.001s | 3×10⁻⁸ | ~38× |
| 500 | 0.054s | <0.001s | 0.120s | ~0.0001s | <10⁻⁹ | ~1200× |
| 1,000 | 0.075s | <0.001s | 0.117s | ~0.0001s | 9×10⁻⁹ | ~1170× |
| 3,000 | 0.076s | <0.001s | 0.140s | ~0.0001s | 3×10⁻⁹ | ~2187× |
| 7,000 | 0.129s | <0.001s | 0.174s | ~0.0001s | 2×10⁻⁹ | ~2417× |
Key takeaways:
- HE is 1,000–2,400× slower than plaintext — the inherent cost of data confidentiality.
- CKKS approximation error is < 10⁻⁷ across all sizes — negligible for any analytics use case.
- Encryption time scales sub-linearly with N due to CKKS vector packing.
SUM-based queries (Q1, Q2, Q6, Q7) are the most expensive due to Galois key rotations.vector_add(Q5) andscalar_multiply(Q4) are the cheapest at ~0.003–0.034s.- CKKS is ~3.5× faster than BFV for rotation-heavy sum queries.
- Carol never sees plaintext data — she operates only on ciphertexts.
- Alice's secret key never leaves her machine — all decryption is local.
- Query results are returned as ciphertexts — only Alice can decrypt them.
- IND-CPA security is guaranteed under the Ring Learning With Errors (RLWE) hardness assumption.
- 128-bit security level with
poly_modulus_degree = 8192.
he_engine.py is the cryptographic core. It defines two systems with an identical query interface:
HEQuerySystem (encrypted path)
alice_setup()— generates CKKS context, public key, secret key, Galois keys, and relinearization keys.alice_encrypt_column()— encodes a Pandas column as a CKKS ciphertext vector.- Carol's methods (
carol_compute_sum,carol_compute_weighted_sum,carol_compute_element_multiply,carol_compute_add_vectors,carol_compute_poly_eval) — perform HE operations on ciphertexts. alice_decrypt()— decrypts Carol's result ciphertext using Alice's secret key.
PlaintextQuerySystem (baseline)
- Runs identical queries on raw NumPy arrays for correctness verification and timing comparison.
The HEQuerySystem and PlaintextQuerySystem share the same query API, making it straightforward to compare results and measure the privacy cost.