Skip to content

Commit 0913fa9

Browse files
committed
Version 1.1.0
1 parent 954786c commit 0913fa9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+8752
-7611
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
*.dat
77
**/config.h
88
**/adapter_output_data
9-
# device/lib/kri_data/*
109
# adpater/thirdparty
1110
# **/data/
1211

CHANGES.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# List of Changes
2+
3+
## Version 1.1.0
4+
5+
### New Features
6+
7+
- Added explicit support for other parameter sets (for degree = 1024, 2048, 8192, and 16384, as well as an alternate prime set for degree = 4096)
8+
- Adapter can now just be build once for any of the supported degrees, and degree can be specied as a command line argument
9+
- Added scripts to [`device/scripts`](device/scripts) to automatically test configurations of the library
10+
11+
### Bug Fixes
12+
13+
- Added an extra index map setting to fix memory bug encountered in certain edge-case configurations of the library
14+
- Fixed error with generated header files for special primes > 30 bits
15+
- Fixed error with IFFT header file generation
16+
- Fixed error with NTT tests
17+
18+
### Minor API Changes
19+
20+
- Scale is now automatically set for default parameters
21+
- `set_custom_parms_ckks` now includes a parameter to set the scale
22+
23+
### Other
24+
25+
- Corrected minor typos in code comments
26+
- Added description comments for some functions
27+
- Added `const` and explicit type casting as good practice
28+
- Added `memset` after array creation instances for when `malloc` is not used
29+
- Removed support for degree < 1024, which was just for initial debugging
30+
- Fixed path issue when building for an Azure Sphere A7 target
31+
- Updated adapter [`CMakeLists.txt`](adapter/CMakeLists.txt) to use Microsoft SEAL 3.7.2
32+
- Other minor code changes
33+
34+
## Version 1.0.0
35+
36+
- Initial commit

README.md

Lines changed: 137 additions & 111 deletions
Large diffs are not rendered by default.

SECURITY.md

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
## Correct Use of SEAL-Embedded
22

33
SEAL-Embedded supports encryption with either a secret key (symmetric) or a public key (asymmetric).
4-
A secret key is stored in device flash RAM, and is vulnerable against attacker with physiscal access to the deivce.
5-
Once a secret key is leaked, all previous data encrypted with the secret key or a public key generated by the secret key are at risk.
6-
Deployments of SEAL-Embedded should avoid using symmetric encryption unless has been reviewed by security and cryptography experts.
4+
When symmetric encryption is used, the secret key must be stored in device memory and is thus vulnerable to attackers with access to the device.
5+
Once the secret key is leaked, all previous data encrypted with the secret key (or a public key associated with the secret key) is at risk.
6+
Therefore, deployments of SEAL-Embedded should avoid using symmetric encryption, unless the deployment has been reviewed by security and cryptography experts.
77

88
## Correct Use of Microsoft SEAL
99

10-
Homomorphic encryption schemes have various and often unexpected security models that may be surprising even to cryptography experts.
11-
In particular, decryptions of Microsoft SEAL ciphertexts should be treated as private information only available to the secret key owner, as sharing decryptions of ciphertexts may in some cases lead to leaking the secret key.
12-
If it is absolutely necessary to share information about the decryption of a ciphertext, for example when building a protocol of some kind, the number of bits shared should be kept to a minimum, and secret keys should be rotated regularly.
13-
Commercial applications of Microsoft SEAL should be carefully reviewed by cryptography experts who are familiar with homomorphic encryption security models.
10+
Please see the [SECURITY.md document for Microsoft SEAL](https://github.com/microsoft/SEAL/blob/main/SECURITY.md#correct-use-of-microsoft-seal).
1411

1512
## Security
1613

@@ -24,7 +21,7 @@ If you believe you have found a security vulnerability in any Microsoft-owned re
2421

2522
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
2623

27-
If you prefer to submit without logging in, send email to [[email protected]](mailto:[email protected]). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
24+
If you prefer to submit without logging in, send an email to [[email protected]](mailto:[email protected]). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
2825

2926
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
3027

@@ -50,4 +47,4 @@ We prefer all communications to be in English.
5047

5148
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
5249

53-
<!-- END MICROSOFT SECURITY.MD BLOCK -->
50+
<!-- END MICROSOFT SECURITY.MD BLOCK -->

adapter/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
3939
endif()
4040
endif()
4141

42-
project(SEAL_Embedded_Adapter VERSION 1.0.0 LANGUAGES CXX)
42+
project(SEAL_Embedded_Adapter VERSION 1.1.0 LANGUAGES CXX)
4343

4444
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.13)
4545
cmake_policy(SET CMP0077 NEW)
@@ -94,7 +94,7 @@ if(SE_ADAPTER_BUILD_DEPS)
9494
FetchContent_Declare(
9595
seal
9696
GIT_REPOSITORY https://github.com/microsoft/SEAL.git
97-
GIT_TAG 6bfac481aae4057ea887d42eb0f24371e9b4c4f9 # 3.7.1
97+
GIT_TAG 79234726053c45eede688400aa219fdec0810bd8 # 3.7.2
9898
)
9999
FetchContent_GetProperties(seal)
100100

adapter/adapter.cpp

Lines changed: 137 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,9 @@ static string save_dir_path = string(SE_ADAPTER_FILE_OUTPUT_DIR) + "/adapter_out
2929
static string ct_str_file_path_asym = string(SE_ADAPTER_FILE_OUTPUT_DIR) + "/out_asym_api_tests";
3030
static string ct_str_file_path_sym = string(SE_ADAPTER_FILE_OUTPUT_DIR) + "/out_sym_api_tests";
3131

32-
void verify_ciphertexts_30bitprime_default(string dirpath, size_t degree, SEALContext &context,
33-
bool symm_enc, string ct_str_file_path,
34-
string sk_binfilename = "")
32+
void verify_ciphertexts(string dirpath, double scale, size_t degree, seal::SEALContext &context,
33+
bool symm_enc, string ct_str_file_path, string sk_binfilename = "")
3534
{
36-
// size_t n = degree;
37-
// EncryptionParameters parms(scheme_type::ckks);
38-
// SEALContext context = setup_seale_30bitprime_default(degree, parms);
3935
auto &parms = context.key_context_data()->parms();
4036
size_t n = parms.poly_modulus_degree();
4137

@@ -49,17 +45,11 @@ void verify_ciphertexts_30bitprime_default(string dirpath, size_t degree, SEALCo
4945
Evaluator evaluator(context);
5046
CKKSEncoder encoder(context);
5147
size_t slot_count = encoder.slot_count();
52-
// double scale = (double)(n * n);
53-
// double scale = pow(2, 40);
54-
// double scale = pow(2, 30);
55-
double scale = (n > 1024) ? pow(2, 25) : pow(2, 20);
48+
5649
cout << "\nNumber of slots: " << slot_count << "\n" << endl;
5750

5851
SecretKey sk = keygen.secret_key();
59-
if (sk_binfilename.size() == 0)
60-
{
61-
sk_binfilename = dirpath + "sk_" + to_string(degree) + ".dat";
62-
}
52+
if (sk_binfilename.size() == 0) sk_binfilename = dirpath + "sk_" + to_string(degree) + ".dat";
6353
sk_bin_file_load(sk_binfilename, context, sk);
6454
Decryptor decryptor(context, sk);
6555

@@ -85,8 +75,9 @@ void verify_ciphertexts_30bitprime_default(string dirpath, size_t degree, SEALCo
8575
// -- We know this should start out being true
8676
assert(pk_wr.is_ntt == true);
8777

88-
bool incl_sp = 1; // Need to read back the special prime
89-
pk_bin_file_load(dirpath, context, pk_wr, incl_sp);
78+
bool incl_sp = 1; // Need to read back the special prime
79+
bool high_byte_first = 0;
80+
pk_bin_file_load(dirpath, context, pk_wr, incl_sp, high_byte_first);
9081
print_pk("pk", pk_wr, 8, incl_sp);
9182

9283
pk_to_non_ntt_form(context, pk_wr);
@@ -111,25 +102,23 @@ void verify_ciphertexts_30bitprime_default(string dirpath, size_t degree, SEALCo
111102
cout << " Test # " << ntest << endl;
112103
cout << "---------------------------------------------" << endl;
113104

114-
// -- Find the expected message from the string file. Comment out if not
115-
// needed.
105+
// -- Find the expected message from the string file. Comment out if not needed.
116106
vector<double> values_orig(slot_count, 0);
117107
cout << "Reading values from file..." << endl;
118-
filepos = poly_string_file_load(ct_str_file_path, values_orig, 1, filepos);
108+
filepos = poly_string_file_load(ct_str_file_path, 1, values_orig, filepos);
119109

120110
// -- Uncomment to check against expected plaintext output (assuming
121111
// corresponding lines in seal_embedded.c are also uncommented)
122-
// vector<int64_t> plaintext_vals(slot_count * 2, 0);
112+
// vector<int64_t> plaintext_vals(slot_count*2, 0);
123113
// cout << "Reading plaintext values from file..." << endl;
124-
// filepos = poly_string_file_load(ct_str_file_path, plaintext_vals, 1, filepos);
114+
// filepos = poly_string_file_load(ct_str_file_path, 1, plaintext_vals, filepos);
125115
// print_poly("\npt ", plaintext_vals, print_size);
126116

127117
// -- Uncomment to check against expected plaintext output (assuming
128118
// corresponding lines in seal_embedded.c are also uncommented)
129-
// vector<int64_t> plaintext_error_vals(slot_count * 2, 0);
119+
// vector<int64_t> plaintext_error_vals(slot_count*2, 0);
130120
// cout << "Reading plaintext error values from file..." << endl;
131-
// filepos =
132-
// poly_string_file_load(ct_str_file_path, plaintext_error_vals, 1, filepos);
121+
// filepos = poly_string_file_load(ct_str_file_path, 1, plaintext_error_vals, filepos);
133122
// print_poly("\npte ", plaintext_error_vals, print_size);
134123

135124
// -- Read in the ciphertext from the string file
@@ -158,6 +147,8 @@ void verify_ciphertexts_30bitprime_default(string dirpath, size_t degree, SEALCo
158147
// bool are_equal = are_equal_poly(msg_d, values_orig, slot_count);
159148
// assert(are_equal);
160149
// if (!are_equal) nfailures++;
150+
151+
// -- Debugging
161152
// Plaintext pt_test;
162153
// encoder.encode(values_orig, scale, pt_test);
163154
// print_poly("pt_test", get_pt_arr_ptr(pt_test), print_size);
@@ -177,35 +168,141 @@ void verify_ciphertexts_30bitprime_default(string dirpath, size_t degree, SEALCo
177168
}
178169
}
179170

180-
// TODO: make this non-main. Need to have a different main?
181-
int main()
171+
int main(int argc, char *argv[])
182172
{
183-
cout << "Parameters: degree 4096, prime bit-lengths: {30, 30, 30, 19}, ntt_form, "
184-
"scale = pow(2, 25)"
185-
<< endl;
173+
// -- Instructions: Uncomment one of the below degrees and run
174+
// or specify degree as a command line argument
175+
// size_t degree = 1024;
176+
// size_t degree = 2048;
186177
size_t degree = 4096;
178+
// size_t degree = 8192;
179+
// size_t degree = 16384;
180+
181+
if (argc > 1)
182+
{
183+
std::istringstream ss(argv[1]);
184+
size_t degree_in;
185+
if (!(ss >> degree_in)) { std::cerr << "Invalid number: " << argv[1] << '\n'; }
186+
else if (!ss.eof())
187+
{
188+
std::cerr << "Trailing characters after number: " << argv[1] << '\n';
189+
}
190+
assert(degree_in == 1024 || degree_in == 2048 || degree_in == 4096 || degree_in == 8192 ||
191+
degree_in == 16384);
192+
degree = degree_in;
193+
}
194+
195+
double scale = pow(2, 25);
196+
cout << "Parameters: degree " << degree << ", ntt_form, prime bit-lengths: {";
197+
switch (degree)
198+
{
199+
case 1024:
200+
cout << "27}, scale = pow(2, 20)" << endl;
201+
scale = pow(2, 20);
202+
break;
203+
case 2048:
204+
cout << "27, 27}, scale = pow(2, 25)" << endl;
205+
scale = pow(2, 25);
206+
break;
207+
#ifdef SEALE_DEFAULT_4K_27BIT
208+
case 4096:
209+
cout << "27, 27, 27, 28}, scale = pow(2, 20)" << endl;
210+
scale = pow(2, 20);
211+
break;
212+
#else
213+
case 4096:
214+
cout << "30, 30, 30, 19}, scale = pow(2, 25)" << endl;
215+
scale = pow(2, 25);
216+
break;
217+
#endif
218+
case 8192:
219+
cout << "30 (x6), 38}, scale = pow(2, 25)" << endl;
220+
scale = pow(2, 25);
221+
break;
222+
case 16384:
223+
cout << "30 (x13), 48}, scale = pow(2, 25)" << endl;
224+
scale = pow(2, 25);
225+
break;
226+
// -- 32768 is technically possible, but we do not support it
227+
// case 32768: cout << "30 (x28), 41}, scale = pow(2, 25)" << endl;
228+
// scale = pow(2,25);
229+
// break;
230+
default: cout << "Please choose a valid degree." << endl; throw;
231+
}
232+
233+
/*
234+
(From SEAL:)
235+
A larger coeff_modulus implies a larger noise budget, hence more encrypted
236+
computation capabilities. However, an upper bound for the total bit-length
237+
of the coeff_modulus is determined by the poly_modulus_degree, as follows:
238+
+----------------------------------------------------+
239+
| poly_modulus_degree | max coeff_modulus bit-length |
240+
+---------------------+------------------------------+
241+
| 1024 | 27 |
242+
| 2048 | 54 |
243+
| 4096 | 109 |
244+
| 8192 | 218 |
245+
| 16384 | 438 |
246+
| 32768 | 881 |
247+
+---------------------+------------------------------+
248+
*/
249+
187250
EncryptionParameters parms(scheme_type::ckks);
188-
SEALContext context = setup_seale_30bitprime_default(degree, parms);
251+
seal::SEALContext context = setup_seale_prime_default(degree, parms);
189252
bool sk_generated = false, pk_generated = false;
190253

191-
string sk_fpath = save_dir_path + "sk_" + to_string(degree) + ".dat";
254+
// -- Testing
255+
// setup_seal_api(1024, {27}, parms);
256+
// setup_seal_api(2048, {27, 27}, parms);
257+
// setup_seal_api(2048, {30, 24}, parms);
258+
// setup_seal_api(4096, {27, 27, 27, 28}, parms);
259+
// setup_seal_api(4096, {30, 30, 30, 19}, parms);
260+
/*
261+
{
262+
vector<int> bit_counts;
263+
for(size_t i = 0; i < 6; i++) bit_counts.push_back(30);
264+
bit_counts.push_back(38);
265+
setup_seal_api(8192, bit_counts, parms);
266+
}
267+
*/
268+
/*
269+
{
270+
for(size_t i = 0; i < 13; i++) bit_counts.push_back(30);
271+
bit_counts.push_back(48);
272+
setup_seal_api(16384, bit_counts, parms);
273+
}
274+
*/
275+
/*
276+
{
277+
for(size_t i = 0; i < 28; i++) bit_counts.push_back(30);
278+
bit_counts.push_back(41);
279+
setup_seal_api(32768, bit_counts, parms);
280+
}
281+
*/
282+
192283
// string str_sk_fpath = save_dir_path + "str_sk_" + to_string(degree) + ".h";
284+
string sk_fpath = save_dir_path + "sk_" + to_string(degree) + ".dat";
193285
string str_sk_fpath = save_dir_path + "str_sk.h";
194286
string seal_sk_fpath = save_dir_path + "sk_" + to_string(degree) + "_seal" + ".dat";
195287
string seal_pk_fpath = save_dir_path + "pk_" + to_string(degree) + "_seal" + ".dat";
196288

197289
SecretKey sk;
198290

199-
// string err_msg1 = "This option is not yet supported. Please choose another
200-
// option.";
291+
// string err_msg1 = "This option is not yet supported. Please choose another option.";
201292
string err_msg2 = "This is not a valid option choice. Please choose a valid option.";
202293

294+
bool is_sym = true; // TODO: Make this command line settable
295+
203296
while (1)
204297
{
205298
cout << "\nChoose an action:\n";
206299
cout << " 0) Quit\n";
207300
cout << " 1) Generate all objects\n";
208-
cout << " 2) Verify ciphertexts\n";
301+
if (is_sym) { cout << " 2) Verify ciphertexts (in symmetric mode) \n"; }
302+
else
303+
{
304+
cout << " 2) Verify ciphertexts (in asymmetric mode)\n";
305+
}
209306
cout << " 3) Generate secret key, public key\n";
210307
cout << " 4) Generate IFFT roots\n";
211308
cout << " 5) Generate fast (a.k.a. \"lazy\") NTT roots\n";
@@ -216,17 +313,15 @@ int main()
216313
int option;
217314
cin >> option;
218315

219-
bool is_sym = true; // TODO: Make this command line settable
220-
string ct_str_file_path = is_sym ? ct_str_file_path_sym : ct_str_file_path_asym;
221-
222-
bool use_seal_sk_fpath = true;
316+
bool use_seal_sk_fpath = true; // This is only used when verifying ciphertexts
223317
switch (option)
224318
{
225319
case 0: exit(0);
226-
case 2:
227-
verify_ciphertexts_30bitprime_default(save_dir_path, degree, context, is_sym,
228-
ct_str_file_path);
229-
break;
320+
case 2: {
321+
string ct_str_file_path = is_sym ? ct_str_file_path_sym : ct_str_file_path_asym;
322+
verify_ciphertexts(save_dir_path, scale, degree, context, is_sym, ct_str_file_path);
323+
}
324+
break;
230325
case 1: [[fallthrough]];
231326
case 3:
232327
cout << "Generating secret key..." << endl;
@@ -253,7 +348,6 @@ int main()
253348
case 9: gen_save_index_map(save_dir_path, context, 0); break;
254349
default: cout << err_msg2 << endl; break;
255350
}
256-
exit(0);
257351
}
258352
return 0;
259353
}

0 commit comments

Comments
 (0)