University of Campinas, Institute of Computing, Brazil.
Laboratory of Security and Cryptography - LASCA,
Multidisciplinary High Performance Computing Laboratory - LMCAD.
Author: Pedro G. M. R. Alves, PhD. candidate @ IC-UNICAMP,
SPOG is a proof of concept for our work looking for efficient techniques to implement RLWE-based HE cryptosystems on GPUs. It works together with cuPoly.
SPOG and cuPoly are ongoing projects and we hope to increase its performance and security in the course of time. Our focus is to provide:
- Exceptional performance on modern GPGPUs.
- An easy-to-use high-level API.
- Easily maintainable code. Easy to fix bugs and easy to scale.
- A model for implementations of cryptographic schemes based on RLWE.
Note that stable
is generally a work in progress, and you probably want to use a tagged release version.
SPOG was tested in a Linux environment with the following packages:
Package | Version |
---|---|
g++ | 8.4.0 |
CUDA | 11.0 |
cmake | 3.13.3 |
googletest | v1.10.0 |
rapidjson | v1.1.0 |
NTL | 11.3.2 |
gmp | 6.1.2 |
- Download and install cuPoly. Be careful to choose a branch compatible with the one you intend to use on SPOG (stable or unstable).
- Download and unzip the most recent commit of SPOG. The "stable" branch shall store the most recent version that was approved on all relevant tests. In the "unstable" branch you will ideas we are working on and may break something. Other branches are feature-related and may be merged some day.
- Create spog/build.
- Change to spog/build and run
$ cmake ..
$ make
cmake will verify the environment to assert that all required packages are installed.
SPOG contains binaries for testing and benchmarking. For testing, use spog_test. Since it is built over googletest you may apply their filters to select tests of interest. For instance,
./spog_test --gtest_filter=FVInstantiation/TestFV.Mul/4096*
runs all tests for homomorphic multiplication on a cyclotomic polynomial ring of degree 4096.
SPOG provides a high-level API, avoiding the need for the programmer to interact with the GPGPU. SPOG requires an initial setup to define the parameters used by BFV and nothing else. cuPoly. is a sister library that provides all the required arithmetic.
There is an embryonic version of a documentation made with doxygen, but it is not up-to-date or even complete. The most up-to-date source to understand how to use SPOG and cuPoly is by looking at the demos provided and the test suite.
The basic parameters needed are
Params p;
p.nphi = N; // ring degree
p.k = |q|; // size of the main base
p.kl = k + 1; // size of the auxiliar base
p.t = |m|; // defines the plaintext domain
All CUDA kernels calls are made and handled by CUDAEngine. Thus, before anything this object must be initialized using the selected parameters.
CUDAEngine::init(k, kl, nphi, t);// Init CUDA
The Homomorphic cryptosystem used by SPOG is BFV. Hence, we use polynomial arithmetic over a cyclotomic ring. Such operations are provided by cuPoly in the form of poly_t struct.
/////////////
// Message //
/////////////
poly_t m1, m2, m3;
poly_set_coeff(&m1, 0, to_ZZ(1));
poly_set_coeff(&m1, 1, to_ZZ(1));
poly_set_coeff(&m2, 1, to_ZZ(1));
poly_set_coeff(&m3, 1, to_ZZ(42));
To work with BFV, once CUDAEngine is on we need to instantiate a BFVContext object, the Sampler singleton, and generate a key set.
// BFV setup
BFVContext* cipher = new BFVContext(p);
Sampler::init(cipher);
SecretKey *sk = bfv_new_sk(cipher);
Keys* keys = bfv_keygen(cipher, sk);
Encryption, decryption, and homomorphic operations are executed by BFV's methods.
poly_t m1, m2, m3;
poly_init(cipher, &m1);
poly_init(cipher, &m2);
poly_init(cipher, &m3);
// initializes m1, m2, and m3
// ...
//
/////////////
// Encrypt //
/////////////
cipher_t* ct1 = bfv_encrypt(cipher, &m1);
cipher_t* ct2 = bfv_encrypt(cipher, &m2);
cipher_t* ct3 = bfv_encrypt(cipher, &m3);
//////////
// Add //
////////
cipher_t *ctR1 = bfv_add(cipher, ct1, ct2);
//////////
// Mul //
////////
cipher_t* ctR2 = bfv_mul(cipher, ctR1, ct3);
/////////////
// Decrypt //
/////////////
/// The secret key is not stored in BFVContext, so you need to pass it as a parameter
poly_t *m_decrypted = bfv_decrypt(cipher, ctR2, sk);
Once we are done, CUDAEngine must be destroyed and the objects created must be released.
// Asserts there is anything being computed on the GPU
cudaDeviceSynchronize();
cudaCheckError();
// Release polynomials and ciphers
poly_free(&m1);
poly_free(&m2);
poly_free(&m3);
poly_free(m_decrypted);
cipher_free(ct1);
cipher_free(ct2);
cipher_free(ct3);
cipher_free(ctR1);
cipher_free(ctR2);
// Release keys
keys_free(cipher, keys);
delete keys;
// Release the BFVContext and the singletons
delete cipher;
Sampler::destroy();
CUDAEngine::destroy();
If you use SPOG/cuPoly, please cite using the template below:
to-do
SPOG is at most alpha-quality software. Implementations may not be correct or secure. Moreover, it was not tested with FV parameters different from those in the test file. Use at your own risk.
SPOG is released under GPLv3.
Privacy Warning: This site tracks visitor information.