Skip to content

Commit c9b40b5

Browse files
authored
Merge pull request #8 from Desilo/chulsoon/merge/upstream/main
Upstream 최신 버전 당겨오기
2 parents c11cca4 + eb905d6 commit c9b40b5

16 files changed

+890
-1515
lines changed

.gitattributes

-1
This file was deleted.

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,5 @@ seal.egg-info
4242
*.pyd
4343
*.pyc
4444
temp
45-
env
45+
.idea
46+
*.bin

.gitmodules

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
[submodule "SEAL"]
22
path = SEAL
33
url = https://github.com/microsoft/SEAL.git
4+
branch = main
45
[submodule "pybind11"]
56
path = pybind11
67
url = https://github.com/pybind/pybind11.git
8+
branch = stable

README.md

+47-45
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ This is a python binding for the Microsoft SEAL library.
1919

2020

2121
## Build
22-
* #### Linux
23-
Clang++ (>= 5.0) or GNU G++ (>= 6.0), CMake (>= 3.12)
22+
23+
* ### Linux
24+
25+
Recommend: Clang++ (>= 10.0) or GNU G++ (>= 9.4), CMake (>= 3.16)
2426

2527
```shell
2628
# Optional
@@ -30,42 +32,60 @@ This is a python binding for the Microsoft SEAL library.
3032
git clone https://github.com/Huelse/SEAL-Python.git
3133
cd SEAL-Python
3234

33-
# Numpy is essential
34-
pip3 install -r requirements.txt
35+
# Install dependencies
36+
pip3 install numpy pybind11
3537

3638
# Init the SEAL and pybind11
3739
git submodule update --init --recursive
38-
# Get the newest repositories (unnecessary)
40+
# Get the newest repositories (dev only)
3941
# git submodule update --remote
4042

4143
# Build the SEAL lib
4244
cd SEAL
43-
cmake -S . -B build -DSEAL_USE_MSGSL=OFF -DSEAL_USE_ZLIB=OFF -DSEAL_USE_ZSTD=OFF
45+
cmake -S . -B build -DSEAL_USE_MSGSL=OFF -DSEAL_USE_ZLIB=OFF
4446
cmake --build build
4547
cd ..
4648

4749
# Run the setup.py
4850
python3 setup.py build_ext -i
51+
52+
# Test
53+
cp seal.*.so examples
54+
cd examples
55+
python3 4_bgv_basics.py
4956
```
5057

51-
* #### Windows
58+
Build examples (after `cmake -S . -B`): `-DSEAL_BUILD_EXAMPLES=ON`
59+
60+
Zstandard compression off: `-DSEAL_USE_ZSTD=OFF`
5261

53-
Visual Studio 2019 or newer is required. And use the **x64 Native Tools Command Prompt for Visual Studio 2019** command prompt to configure and build the Microsoft SEAL library. It's usually can be found in your Start Menu.
62+
[More cmake options](https://github.com/microsoft/SEAL#basic-cmake-options)
63+
64+
65+
* ### Windows
66+
67+
Visual Studio 2019 or newer is required. x64 support only! And use the **x64 Native Tools Command Prompt for VS** command prompt to configure and build the Microsoft SEAL library. It's usually can be found in your Start Menu.
5468

5569
```shell
56-
# Same as above
57-
# Build the SEAL library
58-
cmake -S . -B build -G Ninja -DSEAL_USE_MSGSL=OFF -DSEAL_USE_ZLIB=OFF -DSEAL_USE_ZSTD=OFF
70+
# Run in "x64 Native Tools Command Prompt for VS" command prompt
71+
cmake -S . -B build -G Ninja -DSEAL_USE_MSGSL=OFF -DSEAL_USE_ZLIB=OFF
5972
cmake --build build
6073

61-
# Run the setup.py
74+
# Build
75+
pip install numpy pybind11
6276
python setup.py build_ext -i
77+
78+
# Test
79+
cp seal.*.pyd examples
80+
cd examples
81+
python 4_bgv_basics.py
6382
```
6483

65-
Generally, the Ninja generator is better than the "Visual Studio 16 2019" generator, and there is more information in the Microsoft SEAL official [illustrate](https://github.com/microsoft/SEAL#building-microsoft-seal-manually).
84+
Microsoft SEAL official [docs](https://github.com/microsoft/SEAL#building-microsoft-seal-manually).
85+
6686

87+
* ### Docker
6788

68-
* #### Docker
6989
requires: [Docker](https://www.docker.com/)
7090

7191
To build source code into a docker image (from this directory):
@@ -78,51 +98,28 @@ This is a python binding for the Microsoft SEAL library.
7898
docker run -it huelse/seal
7999
```
80100

101+
102+
81103
## Note
82104

83-
* #### Serialize
105+
* ### Serialize
84106

85-
In most situations, you can use the SEAL's native serialize API to save the data, here is an example:
107+
See more in `examples/7_serialization.py`, here is a simple example:
86108

87109
```python
88110
cipher.save('cipher')
89-
90111
load_cipher = Ciphertext()
91112
load_cipher.load(context, 'cipher') # work if the context is valid.
92113
```
93114

94-
Support type: `Encryptionparams, Ciphertext, Plaintext, SecretKey, Publickey, Relinkeys, Galoiskeys`
115+
Supported classes: `EncryptionParameters, Ciphertext, Plaintext, SecretKey, PublicKey, RelinKeys, GaloisKeys`
95116

96-
Particularly, if you want to use the pickle to serialize your data, you need to do these things like below:
97117

98-
```shell
99-
# 1. Modify the serializable object's header file in SEAL and switch the wrapper.
100-
python helper.py
118+
* ### Other
101119

102-
# 2. Rebuild the SEAL lib like above
103-
cmake --build build
120+
There are a lot of changes in the latest SEAL lib, we try to make the API in python can be used easier, but it may remain some problems unknown, if any problems or bugs, report [issues](https://github.com/Huelse/SEAL-Python/issues).
104121

105-
# 3. Run the setup.py
106-
python setup.py build_ext -i
107-
```
108-
109-
Then, you can pickle the data object like this:
110-
111-
```python
112-
import pickle
113-
114-
cipher.set_parms(parms) # necessary
115-
cipher_dump = pickle.dumps(cipher)
116-
cipher_load = pickle.loads(cipher_dump)
117-
```
118-
119-
Generally, we don't use compression library.
120-
121-
* #### Other
122-
123-
There are a lot of changes in the latest SEAL lib, we try to make the API in python can be used easier, it may remain some problems we unknown, if any problems(bugs), [Issue](https://github.com/Huelse/SEAL-Python/issues) please.
124-
125-
Email: [[email protected]](mailto:[email protected]?subject=Github-SEAL-Python-Issues)
122+
Email: [[email protected]](mailto:[email protected]?subject=Github-SEAL-Python-Issues)
126123

127124

128125

@@ -148,9 +145,14 @@ This is a python binding for the Microsoft SEAL library.
148145

149146
The `.so` or `.pyd` file must be in the current directory, or you have `install` it already.
150147

148+
5. Windows Error LNK2001, RuntimeLibrary and MT_StaticRelease mismatch
149+
150+
Only `x64` is supported, Choose `x64 Native Tools Command Prompt for VS`.
151+
151152

152153

153154
## Contributing
155+
154156
* Professor: [Dr. Chen](https://zhigang-chen.github.io/)
155157

156158
* [Contributors](https://github.com/Huelse/SEAL-Python/graphs/contributors)

SEAL

Submodule SEAL updated 128 files

examples/4_bgv_basics.py

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
from seal import *
2+
import numpy as np
3+
4+
def print_vector(vector):
5+
print('[ ', end='')
6+
for i in range(0, 8):
7+
print(vector[i], end=', ')
8+
print('... ]')
9+
10+
11+
def example_bgv_basics():
12+
parms = EncryptionParameters (scheme_type.bgv)
13+
poly_modulus_degree = 8192
14+
parms.set_poly_modulus_degree(poly_modulus_degree)
15+
parms.set_coeff_modulus(CoeffModulus.BFVDefault(poly_modulus_degree))
16+
parms.set_plain_modulus(PlainModulus.Batching(poly_modulus_degree, 20))
17+
context = SEALContext(parms)
18+
19+
keygen = KeyGenerator(context)
20+
secret_key = keygen.secret_key()
21+
public_key = keygen.create_public_key()
22+
relin_keys = keygen.create_relin_keys()
23+
24+
encryptor = Encryptor(context, public_key)
25+
evaluator = Evaluator(context)
26+
decryptor = Decryptor(context, secret_key)
27+
28+
batch_encoder = BatchEncoder(context)
29+
slot_count = batch_encoder.slot_count()
30+
row_size = slot_count / 2
31+
print(f'Plaintext matrix row size: {row_size}')
32+
33+
pod_matrix = [0] * slot_count
34+
pod_matrix[0] = 1
35+
pod_matrix[1] = 2
36+
pod_matrix[2] = 3
37+
pod_matrix[3] = 4
38+
39+
x_plain = batch_encoder.encode(pod_matrix)
40+
41+
x_encrypted = encryptor.encrypt(x_plain)
42+
print(f'noise budget in freshly encrypted x: {decryptor.invariant_noise_budget(x_encrypted)}')
43+
print('-'*50)
44+
45+
x_squared = evaluator.square(x_encrypted)
46+
print(f'size of x_squared: {x_squared.size()}')
47+
evaluator.relinearize_inplace(x_squared, relin_keys)
48+
print(f'size of x_squared (after relinearization): {x_squared.size()}')
49+
print(f'noise budget in x_squared: {decryptor.invariant_noise_budget(x_squared)} bits')
50+
decrypted_result = decryptor.decrypt(x_squared)
51+
pod_result = batch_encoder.decode(decrypted_result)
52+
print_vector(pod_result)
53+
print('-'*50)
54+
55+
x_4th = evaluator.square(x_squared)
56+
print(f'size of x_4th: {x_4th.size()}')
57+
evaluator.relinearize_inplace(x_4th, relin_keys)
58+
print(f'size of x_4th (after relinearization): { x_4th.size()}')
59+
print(f'noise budget in x_4th: {decryptor.invariant_noise_budget(x_4th)} bits')
60+
decrypted_result = decryptor.decrypt(x_4th)
61+
pod_result = batch_encoder.decode(decrypted_result)
62+
print_vector(pod_result)
63+
print('-'*50)
64+
65+
x_8th = evaluator.square(x_4th)
66+
print(f'size of x_8th: {x_8th.size()}')
67+
evaluator.relinearize_inplace(x_8th, relin_keys)
68+
print(f'size of x_8th (after relinearization): { x_8th.size()}')
69+
print(f'noise budget in x_8th: {decryptor.invariant_noise_budget(x_8th)} bits')
70+
decrypted_result = decryptor.decrypt(x_8th)
71+
pod_result = batch_encoder.decode(decrypted_result)
72+
print_vector(pod_result)
73+
print('run out of noise budget')
74+
print('-'*100)
75+
76+
x_encrypted = encryptor.encrypt(x_plain)
77+
print(f'noise budget in freshly encrypted x: {decryptor.invariant_noise_budget(x_encrypted)}')
78+
print('-'*50)
79+
80+
x_squared = evaluator.square(x_encrypted)
81+
print(f'size of x_squared: {x_squared.size()}')
82+
evaluator.relinearize_inplace(x_squared, relin_keys)
83+
evaluator.mod_switch_to_next_inplace(x_squared)
84+
print(f'noise budget in x_squared (with modulus switching): {decryptor.invariant_noise_budget(x_squared)} bits')
85+
decrypted_result = decryptor.decrypt(x_squared)
86+
pod_result = batch_encoder.decode(decrypted_result)
87+
print_vector(pod_result)
88+
print('-'*50)
89+
90+
x_4th = evaluator.square(x_squared)
91+
print(f'size of x_4th: {x_4th.size()}')
92+
evaluator.relinearize_inplace(x_4th, relin_keys)
93+
evaluator.mod_switch_to_next_inplace(x_4th)
94+
print(f'size of x_4th (after relinearization): { x_4th.size()}')
95+
print(f'noise budget in x_4th (with modulus switching): {decryptor.invariant_noise_budget(x_4th)} bits')
96+
decrypted_result = decryptor.decrypt(x_4th)
97+
pod_result = batch_encoder.decode(decrypted_result)
98+
print_vector(pod_result)
99+
print('-'*50)
100+
101+
x_8th = evaluator.square(x_4th)
102+
print(f'size of x_8th: {x_8th.size()}')
103+
evaluator.relinearize_inplace(x_8th, relin_keys)
104+
evaluator.mod_switch_to_next_inplace(x_8th)
105+
print(f'size of x_8th (after relinearization): { x_8th.size()}')
106+
print(f'noise budget in x_8th (with modulus switching): {decryptor.invariant_noise_budget(x_8th)} bits')
107+
decrypted_result = decryptor.decrypt(x_8th)
108+
pod_result = batch_encoder.decode(decrypted_result)
109+
print_vector(pod_result)
110+
111+
112+
if __name__ == "__main__":
113+
example_bgv_basics()

examples/7_serialization.py

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
from seal import *
2+
import pickle
3+
import time
4+
5+
6+
def get_seal():
7+
parms = EncryptionParameters(scheme_type.ckks)
8+
poly_modulus_degree = 8192
9+
parms.set_poly_modulus_degree(poly_modulus_degree)
10+
parms.set_coeff_modulus(CoeffModulus.Create(poly_modulus_degree, [60, 40, 40, 60]))
11+
scale = 2.0 ** 40
12+
13+
context = SEALContext(parms)
14+
ckks_encoder = CKKSEncoder(context)
15+
slot_count = ckks_encoder.slot_count()
16+
17+
keygen = KeyGenerator(context)
18+
public_key = keygen.create_public_key()
19+
secret_key = keygen.secret_key()
20+
21+
encryptor = Encryptor(context, public_key)
22+
# evaluator = Evaluator(context)
23+
decryptor = Decryptor(context, secret_key)
24+
25+
data = [3.1415926] * slot_count
26+
plain = ckks_encoder.encode(data, scale)
27+
cipher = encryptor.encrypt(plain)
28+
29+
return cipher, context, ckks_encoder, decryptor
30+
31+
32+
def serialization_example():
33+
print('serialization example')
34+
print('-' * 70)
35+
cipher2, context2, ckks_encoder2, decryptor2 = get_seal()
36+
cipher2.save('cipher2.bin')
37+
print('save cipher2 data success')
38+
39+
time.sleep(.5)
40+
41+
cipher3 = Ciphertext()
42+
cipher3.load(context2, 'cipher2.bin')
43+
print('load cipher2 data success')
44+
plain3 = decryptor2.decrypt(cipher3)
45+
data3 = ckks_encoder2.decode(plain3)
46+
print(data3)
47+
print('-' * 70)
48+
49+
50+
def pickle_example():
51+
print('pickle example')
52+
print('-' * 70)
53+
cipher1, context1, ckks_encoder1, decryptor1 = get_seal()
54+
with open('cipher1.bin', 'wb') as f:
55+
pickle.dump(cipher1.to_string(), f)
56+
print('write cipher1 data success')
57+
58+
time.sleep(.5)
59+
60+
with open('cipher1.bin', 'rb') as f:
61+
temp = pickle.load(f)
62+
cipher2 = context1.from_cipher_str(temp)
63+
plain2 = decryptor1.decrypt(cipher2)
64+
data = ckks_encoder1.decode(plain2)
65+
print('read cipher1 data success')
66+
print(data)
67+
68+
print('-' * 70)
69+
70+
71+
if __name__ == "__main__":
72+
serialization_example()
73+
pickle_example()

0 commit comments

Comments
 (0)