Coder Social home page Coder Social logo

eva's Introduction

EVA - Compiler for Microsoft SEAL

EVA is a compiler for homomorphic encryption, that automates away the parts that require cryptographic expertise. This gives you a simple way to write programs that operate on encrypted data without having access to the secret key.

Think of EVA as the "C compiler" of the homomorphic world. Homomorphic computations written in EVA IR (Encrypted Vector Arithmetic Intermediate Representation) get compiled to the "assembly" of the homomorphic encryption library API. Just like C compilers free you from tricky tasks like register allocation, EVA frees you from encryption parameter selection, rescaling insertion, relinearization...

EVA targets Microsoft SEAL — the industry leading library for fully-homomorphic encryption — and currently supports the CKKS scheme for deep computations on encrypted approximate fixed-point arithmetic.

Getting Started

EVA is a native library written in C++17 with bindings for Python. Both Linux and Windows are supported. The instructions below show how to get started with EVA on Ubuntu. For building on Windows EVA's Azure Pipelines script is a useful reference.

Installing Dependencies

To install dependencies on Ubuntu 20.04:

sudo apt install cmake libboost-all-dev libprotobuf-dev protobuf-compiler

Clang is recommended for compilation, as SEAL is faster when compiled with it. To install clang and set it as default:

sudo apt install clang
sudo update-alternatives --install /usr/bin/cc cc /usr/bin/clang 100
sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 100

Next install Microsoft SEAL version 3.6:

git clone -b v3.6.4 https://github.com/microsoft/SEAL.git
cd SEAL
cmake -DSEAL_THROW_ON_TRANSPARENT_CIPHERTEXT=OFF .
make -j
sudo make install

Note that SEAL has to be installed with transparent ciphertext checking turned off, as it is not possible in general to statically ensure a program will not produce a transparent ciphertext. This does not affect the security of ciphertexts encrypted with SEAL.

Building and Installing EVA

Building EVA

EVA builds with CMake version ≥ 3.13:

git submodule update --init
cmake .
make -j

The build process creates a setup.py file in python/. To install the package for development with PIP:

python3 -m pip install -e python/

To create a Python Wheel package for distribution in dist/:

python3 python/setup.py bdist_wheel --dist-dir='.'

To check that the installed Python package is working correctly, run all tests with:

python3 tests/all.py

EVA does not yet support installing the native library for use in other CMake projects (contributions very welcome).

Multicore Support

EVA features highly scalable multicore support using the Galois library. It is included as a submodule, but is turned off by default for faster builds and easier debugging. To build EVA with Galois configure with USE_GALOIS=ON:

cmake -DUSE_GALOIS=ON .

Running the Examples

The examples use EVA's Python APIs. To install dependencies with PIP:

python3 -m pip install -r examples/requirements.txt

To run for example the image processing example in EVA/examples:

cd examples/
python3 image_processing.py

This will compile and run homomorphic evaluations of a Sobel edge detection filter and a Harris corner detection filter on examples/baboon.png, producing results of homomorphic evaluation in *_encrypted.png and reference results from normal execution in *_reference.png. The script also reports the mean squared error between these for each filter.

Programming with PyEVA

PyEVA is a thin Python-embedded DSL for producing EVA programs. We will walk you through compiling a PyEVA program with EVA and running it on top of SEAL.

Writing and Compiling Programs

A program to evaluate a fixed polynomial 3x2+5x-2 on 1024 encrypted values can be written:

from eva import *
poly = EvaProgram('Polynomial', vec_size=1024)
with poly:
    x = Input('x')
    Output('y', 3*x**2 + 5*x - 2)

Next we will compile this program for the CKKS encryption scheme. Two additional pieces of information EVA currently requires to compile for CKKS are the fixed-point scale for inputs and the maximum ranges of coefficients in outputs, both represented in number of bits:

poly.set_output_ranges(30)
poly.set_input_scales(30)

Now the program can be compiled:

from eva.ckks import *
compiler = CKKSCompiler()
compiled_poly, params, signature = compiler.compile(poly)

The compile method transforms the program in-place and returns:

  1. the compiled program;
  2. encryption parameters for Microsoft SEAL with which the program can be executed;
  3. a signature object, that specifies how inputs and outputs need to be encoded and decoded.

The compiled program can be inspected by printing it in the DOT format for the Graphviz visualization software:

print(compiled_poly.to_DOT())

The output can be viewed as a graph in, for example, a number of Graphviz editors available online.

Generating Keys and Encrypting Inputs

Encryption keys can now be generated using the encryption parameters:

from eva.seal import *
public_ctx, secret_ctx = generate_keys(params)

Next a dictionary of inputs is created and encrypted using the public context and the program signature:

inputs = { 'x': [i for i in range(compiled_poly.vec_size)] }
encInputs = public_ctx.encrypt(inputs, signature)

Homomorphic Execution

Everything is now in place for executing the program with Microsoft SEAL:

encOutputs = public_ctx.execute(compiled_poly, encInputs)

Decrypting Results

Finally, the outputs can be decrypted using the secret context:

outputs = secret_ctx.decrypt(encOutputs, signature)

For debugging it is often useful to compare homomorphic results to unencrypted computation. The evaluate method can be used to execute an EVA program on unencrypted data. The two sets of results can then be compared with for example Mean Squared Error:

from eva.metric import valuation_mse
reference = evaluate(compiled_poly, inputs)
print('MSE', valuation_mse(outputs, reference))

Contributing

The EVA project welcomes contributions and suggestions. Please see CONTRIBUTING.md for details.

Credits

This project is a collaboration between the Microsoft Research's Research in Software Engineering (RiSE) group and Cryptography and Privacy Research group.

A huge credit goes to Dr. Roshan Dathathri, who as an intern built the first version of EVA, along with all the transformations required for targeting the CKKS scheme efficiently and the parallelizing runtime required to make execution scale.

Many thanks to Sangeeta Chowdhary, who as an intern put a huge amount of work into making EVA ready for release.

Publications

Roshan Dathathri, Blagovesta Kostova, Olli Saarikivi, Wei Dai, Kim Laine, Madanlal Musuvathi. EVA: An Encrypted Vector Arithmetic Language and Compiler for Efficient Homomorphic Computation. PLDI 2020. arXiv DOI

Roshan Dathathri, Olli Saarikivi, Hao Chen, Kim Laine, Kristin Lauter, Saeed Maleki, Madanlal Musuvathi, Todd Mytkowicz. CHET: An Optimizing Compiler for Fully-Homomorphic Neural-Network Inferencing. PLDI 2019. DOI

eva's People

Contributors

olsaarik 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

eva's Issues

CMake out-of-source build does not create python module correctly

Issue

When building out-of-source, the python module does not seem to be created correctly.
Trying to run python3 tests/all.py results in the following error message:

Traceback (most recent call last):
  File "tests/all.py", line 4, in <module>
    from bug_fixes import *
  File "/mnt/c/Code/EVA/build/tests/bug_fixes.py", line 5, in <module>
    from common import *
  File "/mnt/c/Code/EVA/build/tests/common.py", line 6, in <module>
    from eva import evaluate
  File "/mnt/c/Code/EVA/python/eva/__init__.py", line 4, in <module>
    from ._eva import *
ModuleNotFoundError: No module named 'eva._eva'

How To Reproduce

In a freshly cloned EVA repository:

git submodule update --init
mkdir build
cd build
cmake ..
make -j
python3 -m pip install -e python/
python3 ../tests/all.py

Notes

When building in-tree (i.e., cmake . in the main dir) running the tests works fine. I assume there are some files in the source tree that aren't copied into the build dir but are necessary?

How to control the maximum vector size in EVA??

Hi, I'm running EVA with 16384-length per a individual(sample) data for a simple model.
In the end of the execution, I had the following warning message,

'WARNING: Program uses vector size 16384 while only 4096 slots are required for security. This does not affect correctness, but higher performance may be available with a smaller vector size.'

So, I tried changing some parameters such as 'model.set_input_scales' and 'model.set_output_ranges',
and the required slots (4096 above) has changed to 16384 (maximum case in my case).

If I want use more samples (a vector with length 16384*2 ), then 16384 slots are still less to avoid that warning message.

I have two quenstions.

  1. Is there any way to control the maximum slots (acceptable length of input vector)?
  2. Does the warning message mean that the the security is loosened mathematically?

Thank you in advance for your reply :)

How to do simple addition/multiplication of clear/cipher data?

Not an issue. Just a quick question. I can build/run all test cases, and see how EVA supports polynomial functions and more advanced processing of HE-enc data.
However, it is not obvious to me how primitive operations like addition/multiplication of numbers in clear/cipher vector/matrix works, as seen in other python-to-SEAL bindings, e.g., z = clear_vector_x * cipher_vector_y, and then execute poly(z),....
If I have to use other bindings for such primitive operations, how do we make keys/encrypted-numbers portable with EVA? Thx

Compilation performance issue with constants

Hello,

I finally came up with a small test case for the performance issue I referenced to in my comments on #8

In it I create two programs that do the same thing: prog1 uses python constants, and prog2 uses Inputs with is_encrypted=False.

The compilation time of the former starts going up quadratically but the latter goes up linearly with number of operations.

This indicates to me that something is not quite right.

Thanks for your work on EVA!

from eva import EvaProgram, Input, Output
from eva.ckks import CKKSCompiler
from eva.seal import generate_keys
from random import random
import time

def test_slow_constants():

    for j in range(1, 10):
        n = j * 100
        inputs_values = [random() for _ in range(n)]
        constant_values = [random() for _ in range(n)]

        prog1 = EvaProgram("Normal", vec_size=1)
        prog2 = EvaProgram("Optimized", vec_size=1)
        with prog1:
            inputs = [Input(f'x{i}') for i in range(n)]
            result = sum([
                sum(input*constant for input, constant in zip(inputs, constant_values))
                for _ in range(j)
            ])
            Output('y', result)

        with prog2:
            inputs = [Input(f'x{i}') for i in range(n)]
            plain_inputs = [Input(f'z{i}', is_encrypted=False) for i in range(n)]
            result = sum([
                sum(input*plain_input for input, plain_input in zip(inputs, plain_inputs))
                for _ in range(j)
            ])
            Output('y', result)
        prog1.set_input_scales(30)
        prog1.set_output_ranges(30)
        prog2.set_input_scales(30)
        prog2.set_output_ranges(30)
        compiler = CKKSCompiler()
        start = time.time()
        compiled1, params1, signature1 = compiler.compile(prog1)
        compile_time_1 = time.time() - start

        start = time.time()
        compiled2, params2, signature2 = compiler.compile(prog2)
        compile_time_2 = time.time() - start

        eval_inputs_1 = {f'x{i}': [inputs_values[i]] for i in range(n)}
        eval_inputs_2 = dict(
            **{f'x{i}': [inputs_values[i]] for i in range(n)},
            **{f'z{i}': [constant_values[i]] for i in range(n)}
        )
        public_ctx1, secret_ctx1 = generate_keys(params1)
        public_ctx2, secret_ctx2 = generate_keys(params2)

        encInputs1 = public_ctx1.encrypt(eval_inputs_1, signature1)
        encInputs2 = public_ctx2.encrypt(eval_inputs_2, signature2)
        start = time.time()
        encOutputs1 = public_ctx1.execute(compiled1, encInputs1)
        eval_time_1 = time.time() - start
        start = time.time()
        encOutputs2 = public_ctx2.execute(compiled2, encInputs2)
        eval_time_2 = time.time() - start
        outputs1 = secret_ctx1.decrypt(encOutputs1, signature1)
        outputs2 = secret_ctx2.decrypt(encOutputs2, signature2)
        print(f'For n={n}')
        print(outputs1['y'][0], outputs2['y'][0])
        print(abs(outputs1['y'][0] - outputs2['y'][0]))
        print(f'Compile time 1: {compile_time_1}')
        print(f'Compile time 2: {compile_time_2}')
        print(f'Eval time 1: {eval_time_1}')
        print(f'Eval time 2: {eval_time_2}')
        print('--------------')

Output below:

For n=100
23.211396730172 23.211384219549373
1.2510622628525425e-05
Compile time 1: 0.2712235450744629
Compile time 2: 0.2670736312866211
Eval time 1: 0.1006007194519043
Eval time 2: 0.09510278701782227
--------------
For n=200
90.8838902120143 90.88389847056901
8.258554714757338e-06
Compile time 1: 2.812283515930176
Compile time 2: 1.6775407791137695
Eval time 1: 0.34754157066345215
Eval time 2: 0.3492898941040039
--------------
For n=300
236.33221162337733 236.3322501533622
3.852998486308934e-05
Compile time 1: 12.8867027759552
Compile time 2: 5.266862392425537
Eval time 1: 0.7767889499664307
Eval time 2: 0.754633903503418
--------------
For n=400
386.9504582821064 386.9504789357373
2.0653630883771257e-05
Compile time 1: 38.55613350868225
Compile time 2: 12.4056236743927
Eval time 1: 1.44482421875
Eval time 2: 1.320909023284912
--------------
For n=500
659.1741082156925 659.174056261611
5.1954081527583185e-05
Compile time 1: 90.17314314842224
Compile time 2: 23.962910175323486
Eval time 1: 2.177649736404419
Eval time 2: 2.1107213497161865
--------------
For n=600
878.7944020949869 878.7944813848235
7.928983654892363e-05
Compile time 1: 179.5491852760315
Compile time 2: 41.59600567817688
Eval time 1: 3.1147239208221436
Eval time 2: 3.194528102874756
--------------

Evaluate a function on a clear data chosen by the evaluator

Can Eva allow to run a function f on two variables a and b such that a is encrypted (chosen by the encryptor) and b is plaintext (chosen by the evaluator)?

Here is an example of a code (that does not compile) that shows what I would like to achieve

from eva import *
from time import time
add = EvaProgram('add', vec_size=16)
with add:
    a = Input('a', True)
    b = Input('b', False)
    Output('c', a+b)

# Scale of inputs/outputs
add.set_output_ranges(30)
add.set_input_scales(30)

from eva.ckks import *
compiler = CKKSCompiler()
compiled_add, params, signature = compiler.compile(add)

### Generating Keys and Encrypting Inputs
from eva.seal import *
public_ctx, secret_ctx = generate_keys(params)

# Encryptor chooses a 
#inputs = { 'a': [i for i in range(compiled_add.vec_size)], 'b': [i for i in range(compiled_add.vec_size)] }
inputs_a = { 'a': [i for i in range(compiled_add.vec_size)] }
encInputs = public_ctx.encrypt(inputs_a, signature)

# Evaluator chooses b
inputs_b = { 'b': [i for i in range(compiled_add.vec_size)] }
encInputs = inputs_a + inputs_b # This is what I would like to do

# Homomorphic Execution
encOutputs = public_ctx.execute(compiled_add, encInputs)

# Decryption of results
outputs = secret_ctx.decrypt(encOutputs, signature)

print(outputs)

How to save and load key instances?

Hello, I'm a person who study about homomorphic encryption.
Practically, the public key has to be saved as a file and be sent to someone to encrypt his own data. However, I can't find how to save public key instance
(e.g <eva._eva._seal.SEALPublic at 0x7f37b454f2b0>) in a file format. I tried pickle module, but it doens't work.

Is there any way to save a public key and encrypted data into a file format?? I guess it can be accomplished in SEAL level not EVA. Thank you in advance for your reply.

#build_in_window

I don't know how to install EVA to python library in window by using azure pipeline ! Someone help !

What are input scale and output range for?

Hello,

I have been writing some small codes with EVA, however I don't really understand what the 2 additional parameters do exactly:
set_output_ranges and set_input_scales.
By testing a bit it seems set_input_scales changes the precision of the results but slows the execution.
set_output_ranges however I don't know what it does at all.

Thx

ACTION REQUIRED: Microsoft needs this private repository to complete compliance info

There are open compliance tasks that need to be reviewed for your EVA repo.

Action required: 4 compliance tasks

To bring this repository to the standard required for 2021, we require administrators of this and all Microsoft GitHub repositories to complete a small set of tasks within the next 60 days. This is critical work to ensure the compliance and security of your microsoft GitHub organization.

Please take a few minutes to complete the tasks at: https://repos.opensource.microsoft.com/orgs/microsoft/repos/EVA/compliance

  • The GitHub AE (GitHub inside Microsoft) migration survey has not been completed for this private repository
  • No Service Tree mapping has been set for this repo. If this team does not use Service Tree, they can also opt-out of providing Service Tree data in the Compliance tab.
  • No repository maintainers are set. The Open Source Maintainers are the decision-makers and actionable owners of the repository, irrespective of administrator permission grants on GitHub.
  • Classification of the repository as production/non-production is missing in the Compliance tab.

You can close this work item once you have completed the compliance tasks, or it will automatically close within a day of taking action.

If you no longer need this repository, it might be quickest to delete the repo, too.

GitHub inside Microsoft program information

More information about GitHub inside Microsoft and the new GitHub AE product can be found at https://aka.ms/gim or by contacting [email protected]

FYI: current admins at Microsoft include @olsaarik, @WeiDaiWD, @kimlaine

"bad optional access" (naive matmul)

I am looking at GEMM computations in EVA.

EVA uses vectorised computations, though following the paper Secure Outsourced Matrix Computation and Application to Neural Networks, we can run a naive encrypted matmul by having the vector size be 1.

This issue asks if the EVA Extension Library (EXL) will be released, which may already implement this, however it is not current available as far as I know.

I have tried to implement this, however I am getting an error: RuntimeError: bad optional access.

You can see my example before, is there something I am missing?

#!/usr/bin/env python
from eva import EvaProgram, Input, Output, evaluate
from eva.ckks import CKKSCompiler
from eva.seal import generate_keys
from eva.metric import valuation_mse
import numpy as np


def get_gemm(N, K, M):
    gemm = EvaProgram("gemm", vec_size=1)
    with gemm:
        outputs = [[0] * N] * M
        for n in range(N):
            for m in range(M):
                for k in range(K):
                    x = Input(f"x_{n}_{k}")
                    w = Input(f"w_{k}_{m}")
                    outputs[n][m] += x * m
        for n in range(N):
            for m in range(M):
                Output(f"out_{n}_{m}", outputs[n][m])

    gemm.set_input_scales(25)
    gemm.set_output_ranges(10)
    return gemm


def generate_inputs(N, K):
    inputs = dict()
    i = 0
    for n in range(N):
        for k in range(K):
            inputs[f"x_{n}_{k}"] = [i]
            i += 1
    return inputs


def generate_weights(K, M):
    inputs = dict()
    i = 0
    for k in range(K):
        for m in range(M):
            inputs[f"w_{k}_{m}"] = [i]
            i += 1
    return inputs


def main():
    N, K, M = 8, 8, 8
    inputs = generate_inputs(N, K)
    weights = generate_weights(K, M)
    gemm = get_gemm(N, K, M)

    data = {**weights, **inputs}
    print(data)
    for prog in [gemm]:
        print(f"Compiling {prog.name}")

        compiler = CKKSCompiler()
        compiled, params, signature = compiler.compile(prog)
        public_ctx, secret_ctx = generate_keys(params)
        enc_inputs = public_ctx.encrypt(data, signature)
        print("excuting GEMM")
        enc_outputs = public_ctx.execute(compiled, enc_inputs)
        outputs = secret_ctx.decrypt(enc_outputs, signature)

        reference = evaluate(compiled, inputs)

        print("MSE", valuation_mse(outputs, reference))
        print()


if __name__ == "__main__":
    main()

cpu_affinity

_default_num_threads = len(psutil.Process().cpu_affinity()) does not work on MacOs.

from eva import EvaProgram, Input, Output, evaluate
File "..../EVA/python/eva/init.py", line 10, in
_default_num_threads = len(psutil.Process().cpu_affinity())
AttributeError: 'Process' object has no attribute 'cpu_affinity'

simple question. is this a problem of graphviz?

I made a code like this (there's no difference with original code in EVA git)
file name is 0819.py

from eva import *
poly = EvaProgram('Polynomial', vec_size=1024)
with poly:
    x = Input('x')
    Output('y', 3*x**2 + 5*x - 2)

poly.set_output_ranges(30)
poly.set_input_scales(30)

from eva.ckks import *
compiler = CKKSCompiler()
compiled_poly, params, signature = compiler.compile(poly)

print(compiled_poly.to_DOT())

from eva.seal import *
public_ctx, secret_ctx = generate_keys(params)

inputs = { 'x': [i for i in range(compiled_poly.vec_size)] }
encInputs = public_ctx.encrypt(inputs, signature)

encOutputs = public_ctx.execute(compiled_poly, encInputs)

outputs = secret_ctx.decrypt(encOutputs, signature)

from eva.metric import valuation_mse
reference = evaluate(compiled_poly, inputs)
print('MSE', valuation_mse(outputs, reference))

But when I type "python3 0819.py" in ubuntu, I can see this below.
Is it a problem of graphviz?
or should I change the code?

WARNING: Program specifies vector size 1024 while at least 4096 slots are required for security. This does not affect correctness, as the smaller vector size will be transparently emulated. However, using a vector size up to 4096 would come at no additional cost.
digraph "Polynomial" {
t7 [label="Constant"];
t7_EncodeAtScaleAttribute [shape=box label="scale=30"];
t7_EncodeAtScaleAttribute -> t7;
t7_EncodeAtLevelAttribute [shape=box label="level=1"];
t7_EncodeAtLevelAttribute -> t7;
t17 [label="Encode"];
t7 -> t17 [label="0"];
t17_EncodeAtScaleAttribute [shape=box label="scale=90"];
t17_EncodeAtScaleAttribute -> t17;
t17_EncodeAtLevelAttribute [shape=box label="level=0"];
t17_EncodeAtLevelAttribute -> t17;
t11 [label="Constant"];
t11_EncodeAtScaleAttribute [shape=box label="scale=30"];
t11_EncodeAtScaleAttribute -> t11;
t11_EncodeAtLevelAttribute [shape=box label="level=1"];
t11_EncodeAtLevelAttribute -> t11;
t16 [label="Encode"];
t11 -> t16 [label="0"];
t16_EncodeAtScaleAttribute [shape=box label="scale=30"];
t16_EncodeAtScaleAttribute -> t16;
t16_EncodeAtLevelAttribute [shape=box label="level=0"];
t16_EncodeAtLevelAttribute -> t16;
t0 [label="Input : Cipher"];
t0_EncodeAtScaleAttribute [shape=box label="scale=30"];
t0_EncodeAtScaleAttribute -> t0;
t0_EncodeAtLevelAttribute [shape=box label="level=0"];
t0_EncodeAtLevelAttribute -> t0;
t4 [label="Constant"];
t4_EncodeAtScaleAttribute [shape=box label="scale=30"];
t4_EncodeAtScaleAttribute -> t4;
t4_EncodeAtLevelAttribute [shape=box label="level=1"];
t4_EncodeAtLevelAttribute -> t4;
t15 [label="Encode"];
t4 -> t15 [label="0"];
t15_EncodeAtScaleAttribute [shape=box label="scale=30"];
t15_EncodeAtScaleAttribute -> t15;
t15_EncodeAtLevelAttribute [shape=box label="level=0"];
t15_EncodeAtLevelAttribute -> t15;
t5 [label="Mul"];
t15 -> t5 [label="0"];
t0 -> t5 [label="1"];
t12 [label="Mul"];
t5 -> t12 [label="0"];
t16 -> t12 [label="1"];
t2 [label="Constant"];
t2_EncodeAtScaleAttribute [shape=box label="scale=30"];
t2_EncodeAtScaleAttribute -> t2;
t2_EncodeAtLevelAttribute [shape=box label="level=1"];
t2_EncodeAtLevelAttribute -> t2;
t14 [label="Encode"];
t2 -> t14 [label="0"];
t14_EncodeAtScaleAttribute [shape=box label="scale=30"];
t14_EncodeAtScaleAttribute -> t14;
t14_EncodeAtLevelAttribute [shape=box label="level=0"];
t14_EncodeAtLevelAttribute -> t14;
t10 [label="Mul"];
t14 -> t10 [label="0"];
t0 -> t10 [label="1"];
t3 [label="Mul"];
t10 -> t3 [label="0"];
t0 -> t3 [label="1"];
t6 [label="Add"];
t3 -> t6 [label="0"];
t12 -> t6 [label="1"];
t8 [label="Sub"];
t6 -> t8 [label="0"];
t17 -> t8 [label="1"];
t13 [label="Rescale(60)"];
t8 -> t13 [label="0"];
t18 [label="Relinearize"];
t13 -> t18 [label="0"];
t9 [label="Output"];
t18 -> t9 [label="0"];
t9_RangeAttribute [shape=box label="range=30"];
t9_RangeAttribute -> t9;
}

MSE 2.0307120156632308e-05

Horizontal sum - encrypted size must be 2

Hi,

I'm trying to run a horizontal_sum on a vector of values and return one single sum (or a vector that has that sum in every position) by following your std test.

from eva import EvaProgram, Input, Output
from eva.ckks import CKKSCompiler
from eva.seal import generate_keys
from eva.std.numeric import horizontal_sum

vec_sz = 16

poly = EvaProgram('poly', vec_size=vec_sz)
with poly:
  a = Input('a')
  b = Input('b')

  diff = a - b
  sq_diff = diff * diff
  diff = horizontal_sum(sq_diff)

  Output('diff', diff)

poly.set_input_scales(40)
poly.set_output_ranges(10)
a = [i % 10 for i in range(vec_sz)]
b = [i % 5 for i in range(vec_sz)]

compiler = CKKSCompiler()
compiled_poly, params, signature = compiler.compile(poly)
public_ctx, secret_ctx = generate_keys(params)
inputs = {'a': a, 'b': b}
encInputs = public_ctx.encrypt(inputs, signature)
encOutputs = public_ctx.execute(poly, encInputs)
outputs = secret_ctx.decrypt(encOutputs, signature)
print(outputs)

I'm getting the following error:

Traceback (most recent call last):
  File "std_test.py", line 29, in <module>
    encOutputs = public_ctx.execute(poly, encInputs)
ValueError: encrypted size must be 2

I might be missing something obvious, but it seems that this is very similar to the std example.

cc: @cgouert

__pow__ raises invalid value error

In /python/eva/init.py, line 100, in pow: the condition tested is

if exponent < 1:
            raise ValueError("exponent must be greater than zero, got " + exponent)

But it should probably be str(exponent). I think the fact that it has to be an integer and not a float should be tested too.

Is there any way to implement sqrt since x**0.5 is not allowed?

Thanks in advance to those who can enlighten me!

Graph with Iteration-loop

Hi,

I am writing a logistic regression model training using EVA.
I have some questions on "updating encrypted LR model"

Basically, we need to update the LR model like '[w] <- [w] + gamma * [g]` in a for-loop.
But I counted "Bad variant access" error.

C++ Support

Does this compiler support the transformation from naked C++ code to encrypted C++ code like Python?

Any plans for PyPi or Conda?

Thank you for the great work on this project!

Are there any plans for providing pre-built packages on PyPI or Conda?

Multi-core compiler evaluation

Hello!
Really great work with EVA!

I was trying to use it but I was unable to scale it efficiently in time. I checked via htop on Ubuntu 20 that it was being used only one core.
Now, I am on a VM so if the problem is this that's okay but otherwise would it be possible to let the code being compiled have multi-core support?

I tried to build EVA with the cmake -DUSE_GALOIS=ON . command, but nothing changed.

Thank you for your time!

List of floating-point numbers as input possible (CKKS)?

Hi,

I want to do a simple sum calculation of some floating-point numbers, but I just want to use an List as input.
I know that we can do something like this to sum up a specific amount of numbers:

sum = EvaProgram('Sum', vec_size=4096)
with sum:
    x = Input('x')
    y = Input('y')
    z = Input('z')
    Output('sum', x+y+z)

Is there a way to transmit data as a list which contains all summands? Something like this:

sum = EvaProgram('Sum', vec_size=4096)
with sum:
    summands = Input('summands')

    result = 0
    for summand in summands:
            result = result + summand

    Output('sum', result)

Or is this not possible? Thank you.

eva import fails with Python 3.8.5

I'm getting this error after successful compilation and pip install on Ubuntu 20.04 with Python 3.8.5

pip3 install python/.
Processing ./python
Building wheels for collected packages: eva
  Building wheel for eva (setup.py) ... done
  Created wheel for eva: filename=eva-1.0.0-cp38-cp38-linux_x86_64.whl size=2014160 sha256=3f2f531efb8fb7860e413fcb22983cdd9c4e3cd075cf90012cbb24f6de4cc5bb
  Stored in directory: /tmp/pip-ephem-wheel-cache-7gz0p8dr/wheels/29/d5/97/d004a0d73f92dfdca9ed66648f34bf84be5de4325b55dd89db
Successfully built eva
Installing collected packages: eva
  Attempting uninstall: eva
    Found existing installation: eva 1.0.0
    Uninstalling eva-1.0.0:
      Successfully uninstalled eva-1.0.0
Successfully installed eva-1.0.0
python3 tests/all.py
Traceback (most recent call last):
  File "tests/all.py", line 4, in <module>
    from bug_fixes import *
  File "/home/hroth/Code2/EVA/tests/bug_fixes.py", line 5, in <module>
    from common import *
  File "/home/hroth/Code2/EVA/tests/common.py", line 6, in <module>
    from eva import evaluate
  File "/home/hroth/.local/lib/python3.8/site-packages/eva/__init__.py", line 4, in <module>
    from ._eva import *
ModuleNotFoundError: No module named 'eva._eva'

Fair security level performance comparison against TenSEAL

I am getting familiar with EVA, and am generating some basic linear algebra programs.

I am working with the vector dot product, and have three versions of the program, one using EVA with vector size 1, one with vector size=N, and a third that uses the dot product in TenSEAL.

However, I find though both are derived from SEAL, they have different ways of defining the security level.

For EVA, I set the security level to 128, whereas for TenSEAL it's a bit more involved. Right now I am setting:

poly_mod_degree = 8192
coeff_mod_bit_sizes = [60, 40, 40, 60]

When I run the dot benchmark, TenSEAL is much slower, and also fails to meet my accuracy requirements for size 512 and above.

image

I have been looking at the security config of EVA,

TenSEAL will be choosing vector sizes using its own scheme, but regarding the precision/security level, how do I ensure that my comparison is fair?

When I run make -j,it reports some wrong about clang

When I run make -j,it report " clang: error: unable to execute command: Segmentation fault (core dumped)
clang: error: clang frontend command failed due to signal (use -v to see invocation)".

clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
clang: note: diagnostic msg: PLEASE submit a bug report to http://llvm.org/bugs/ and include the crash backtrace, preprocessed source, and associated run script.
clang: note: diagnostic msg:


PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang: note: diagnostic msg: /tmp/ckks_serialization-dc57e0.cpp
clang: note: diagnostic msg: /tmp/ckks_serialization-dc57e0.sh
clang: note: diagnostic msg:


eva/CMakeFiles/eva.dir/build.make:159: recipe for target 'eva/CMakeFiles/eva.dir/serialization/ckks_serialization.cpp.o' failed
make[2]: *** [eva/CMakeFiles/eva.dir/serialization/ckks_serialization.cpp.o] Error 254
CMakeFiles/Makefile2:257: recipe for target 'eva/CMakeFiles/eva.dir/all' failed
make[1]: *** [eva/CMakeFiles/eva.dir/all] Error 2
Makefile:90: recipe for target 'all' failed
make: *** [all] Error 2

That's all of the message.Who can tell me how to solve it.I'll appreciate if I can get the way to solve it.

EVA for ML tasks

Hello,

I am trying to use EVA for a simple and encrypted MNIST model classifier.

The code for my ConvNet is the following

class ConvNet(torch.nn.Module):
    def __init__(self, hidden=64, output=10):
        super(ConvNet, self).__init__()
        torch.nn.Sequential()
        self.conv1 = torch.nn.Conv2d(1, 4, kernel_size=7, padding=0, stride=3)
        self.fc1 = torch.nn.Linear(256, hidden)
        self.fc2 = torch.nn.Linear(hidden, output)

    def forward(self, x):
        x = self.conv1(x)
        x = x * x
        x = x.view(-1, 256)
        x = self.fc1(x)
        x = x * x
        x = self.fc2(x)
        return x

However, having this simple piece of code

prog = EvaProgram('prog', vec_size=32*32)
with prog:
    image = Input('image')
    result = model(image)
    probs = torch.softmax(torch.tensor(result), 0)
    label_max = torch.argmax(probs)
    print(f'label_max type {type(label_max)}')
    print(f'label_max value {label_max}')
    Output('label_max', label_max.numpy())

Throws me this error: TypeError: conv2d(): argument 'input' (position 1) must be Tensor, not Expr

If however I replace the code for EVA with:

prog = EvaProgram('prog', vec_size=32*32)
with prog:
    result = model(image)
    probs = torch.softmax(torch.tensor(result), 0)
    label_max = torch.argmax(probs)
    print(f'label_max type {type(label_max)}')
    print(f'label_max value {label_max}')
    Output('label_max', label_max.numpy())

It gives me TypeError: No conversion to Term available for 0.

I get what both errors mean but I couldn't find any way of how to solve them. I was wondering if EVA supports ML tasks and if there any concrete examples other the one with image_processing, Thanks a lot!

Error: member access into incomplete type 'PyFrameObject'

Hi, I am trying to compile the EVA on different machines.
On Ubuntu 22.04 with Python 3.8.10, I could compile EVA without errors.
However, on MacOS with Python 3.11.6, I encounter the following error :

"EVA/third_party/pybind11/include/pybind11/pybind11.h:2220:14: error: member access into incomplete type 'PyFrameObject' (aka '_frame')
        frame->f_code->co_argcount > 0) {". 

I have searched this issue online and got this link: cython/cython#4681.
It seems that the errors are caused due to different versions of Python used.

Any idea on how to fix this issue?

Thanks.

Perform inference on multiple data in SIMD fashion

Hi Olli, I have a beginner's question. I managed to compile and execute successfully a code that runs an inference of some data 'x' (which is a 1D vector) on a simple linear regression model (composed of 1D vector 'weight' and a single value 'bias'). Here is the code

from eva import *
from eva.std.numeric import horizontal_sum
inference = EvaProgram('Inference', vec_size=len(weight_list))
with inference:
    x = Input('x', True)
    weight = Input('weight', True)
    bias = Input('bias', True)
    Output('out', horizontal_sum(x*weight)+bias)
    
inference.set_output_ranges(60)
inference.set_input_scales(60)

from eva.ckks import *
compiler = CKKSCompiler()
compiled_inference, params, signature = compiler.compile(inference)

How can I perform inference on a batch of data 'x' (x becomes a 2D vector) in SIMD fashion? Is this approach more efficient than calling the previous program multiple times?

Do "a+b", how to provide an encrypted a and an encrypted b for execute?

with poly:
    c = Input('a').__add__(Input('b'))
    Output('c', c)
……
inputs_a = { 'a': [1] }
inputs_b = { 'b' : [2] }
encInputs_a = public_ctx.encrypt(inputs_a, signature)
encInputs_b = public_ctx.encrypt(inputs_b, signature)
# how can i get the result now?
# like this? it doesn't work for me.
encOutputs = public_ctx.execute(compiled_poly, [encInputs_a, encInputs_b])

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.