Homomorphic encryption lets you compute on encrypted data without decrypting it first.

Imagine you have a sensitive dataset, like medical records, and you want to run some analysis on it. Normally, you’d have to decrypt the data, perform the analysis, and then re-encrypt it. But with homomorphic encryption, you can send the encrypted data to a third party (like a cloud provider), have them perform computations on it while it’s still encrypted, and then receive the encrypted result. You can then decrypt the result, and it will be the same as if the computations were done on the original, unencrypted data. This unlocks incredible possibilities for privacy-preserving cloud computing, secure multi-party computation, and much more.

Let’s see this in action. While full homomorphic encryption (FHE) is computationally intensive and not yet widespread for general use, we can illustrate the concept with partially homomorphic encryption schemes. A common example is using the Paillier cryptosystem for additive homomorphic encryption.

Here’s a simplified Python example using the phe library (you’d need to install it: pip install phe):

from phe import paillier

# 1. Key Generation
public_key, private_key = paillier.generate_keypair()

# 2. Encryption
secret_value_1 = 10
secret_value_2 = 20

encrypted_value_1 = public_key.encrypt(secret_value_1)
encrypted_value_2 = public_key.encrypt(secret_value_2)

print(f"Encrypted value 1: {encrypted_value_1}")
print(f"Encrypted value 2: {encrypted_value_2}")

# 3. Homomorphic Operation (Addition)
# The 'encrypted_value_1 + encrypted_value_2' operation is performed on ciphertext
encrypted_sum = encrypted_value_1 + encrypted_value_2

print(f"Encrypted sum: {encrypted_sum}")

# 4. Decryption
# Decrypting the result of the homomorphic operation
decrypted_sum = private_key.decrypt(encrypted_sum)

print(f"Decrypted sum: {decrypted_sum}")

# Verification: The sum of the original values
original_sum = secret_value_1 + secret_value_2
print(f"Original sum: {original_sum}")

assert decrypted_sum == original_sum

In this snippet, public_key.encrypt() transforms our plain numbers into ciphertext. The magic happens in encrypted_value_1 + encrypted_value_2. This addition doesn’t involve private_key or the original numbers 10 and 20. The paillier library has defined addition for its encrypted objects such that when you add two encrypted numbers, the resulting ciphertext, when decrypted, yields the sum of the original plaintexts.

The fundamental problem homomorphic encryption solves is the tension between data utility and data privacy. Traditionally, to gain insights from data, you need to access and process it, which implies exposing it. This is a major hurdle for sensitive sectors like healthcare, finance, and government. Homomorphic encryption provides a way to bridge this gap, allowing computations to be performed on data without ever needing to reveal the data itself.

Internally, schemes like Paillier rely on number theory, specifically properties of modular arithmetic and prime numbers. For additive homomorphic encryption, the encryption process often involves raising a random number to a power related to the public key, modulo a large number formed by the product of primes. The structure of this encryption is such that when you multiply two ciphertexts together (for multiplicative homomorphism) or add them (for additive homomorphism), the resulting ciphertext has a mathematical relationship to the original plaintexts that allows decryption to recover the desired computed result.

For example, in Paillier, encrypting a message m with public key (n, g) results in c = g^m * r^n mod n^2, where r is a random number. If you have two ciphertexts c1 and c2 encrypting m1 and m2 respectively, their product c1 * c2 mod n^2 will be (g^m1 * r1^n) * (g^m2 * r2^n) mod n^2 = g^(m1+m2) * (r1*r2)^n mod n^2. This new ciphertext, when decrypted, yields m1 + m2, demonstrating the additive property.

The power of homomorphic encryption lies in its ability to enable computation on data in its encrypted form. This means that outsourcing computations to untrusted environments, like public clouds, becomes feasible without compromising data confidentiality. You can encrypt your data, send it to the cloud, have the cloud perform complex operations (like machine learning model training or statistical analysis) on the encrypted data, and receive the encrypted result. Only you, with your private key, can decrypt the final output. This is often referred to as "secure outsourcing of computation."

A critical aspect often overlooked is the trade-off between the type of homomorphic operations supported and the computational overhead. Partially homomorphic encryption (PHE) schemes like RSA (multiplicative) or Paillier (additive) are efficient but only support one type of operation. Somewhat homomorphic encryption (SHE) supports a limited number of both additions and multiplications. Fully homomorphic encryption (FHE) supports an arbitrary number of both, but at a significant performance cost. The "noise" introduced during encryption grows with each homomorphic operation. In FHE, a process called "bootstrapping" is used to reduce this noise, allowing for an unlimited number of operations, but bootstrapping itself is computationally very expensive.

The ultimate goal is FHE that is practical for everyday use. Current research focuses on reducing the computational overhead of FHE, particularly the cost of bootstrapping, and developing more efficient bootstrapping techniques.

The next frontier is understanding the nuances of different FHE schemes and their specific use-case suitability.

Want structured learning?

Take the full Cryptography course →