Skip to content

Commit

Permalink
feat(core): Add Compact Public Key
Browse files Browse the repository at this point in the history
- Based on "TFHE Public-Key Encryption Revisited "
  https://eprint.iacr.org/2023/603.pdf

Co-authored-by: tmontaigu <thomas.montaigu@laposte.net>
  • Loading branch information
IceTDrinker and tmontaigu committed Jun 7, 2023
1 parent 200c8a1 commit 3508019
Show file tree
Hide file tree
Showing 91 changed files with 5,835 additions and 460 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ target/

# Some of our bench outputs
/tfhe/benchmarks_parameters
/tfhe/shortint_key_sizes.csv
18 changes: 13 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,13 @@ test_boolean: install_rs_build_toolchain
--features=$(TARGET_ARCH_FEATURE),boolean -p tfhe -- boolean::

.PHONY: test_c_api # Run the tests for the C API
test_c_api: build_c_api
test_c_api: install_rs_check_toolchain
RUSTFLAGS="$(RUSTFLAGS)" cargo $(CARGO_RS_CHECK_TOOLCHAIN) test --profile $(CARGO_PROFILE) \
--features=$(TARGET_ARCH_FEATURE),boolean-c-api,shortint-c-api,high-level-c-api \
-p tfhe \
c_api

"$(MAKE)" build_c_api
./scripts/c_api_tests.sh

.PHONY: test_shortint_ci # Run the tests for shortint ci
Expand Down Expand Up @@ -307,13 +313,15 @@ format_doc_latex:
@printf "\n===============================\n"

.PHONY: check_compile_tests # Build tests in debug without running them
check_compile_tests: build_c_api
check_compile_tests:
RUSTFLAGS="$(RUSTFLAGS)" cargo $(CARGO_RS_BUILD_TOOLCHAIN) test --no-run \
--features=$(TARGET_ARCH_FEATURE),experimental,boolean,shortint,integer,internal-keycache \
-p tfhe
@if [[ "$(OS)" == "Linux" || "$(OS)" == "Darwin" ]]; then \
./scripts/c_api_tests.sh --build-only; \
fi

@if [[ "$(OS)" == "Linux" || "$(OS)" == "Darwin" ]]; then \
"$(MAKE)" build_c_api; \
./scripts/c_api_tests.sh --build-only; \
fi

.PHONY: build_nodejs_test_docker # Build a docker image with tools to run nodejs tests for wasm API
build_nodejs_test_docker:
Expand Down
11 changes: 10 additions & 1 deletion tfhe/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,12 @@ experimental-force_fft_algo_dif4 = []
__c_api = ["cbindgen", "bincode"]
boolean-c-api = ["boolean", "__c_api"]
shortint-c-api = ["shortint", "__c_api"]
high-level-c-api = ["boolean", "shortint", "integer", "__c_api"]
high-level-c-api = [
"boolean-c-api",
"shortint-c-api",
"integer",
"__c_api"
]

__wasm_api = [
"wasm-bindgen",
Expand Down Expand Up @@ -200,6 +205,10 @@ required-features = ["integer", "internal-keycache"]
name = "shortint_key_sizes"
required-features = ["shortint", "internal-keycache"]

[[example]]
name = "integer_compact_pk_ct_sizes"
required-features = ["integer", "internal-keycache"]

[[example]]
name = "micro_bench_and"
required-features = ["boolean"]
Expand Down
44 changes: 25 additions & 19 deletions tfhe/c_api_tests/test_high_level_128_bits.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,24 @@ int uint128_client_key(const ClientKey *client_key) {
FheUint128 *lhs = NULL;
FheUint128 *rhs = NULL;
FheUint128 *result = NULL;
U128 lhs_clear = {10, 20};
U128 rhs_clear = {1, 2};
U128 result_clear = {0};

ok = fhe_uint128_try_encrypt_with_client_key_u128(10, 20, client_key, &lhs);
ok = fhe_uint128_try_encrypt_with_client_key_u128(lhs_clear, client_key, &lhs);
assert(ok == 0);

ok = fhe_uint128_try_encrypt_with_client_key_u128(1, 2, client_key, &rhs);
ok = fhe_uint128_try_encrypt_with_client_key_u128(rhs_clear, client_key, &rhs);
assert(ok == 0);

ok = fhe_uint128_sub(lhs, rhs, &result);
assert(ok == 0);

uint64_t w0, w1;
ok = fhe_uint128_decrypt(result, client_key, &w0, &w1);
ok = fhe_uint128_decrypt(result, client_key, &result_clear);
assert(ok == 0);

assert(w0 == 9);
assert(w1 == 18);
assert(result_clear.w0 == 9);
assert(result_clear.w1 == 18);

fhe_uint128_destroy(lhs);
fhe_uint128_destroy(rhs);
Expand All @@ -37,22 +39,24 @@ int uint128_encrypt_trivial(const ClientKey *client_key) {
FheUint128 *lhs = NULL;
FheUint128 *rhs = NULL;
FheUint128 *result = NULL;

ok = fhe_uint128_try_encrypt_trivial_u128(10, 20, &lhs);
U128 lhs_clear = {10, 20};
U128 rhs_clear = {1, 2};
U128 result_clear = {0};

ok = fhe_uint128_try_encrypt_trivial_u128(lhs_clear, &lhs);
assert(ok == 0);

ok = fhe_uint128_try_encrypt_trivial_u128(1, 2, &rhs);
ok = fhe_uint128_try_encrypt_trivial_u128(rhs_clear, &rhs);
assert(ok == 0);

ok = fhe_uint128_sub(lhs, rhs, &result);
assert(ok == 0);

uint64_t w0, w1;
ok = fhe_uint128_decrypt(result, client_key, &w0, &w1);
ok = fhe_uint128_decrypt(result, client_key, &result_clear);
assert(ok == 0);

assert(w0 == 9);
assert(w1 == 18);
assert(result_clear.w0 == 9);
assert(result_clear.w1 == 18);

fhe_uint128_destroy(lhs);
fhe_uint128_destroy(rhs);
Expand All @@ -65,22 +69,24 @@ int uint128_public_key(const ClientKey *client_key, const PublicKey *public_key)
FheUint128 *lhs = NULL;
FheUint128 *rhs = NULL;
FheUint128 *result = NULL;
U128 lhs_clear = {10, 20};
U128 rhs_clear = {1, 2};
U128 result_clear = {0};

ok = fhe_uint128_try_encrypt_with_public_key_u128(1, 2, public_key, &lhs);
ok = fhe_uint128_try_encrypt_with_public_key_u128(lhs_clear, public_key, &lhs);
assert(ok == 0);

ok = fhe_uint128_try_encrypt_with_public_key_u128(10, 20, public_key, &rhs);
ok = fhe_uint128_try_encrypt_with_public_key_u128(rhs_clear, public_key, &rhs);
assert(ok == 0);

ok = fhe_uint128_add(lhs, rhs, &result);
assert(ok == 0);

uint64_t w0, w1;
ok = fhe_uint128_decrypt(result, client_key, &w0, &w1);
ok = fhe_uint128_decrypt(result, client_key, &result_clear);
assert(ok == 0);

assert(w0 == 11);
assert(w1 == 22);
assert(result_clear.w0 == 11);
assert(result_clear.w1 == 22);

fhe_uint128_destroy(lhs);
fhe_uint128_destroy(rhs);
Expand Down
78 changes: 21 additions & 57 deletions tfhe/c_api_tests/test_high_level_256_bits.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,9 @@ int uint256_client_key(const ClientKey *client_key) {
FheUint256 *rhs = NULL;
FheUint256 *result = NULL;
FheUint64 *cast_result = NULL;
U256 *lhs_clear = NULL;
U256 *rhs_clear = NULL;
U256 *result_clear = NULL;

ok = u256_from_u64_words(1, 2, 3, 4, &lhs_clear);
assert(ok == 0);
ok = u256_from_u64_words(5, 6, 7, 8, &rhs_clear);
assert(ok == 0);
U256 lhs_clear = {1 , 2, 3, 4};
U256 rhs_clear = {5, 6, 7, 8};
U256 result_clear = { 0 };

ok = fhe_uint256_try_encrypt_with_client_key_u256(lhs_clear, client_key, &lhs);
assert(ok == 0);
Expand All @@ -31,14 +26,10 @@ int uint256_client_key(const ClientKey *client_key) {
ok = fhe_uint256_decrypt(result, client_key, &result_clear);
assert(ok == 0);

uint64_t w0, w1, w2, w3;
ok = u256_to_u64_words(result_clear, &w0, &w1, &w2, &w3);
assert(ok == 0);

assert(w0 == 6);
assert(w1 == 8);
assert(w2 == 10);
assert(w3 == 12);
assert(result_clear.w0 == 6);
assert(result_clear.w1 == 8);
assert(result_clear.w2 == 10);
assert(result_clear.w3 == 12);

// try some casting
ok = fhe_uint256_cast_into_fhe_uint64(result, &cast_result);
Expand All @@ -48,9 +39,6 @@ int uint256_client_key(const ClientKey *client_key) {
assert(ok == 0);
assert(u64_clear == 6);

u256_destroy(lhs_clear);
u256_destroy(rhs_clear);
u256_destroy(result_clear);
fhe_uint256_destroy(lhs);
fhe_uint256_destroy(rhs);
fhe_uint256_destroy(result);
Expand All @@ -63,14 +51,9 @@ int uint256_encrypt_trivial(const ClientKey *client_key) {
FheUint256 *lhs = NULL;
FheUint256 *rhs = NULL;
FheUint256 *result = NULL;
U256 *lhs_clear = NULL;
U256 *rhs_clear = NULL;
U256 *result_clear = NULL;

ok = u256_from_u64_words(1, 2, 3, 4, &lhs_clear);
assert(ok == 0);
ok = u256_from_u64_words(5, 6, 7, 8, &rhs_clear);
assert(ok == 0);
U256 lhs_clear = {1 , 2, 3, 4};
U256 rhs_clear = {5, 6, 7, 8};
U256 result_clear = { 0 };

ok = fhe_uint256_try_encrypt_trivial_u256(lhs_clear, &lhs);
assert(ok == 0);
Expand All @@ -84,18 +67,11 @@ int uint256_encrypt_trivial(const ClientKey *client_key) {
ok = fhe_uint256_decrypt(result, client_key, &result_clear);
assert(ok == 0);

uint64_t w0, w1, w2, w3;
ok = u256_to_u64_words(result_clear, &w0, &w1, &w2, &w3);
assert(ok == 0);

assert(w0 == 6);
assert(w1 == 8);
assert(w2 == 10);
assert(w3 == 12);
assert(result_clear.w0 == 6);
assert(result_clear.w1 == 8);
assert(result_clear.w2 == 10);
assert(result_clear.w3 == 12);

u256_destroy(lhs_clear);
u256_destroy(rhs_clear);
u256_destroy(result_clear);
fhe_uint256_destroy(lhs);
fhe_uint256_destroy(rhs);
fhe_uint256_destroy(result);
Expand All @@ -107,14 +83,9 @@ int uint256_public_key(const ClientKey *client_key, const PublicKey *public_key)
FheUint256 *lhs = NULL;
FheUint256 *rhs = NULL;
FheUint256 *result = NULL;
U256 *lhs_clear = NULL;
U256 *rhs_clear = NULL;
U256 *result_clear = NULL;

ok = u256_from_u64_words(5, 6, 7, 8, &lhs_clear);
assert(ok == 0);
ok = u256_from_u64_words(1, 2, 3, 4, &rhs_clear);
assert(ok == 0);
U256 lhs_clear = {5, 6, 7, 8};
U256 rhs_clear = {1 , 2, 3, 4};
U256 result_clear = { 0 };

ok = fhe_uint256_try_encrypt_with_public_key_u256(lhs_clear, public_key, &lhs);
assert(ok == 0);
Expand All @@ -128,18 +99,11 @@ int uint256_public_key(const ClientKey *client_key, const PublicKey *public_key)
ok = fhe_uint256_decrypt(result, client_key, &result_clear);
assert(ok == 0);

uint64_t w0, w1, w2, w3;
ok = u256_to_u64_words(result_clear, &w0, &w1, &w2, &w3);
assert(ok == 0);

assert(w0 == 4);
assert(w1 == 4);
assert(w2 == 4);
assert(w3 == 4);
assert(result_clear.w0 == 4);
assert(result_clear.w1 == 4);
assert(result_clear.w2 == 4);
assert(result_clear.w3 == 4);

u256_destroy(lhs_clear);
u256_destroy(rhs_clear);
u256_destroy(result_clear);
fhe_uint256_destroy(lhs);
fhe_uint256_destroy(rhs);
fhe_uint256_destroy(result);
Expand Down
Loading

0 comments on commit 3508019

Please sign in to comment.