Expand description

An implementation of the (additive homomorphism only) Fan-Vercauteren (FV) lattice-based homomorphic encryption scheme.

Overview

Homomorphic encryption supports operations on encrypted data without knowing the decryption key.

In order to use lattice-based homomorphic encryption, we first need to decide on the scheme to use and set up the parameters, including the polynomial degree (n) and the modulus (q).

Currently, we only support one scheme (FV) and one set of parameters, corresponding to a polynomial degree of 2048 and a 54-bit prime modulus.

let scheme = cupcake::default();

Setup

In order to encrypt and decrypt data, we needs to generate a keypair, i.e. a secret key and a public key.

let scheme = cupcake::default();
use cupcake::traits::{KeyGeneration};
let (pk, sk) = scheme.generate_keypair();

The public key can be used for encryption and the secret key can be used for encryption or decryption.

Encryption and Decryption

The default plaintext space of Cupcake is Vec<u8> of fixed size n. We can encrypt a vector under a public key like so

use cupcake::traits::{SKEncryption, PKEncryption};
let v = vec![1; scheme.n];
let ct = scheme.encrypt(&v, &pk);

Then, the ciphertext ct can be decrypted using the secret key:

let w: Vec<u8>= scheme.decrypt(&ct, &sk);
assert_eq!(v, w);

You may also use other plaintext types, which are vectors of Scalar of size n. Here Scalar represents an integer modulo a fixed modulus t. See the following example:

use cupcake::integer_arith::scalar::Scalar;
let t = 199;
let scheme = cupcake::default_with_plaintext_mod(t);
let (pk, sk) = scheme.generate_keypair();
let plain_modulus = scheme.t.clone();
let pt = vec![Scalar::from(t-1 as u32); scheme.n];
let ct = scheme.encrypt(&pt, &pk);
let pt_actual: Vec<Scalar> = scheme.decrypt(&ct, &sk);
assert_eq!(pt_actual, pt);

Homomorphic Operations

We can encrypt two vectors and add up the resulting ciphertexts.

use cupcake::traits::{AdditiveHomomorphicScheme};
let z1 = vec![1; scheme.n];
let mut ctz1 = scheme.encrypt(&z1, &pk);
let z2 = vec![2; scheme.n];
let ctz2 = scheme.encrypt(&z2, &pk);
scheme.add_inplace(&mut ctz1, &ctz2);
// Now ctz1 should decrypt to vec![3; scheme.n];
let expected = vec![3; scheme.n];
let actual: Vec<u8> = scheme.decrypt(&ctz1, &sk);
assert_eq!(actual, expected);

Alternatively, we can add a plaintext vector into a ciphertext

use cupcake::traits::CipherPlainAddition;
let z = vec![1; scheme.n];
let mut ctz = scheme.encrypt(&z, &pk);
let p = vec![4; scheme.n];
scheme.add_plain_inplace(&mut ctz, &p);
// Now ctz should decrypt to vec![5; scheme.n]
let expected = vec![5; scheme.n];
let actual: Vec<u8> = scheme.decrypt(&ctz, &sk);
assert_eq!(actual, expected);

Rerandomization

Furthermore, you can rerandomize a ciphertext using the public key. The output is another ciphertext which will be still decrypt to the same plaintext, but cannot be linked to the input.

let mu = vec![1; scheme.n];
let mut ct = scheme.encrypt(&mu, &pk);
scheme.rerandomize(&mut ct, &pk);
// The new ct should still decrypt to mu.
let actual: Vec<u8> = scheme.decrypt(&ct, &sk);
let expected = mu;
assert_eq!(actual, expected);

Serialization

We provide methods to serialize a ciphertext into a Vec<u8>. Note that after deserialization, a proper context needs to be set before the further operations can be done on the ciphertext. See the following example:

use crate::cupcake::traits::Serializable;
let v = vec![1; scheme.n];
let w = vec![1; scheme.n];
let ctv = scheme.encrypt(&v, &pk);
let ctw = scheme.encrypt(&w, &pk);

We can call the to_bytes function to serialize.

let ctv_serialized = ctv.to_bytes();
let ctw_serialized = ctw.to_bytes();

In order to deserialize, use scheme.from_bytes.

let mut ctv_deserialized = scheme.from_bytes(&ctv_serialized);
let ctw_deserialized = scheme.from_bytes(&ctw_serialized);
assert_eq!(ctv, ctv_deserialized);

We can perform homomorphic operations on deserialized ciphertexts.

scheme.add_inplace(&mut ctv_deserialized, &ctw_deserialized);
let expected = vec![2; scheme.n];
let actual: Vec<u8>= scheme.decrypt(&ctv_deserialized, &sk);
assert_eq!(actual, expected);

Modules

Structs

(Additive only version of) the Fan-Vercauteren homomoprhic encryption scheme.

SecretKey type

Functions

Type Definitions

Default plaintext type

Default scheme type

Ciphertext type

Plaintext type