GithubHelp home page GithubHelp logo

openmined / tenseal Goto Github PK

View Code? Open in Web Editor NEW
744.0 21.0 154.0 3.19 MB

A library for doing homomorphic encryption operations on tensors

License: Apache License 2.0

Python 29.82% CMake 0.78% C++ 42.11% Jupyter Notebook 25.73% C 0.12% Starlark 1.45%
tensor homomorphic-encryption cryptography deep-learning python cpp microsoft-seal encryption docker-image hacktoberfest

tenseal's Introduction


TenSEAL
TenSEAL


A library for doing homomorphic encryption operations on tensors

Tests Linux Package MacOS Package Windows Package

Downloads Version OpenCollective Slack

TenSEAL is a library for doing homomorphic encryption operations on tensors, built on top of Microsoft SEAL. It provides ease of use through a Python API, while preserving efficiency by implementing most of its operations using C++.

Features

  • 🔑 Encryption/Decryption of vectors of integers using BFV
  • 🗝️ Encryption/Decryption of vectors of real numbers using CKKS
  • 🔥 Element-wise addition, subtraction and multiplication of encrypted-encrypted vectors and encrypted-plain vectors
  • 🌀 Dot product and vector-matrix multiplication
  • ⚡ Complete SEAL API under tenseal.sealapi

Usage

We show the basic operations over encrypted data, more advanced usage for machine learning applications can be found on our tutorial section

import tenseal as ts

# Setup TenSEAL context
context = ts.context(
            ts.SCHEME_TYPE.CKKS,
            poly_modulus_degree=8192,
            coeff_mod_bit_sizes=[60, 40, 40, 60]
          )
context.generate_galois_keys()
context.global_scale = 2**40

v1 = [0, 1, 2, 3, 4]
v2 = [4, 3, 2, 1, 0]

# encrypted vectors
enc_v1 = ts.ckks_vector(context, v1)
enc_v2 = ts.ckks_vector(context, v2)

result = enc_v1 + enc_v2
result.decrypt() # ~ [4, 4, 4, 4, 4]

result = enc_v1.dot(enc_v2)
result.decrypt() # ~ [10]

matrix = [
  [73, 0.5, 8],
  [81, -5, 66],
  [-100, -78, -2],
  [0, 9, 17],
  [69, 11 , 10],
]
result = enc_v1.matmul(matrix)
result.decrypt() # ~ [157, -90, 153]

Installation

Using pip

$ pip install tenseal

This installs the last packaged version on pypi. If your platform doesn't have a ready package, please open an issue to let us know.

Build from Source

Supported platforms and their requirements are listed below: (this are only required for building TenSEAL from source)

  • Linux: A modern version of GNU G++ (>= 6.0) or Clang++ (>= 5.0).
  • MacOS: Xcode toolchain (>= 9.3)
  • Windows: Microsoft Visual Studio (>= 10.0.40219.1, Visual Studio 2010 SP1 or later).

If you want to install tenseal from the repository, you should first make sure to have the requirements for your platform (listed above) and CMake (3.14 or higher) installed, then get the third party libraries (if you didn't already) by running the following command from the root directory of the project

$ git submodule init
$ git submodule update

TenSEAL uses Protocol Buffers for serialization, and you will need the protocol buffer compiler too.

If you are on Windows, you will first need to build SEAL library using Visual Studio, you should use the solution file SEAL.sln in third_party/SEAL to build the project native\src\SEAL.vcxproj with Configuration=Release and Platform=x64. For more details check the instructions in Building Microsoft SEAL

You can then trigger the build and the installation

$ pip install .

Use Docker

You can use our Docker image for a ready to use environment with TenSEAL installed

$ docker container run --interactive --tty openmined/tenseal

Note: openmined/tenseal points to the image from the last release, use openmined/tenseal:dev for the image built from the master branch.

You can also build your custom image, this might be handy for developers working on the project

$ docker build -t tenseal -f docker-images/Dockerfile-py38 .

To interactively run this docker image as a container after it has been built you can run

$ docker container run -it tenseal

Using Bazel

To use this library in another Bazel project, add the following in your WORKSPACE file:


git_repository(
   name = "org_openmined_tenseal",
   remote = "https://github.com/OpenMined/TenSEAL",
   branch = "master",
   init_submodules = True,
)

load("@org_openmined_tenseal//tenseal:preload.bzl", "tenseal_preload")

tenseal_preload()

load("@org_openmined_tenseal//tenseal:deps.bzl", "tenseal_deps")

tenseal_deps()

Benchmarks

You can benchmark the implementation at any point by running

$ bazel run -c opt --spawn_strategy=standalone //tests/cpp/benchmarks:benchmark

The benchmarks from every PR merge are uploaded here.

Tutorials

Publications

A. Benaissa, B. Retiat, B. Cebere, A.E. Belfedhal, "TenSEAL: A Library for Encrypted Tensor Operations Using Homomorphic Encryption", ICLR 2021 Workshop on Distributed and Private Machine Learning (DPML 2021).

@misc{tenseal2021,
    title={TenSEAL: A Library for Encrypted Tensor Operations Using Homomorphic Encryption}, 
    author={Ayoub Benaissa and Bilal Retiat and Bogdan Cebere and Alaa Eddine Belfedhal},
    year={2021},
    eprint={2104.03152},
    archivePrefix={arXiv},
    primaryClass={cs.CR}
}

Support

For support in using this library, please join the #support Slack channel. Click here to join our Slack community!

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

License

Apache License 2.0

tenseal's People

Contributors

alexandrumeterez avatar bcebere avatar bquast avatar cereallarceny avatar cerinebnsd avatar chinmayshah99 avatar comidan avatar dreamingraven avatar ianqs avatar klmcguir avatar mrader1248 avatar philomath213 avatar pierreeliseeflory avatar prajwalpanzade avatar rand0musername avatar shangsuru avatar standbyme avatar vdasu avatar xueyumusic avatar youben11 avatar zsoumia avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tenseal's Issues

Wrong result when performing dot product with CKKS scheme

Hi. I am new to TenSEAL, and I have some trouble performing dot product.
I am trying to make a dot product between two encrypted vectors, and the decrypted result is far away from the result expected. However, I am able to perform 9 multiplications and additions with my context parameters.

Am I doing something wrong ?

I built TenSEAL from source the 4th July

How to Repro

import tenseal as ts
import numpy as np

context = ts.context(ts.SCHEME_TYPE.CKKS, 16384, coeff_mod_bit_sizes=[60, 40, 40, 40, 40, 40, 40, 40, 40, 40])
context.global_scale = pow(2, 40)
context.generate_galois_keys()

plain_vector = [-1, 0, 9, 6, 90]
vec = np.array(plain_vector)
plain_vector2 = [-1, 3, 2, 3, 0]
vec2 = np.array(plain_vector2)

encrypted_vector = ts.ckks_vector(context, plain_vector)
encrypted_vector2 = ts.ckks_vector(context, plain_vector2)

unencrypted_dot = vec.dot(vec2)
encrypted_dot = encrypted_vector.dot(encrypted_vector)

print("unencrypted dot : " + str(unencrypted_dot))
print("encrypted dot : " + str(encrypted_dot .decrypt()[0]))

output :

unencrypted dot : 37
encrypted dot : 8212.915956094734

Any advice will be appreciate

Provide SEAL API

Context

The goal of TenSEAL isn't to wrap SEAL and make it available to use in Python but as we have everything setup to make a full port of it to Python (making every cpp object and API call available through python), I think that it would be nice to make a tenseal.seal_api submodule that do this.

TODO

  • Bind all SEAL objects (providing access to all their methods and public attributes), preferably done in a separate file sealapi.cpp under tenseal/.
  • Customize the build (setup.py and CMakeLists.txt) to make the build of the SEAL API optional.

CmakeFile for SEAL and pybind11

Description

When loading TenSEAL into Clion, I receive the following error when trying to specify the CmakeLists.txt. Specifically

/home/ian/clion/bin/cmake/linux/bin/cmake -DCMAKE_BUILD_TYPE=Debug -G "CodeBlocks - Unix Makefiles" /home/ian/PycharmProjects/TenSEAL
-- The C compiler identification is GNU 10.1.0
-- The CXX compiler identification is GNU 10.1.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc - works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ - works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMake Error at CMakeLists.txt:19 (add_subdirectory):
  The source directory

    /home/ian/PycharmProjects/TenSEAL/third_party/SEAL

  does not contain a CMakeLists.txt file.


CMake Error at CMakeLists.txt:22 (add_subdirectory):
  The source directory

    /home/ian/PycharmProjects/TenSEAL/third_party/pybind11

  does not contain a CMakeLists.txt file.


-- Found Protobuf: /usr/lib/libprotobuf.so;-lpthread (found version "3.12.3") 
CMake Error at CMakeLists.txt:40 (pybind11_add_module):
  Unknown CMake command "pybind11_add_module".


-- Configuring incomplete, errors occurred!
See also "/home/ian/PycharmProjects/TenSEAL/cmake-build-debug/CMakeFiles/CMakeOutput.log".
See also "/home/ian/PycharmProjects/TenSEAL/cmake-build-debug/CMakeFiles/CMakeError.log".

[Failed to reload]

Are you interested in working on this improvement yourself?

  • No, I am not (I'd love to but I don't have the prerequisite knowledge

Additional Context

Add any other context or screenshots.

Review context comparisons

Description

We need to define and add the relevant checks for the
bool TenSEALContext::equals(const std::shared_ptr<TenSEALContext>& other)
method.

Some existing checks:

  • same scale
  • ....

Make encoders part of TenSEALContext

Context

Current implementation instantiate an encoder whenever needed which might incur some extra overhead, and reserving space for all the 3 different kind of encoders is non-efficient.

Possible solution

Keep 3 pointers to all kind of encoders in TenSEALContext ([Integer|Batch]Encoder for BFV and CKKSEncoder for CKKS) and have a method get_encoder that when asked for a specific encoder, check either it's created or not yet, create a new one if it's not, and return a pointer to the encoder.

Question to take into account: is it safe to share pointers to encoders? are they thread-safe?

TenSEALEncoder improvements

We can further improve the encoder interface by:

  • providing encode/decode templates to the contexts.
  • simplifying the tensor/context logic by forwarding the encode/decode calls directly to the Encoder factory.(instead of getting an encoder object first)

CKKSTensor - add, sub, mul

Feature Description

Add element-wise operations (add, sub, mul) to CKKSTensor. These methods should first check the shapes of the operands to check if they are compatible (same shape or one can be broadcasted), then perform the operation depending on their shapes. These methods should have approximately the same code, at the difference of performing different operations (with mul requiring relin/rescale).

Performing these operation in parallel using the threadpool should be prefered.

Additional Context

The methods' API is already set.

CKKSTensor - square and power

Feature Description

Implement the power and square methods for CKKSTensor. Helper functions for performing power and square for ciphertext should already be available, these methods should mainly loop over internal ciphertexts to perform these operations.

Performing these operation in parallel using the threadpool should be prefered.

Calling matmul on a medium sized matrix throws an std::bad_alloc exception

Describe the bug
CKKSVector::matmul_plain seems to be consuming memory linear in the size of the input, a small input matrix works fine, but as we use larger matrices, matmul throw an std::bad_alloc exception.

To Reproduce
Script to reproduce: you can increase the size if the exception isn't thrown

import tenseal as ts
import torch

context = ts.context(ts.SCHEME_TYPE.CKKS, 8192, coeff_mod_bit_sizes=[40, 20, 20, 40])
context.global_scale = 2 ** 20
context.generate_galois_keys()

size = 20
mat = torch.rand(size,256).tolist()
vec = ts.ckks_vector(context, [1]*(size))
vec.mm(mat)

Expected behavior
The operation should return the result of the vector-matrix multiplication.

Environement (please complete the following information):

  • OS: Linux
  • TenSEAL Version 0.1.1a0

Build failure

I ran the instructions in the README.md to install.

  103  [2020-04-09 22:02:08 +0100] git clone [email protected]:OpenMined/TenSEAL.git
  104  [2020-04-09 22:02:18 +0100] cd TenSEAL/
  108  [2020-04-09 22:03:13 +0100] git submodule init
  109  [2020-04-09 22:03:17 +0100] git submodule update
  110  [2020-04-09 22:03:31 +0100] pip install .
  111  [2020-04-09 22:04:59 +0100] history

and got the following error.

pip install .
Processing /Users/atrask/Dropbox/Laboratory/openmined/TenSEAL
Building wheels for collected packages: tenseal
  Building wheel for tenseal (setup.py) ... error
  ERROR: Command errored out with exit status 1:
   command: /Users/atrask/opt/anaconda3/bin/python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/var/folders/zc/t5ztbg0563q8r1f5b601mzzh00g5p3/T/pip-req-build-tjz7l9d0/setup.py'"'"'; __file__='"'"'/private/var/folders/zc/t5ztbg0563q8r1f5b601mzzh00g5p3/T/pip-req-build-tjz7l9d0/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /private/var/folders/zc/t5ztbg0563q8r1f5b601mzzh00g5p3/T/pip-wheel-2mqw6869
       cwd: /private/var/folders/zc/t5ztbg0563q8r1f5b601mzzh00g5p3/T/pip-req-build-tjz7l9d0/
  Complete output (48 lines):
  /Users/atrask/opt/anaconda3/lib/python3.7/site-packages/setuptools/dist.py:453: UserWarning: Normalizing '0.1.2-dev' to '0.1.2.dev0'
    normalized_version,
  running bdist_wheel
  running build
  running build_py
  running build_ext
  Traceback (most recent call last):
    File "/private/var/folders/zc/t5ztbg0563q8r1f5b601mzzh00g5p3/T/pip-req-build-tjz7l9d0/setup.py", line 33, in run
      out = subprocess.check_output(['cmake', '--version'])
    File "/Users/atrask/opt/anaconda3/lib/python3.7/subprocess.py", line 411, in check_output
      **kwargs).stdout
    File "/Users/atrask/opt/anaconda3/lib/python3.7/subprocess.py", line 488, in run
      with Popen(*popenargs, **kwargs) as process:
    File "/Users/atrask/opt/anaconda3/lib/python3.7/subprocess.py", line 800, in __init__
      restore_signals, start_new_session)
    File "/Users/atrask/opt/anaconda3/lib/python3.7/subprocess.py", line 1551, in _execute_child
      raise child_exception_type(errno_num, err_msg, err_filename)
  FileNotFoundError: [Errno 2] No such file or directory: 'cmake': 'cmake'
  
  During handling of the above exception, another exception occurred:
  
  Traceback (most recent call last):
    File "<string>", line 1, in <module>
    File "/private/var/folders/zc/t5ztbg0563q8r1f5b601mzzh00g5p3/T/pip-req-build-tjz7l9d0/setup.py", line 93, in <module>
      zip_safe=False,
    File "/Users/atrask/opt/anaconda3/lib/python3.7/site-packages/setuptools/__init__.py", line 144, in setup
      return distutils.core.setup(**attrs)
    File "/Users/atrask/opt/anaconda3/lib/python3.7/distutils/core.py", line 148, in setup
      dist.run_commands()
    File "/Users/atrask/opt/anaconda3/lib/python3.7/distutils/dist.py", line 966, in run_commands
      self.run_command(cmd)
    File "/Users/atrask/opt/anaconda3/lib/python3.7/distutils/dist.py", line 985, in run_command
      cmd_obj.run()
    File "/Users/atrask/opt/anaconda3/lib/python3.7/site-packages/wheel/bdist_wheel.py", line 223, in run
      self.run_command('build')
    File "/Users/atrask/opt/anaconda3/lib/python3.7/distutils/cmd.py", line 313, in run_command
      self.distribution.run_command(command)
    File "/Users/atrask/opt/anaconda3/lib/python3.7/distutils/dist.py", line 985, in run_command
      cmd_obj.run()
    File "/Users/atrask/opt/anaconda3/lib/python3.7/distutils/command/build.py", line 135, in run
      self.run_command(cmd_name)
    File "/Users/atrask/opt/anaconda3/lib/python3.7/distutils/cmd.py", line 313, in run_command
      self.distribution.run_command(command)
    File "/Users/atrask/opt/anaconda3/lib/python3.7/distutils/dist.py", line 985, in run_command
      cmd_obj.run()
    File "/private/var/folders/zc/t5ztbg0563q8r1f5b601mzzh00g5p3/T/pip-req-build-tjz7l9d0/setup.py", line 36, in run
      ", ".join(e.name for e in self.extensions))
  RuntimeError: CMake must be installed to build the following extensions: _tenseal_cpp
  ----------------------------------------
  ERROR: Failed building wheel for tenseal
  Running setup.py clean for tenseal
Failed to build tenseal
Installing collected packages: tenseal
  Attempting uninstall: tenseal
    Found existing installation: tenseal 0.1.0.dev0
    Uninstalling tenseal-0.1.0.dev0:
      Successfully uninstalled tenseal-0.1.0.dev0
    Running setup.py install for tenseal ... error
    ERROR: Command errored out with exit status 1:
     command: /Users/atrask/opt/anaconda3/bin/python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/var/folders/zc/t5ztbg0563q8r1f5b601mzzh00g5p3/T/pip-req-build-tjz7l9d0/setup.py'"'"'; __file__='"'"'/private/var/folders/zc/t5ztbg0563q8r1f5b601mzzh00g5p3/T/pip-req-build-tjz7l9d0/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /private/var/folders/zc/t5ztbg0563q8r1f5b601mzzh00g5p3/T/pip-record-uib43cop/install-record.txt --single-version-externally-managed --compile --install-headers /Users/atrask/opt/anaconda3/include/python3.7m/tenseal
         cwd: /private/var/folders/zc/t5ztbg0563q8r1f5b601mzzh00g5p3/T/pip-req-build-tjz7l9d0/
    Complete output (57 lines):
    /Users/atrask/opt/anaconda3/lib/python3.7/site-packages/setuptools/dist.py:453: UserWarning: Normalizing '0.1.2-dev' to '0.1.2.dev0'
      normalized_version,
    running install
    running build
    running build_py
    creating build
    creating build/lib.macosx-10.9-x86_64-3.7
    creating build/lib.macosx-10.9-x86_64-3.7/tenseal
    copying tenseal/version.py -> build/lib.macosx-10.9-x86_64-3.7/tenseal
    copying tenseal/__init__.py -> build/lib.macosx-10.9-x86_64-3.7/tenseal
    creating build/lib.macosx-10.9-x86_64-3.7/tenseal/tensors
    copying tenseal/tensors/__init__.py -> build/lib.macosx-10.9-x86_64-3.7/tenseal/tensors
    running build_ext
    Traceback (most recent call last):
      File "/private/var/folders/zc/t5ztbg0563q8r1f5b601mzzh00g5p3/T/pip-req-build-tjz7l9d0/setup.py", line 33, in run
        out = subprocess.check_output(['cmake', '--version'])
      File "/Users/atrask/opt/anaconda3/lib/python3.7/subprocess.py", line 411, in check_output
        **kwargs).stdout
      File "/Users/atrask/opt/anaconda3/lib/python3.7/subprocess.py", line 488, in run
        with Popen(*popenargs, **kwargs) as process:
      File "/Users/atrask/opt/anaconda3/lib/python3.7/subprocess.py", line 800, in __init__
        restore_signals, start_new_session)
      File "/Users/atrask/opt/anaconda3/lib/python3.7/subprocess.py", line 1551, in _execute_child
        raise child_exception_type(errno_num, err_msg, err_filename)
    FileNotFoundError: [Errno 2] No such file or directory: 'cmake': 'cmake'
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/private/var/folders/zc/t5ztbg0563q8r1f5b601mzzh00g5p3/T/pip-req-build-tjz7l9d0/setup.py", line 93, in <module>
        zip_safe=False,
      File "/Users/atrask/opt/anaconda3/lib/python3.7/site-packages/setuptools/__init__.py", line 144, in setup
        return distutils.core.setup(**attrs)
      File "/Users/atrask/opt/anaconda3/lib/python3.7/distutils/core.py", line 148, in setup
        dist.run_commands()
      File "/Users/atrask/opt/anaconda3/lib/python3.7/distutils/dist.py", line 966, in run_commands
        self.run_command(cmd)
      File "/Users/atrask/opt/anaconda3/lib/python3.7/distutils/dist.py", line 985, in run_command
        cmd_obj.run()
      File "/Users/atrask/opt/anaconda3/lib/python3.7/site-packages/setuptools/command/install.py", line 61, in run
        return orig.install.run(self)
      File "/Users/atrask/opt/anaconda3/lib/python3.7/distutils/command/install.py", line 545, in run
        self.run_command('build')
      File "/Users/atrask/opt/anaconda3/lib/python3.7/distutils/cmd.py", line 313, in run_command
        self.distribution.run_command(command)
      File "/Users/atrask/opt/anaconda3/lib/python3.7/distutils/dist.py", line 985, in run_command
        cmd_obj.run()
      File "/Users/atrask/opt/anaconda3/lib/python3.7/distutils/command/build.py", line 135, in run
        self.run_command(cmd_name)
      File "/Users/atrask/opt/anaconda3/lib/python3.7/distutils/cmd.py", line 313, in run_command
        self.distribution.run_command(command)
      File "/Users/atrask/opt/anaconda3/lib/python3.7/distutils/dist.py", line 985, in run_command
        cmd_obj.run()
      File "/private/var/folders/zc/t5ztbg0563q8r1f5b601mzzh00g5p3/T/pip-req-build-tjz7l9d0/setup.py", line 36, in run
        ", ".join(e.name for e in self.extensions))
    RuntimeError: CMake must be installed to build the following extensions: _tenseal_cpp
    ----------------------------------------
  Rolling back uninstall of tenseal
  Moving to /Users/atrask/opt/anaconda3/lib/python3.7/site-packages/tenseal-0.1.0.dev0.dist-info/
   from /Users/atrask/opt/anaconda3/lib/python3.7/site-packages/~enseal-0.1.0.dev0.dist-info
  Moving to /Users/atrask/opt/anaconda3/lib/python3.7/site-packages/tenseal/
   from /Users/atrask/opt/anaconda3/lib/python3.7/site-packages/~enseal
ERROR: Command errored out with exit status 1: /Users/atrask/opt/anaconda3/bin/python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/var/folders/zc/t5ztbg0563q8r1f5b601mzzh00g5p3/T/pip-req-build-tjz7l9d0/setup.py'"'"'; __file__='"'"'/private/var/folders/zc/t5ztbg0563q8r1f5b601mzzh00g5p3/T/pip-req-build-tjz7l9d0/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /private/var/folders/zc/t5ztbg0563q8r1f5b601mzzh00g5p3/T/pip-record-uib43cop/install-record.txt --single-version-externally-managed --compile --install-headers /Users/atrask/opt/anaconda3/include/python3.7m/tenseal Check the logs for full command output.

I'm on OSX Catalina, Python 3.7.6

Serialise, deserialise; for pickle, deepcopy

Feature Description

I feel it would be vital to be able to deep-copy objects like context, private key, and ciphertext.
Similarly It will also be vital to real use to be able to pickle, and unpickle, context, private key, and ciphertext, or at the least save to a file-like object, but not necessarily a file itself.

Is your feature request related to a problem?

I would like to save directly to a non local system such as a database the necessary objects to encrypt, evaluate, and decrypt ciphertext, without having to write to the local filesystem, thus I need to create a file-like object to store elsewhere. Similarly to this end this will involve serialisation and desirialisation, probably from pickle, which currentley does not work with the pybin11 bindings here. This also prevents things like python deep-copying any of the tenseal objects which is necessary under certain use cases like several workers copying from the same object to evaluate/ compute some function.

What alternatives have you considered?

Saving to a file and loading that file to a database; time consuming, IO intensive, bottlenecked, and not easily scalable.

Additional Context

Here is a unit test showcasing the current inability to pickle, and deep-copy, unless I am misunderstanding how it is to be done here:
test.py

import copy
import unittest


class seal_tests(unittest.TestCase):
    """Unit test class aggregating all tests for the seal class."""

    def get_context_bfv(self):
        import tenseal as ts
        context = ts.context(ts.SCHEME_TYPE.BFV, poly_modulus_degree=4096,
                             plain_modulus=1032193)
        return context

    def test_copy_context_bfv(self):
        context = self.get_context_bfv()
        copy.deepcopy(context)

    def get_keys_bfv(self):
        context = self.get_context_bfv()
        sk = context.secret_key()
        return (context, sk)

    def test_copy_keys_bfv(self):
        context, sk = self.get_keys_bfv()
        copy.deepcopy(sk)

    def get_ciphertext(self):
        import tenseal as ts
        context = self.get_context_bfv()
        plain_vector = [60, 66, 73, 81, 90]
        encrypted_vector = ts.bfv_vector(context, plain_vector)
        return encrypted_vector

    def test_copy_ciphertext(self):
        ciphertext = self.get_ciphertext()
        copy.deepcopy(ciphertext)


if __name__ == "__main__":
    # run all the unit-tests
    unittest.main()

when run python3 ./test.py

EEE
======================================================================
ERROR: test_copy_ciphertext (__main__.seal_tests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "./test.py", line 36, in test_copy_ciphertext
    copy.deepcopy(ciphertext)
  File "/usr/lib/python3.8/copy.py", line 161, in deepcopy
    rv = reductor(4)
TypeError: cannot pickle '_tenseal_cpp.BFVVector' object

======================================================================
ERROR: test_copy_context_bfv (__main__.seal_tests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "./test.py", line 16, in test_copy_context_bfv
    copy.deepcopy(context)
  File "/usr/lib/python3.8/copy.py", line 161, in deepcopy
    rv = reductor(4)
TypeError: cannot pickle '_tenseal_cpp.TenSEALContext' object

======================================================================
ERROR: test_copy_keys_bfv (__main__.seal_tests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "./test.py", line 25, in test_copy_keys_bfv
    copy.deepcopy(sk)
  File "/usr/lib/python3.8/copy.py", line 161, in deepcopy
    rv = reductor(4)
TypeError: cannot pickle '_tenseal_cpp.SecretKey' object

----------------------------------------------------------------------
Ran 3 tests in 0.048s

FAILED (errors=3)

About the saving and loading of tenseal data and keys.

I use tenseal directly
context = ts.context(ts.SCHEME_TYPE.CKKS, 8192, coeff_mod_bit_sizes=[60, 40, 40, 60])
ckks_vec = ts.ckks_vector(context, plain_vec, scale)
Q:How to save and load the secret_key、public_key、relin_keys and the ckks_vec in the context to a local file?

Polynomial evaluation for CKKSVector

Feature Description

Add a method for evaluating univariate polynomials where the variable is a CKKSVector. The method should meet the following criteria:

  • Use square and multiply for exponentiation for both efficiency and minimizing the multiplicative depth
  • The method should receive a list of coefficients of variable size (n+1), with the first being the constant term, and the last being the coefficient of x^n
  • coefficients 1 and 0 shouldn't involve a multiplication

For the naming, polyval seems like a good name (borrowed from the numpy API)

A aggregation function for an encrypted vector (add_many/multiply_many)

Feature Description

A single encrypted TenSEAL vector should be able to be naively aggregated by either a sum or product.

Is your feature request related to a problem?

This would be especially useful for common operations such as dot product and euclidean distance.

What alternatives have you considered?

Currently the only known method I understand might for summation work is to perform a matrix multiplication with an identity vector which is not ideal.

Additional Context

Ideally the operation would look something like
encrypted_vec.add_many()

Rotate Vector through tensor API

Feature Description

It would be nice to expose the rotate vector function through the tensor API. This would provide users with a more intuitive method of rotating vectors as opposed to having to do so through the sealapi evaluator object.

Is your feature request related to a problem?

This feature would make it easier to test out algorithms that require rotations to function (such has efficient encrypted matrix multiplications).

What alternatives have you considered?

Users could continue to use the sealapi evaluator object however this is clunky and unintuitive to the current design principle of abstracting away the evaluator.

Additional Context

I've already made the necessary changes to try to do so with the CKKS vector that is ready to be code checked.

CKKSTensor - polynom evaluation

Feature Description

Implement the method for performing a polynomial evaluation on CKKSTensor. A helper function for performing polynom evaluation on ciphertext is provided, this feature will mainly loop over internal ciphertexts and use the helper function.

Performing this operation in parallel using the threadpool should be prefered.

Drop BFVNaiveVector

This type of vector was first created mainly for experimentation, I don't think he provide any useful feature that other vectors doesn't provide, he is actually really inefficient and it would be just more work supporting it via adding new features and testing.

I think we should drop it completely.

Relinearization [and Rescaling]

After every multiplication for CKKS and BFV, we need to relinearize our ciphertext, CKKS also need rescaling (as the scale becomes Delta**2). We need to have these operations done automatically by default after every multiplication, with the ability to choose to not do so.

Configure TenSEAL to auto relin/rescale

Context

We want to both make relinearization/rescaling transparent to the user and offer experienced users flexibility to implement their ideas.

Possible solution

A good place to configure this would be the TenSEALContext object where you can for example call context.[enable|disable]_auto_[relin|rescale]() to turn on/off relin/rescaling.

See also #35

Cpp library for TenSEAL

What?

Provide a Cpp library for TenSEAL.

Why?

As TenSEAL is mainly engineered to work with python, the Cpp API doesn't look really great for Cpp devs, we can rework it so that it can also be used as a Cpp library, while making sure to keep the python compatibility, the python API should always comes first, but it would be great if we can find a middle ground for both of them.

Breakdown

  • Refactor the Cpp API (while keeping the Python API)
  • Provides an easily installable Cpp library

Additional Context

@bcebere recently #73 built a separate cpp library for doing cpp tests, which gave me the idea that it might be useful to provide users with a separate cpp library.

Parameter what's stored while serializing the context

Description

API for serialization can use some parametrization. Some examples based on a client/server use case need to save the context without secret-key, galois-keys ...

ctx.serialize(save_sk=False)

This will not save the secret key even if the context holds it, without removing the secret key from the ctx object. Without such API, someone will need to first remove the secret-key by calling .make_context_public() then serialize, but he can also want to use the full context with a secret-key later on.

CFLAGS improvements

Tensors should not include headers using a relative path, this can lead to compile issues.

We should update the include paths to prevent this.

Provide a SEAL API binding to set scale manually after a multiplication

Context

Currently after a multiplication has been done, there is no way to set the scale manually to allow further computation such as addition with a plaintext.

Example :

# First do a multiplication and rescale
evaluator.multiply(ctx, ptx, output)
evaluator.rescale_to_next_inplace(output)
evaluator.mod_switch_to_inplace(ptx, output.parms_id())

# This is not allowed currently
output.scale(scale)

# Therefore this will fail because seal won't allow two objects of different scale to be summed
evaluator.add_plaintext_inplace(output, ptx)

Proposed solution

I think a simple binding such as ctx.scale(scale) or ctx.set_scale(scale) would be enough to solve this problem.

Review vector copies on operations

Description

Operations like add_inplace, sub_inplace, or mul_inplace require to copy of the operand, although we shouldn't modify that object.

The flow should be optimized to reuse the existing object.

Segfault when scale out of bounds in parallel matmul

Description

There is a segmentation fault if a scale out of bounds error is raised during a parallel vector matrix multiplication

How to Reproduce

import tenseal as ts

N_THREADS = None
# setting it to only one thread doesn't result in a segfault
# N_THREADS = 1

ctx = ts.context(ts.SCHEME_TYPE.CKKS, 8192, -1, [60, 40, 60], n_threads=N_THREADS)
ctx.global_scale = 2 ** 40
ctx.generate_galois_keys()

vec = ts.ckks_vector(ctx, [0, 1])
vec.square_()
# should raise out of bound
# but it's resulting in a segfault
vec.mm_([[1, 2], [3, 4]])

Expected Behavior

Only the scale out of bounds exception should be raised

System Information

  • OS: Linux
  • Python 3.8
  • TenSEAL 0.2.0a1

Additional Context

Add any other context about the problem here.

Get the max number of slots available

Feature Description

In both CKKS and BFV (when using the batchencoder), we can batch many values at a time, up to some extent, we want to provide an API endpoint (e.g. .max_slots()) to return this maximum value.

What alternatives have you considered?

We can also add API endpoints for getting poly_mod_degree which we can infer the number of slots later depending on the scheme used, however, this requires some HE expertise, and a simple endpoint that doesn't require further computation might be simpler.

PlainTensor tolist

Feature Description

When we are decrypting tensors, we are returning their internal representations, which is just a vector, but the goal would be to return them as a tensor (depending on their shape). This feature is about converting the internal representation into the appropriate tensor, in a nested vector format, so that it will be returned as Python list in the Python interface.

Additional Context

Nested vectors might not be the best choice.

CKKSTensor negate

Feature Description

Implement the negate operation for CKKSTensor. This feature should mainly loop over internal ciphertexts and perform the negate operation

Performing this operation in parallel using the threadpool should be prefered.

Automate build-push to PyPI

As TenSEAL includes a binary extension, it needs some extra attention on the build process to support different platforms, but the ideal would be to have this process automated on release, so whenever a new version comes in, it gets built and pushed to PyPI.

Some resources

Automate tests on MacOS and Windows

Feature Description

We need to test on all platforms (Linux, MacOS, Windows) on every PR.

Is your feature request related to a problem?

The build on MacOS and Windows was only ran on release, which made us spot problems on release time, instead of catching them early on every codebase change.

CKKSTensor - Batching

Feature Description

A tensor of shape (batch_size, height, width, depth) should be stored in an encrypted tensor of shape (height, width, depth) where the batch_size dimension should be batched across ciphertexts. We shouldn't allow the user to customize which axis need to be batched, but we leave the responsibility of reshaping it with the batch_axis as the first dimension to the user.

The API should looks something like this, with batch specifying if we should batch the first dimension or not
tenseal.ckks_tensor(context, plain_tensor, batch=True)

What alternatives have you considered?

We could allow the user to specify the batch_axis, but I guess this will add complexity to the code. And specifying an input tensor format to the user shouldn't be an issue.

Add support Slack channel links to main readme file

Where?

Main readme

Who?

All contributors

What?

Users of this library should have a good idea of where to get support within Slack so that the general channel does not become a place for people dropping software implementation problems. Please add the following section somewhere in your readme:

## Support
For support in using this library, please join the **#lib_tenseal** Slack channel. If you’d like to follow along with any code changes to the library, please join the **#code_tenseal** Slack channel. [Click here to join our Slack community!](https://slack.openmined.org)

When finished, it should look exactly as it does here: https://github.com/OpenMined/.github/blob/master/README-TEMPLATE.md#support

Additional Context

None

Add Bazel support

Feature Description

Bazel support would have numerous advantages in TenSEAL's build system.

Pros

  • We would be extending the cmake build system, not replacing it.
  • Well-established ML tools like PyTorch or Tensorflow support Bazel too, and it would make the integration seamless there.
  • The integration with SEAL would be easy, no submodule required, as in this example. Bazel has bindings to other build systems as well https://github.com/OpenMined/PIR/blob/master/third_party/seal.BUILD
  • It would be a major improvement for integration/deployment in Bazel system, it would install all the depends without any hassle, just the TenSEAL reference in their bazel file, as in this example https://github.com/OpenMined/PIR
  • It supports multiple languages, like C++/Python/Go/Rust and so on.
  • It supports pytest/gtest, no need for installing/running extra tools. Just bazel test and it executes all the tests in the repository, no matter the language/framework.

Cons

Bazel tests with Windows support

Description

Bazel is compatbile with Windows, but the workflows fail on that platform.

There are several issues to fix:

Need a way to check if a key is available

Description

If someone needs to check if galois_keys are present in a context, he will need to do that in a try except since accessing that attribute will throw an error if the keys doesn't exist. We need a flexible way to check a boolean or something to know if a key is available )

Additional Context

Here is how the error looks in the interpreter, where ctx is a TenSEALContext

>>> ctx.galois_keys()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: the current context doesn't hold a Galois keys

Holds the scale in TenSEALContext

This issue is mainly related to the use of the CKKS scheme

Motivation

  1. API would be simpler if the user provides the scale once at context creation, this wasn't the case because we thought that the user would need to choose the scale for each tensor.
  2. In a secure computation which is controlled by a single TenSEALContext, we will generally wants to have the same scale for all our ciphertexts.
  3. After some multiplication and rescaling operations, we will sometimes need to assume that all ciphertexts are on the same scale, while this is not true, the ratio between the actual scales should be around 1 if the initial scales used for encoding were the same.

Proposed solution

Hold the scale in the TenSEALContext for CKKS: this can also help us advise the user of choosing coeff modulus that are ~= sclae (e.g. scale=2**20 & coeff_mod_bit_sizes=[X, 20, 20, X]). Every multiplication should rescale the ciphertext using the next coeff modulus. If we assume that the initial scale is a power of two and that the coeff_modulus are of the same bit size as the initial scale, then all ciphertext should have a scale ~= init_scale no matter their multiplicative depth.

Ping: @philomath213 @s0l0ist

Implement Thread Pool

Description

As suggested by @bcebere in #115 , parallel computation using threads shouldn't create them from scratch every time, but instead should assign jobs to a pool of available threads.

We need to add a thread pool system in tenseal/utils as well as integrate it in the vector-matrix multiplication operation.

Should we disable SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT?

Default build of SEAL enforce SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT to on which will throw an error whenever the result ciphertext of an evaluation is transparent.

Current implementation workaround issues regarding transparent ciphertexts in vector operations #33. An open question is whether we should disable it completely? Does our use cases get affected?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.