{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreid5oz55v6rbvarxj4qzhppidst5sufmrmn76mzywk7qcav2gqj5ca",
    "uri": "at://did:plc:ffyfov3xy6shybcwf7hgoqda/app.bsky.feed.post/3mehwqamstl42"
  },
  "path": "/blog/dev-e2ee-backend-part-1-homomorphic-encryption/",
  "publishedAt": "2026-02-09T17:00:00.000Z",
  "site": "https://peterspath.net",
  "tags": [
    "github.com/peterspath/HomomorphicSum"
  ],
  "textContent": "This is the first post in a series exploring a truly privacy-preserving, end-to-end encrypted backend and client.\n\nThe goal of this part: a demo that can calculate totals on encrypted user data **without ever seeing the plaintext**.\n\n### Why This Matters\n\nTraditional E2EE protects data **at rest** and **in transit** , but the moment the server needs to do anything useful (e.g., compute total revenue, average score, or aggregate telemetry), it must decrypt. That defeats the purpose of zero-trust architecture.\n\n**Homomorphic encryption** changes the game:\n`Encrypt(a) + Encrypt(b) = Encrypt(a + b)`\n\nThe server adds (or multiplies) ciphertexts directly. The result decrypts to the correct plaintext on the client.\n\n### The Demo: Homomorphic Sum of 72 Encrypted Numbers\n\nHere’s a complete, runnable Swift example using **Apple’s excellent open-source HomomorphicEncryption framework** (BFV scheme with `UInt64`).\n\n\n    // Key parts\n\n    let params = try EncryptionParameters<Bfv<UInt64>>(from: .n_8192_logq_40_60_60_logt_26)\n    let context = try Context(encryptionParameters: params)\n    let secretKey = try context.generateSecretKey()\n\n    // Encrypt each value separately (coefficient encoding, one value per ciphertext)\n    let (ciphertexts, plaintexts) = try encryptRandomNumbers(numberOfValues: 72, context: context, secretKey: secretKey)\n\n    let encryptedSum = try calculateEncryptedSum(ciphertexts: ciphertexts)\n\n    // Decrypt & verify\n    let decrypted = try encryptedSum.decrypt(using: secretKey)\n    let result = try decrypted.decode(format: .coefficient)[0]\n\n    print(\"Expected: \\(plaintexts.reduce(0, +)) | Actual: \\(result)\")\n\n\n**Output**\n\n\n    Expected sum: 41869\n    Result from homomorphic operation: 41869\n    Match: ✓ Success!\n\n\nRepo: github.com/peterspath/HomomorphicSum\n\n### Why These Parameters?\n\n  * Polynomial degree **N = 8192** → supports up to ~8192 operations before noise becomes critical\n  * Plaintext modulus **t ≈ 2²⁶** → plenty of room for the sum of 72 numbers (each ≤999) without modular wrap-around\n  * `logq_40_60_60` gives sufficient ciphertext modulus bits to keep noise growth manageable during addition\n\n\n\nAddition of ciphertexts is **extremely cheap** compared to multiplication (no relinearization needed).\n\n### How Addition Works Under the Hood (BFV)\n\nIn BFV, a ciphertext encrypts a plaintext polynomial in the ring `R_t = Z_t[X]/(X^N + 1)`. When you add two ciphertexts:\n\n`ct₁ + ct₂ = (c0₁ + c0₂, c1₁ + c1₂) mod q`\n\nDecrypting this recovers exactly `m₁ + m₂ mod t`.\n\nBecause we used **coefficient encoding** with one value per ciphertext, each ciphertext holds a single scalar. This is the simplest way to demonstrate correctness before moving to packed/SIMD encoding.",
  "title": "E2EE Backend part 1: Homomorphic Encryption"
}