Open this lesson in your favourite AI. It'll walk you through the why, explain the demo, and quiz you on the try-it list.
The reason HE matters in 2024 is not the maths — the maths has been settled since 2009 — it's that the cost-benefit ratio finally crossed the line for real applications. Three families dominate. Private ML inference: a hospital sends an encrypted scan to a cloud-hosted classifier; the classifier returns an encrypted prediction; the cloud sees nothing. Secure multiparty computation with HE as the underlying primitive: parties pool data without revealing their inputs (private set intersection, federated analytics, advertising attribution). Verifiable e-voting and tally: votes are encrypted under a public key, tallies are computed homomorphically, and a threshold of trustees decrypts only the aggregate. Each use case puts different demands on the scheme — depth requirements, throughput, ciphertext size, latency tolerance — and the right scheme is rarely the same across the three. Knowing the use case landscape upfront lets you skip the wrong libraries and pick the right rung in the FHE/SHE/PHE hierarchy from the start.
Three sketches at the same level of abstraction. (1) ML inference: client encrypts , sends to server, server runs homomorphically, returns ciphertext. (2) Private set intersection by HE: each party encrypts a polynomial whose roots are their set elements; the parties multiply ciphertexts to find the GCD of polynomials, whose roots are the intersection. (3) E-voting: each voter encrypts or under a tally key; the bulletin board sums all ciphertexts; the trustees jointly decrypt only the sum.
1000 instead of 0 or 1, then re-run. The tally is wrong by 1000. This is why real e-voting protocols pair HE with zero-knowledge proofs that each ciphertext encrypts a value in .COUNT(*) WHERE x > 5. Justify each choice using the multiplicative-depth picture.Use these three in order. Each builds on the one before.
In one paragraph, explain how the same primitive — homomorphic encryption — can power three apparently different use cases (private ML, MPC, e-voting). What's the common abstraction underneath?
Walk me through what a real private CNN inference looks like end-to-end with CKKS: how is the image encoded into a ciphertext, what gets bootstrapped, and where do polynomial approximations of ReLU enter the picture?
Compare HE-based PSI to OPRF-based PSI for two parties of size $n$ and $m$. Where does HE win, where does OPRF win, and at what point does communication cost dominate the choice?
// main.go
// Toy private-tally e-voting using the toy additively-homomorphic scheme from task 3.
// 1000 voters each cast a 0/1 ballot; the server tallies homomorphically; a trustee decrypts.
package main
import (
"crypto/rand"
"fmt"
"math/big"
mathrand "math/rand"
)
const N = 100_003
const MASK = int64(1) << 40
type CT struct{ b, r int64 }
func Enc(m int64) CT {
rBig, _ := rand.Int(rand.Reader, big.NewInt(MASK))
r := rBig.Int64()
return CT{(m + r) % MASK, r}
}
func Dec(c CT) int64 {
val := ((c.b - c.r) % MASK + MASK) % MASK
return val % N
}
func AddCT(c1, c2 CT) CT {
return CT{(c1.b + c2.b) % MASK, (c1.r + c2.r) % MASK}
}
func main() {
rng := mathrand.New(mathrand.NewSource(7))
ballots := make([]int64, 1000)
for i := range ballots {
ballots[i] = int64(rng.Intn(2))
}
encBallots := make([]CT, 1000)
for i, b := range ballots {
encBallots[i] = Enc(b)
}
// Server-side tally — never decrypts an individual ballot.
tallyCT := encBallots[0]
for _, c := range encBallots[1:] {
tallyCT = AddCT(tallyCT, c)
}
var plainSum int64
for _, b := range ballots {
plainSum += b
}
fmt.Println("plaintext tally :", plainSum)
fmt.Println("homomorphic tally :", Dec(tallyCT))
fmt.Println("individual ballots leaked? no — server only ever held ciphertexts.")
}
go run main.go