Giter VIP home page Giter VIP logo

nufhe's Introduction

Cryptographic primitives, hosted on the decentralized nodes of the Threshold network, offering accessible, intuitive, and extensible runtimes and interfaces for secrets management and dynamic access control.

pypi pyversions codecov discord license


TACo Access Control

TACo (Threshold Access Control) is end-to-end encrypted data sharing and communication, without the requirement of trusting a centralized authority, who might unilaterally deny service or even decrypt private user data. It is the only access control layer available to Web3 developers that can offer a decentralized service, through a live, well-collateralized and battle-tested network. See more here: https://docs.threshold.network/applications/threshold-access-control

Getting Involved

NuCypher is a community-driven project and we're very open to outside contributions.

All our development discussions happen in our Discord server, where we're happy to answer technical questions, discuss feature requests, and accept bug reports.

If you're interested in contributing code, please check out our Contribution Guide and browse our Open Issues for potential areas to contribute.

Security

If you identify vulnerabilities with any nucypher code, please email [email protected] with relevant information to your findings. We will work with researchers to coordinate vulnerability disclosure between our stakers, partners, and users to ensure successful mitigation of vulnerabilities.

Throughout the reporting process, we expect researchers to honor an embargo period that may vary depending on the severity of the disclosure. This ensures that we have the opportunity to fix any issues, identify further issues (if any), and inform our users.

Sometimes vulnerabilities are of a more sensitive nature and require extra precautions. We are happy to work together to use a more secure medium, such as Signal. Email [email protected] and we will coordinate a communication channel that we're both comfortable with.

A great place to begin your research is by working on our testnet. Please see our documentation to get started. We ask that you please respect testnet machines and their owners. If you find a vulnerability that you suspect has given you access to a machine against the owner's permission, stop what you're doing and immediately email [email protected].

nufhe's People

Contributors

derekpierre avatar fjarri avatar innovativeinventor avatar tuxxy 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  avatar  avatar

nufhe's Issues

syntax exception when importing

after installing nufhe and the other dependencies, I get this exception when i try to import nufhe

SyntaxException: (SyntaxError) invalid syntax (<unknown>, line 4) ('i32 = dtypes.ctype(numpy.int32)\n\ndef lsh(label, sh') in file '/Users/jay/anaconda/lib/python3.5/site-packages/nufhe/transform/ntt.mako' at line: 21 char: 1

any tips?

Connect TFHE to other HE schemes

Hi all!
I'd like to know if it is possible to connect TFHE with another HE scheme working on integers like BGV/BFV in order to perform SIMD operations by using functions on Lwe already provided by this library.

Thanks in advance.

using multi-GPU on nuFHE problem

Hello. I have 2 questions about nuFHE.

  1. I wanna connect several GPU to increase the speed of nuFHE. Is this possible?
  2. I wanna compute 1 ciphertext and 1 encoding text before generating the ciphertext. Is this possible?

I'll wait for your reply.
Thanks.

need webgl support

cuda/opencl are all needing 3rd-party plugins to installed,only webgl is work natively(no plugins needed) in browser like env:browser,electron and so on.
why not add support for webgl?
@fjarri

Reference papers that nuFHE uses

The work in this project is incredible but quite hard to grasp.

What are the papers that the team has used to implement this and would it be possible to add this list to the README to give others some background into FHE?

shape of the keyswitch_key

Hello.
I want to ask about the shape of the Keyswitch_key defined in the nuFHE library.

In the paper(TFHE:Fast fully Homomorphic Encryption over the Torus), the keyswitching key is the encryption of the component of the 'cloud key(which is of the size 1024)' under the secret key we had(of the size 500).

When I saw the shape of the a, b of the keyswitching key in nuFHE, a had size of (1024, 8, 4, 500), and b had size of (1024, 8, 4)
I can see that 8 was used instead of 16 for binary decomposition. But where did 4 came out from?
Also, the component(cloud_key.keyswitch_key.lwe.a[0,0,0,:]) was all zero. Can I ask why?

gate_constant doesn't work as expected

I'm trying to compute a operation with a constant. I tried to use the constant gate but it seems that it process my numpy array backwards.
I'm passing a 32 bits constant with 31 False and the last bit at True and the results after going through the gate and deciphering it i get the first bit at True and 31 last bits at False

Here is the code i used to test it

import numpy
import nufhe
import time
from reikna.cluda import any_api


thr = any_api().Thread.create(interactive=True)

rng = numpy.random.RandomState()
secret_key, cloud_key = nufhe.make_key_pair(thr, rng)

size = 32

bits1 = numpy.zeros((size,), dtype=numpy.bool)
bits1[-1] = 1

ciphertext1 = nufhe.encrypt(thr, rng, secret_key, bits1)
reference = bits1

result = nufhe.empty_ciphertext(thr, cloud_key.params, ciphertext1.shape)
time_start = time.clock()
nufhe.gate_constant(thr, cloud_key, result, ciphertext1)
time_elapsed = (time.clock() - time_start)
print("Computation time took {}".format(time_elapsed))

result_bits = nufhe.decrypt(thr, secret_key, result)
print(reference)
print(result_bits)
assert (result_bits == reference).all()

Expected
[False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False True]
Actual
[ True False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False False]

Indexable and computable LweSampleArray's

I can

vm.gate_nand(cipherbit1,cipherbit2)

and get

<nufhe.lwe.LweSampleArray at  ... >

but I can't

vm.gate_nand(cipherbit1[0],cipherbit2[0])

cause I get

ERROR:root:Failed to compile
...

Can we make LweSampleArray indexable, and make it possible to compute on a single subset of bits from a larger LweSampleArray?

Some of the details about FFTs in `implementation_details.rst` are incorrect

Hi there! I was reading this doc and I found it helpful, but it had two mistakes about FFTs I thought you might want to correct. Note I did not study the NTT section in detail. Please let me know if you spot any errors in my corrections.

Factor of 2 error in naive approach

The doc states

This way the regular convolution of these extended arrays will result in the negacyclic convolution of original arrays.

I believe it should be 2 times the negacyclic convolution. A demonstration shows that we have to halve the output post ifft to make it correct: https://gist.github.com/j2kun/4555ea100efc4b5f574e030623706cd8

Tangent FFT approach does not work

Demo implementation of the algorithm described in the doc: https://gist.github.com/j2kun/49a52731e05f3247ab6f9519ac193aa3

It seems the correct approach is given (in less detail) by https://math.stackexchange.com/a/1445170, which differs from the nufhe doc by applying a different initial mapping (adding instead of subtracting), removing the conjugation step post ifft, and inverting the twist post ifft instead of applying a second twist by the root of unity.

Corrected implementation: https://gist.github.com/j2kun/874ce05ae956611cb91dd8822c34d1de

How to install nuFHE

Hello.
I want to know how to install nuFHE.
I would be grateful if you can give us details of what steps you should take to use your good project.
Thanks.

fatal error: include/cufhe_cpu.h: No such file or directory

(base) user@HP-Z8-G4-Workstation:~/cuFHE-master/cufhe/test$ cc test_api_cpu.cc
test_api_cpu.cc:24:10: fatal error: include/cufhe_cpu.h: No such file or directory
#include <include/cufhe_cpu.h>
^~~~~~~~~~~~~~~~~~~~~
compilation terminated.

Some detail about TLWE sample

I want to verify the correctness of TLWE encryption to better understand the polynomial multiplication, but I find some problem, here is what I do:

Assume a TLWE sample(A,b) whose k =1, degree = 1024, coefficients are in int32 (-2^31~2^31); A tlwekey s is a 1024 degree polynomial whose coefficients are 1/0 . b = <A,s> + noise, this is what I want to verify. I extract (A,b), s, noise by following way:

Getting (A,b):
In function ''tgsw_encrypt_int()'' of tgsw.py, there is a line "tgsw_encrypt_zero", and I regard it as creating TGSW samples that encrypts zero, where each column should be an TLWE sample that encrypts zero. I just extract one column, a TLWE sample (A,b), where A,b are both 1024 degree polynomial of coefficient in int32

Getting s:
The tlwekey s is obtained by "cloud_key.tgsw_key.tlwe_key.key.coeffs.get()", and it does is a 1024 degree polynomial of coefficients 1/0.

Getting noise:
The noise is obtained from function "tlwe_encrypt_zero()" of tlwe.py, there are noises1 and noises2 in the function, the noises1 is exactly A, so I regard noises2 as noise.

Problem: By using the extracted variables above, I find b != <A,s> + noise (mod X^N+1 , mod int32) , I wonder what is the problem, is there any detail that I miss or did wrong ?

Thanks.

Performance evaluation

I am unable to find the script used to evaluate the performance of NuFHE as stated in the README. I have tried
pytest -rA test/test_gates.py
but none of the results seem to match the reported statistic. I understand the result will likely be different numerically, but I can't find the statistic that matches in name.

installing nufhe in raspberry pi4 model b computer.

i am tring to install nufhe in raspberry, library not installing and giving error

fatal error : CL/cl.h no such fiel or directory

please suggest how to do it or requirement to install the nufhe in raspberry pi.

key genration error

TypeError Traceback (most recent call last)
in ()
259 lines.append([int(v) for v in line.split()])
260 ctx = nufhe.Context()
--> 261 secret_key, cloud_key = ctx.make_key_pair()
262 vm = ctx.make_virtual_machine(cloud_key)
263 size=16

7 frames
/usr/local/lib/python3.7/dist-packages/pyopencl/array.py in _new_with_changes(self, data, offset, shape, dtype, strides, queue, allocator)
641 strides=strides, data=data, offset=offset,
642 events=events,
--> 643 _fast=fast, _context=self.context, _queue=queue, _size=size)
644
645 def with_queue(self, queue):

TypeError: init() got an unexpected keyword argument 'data'

gate_mux with the OverflowError :"Python int too large to convert to C long"

Hello, I want to use gate_mux, but I get an error "Python int too large to convert to C long" when compiling. Do you know what the reason is?

`
import random
import numpy
import nufhe
from reikna.cluda import any_api
size = 32
bits1 = [random.choice([False, True]) for i in range(size)]
bits2 = [random.choice([False, True]) for i in range(size)]
bits3 = [random.choice([False, True]) for i in range(size)]

thr = any_api().Thread.create(interactive=True)
rng = nufhe.DeterministicRNG()
secret_key, cloud_key = nufhe.make_key_pair(thr, rng)
ciphertext1 = nufhe.encrypt(thr, rng, secret_key, bits1)
ciphertext2 = nufhe.encrypt(thr, rng, secret_key, bits2)
ciphertext3 = nufhe.encrypt(thr, rng, secret_key, bits3)
result = nufhe.empty_ciphertext(thr, cloud_key.params, ciphertext1.shape)
nufhe.gate_mux(thr, cloud_key, result, ciphertext1, ciphertext2, ciphertext3)

result_bits = nufhe.decrypt(thr, secret_key, result)
`

80-bit security key instead of 128

Dear all,

Thank you very much for your hard work and this wonderfull project.

I would like to know if it is possible to use a 80 bit security key instead of 128 as written in the documentation

image

Kind regards

Adrien

speed of gate bootstrapping

I tried to test the speed of nufhe gate bootstrapping by the following way but found it much slower than the result shown in nufhe's main page(0.13ms),how can I get appropriate test result?My GPU is GTX 1660Ti.

import random
import nufhe
import time

size = 32
bits1 = [random.choice([False, True]) for i in range(size)]
bits2 = [random.choice([False, True]) for i in range(size)]
reference = [not (b1 and b2) for b1, b2 in zip(bits1, bits2)]

ctx = nufhe.Context()
secret_key, cloud_key = ctx.make_key_pair()

ciphertext1 = ctx.encrypt(secret_key, bits1)
ciphertext2 = ctx.encrypt(secret_key, bits2)

vm = ctx.make_virtual_machine(cloud_key)
t1 = time.time()
result = vm.gate_nand(ciphertext1, ciphertext2)
t2 = time.time()
print(t2-t1) # around 3.0s
result_bits = ctx.decrypt(secret_key, result)

assert all(result_bits == reference)

About the possibility of operation of non-ciphertext and ciphertext

Hello.
In order to reduce execution time. I wanna compute the operation (ex. gate_nand, gate_or etc) at the stage before generating the ciphertext.
So I wanna compute 1 ciphertext and 1 encoding text before generating the ciphertext (any state before a complete ciphertext is generated).
Is this possible?

mux gate not working in program

zero= np.zeros((size,), dtype=bool)
A = fixSizeBoolList(3,size)
B = fixSizeBoolList(2,size)
theta = fixSizeBoolList(0,size)
temp=fixSizeBoolList(0,size)
Y = fixSizeBoolList(7,size)
ciX=ctx.encrypt(secret_key, A)
ciY=ctx.encrypt(secret_key, B)
print("cix:",ctx.decrypt(secret_key, ciX))
print("ciy:",ctx.decrypt(secret_key, ciY))
enc_theta=ctx.encrypt(secret_key, theta)
enc_temp=ctx.encrypt(secret_key, theta)
enc_val=ctx.encrypt(secret_key, Y)
abc=vm.gate_constant(zero)
begin = time.time()
#not_result=equal_check(ciX, ciY)
for j in range(0,size):
print("=================iteration==========",j)
ciX=ciX
print("cix:",ctx.decrypt(secret_key, ciX))
enc_theta=shift(ciX)
for i in range(size):
enc_temp[i]=ciY[j]
abc=vm.gate_copy(enc_temp)
print("enc_theta:",ctx.decrypt(secret_key, enc_theta))
'''for i in range(size):
abc.a[i]=ciY.a[j]
abc.b[i]=ciY.b[j]'''
print("Abc:",ctx.decrypt(secret_key, enc_temp))
mux_result=vm.gate_mux(enc_temp, enc_theta,ciX)
print("mux result:",ctx.decrypt(secret_key, mux_result))
ciX=mux_result
end = time.time()
print(f"Total runtime for 32-bit full adder is {float(end - begin)} second")
#assert all(result_bits == reference)

result=ctx.decrypt(secret_key, ciX)
#print("mux result:",)
print("result is",boolListToInt(result))

After tracing result is

cix: [ True True False False False False False False]
ciy: [False True False False False False False False]
=================iteration========== 0
cix: [ True True False False False False False False]
enc_theta: [False True True False False False False False]
Abc: [False False False False False False False False]
mux result: [False True True False False False False False]
=================iteration========== 1
cix: [False True True False False False False False]
enc_theta: [False False True True False False False False]
Abc: [ True True True True True True True True]
/usr/local/lib/python3.9/dist-packages/google/colab/_variable_inspector.py:27: UserWarning: device_allocation in out-of-thread context could not be cleaned up
globals().clear()
/usr/local/lib/python3.9/dist-packages/google/colab/_variable_inspector.py:27: UserWarning: device_allocation in out-of-thread context could not be cleaned up
globals().clear()
mux result: [False False True True False False False False]
=================iteration========== 2
cix: [False False True True False False False False]
enc_theta: [False False False True True False False False]
Abc: [False False False False False False False False]
mux result: [False False False True True False False False]
=================iteration========== 3
cix: [False False False True True False False False]
enc_theta: [False False False False True True False False]
Abc: [False False False False False False False False]
mux result: [False False False False True True False False]
=================iteration========== 4
cix: [False False False False True True False False]
enc_theta: [False False False False False True True False]
Abc: [False False False False False False False False]
mux result: [False False False False False True True False]
=================iteration========== 5
cix: [False False False False False True True False]
enc_theta: [False False False False False False True True]
Abc: [False False False False False False False False]
mux result: [False False False False False False True True]
=================iteration========== 6
cix: [False False False False False False True True]
enc_theta: [False False False False False False False True]
Abc: [False False False False False False False False]
mux result: [False False False False False False False True]
=================iteration========== 7
cix: [False False False False False False False True]
enc_theta: [False False False False False False False False]
Abc: [False False False False False False False False]
mux result: [False False False False False False False False]
Total runtime for 32-bit full adder is 0.6157827377319336 second
result is 0
/usr/local/lib/python3.9/dist-packages/google/colab/_variable_inspector.py:27: UserWarning: device_allocation in out-of-thread context could not be cleaned up
globals().clear()
/usr/local/lib/python3.9/dist-packages/google/colab/_variable_inspector.py:27: UserWarning: device_allocation in out-of-thread context could not be cleaned up
globals().clear()

Readme test doesn't pass

Problem

Usage example test doesn't pass

Steps to reproduce

python examples/gate_nand.py

Environment

nuFHE 0.0.2
python 3.6
ubuntu 18.04

Details

I've also printed out some variables when size = 4

bits1 = [True, True, False, True]
bits2 = [True, False, True, True]
bits1 NAND bits2 = [False, True, True, False]
decrypted_bits1 GATE_NAND decrypted_bits2 = [True, True, True, True]

nufhe not integrating with gradio

To create a public link, set share=True in launch().
['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1']
['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1']
twos completed
Traceback (most recent call last):
File "/usr/local/lib/python3.10/dist-packages/gradio/routes.py", line 488, in run_predict
output = await app.get_blocks().process_api(
File "/usr/local/lib/python3.10/dist-packages/gradio/blocks.py", line 1431, in process_api
result = await self.call_function(
File "/usr/local/lib/python3.10/dist-packages/gradio/blocks.py", line 1109, in call_function
prediction = await anyio.to_thread.run_sync(
File "/usr/local/lib/python3.10/dist-packages/anyio/to_thread.py", line 33, in run_sync
return await get_asynclib().run_sync_in_worker_thread(
File "/usr/local/lib/python3.10/dist-packages/anyio/_backends/_asyncio.py", line 877, in run_sync_in_worker_thread
return await future
File "/usr/local/lib/python3.10/dist-packages/anyio/_backends/_asyncio.py", line 807, in run
result = context.run(func, *args)
File "/usr/local/lib/python3.10/dist-packages/gradio/utils.py", line 706, in wrapper
response = f(*args, **kwargs)
File "", line 111, in greet
ciX=ctx.encrypt(secret_key, A)
File "/usr/local/lib/python3.10/dist-packages/nufhe/api_high_level.py", line 232, in encrypt
return encrypt(self.thread, self.rng, secret_key, message)
File "/usr/local/lib/python3.10/dist-packages/nufhe/api_low_level.py", line 277, in encrypt
result = empty_ciphertext(thr, key.params, message.shape)
File "/usr/local/lib/python3.10/dist-packages/nufhe/api_low_level.py", line 302, in empty_ciphertext
return LweSampleArray.empty(thr, params.in_out_params, shape)
File "/usr/local/lib/python3.10/dist-packages/nufhe/lwe.py", line 154, in empty
a = thr.array(shape + (params.size,), Torus32)
File "/usr/local/lib/python3.10/dist-packages/reikna/cluda/cuda.py", line 191, in array
return Array(
File "/usr/local/lib/python3.10/dist-packages/reikna/cluda/cuda.py", line 89, in init
gpuarray.GPUArray.init(
File "/usr/local/lib/python3.10/dist-packages/pycuda/gpuarray.py", line 268, in init
self.gpudata = self.allocator(self.size * self.dtype.itemsize)
pycuda._driver.LogicError: cuMemAlloc failed: invalid device context

GPU concatenation raises an error after computation

Hello,

We are trying to use the concatenation of two ciphertext on a GPU device, but we are encountering different issues.
We have tried different approaches :

  1. An implementation that is similar to https://github.com/nucypher/nufhe/blob/master/examples/multi_gpu.py, but the concatenation call raises an error when the Thread ends "PyCUDA ERROR: The context stack was not empty upon module cleanup."
    Run python3 code.py 2 1 to reproduce it
  2. We try the same implementation but without the Thread encapsulation. This time the concatenation seems to run fine, but the decryption then raised an error "pycuda._driver.LogicError: cuLaunchKernel failed: invalid resource handle", preventing us to use the result
    Run python3 code.py 3 1 to reproduce it
  3. We try a method similar to the one used in the pytest : https://github.com/nucypher/nufhe/blob/master/test/test_lwe.py
    It run fine when we do not output the result
    Run python3 code.py 5 to check it
  4. We try a method similar to the one of point 3, but outputting the result. Again the decryption raises an error.
    Run python3 code.py 7 1 to reproduce it
    We tried to save the result into a file, and then load it. It works but only when the loading is done on another call, if it is done just after the saving it fails:
    Run python3 code.py 77 to reproduce it (it will save the result and load it for decryption right after).
    While, python3 code.py 7 followed by python3 code.py 11 does not raise errors.

Another problem that we observe is that some tests that seems to run fine, cannot be done consecutively. For example
python3 code.py 10
python3 code.py 14
python3 code.py 15
etc ..
While
python3 code.py 2
python3 code.py 3
python3 code.py 5
python3 code.py 7
Do not raise errors.

If you have ideas of what I'm doing wrong, or an example of a code performing a concatenation on GPU, and output the result. It would be of great help.

Many thanks

Here is the source of 'code.py' I'm referring to:

from threading import Thread
from queue import Queue

import random
import nufhe
import sys

from nufhe.api_low_level import  NuFHECloudKey, NuFHESecretKey
from nufhe.lwe import LweSampleArray, concatenate

from reikna.cluda import cuda_api, ocl_api, get_api, supported_api_ids, find_devices


class MyThread:
    """
    A simple wrapper that allows one to receive the value
    returned from the thread worker transparently.
    """

    def __init__(self, target, args=()):
        self.return_queue = Queue()
        self.target = target
        self.thread = Thread(target=self._target_wrapper, args=args)

    def _target_wrapper(self, *args):
        res = self.target(*args)
        self.return_queue.put(res)

    def start(self):
        self.thread.start()
        return self

    def join(self):
        ret_val = self.return_queue.get()
        self.thread.join()
        return ret_val

def concate(device_id, cloud_key_cpu, ciphertext1_cpu, ciphertext2_cpu, get_error):
    """
    The thread concat function.
    Runs a concatenation over two provided ciphertexts and returns the serialized result.
    """

    print("Running a thread with", device_id)

    ctx = nufhe.Context(device_id=device_id)

    cloud_key = ctx.load_cloud_key(cloud_key_cpu)
    ciphertext1 = ctx.load_ciphertext(ciphertext1_cpu)
    ciphertext2 = ctx.load_ciphertext(ciphertext2_cpu)
    if get_error == 1 :
        result = nufhe.lwe.concatenate([ciphertext1, ciphertext2], axis=0, out=None)
    else :
        result = ciphertext1
    result_serialize = result.dumps()

    print("Done")
    return result_serialize


def mythread():
    api_id = "cuda"
    api = get_api(api_id)
    devices = find_devices(api)
    platform = api.get_platforms()[0]
    device = platform.get_devices()[0]
    thread = api.Thread(device)
    return thread


def lwe_concatenate(thread, key_pair_s, size=32,axis=0, out=None):
    print(thread)
    # Load secret and cloud keys form serialized couple
    secret_key_s, cloud_key_s = key_pair_s
    secret_key = NuFHESecretKey.loads(secret_key_s, thread)
    cloud_key = NuFHECloudKey.loads(cloud_key_s, thread)
    rng = nufhe.DeterministicRNG()
    # Encrypt random bit vectors
    bits1 = [random.choice([False, True]) for i in range(size//2)]
    bits2 = [random.choice([False, True]) for i in range(size//2)]
    ciphertexts = [nufhe.encrypt(thread, rng, secret_key, bits1), nufhe.encrypt(thread, rng, secret_key, bits2)]
    # Concatenate the vectors
    out = nufhe.lwe.concatenate(ciphertexts, axis=axis, out=out)
    # Decrypt
    r = nufhe.decrypt(thread, secret_key, out)
    assert r.tolist() == bits1 + bits2
    print("Done")

if __name__ == '__main__':

    bits = [False, False, True, True, True, True, False, True, False, False, False, False, False, True, False, False, True, False, True, True, False, True, True, True, True, False, True, False, False, False, False, False]
    size = len(bits)
    print(bits)

    ctx = nufhe.Context()
    secret_key, cloud_key = ctx.make_key_pair()
    ciphertext = ctx.encrypt(secret_key, bits)

    # Serialize the cloud key to pass it to child threads.
    ck = cloud_key.dumps()

    # Split ciphertexts into two parts each and serialize them.
    ct_part1 = ciphertext[:size//2].dumps()
    ct_part2 = ciphertext[size//2:].dumps()

    # Start threads each applying concatenation of the ciphertext.
    devices = nufhe.find_devices()

    test = 2
    get_error = 0
    if len(sys.argv) > 1 :
        test = int(sys.argv[1])
    if len(sys.argv) > 2 :
       get_error = int(sys.argv[2])

    # The low level thread is started at the beginning
    # As starting two threads on the same device raises an error.
    # Exception ignored in: <bound method Thread.__del__ of <reikna.cluda.cuda.Thread object at 0x7fdf7beddd68>>
    # Traceback (most recent call last):
    # File "/usr/local/lib/python3.6/dist-packages/reikna/cluda/cuda.py", line 246, in __del__
    # File "/usr/local/lib/python3.6/dist-packages/reikna/cluda/api.py", line 566, in release
    # File "/usr/local/lib/python3.6/dist-packages/reikna/cluda/cuda.py", line 241, in _release_specific
    # pycuda._driver.LogicError: context::pop failed: invalid device context - cannot pop non-current context

    if (test%5 ==0 or test%7==0):
        thr = mythread()
 
    if (test%2 == 0):
            print("test = 0[2]")
            # Try the concatenation inside a Thread
            # Similar implementation as in https://github.com/nucypher/nufhe/blob/master/examples/multi_gpu.py
            # But here the concatenation line induces an error "PyCUDA ERROR: The context stack was not empty upon module cleanup." that is raised when the Thread ends.
            t = MyThread(target=concate, args=(devices[0], ck, ct_part1, ct_part2, get_error)).start()
            print("Thread started")
            result = t.join()
            print("join done")
            result = ctx.load_ciphertext(result)
            print("result loaded")
            r = ctx.decrypt(secret_key, result)
            print("result decrypted")
            #assert r.tolist() == bits

    if (test%3==0):
            print("test = 0[3]")
            # Try the concatenation directly, the concatenation does not raise an error
            # But the decryption raises an error "pycuda._driver.LogicError: cuLaunchKernel failed: invalid resource handle"
            result = concate(devices[0], ck, ct_part1, ct_part2, 1)
            print("concatenation done")
            result = ctx.load_ciphertext(result)
            print("result loaded")
            if (get_error == 1):
                r = ctx.decrypt(secret_key, result)
                print("result decrypted")
                assert r.tolist() == bits

    if (test%5==0):
            print("test = 0[5]")
            # The concatenation is done without input and ouput.
            # Using a thread and a method similar to the one used in the pytest
            # https://github.com/nucypher/nufhe/blob/master/test/test_lwe.py
            lwe_concatenate(thr, (secret_key.dumps(), cloud_key.dumps()), size, 0, None)

    if (test%7==0):
            print("test = 0[7]")
            # Same method as above but with input and output
            # Similarly as in test=0[3], the decryption raises an error
            # But we can write the encrypted result into a file and then read it
            ciphertext1 = LweSampleArray.loads(ct_part1, thr)
            ciphertext2 = LweSampleArray.loads(ct_part2, thr)
            ciphertexts = [ciphertext1, ciphertext2]
            result = nufhe.lwe.concatenate(ciphertexts, axis=0, out=None)
            print("concatenation done")
            if (get_error == 1):
                r = ctx.decrypt(secret_key, result)
                print("result decrypted")
                assert r.tolist() == bits
            with open("result","wb") as f :
                result.dump(file_obj=f)
                f.close()
                secret_key.dump(file_obj=open("secret_key","wb"))
                print("Result and Secret_Key saved into files")

    if (test%11==0):
            print("test = 0[11]")
            # Read the saved file. 
            # The decryption raises an error if it is realised just after writing the file.
            # pycuda._driver.LogicError: cuLaunchKernel failed: invalid resource handle
            with open("result","rb") as f :
                secret_key_loaded = ctx.load_secret_key(open("secret_key","rb"))
                result = ctx.load_ciphertext(f)
                r = ctx.decrypt(secret_key_loaded, result)
                print(r.tolist())
                f.close()   
                assert r.tolist() == bits

    # The thread is clear at the end
    if (test%5 ==0 or test%7==0):
        nufhe.clear_computation_cache(thr)

    print("The end")

Precision in binary gates, how to use binary gates in sequence

Dear all,

Thank you for all of you work and for this project .

I am trying to use binary gates in a sequence (approx ~70) with the best performance. But I see that there are some differences when decrypted compared to the operations done on the clear ciphertext. I have a median similarity of 70% (i.e. 70% of the decrypted cipher text is the same as the clear file).

So firstly, I would like to know if my use of the binary gates was wrong ?

Also, I would like to know if there has been some verifications/statistics about noise propagation when boostrapping ? From what I understood from the code, after each gate there is bootstrapping.

I copy pasted my code down there if you want to have a look, this one gives ~52% accuracy

Thank you !

def sat_clause(x_0, x_1, x_2, x_3, x_4, x_5, x_6, x_7, x_8, thr, perf_params, cloud_key):
	params = cloud_key.params
      
    # I have 23 terms with OR gates, so each of this term is initialized with an empty ciphertext

	_0 = empty_ciphertext(thr, params, x_0.shape)
	_1 = empty_ciphertext(thr, params, x_0.shape)
	_2 = empty_ciphertext(thr, params, x_0.shape)
	_3 = empty_ciphertext(thr, params, x_0.shape)
	_4 = empty_ciphertext(thr, params, x_0.shape)
	_5 = empty_ciphertext(thr, params, x_0.shape)
	_6 = empty_ciphertext(thr, params, x_0.shape)
	_7 = empty_ciphertext(thr, params, x_0.shape)
	_8 = empty_ciphertext(thr, params, x_0.shape)
	_9 = empty_ciphertext(thr, params, x_0.shape)
	_10 = empty_ciphertext(thr, params, x_0.shape)
	_11 = empty_ciphertext(thr, params, x_0.shape)
	_12 = empty_ciphertext(thr, params, x_0.shape)
	_13 = empty_ciphertext(thr, params, x_0.shape)
	_14 = empty_ciphertext(thr, params, x_0.shape)
	_15 = empty_ciphertext(thr, params, x_0.shape)
	_16 = empty_ciphertext(thr, params, x_0.shape)
	_17 = empty_ciphertext(thr, params, x_0.shape)
	_18 = empty_ciphertext(thr, params, x_0.shape)
	_19 = empty_ciphertext(thr, params, x_0.shape)
	_20 = empty_ciphertext(thr, params, x_0.shape)
	_21 = empty_ciphertext(thr, params, x_0.shape)
	_22 = empty_ciphertext(thr, params, x_0.shape)

        # each term will be save in their respective ciphertext (term 0 is saved in ciphertext 0_ , ... )

	# x_5|x_8|~x_7
	gate_or(thr, cloud_key, _0, x_5, x_8, perf_params)
	gate_oryn(thr, cloud_key, _0, _0.copy(), x_7, perf_params)

	# x_5|~x_1|~x_7
	gate_oryn(thr, cloud_key, _1, x_5, x_1, perf_params)
	gate_oryn(thr, cloud_key, _1, _1.copy(), x_7, perf_params) # doing (x_5 | ~x_1) | ~x_7

	# x_5|~x_3|~x_7
	gate_oryn(thr, cloud_key, _2, x_5, x_3, perf_params)
	gate_oryn(thr, cloud_key, _2, _2.copy(), x_7, perf_params)

	# x_5|~x_4|~x_7
	gate_oryn(thr, cloud_key, _3, x_5, x_4, perf_params)
	gate_oryn(thr, cloud_key, _3, _3.copy(), x_7, perf_params)

	# x_5|~x_6|~x_7
	gate_oryn(thr, cloud_key, _4, x_5, x_6, perf_params)
	gate_oryn(thr, cloud_key, _4, _4.copy(), x_7, perf_params)

	# x_0|x_2|x_6|~x_4
	gate_or(thr, cloud_key, _5, x_0, x_2, perf_params)
	gate_or(thr, cloud_key, _5, _5.copy(), x_6, perf_params)
	gate_oryn(thr, cloud_key, _5, _5.copy(), x_4, perf_params)

	# x_1|x_2|x_7|~x_4
	gate_or(thr, cloud_key, _6, x_1, x_2, perf_params)
	gate_or(thr, cloud_key, _6, _6.copy(), x_7, perf_params)
	gate_oryn(thr, cloud_key, _6, _6.copy(), x_4, perf_params)

	# x_1|x_4|x_8|~x_6
	gate_or(thr, cloud_key, _7, x_1, x_4, perf_params)
	gate_or(thr, cloud_key, _7, _7.copy(), x_8, perf_params)
	gate_oryn(thr, cloud_key, _7, _7.copy(), x_6, perf_params)

	# x_2|x_3|x_7|~x_4
	gate_or(thr, cloud_key, _8, x_2, x_3, perf_params)
	gate_or(thr, cloud_key, _8, _8.copy(), x_7, perf_params)
	gate_oryn(thr, cloud_key, _8, _8.copy(), x_4, perf_params)

	# x_3|x_7|x_8|~x_5
	gate_or(thr, cloud_key, _9, x_3, x_7, perf_params)
	gate_or(thr, cloud_key, _9, _9.copy(), x_8, perf_params)
	gate_oryn(thr, cloud_key, _9, _9.copy(), x_5, perf_params)

	# x_1|x_2|~x_0|~x_4
	gate_or(thr, cloud_key, _10, x_1, x_2, perf_params)
	gate_oryn(thr, cloud_key, _10, _10.copy(), x_0, perf_params)
	gate_oryn(thr, cloud_key, _10, _10.copy(), x_4, perf_params)

	# x_2|x_7|~x_4|~x_8
	gate_or(thr, cloud_key, _11, x_2, x_7, perf_params)
	gate_oryn(thr, cloud_key, _11, _11.copy(), x_4, perf_params)
	gate_oryn(thr, cloud_key, _11, _11.copy(), x_8, perf_params)

	# x_4|x_7|~x_5|~x_6
	gate_or(thr, cloud_key, _12, x_4, x_7, perf_params)
	gate_oryn(thr, cloud_key, _12, _12.copy(), x_5, perf_params)
	gate_oryn(thr, cloud_key, _12, _12.copy(), x_6, perf_params)

	# x_6|x_7|~x_4|~x_5
	gate_or(thr, cloud_key, _13, x_6, x_7, perf_params)
	gate_oryn(thr, cloud_key, _13, _13.copy(), x_4, perf_params)
	gate_oryn(thr, cloud_key, _13, _13.copy(), x_5, perf_params)

	# x_1|x_3|x_5|x_8|~x_4
	gate_or(thr, cloud_key, _14, x_1, x_3, perf_params)
	gate_or(thr, cloud_key, _14, _14.copy(), x_5, perf_params)
	gate_or(thr, cloud_key, _14, _14.copy(), x_8, perf_params)
	gate_oryn(thr, cloud_key, _14, _14.copy(), x_4, perf_params)

	# x_6|~x_0|~x_4|~x_7
	gate_oryn(thr, cloud_key, _15, x_6, x_0, perf_params)
	gate_oryn(thr, cloud_key, _15, _15.copy(), x_4, perf_params)
	gate_oryn(thr, cloud_key, _15, _15.copy(), x_7, perf_params)

	# x_6|~x_1|~x_4|~x_8
	gate_oryn(thr, cloud_key, _16, x_6, x_1, perf_params)
	gate_oryn(thr, cloud_key, _16, _16.copy(), x_4, perf_params)
	gate_oryn(thr, cloud_key, _16, _16.copy(), x_8, perf_params)

	# x_0|x_4|x_5|~x_1|~x_6
	gate_or(thr, cloud_key, _17, x_0, x_4, perf_params)
	gate_or(thr, cloud_key, _17, _17.copy(), x_5, perf_params)
	gate_oryn(thr, cloud_key, _17, _17.copy(), x_1, perf_params)
	gate_oryn(thr, cloud_key, _17, _17.copy(), x_6, perf_params)

	# ~x_0|~x_1|~x_6|~x_8
	n_x_0 = empty_ciphertext(thr, params, x_0.shape)
	gate_not(thr, cloud_key, n_x_0, x_0, perf_params)
	gate_oryn(thr, cloud_key, _18, x_0, x_1, perf_params)
	gate_oryn(thr, cloud_key, _18, _18.copy(), x_6, perf_params)
	gate_oryn(thr, cloud_key, _18, _18.copy(), x_8, perf_params)

	# x_1|x_7|~x_0|~x_5|~x_6
	gate_or(thr, cloud_key, _19, x_1, x_7, perf_params)
	gate_oryn(thr, cloud_key, _19, _19.copy(), x_0, perf_params)
	gate_oryn(thr, cloud_key, _19, _19.copy(), x_5, perf_params)
	gate_oryn(thr, cloud_key, _19, _19.copy(), x_6, perf_params)

	# x_1|x_3|x_6|x_8|~x_2|~x_7
	gate_or(thr, cloud_key, _20, x_1, x_3, perf_params)
	gate_or(thr, cloud_key, _20, _20.copy(), x_6, perf_params)
	gate_or(thr, cloud_key, _20, _20.copy(), x_8, perf_params)
	gate_oryn(thr, cloud_key, _20, _20.copy(), x_2, perf_params)
	gate_oryn(thr, cloud_key, _20, _20.copy(), x_7, perf_params)

	# x_4|~x_0|~x_1|~x_6|~x_7
	gate_oryn(thr, cloud_key, _21, x_4, x_0, perf_params)
	gate_oryn(thr, cloud_key, _21, _21.copy(), x_1, perf_params)
	gate_oryn(thr, cloud_key, _21, _21.copy(), x_6, perf_params)
	gate_oryn(thr, cloud_key, _21, _21.copy(), x_7, perf_params)

	# x_7|~x_1|~x_5|~x_6|~x_8
	gate_oryn(thr, cloud_key, _22, x_7, x_1, perf_params)
	gate_oryn(thr, cloud_key, _22, _22.copy(), x_5, perf_params)
	gate_oryn(thr, cloud_key, _22, _22.copy(), x_6, perf_params)
	gate_oryn(thr, cloud_key, _22, _22.copy(), x_8, perf_params)

	answer = empty_ciphertext(thr, params, x_0.shape)

        # apply AND gate on each term

	gate_and(thr, cloud_key, answer, _0, _1, perf_params)
	gate_and(thr, cloud_key, answer, answer.copy(), _2, perf_params)
	gate_and(thr, cloud_key, answer, answer.copy(), _3, perf_params)
	gate_and(thr, cloud_key, answer, answer.copy(), _4, perf_params)
	gate_and(thr, cloud_key, answer, answer.copy(), _5, perf_params)
	gate_and(thr, cloud_key, answer, answer.copy(), _6, perf_params)
	gate_and(thr, cloud_key, answer, answer.copy(), _7, perf_params)
	gate_and(thr, cloud_key, answer, answer.copy(), _8, perf_params)
	gate_and(thr, cloud_key, answer, answer.copy(), _9, perf_params)
	gate_and(thr, cloud_key, answer, answer.copy(), _10, perf_params)
	gate_and(thr, cloud_key, answer, answer.copy(), _11, perf_params)
	gate_and(thr, cloud_key, answer, answer.copy(), _12, perf_params)
	gate_and(thr, cloud_key, answer, answer.copy(), _13, perf_params)
	gate_and(thr, cloud_key, answer, answer.copy(), _14, perf_params)
	gate_and(thr, cloud_key, answer, answer.copy(), _15, perf_params)
	gate_and(thr, cloud_key, answer, answer.copy(), _16, perf_params)
	gate_and(thr, cloud_key, answer, answer.copy(), _17, perf_params)
	gate_and(thr, cloud_key, answer, answer.copy(), _18, perf_params)
	gate_and(thr, cloud_key, answer, answer.copy(), _19, perf_params)
	gate_and(thr, cloud_key, answer, answer.copy(), _20, perf_params)
	gate_and(thr, cloud_key, answer, answer.copy(), _21, perf_params)
	gate_and(thr, cloud_key, answer, answer.copy(), _22, perf_params)

	return answer

The function that does the same equation but on the clear array:

def check_answer(x_0, x_1, x_2, x_3, x_4, x_5, x_6, x_7, x_8):
	answer = (x_5 | x_8 | ~x_7) & (x_5 | ~x_1 | ~x_7) & (x_5 | ~x_3 | ~x_7) & (x_5 | ~x_4 | ~x_7) & (x_5 | ~x_6 | ~x_7) & (x_0 | x_2 | x_6 | ~x_4) & (x_1 | x_2 | x_7 | ~x_4) & (x_1 | x_4 | x_8 | ~x_6) & (x_2 | x_3 | x_7 | ~x_4) & (x_3 | x_7 | x_8 | ~x_5) & (x_1 | x_2 | ~x_0 | ~x_4) & (x_2 | x_7 | ~x_4 | ~x_8) & (x_4 | x_7 | ~x_5 | ~x_6) & (x_6 | x_7 | ~x_4 | ~x_5) & (x_1 | x_3 | x_5 | x_8 | ~x_4) & (x_6 | ~x_0 | ~x_4 | ~x_7) & (x_6 | ~x_1 | ~x_4 | ~x_8) & (x_0 | x_4 | x_5 | ~x_1 | ~x_6) & (~x_0 | ~x_1 | ~x_6 | ~x_8) & (x_1 | x_7 | ~x_0 | ~x_5 | ~x_6) & (x_1 | x_3 | x_6 | x_8 | ~x_2 | ~x_7) & (x_4 | ~x_0 | ~x_1 | ~x_6 | ~x_7) & (x_7 | ~x_1 | ~x_5 | ~x_6 | ~x_8)

	return answer

Can we decomp tlwe in Galios Field?

Assume that before calculating CMUX —— C*(d1-d0) + d0,we have transferred C,d0,d1 to Galios numbers by ntt. But when it comes to CMUX, we have to decomp tlwesample (d1-d0), which I thought can only be done in int32 field.

So, can we do the decomposition in ntt-transfered field? And what's the actual realization in nufhe for this question?

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.