diff --git a/CHANGELOG.md b/CHANGELOG.md index 0facc24..6cde491 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,3 +6,9 @@ - Added Naor-Pinkas oblivious transfer. - Added IKNP oblivious transfer extension. + +## Version 0.2.0 + +### Features + +- Added KKRT oblivious transfer. diff --git a/CMakeLists.txt b/CMakeLists.txt index e2942a2..f782cd9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,7 +30,7 @@ if(NOT CMAKE_BUILD_TYPE) endif() message(STATUS "Build type (CMAKE_BUILD_TYPE): ${CMAKE_BUILD_TYPE}") -project(VERSE VERSION 0.1.0 LANGUAGES CXX C) +project(VERSE VERSION 0.2.0 LANGUAGES CXX C) ######################## # Global configuration # @@ -193,7 +193,7 @@ if(NOT TARGET Threads::Threads) endif() # PETAce-Network::network -find_package(PETAce-Network 0.1 QUIET CONFIG) +find_package(PETAce-Network 0.2 QUIET CONFIG) if(PETAce-Network_FOUND) message(STATUS "PETAce-Network: found") if(PETAce-Network_STATIC_FOUND) @@ -217,7 +217,7 @@ else() endif() # PETAce-Solo::solo -find_package(PETAce-Solo 0.1 QUIET CONFIG) +find_package(PETAce-Solo 0.2 QUIET CONFIG) if(PETAce-Solo_FOUND) message(STATUS "PETAce-Solo: found") if(PETAce-Solo_STATIC_FOUND) diff --git a/README.md b/README.md index fe3cfdb..7a4a7a9 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ It is one of the many components in [the framework PETAce](https://github.com/ti PETAce-Verse implements frequently, repeatedly called subprotocols, as implied by the same "Verse". Examples are oblivious transfer, oblivious pseudorandom functions, (vector) oblivious linear evaluation, etc. -Currently, PETAce-Verse includes: [Naor-Pinkas OT](https://dl.acm.org/doi/10.5555/365411.365502) and [IKNP OT](https://link.springer.com/chapter/10.1007/978-3-540-45146-4_9) with [optimization](https://link.springer.com/article/10.1007/s00145-016-9236-6). +Currently, PETAce-Verse includes: [Naor-Pinkas OT](https://dl.acm.org/doi/10.5555/365411.365502), [IKNP OT](https://link.springer.com/chapter/10.1007/978-3-540-45146-4_9) with [optimization](https://link.springer.com/article/10.1007/s00145-016-9236-6), and [KKRT OT](https://dl.acm.org/doi/abs/10.1145/2976749.2978381). ## Requirements @@ -17,8 +17,8 @@ Currently, PETAce-Verse includes: [Naor-Pinkas OT](https://dl.acm.org/doi/10.555 | Required dependency | Tested version | Use | |--------------------------------------------------------------------------------|----------------|---------------------------------| -| [PETAce-Solo](https://github.com/tiktok-privacy-innovation/PETAce-Solo) | 0.1.0 | Cryptography primitives | -| [PETAce-Network](https://github.com/tiktok-privacy-innovation/PETAce-Network) | 0.1.0 | Network communication protocols | +| [PETAce-Solo](https://github.com/tiktok-privacy-innovation/PETAce-Solo) | 0.2.0 | Cryptography primitives | +| [PETAce-Network](https://github.com/tiktok-privacy-innovation/PETAce-Network) | 0.2.0 | Network communication protocols | | Optional dependency | Tested version | Use | |----------------------------------------------------|----------------|-------------------| @@ -75,13 +75,13 @@ This project is licensed under the [Apache-2.0 License](LICENSE). To cite PETAce in academic papers, please use the following BibTeX entries. -### Version 0.1.0 +### Version 0.2.0 ```tex @misc{petace, - title = {PETAce (release 0.1.0)}, + title = {PETAce (release 0.2.0)}, howpublished = {\url{https://github.com/tiktok-privacy-innovation/PETAce}}, - month = July, + month = Oct, year = 2023, note = {TikTok Pte. Ltd.}, key = {PETAce} diff --git a/cmake/PETAce-Network.cmake b/cmake/PETAce-Network.cmake index c96e401..060a5f1 100644 --- a/cmake/PETAce-Network.cmake +++ b/cmake/PETAce-Network.cmake @@ -14,8 +14,8 @@ FetchContent_Declare( network - GIT_REPOSITORY git@github.com:tiktok-privacy-innovation/PETAce-Network.git - GIT_TAG 096245f85cec4d0065488225bf1b2f1dc979efb2 # v0.1.0 + GIT_REPOSITORY https://github.com/tiktok-privacy-innovation/PETAce-Network.git + GIT_TAG 92d1a6f079cd11e01bc8e610cb92126ede2964b1 # 0.2.0 ) FetchContent_GetProperties(network) diff --git a/cmake/PETAce-Solo.cmake b/cmake/PETAce-Solo.cmake index 1fff8ed..ceae164 100644 --- a/cmake/PETAce-Solo.cmake +++ b/cmake/PETAce-Solo.cmake @@ -14,8 +14,8 @@ FetchContent_Declare( solo - GIT_REPOSITORY git@github.com:tiktok-privacy-innovation/PETAce-Solo.git - GIT_TAG 471d70069a684a23b6c11319643a73e005547a01 # v0.1.0 + GIT_REPOSITORY https://github.com/tiktok-privacy-innovation/PETAce-Solo.git + GIT_TAG ead22f615120a0cd9926cfc5d5787fe4bcda379c # 0.2.0 ) FetchContent_GetProperties(solo) diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 6885fe1..20cf189 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -14,14 +14,14 @@ cmake_minimum_required(VERSION 3.14) -project(VERSEExamples VERSION 0.1.0 LANGUAGES CXX) +project(VERSEExamples VERSION 0.2.0 LANGUAGES CXX) # If not called from root CMakeLists.txt if(NOT DEFINED VERSE_BUILD_EXAMPLE) set(VERSE_BUILD_EXAMPLE ON) # Import Microsoft VERSE - find_package(PETAce-Verse 0.1.0 EXACT REQUIRED) + find_package(PETAce-Verse 0.2.0 EXACT REQUIRED) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) endif() @@ -33,6 +33,7 @@ if(VERSE_BUILD_EXAMPLE) set(PETACE_VERSE_EXAMPLE_FILES ${PETACE_VERSE_EXAMPLE_FILES} ${CMAKE_CURRENT_LIST_DIR}/example.cpp ${CMAKE_CURRENT_LIST_DIR}/iknp_ot_example.cpp + ${CMAKE_CURRENT_LIST_DIR}/kkrt_ot_example.cpp ${CMAKE_CURRENT_LIST_DIR}/np_ot_example.cpp ) diff --git a/example/example.cpp b/example/example.cpp index ada925f..f7f59af 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -23,15 +23,16 @@ int main(int argc, char* argv[]) { throw std::runtime_error("Parameters are incorrect!"); } while (true) { - std::cout << "+---------------------------------------------------------+" << std::endl; - std::cout << "| The following examples should be executed while reading |" << std::endl; - std::cout << "| comments in associated files in examples/. |" << std::endl; - std::cout << "+---------------------------------------------------------+" << std::endl; - std::cout << "| Examples | Source Files |" << std::endl; - std::cout << "+----------------------------+----------------------------+" << std::endl; - std::cout << "| 1. Naor Pinkas OT | np_ot_example.cpp |" << std::endl; - std::cout << "| 2. IKNP OT | iknp_ot_example.cpp |" << std::endl; - std::cout << "+----------------------------+----------------------------+" << std::endl; + std::cout << "+--------------------------------------------------------------------+" << std::endl; + std::cout << "| The following examples should be executed while reading |" << std::endl; + std::cout << "| comments in associated files in examples/. |" << std::endl; + std::cout << "+--------------------------------------------------------------------+" << std::endl; + std::cout << "| Examples | Source Files |" << std::endl; + std::cout << "+----------------------------+---------------------------------------+" << std::endl; + std::cout << "| 1. Naor Pinkas OT | np_ot_example.cpp |" << std::endl; + std::cout << "| 2. IKNP 1-out-of-2 OT | iknp_ot_example.cpp |" << std::endl; + std::cout << "| 3. KKRT 1-out-of-n OT | kkrt_ot_example.cpp |" << std::endl; + std::cout << "+----------------------------+---------------------------------------+" << std::endl; int selection = 0; std::cin >> selection; @@ -43,6 +44,10 @@ int main(int argc, char* argv[]) { iknp_ot_example( atoi(argv[5]), std::string(argv[1]), atoi(argv[2]), std::string(argv[3]), atoi(argv[4])); break; + case 3: + kkrt_ot_example( + atoi(argv[5]), std::string(argv[1]), atoi(argv[2]), std::string(argv[3]), atoi(argv[4])); + break; case 0: return 0; } diff --git a/example/example.h b/example/example.h index 1fc5475..f735d07 100644 --- a/example/example.h +++ b/example/example.h @@ -21,3 +21,6 @@ void np_ot_example(std::size_t party_id, std::string local_addr, std::size_t loc void iknp_ot_example(std::size_t party_id, std::string local_addr, std::size_t local_port, std::string remote_addr, std::size_t remote_port); + +void kkrt_ot_example(std::size_t party_id, std::string local_addr, std::size_t local_port, std::string remote_addr, + std::size_t remote_port); diff --git a/example/kkrt_ot_example.cpp b/example/kkrt_ot_example.cpp new file mode 100644 index 0000000..1d9dcc8 --- /dev/null +++ b/example/kkrt_ot_example.cpp @@ -0,0 +1,84 @@ +// Copyright 2023 TikTok Pte. Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "example.h" + +#include "network/net_factory.h" + +#include "verse/util/common.h" +#include "verse/verse_factory.h" + +void kkrt_ot_example(std::size_t party_id, std::string local_addr, std::size_t local_port, std::string remote_addr, + std::size_t remote_port) { + petace::network::NetParams net_params; + net_params.remote_addr = remote_addr; + net_params.remote_port = static_cast(remote_port); + net_params.local_addr = local_addr; + net_params.local_port = static_cast(local_port); + auto net = petace::network::NetFactory::get_instance().build(petace::network::NetScheme::SOCKET, net_params); + + petace::verse::VerseParams params; + params.base_ot_sizes = 512; + params.ext_ot_sizes = 1024; + std::vector base_recv_ots; + std::vector> base_send_ots; + std::vector base_choices; + std::vector ext_choices; + for (std::size_t i = 0; i < 4; i++) { + base_choices.emplace_back(petace::verse::read_block_from_dev_urandom()); + } + for (std::size_t i = 0; i < params.ext_ot_sizes; i++) { + ext_choices.emplace_back(_mm_set_epi64x(0, i)); + } + + auto npot_sender = petace::verse::VerseFactory::get_instance().build( + petace::verse::OTScheme::NaorPinkasSender, params); + auto npot_receiver = petace::verse::VerseFactory::get_instance().build( + petace::verse::OTScheme::NaorPinkasReceiver, params); + auto kkrt_sender = petace::verse::VerseFactory::get_instance().build( + petace::verse::OTScheme::KkrtSender, params); + auto kkrt_receiver = petace::verse::VerseFactory::get_instance().build( + petace::verse::OTScheme::KkrtReceiver, params); + + std::vector recv_msgs; + if (party_id == 0) { + npot_receiver->receive(net, base_choices, base_recv_ots); + kkrt_sender->set_base_ots(base_choices, base_recv_ots); + kkrt_sender->send(net, params.ext_ot_sizes); + + std::cout << "sender messages" << std::endl; + petace::verse::block output; + for (std::size_t i = 0; i < 16; i++) { + std::cout << std::dec << "ot index: " << i << std::endl; + for (std::size_t j = 0; j < 16; j++) { + kkrt_sender->encode(i, _mm_set_epi64x(0, j), output); + std::cout << std::hex << output[0] << "|" << output[1] << std::endl; + } + std::cout << std::endl; + } + } else { + npot_sender->send(net, base_send_ots); + kkrt_receiver->set_base_ots(base_send_ots); + kkrt_receiver->receive(net, ext_choices, recv_msgs); + std::cout << "reciver messages" << std::endl; + for (std::size_t i = 0; i < 16; i++) { + std::cout << std::dec << "ot index: " << i << std::endl; + std::cout << std::hex << recv_msgs[i][0] << "|" << recv_msgs[i][1] << "--" << ext_choices[i][0] + << std::endl; + } + } +} diff --git a/src/verse/CMakeLists.txt b/src/verse/CMakeLists.txt index 8e18a0c..aee19af 100644 --- a/src/verse/CMakeLists.txt +++ b/src/verse/CMakeLists.txt @@ -23,5 +23,6 @@ install( add_subdirectory(util) add_subdirectory(base-ot) add_subdirectory(two-choose-one) +add_subdirectory(n-choose-one) set(VERSE_SOURCE_FILES ${VERSE_SOURCE_FILES} PARENT_SCOPE) diff --git a/src/verse/n-choose-one/CMakeLists.txt b/src/verse/n-choose-one/CMakeLists.txt new file mode 100644 index 0000000..f6d2b58 --- /dev/null +++ b/src/verse/n-choose-one/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright 2023 TikTok Pte. Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Add header files for installation +install( + FILES + ${CMAKE_CURRENT_LIST_DIR}/nco_ot_ext_receiver.h + ${CMAKE_CURRENT_LIST_DIR}/nco_ot_ext_sender.h + DESTINATION + ${VERSE_INCLUDES_INSTALL_DIR}/verse/n-choose-one +) +add_subdirectory(kkrt) + +set(VERSE_SOURCE_FILES ${VERSE_SOURCE_FILES} PARENT_SCOPE) diff --git a/src/verse/n-choose-one/kkrt/CMakeLists.txt b/src/verse/n-choose-one/kkrt/CMakeLists.txt new file mode 100644 index 0000000..3b9811b --- /dev/null +++ b/src/verse/n-choose-one/kkrt/CMakeLists.txt @@ -0,0 +1,28 @@ +# Copyright 2023 TikTok Pte. Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Source files in this directory +set(VERSE_SOURCE_FILES ${VERSE_SOURCE_FILES} + ${CMAKE_CURRENT_LIST_DIR}/kkrt_nco_ot_ext.cpp +) + +# Add header files for installation +install( + FILES + ${CMAKE_CURRENT_LIST_DIR}/kkrt_nco_ot_ext.h + DESTINATION + ${VERSE_INCLUDES_INSTALL_DIR}/verse/n-choose-one/kkrt +) + +set(VERSE_SOURCE_FILES ${VERSE_SOURCE_FILES} PARENT_SCOPE) diff --git a/src/verse/n-choose-one/kkrt/kkrt_nco_ot_ext.cpp b/src/verse/n-choose-one/kkrt/kkrt_nco_ot_ext.cpp new file mode 100644 index 0000000..b0a13b9 --- /dev/null +++ b/src/verse/n-choose-one/kkrt/kkrt_nco_ot_ext.cpp @@ -0,0 +1,209 @@ +// Copyright 2023 TikTok Pte. Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "verse/n-choose-one/kkrt/kkrt_nco_ot_ext.h" + +#include + +#include "verse/util/common.h" + +namespace petace { +namespace verse { + +void KkrtNcoOtExtSender::set_base_ots(const std::vector& choices, const std::vector& base_recv_ots) { + solo::PRNGFactory prng_factory(solo::PRNGScheme::AES_ECB_CTR); + for (std::size_t i = 0; i < base_recv_ots.size(); i++) { + std::vector seed(sizeof(block)); + memcpy(seed.data(), reinterpret_cast(const_cast(base_recv_ots.data() + i)), sizeof(block)); + prng_.emplace_back(prng_factory.create(seed)); + } + base_choices_.insert(base_choices_.begin(), choices.begin(), choices.end()); + return; +} + +void KkrtNcoOtExtSender::send(const std::shared_ptr& net, const std::size_t ext_ot_sizes) { + if (base_ot_sizes_ % (sizeof(block) * 8) != 0) { + throw std::invalid_argument("OT base size is not supported."); + } + ext_ot_sizes_ = ext_ot_sizes; + if (ext_ot_sizes_ % (sizeof(block) * 8) != 0) { + ext_ot_sizes_ += sizeof(block) * 8 - (ext_ot_sizes_ % (sizeof(block) * 8)); + } + if (ext_ot_sizes_ % (sizeof(block) * 8) != 0) { + throw std::invalid_argument("OT extension size is not supported."); + } + + std::size_t rows = base_ot_sizes_; + std::size_t cols = ext_ot_sizes_ / (sizeof(block) * 8); + + std::vector recv_matrix(rows * cols); + recv_block(net, recv_matrix.data(), rows * cols); + + std::vector> ext_matrix(rows, std::vector(cols)); + for (std::size_t i = 0; i < rows; i++) { + prng_[i]->generate(cols * sizeof(block), reinterpret_cast(&(ext_matrix[i][0]))); + } + + std::vector input(sizeof(block) * 8); + std::vector output(sizeof(block) * 8); + std::size_t threshhold = rows / (sizeof(block) * 8); + + q_mat.resize(ext_ot_sizes_); + for (std::size_t i = 0; i < ext_ot_sizes_; i++) { + q_mat[i].resize(threshhold); + } + for (std::size_t i = 0; i < cols; i++) { + for (std::size_t j = 0; j < threshhold; j++) { + for (std::size_t k = 0; k < sizeof(block) * 8; k++) { + input[k] = ext_matrix[j * sizeof(block) * 8 + k][i]; + } + matrix_transpose(input, sizeof(block) * 8, sizeof(block) * 8, output); + + for (std::size_t k = 0; k < sizeof(block) * 8; k++) { + q_mat[i * sizeof(block) * 8 + k][j] = output[k]; + q_mat[i * sizeof(block) * 8 + k][j] ^= + (recv_matrix[(i * sizeof(block) * 8 + k) * threshhold + j] & base_choices_[j]); + } + } + } + + return; +} + +void KkrtNcoOtExtSender::encode(const std::size_t idx, const block& input, block& output) { + std::size_t threshhold = base_ot_sizes_ / (sizeof(block) * 8); + std::vector enc_input(threshhold); + auto hash = solo::Hash::create(solo::HashScheme::SHA_256); + + for (std::size_t j = 0; j < threshhold; j++) { + auto hash_in = input ^ _mm_set_epi64x(0, j); + hash->compute(reinterpret_cast(&hash_in), sizeof(block), + reinterpret_cast(&enc_input[j]), sizeof(block)); + enc_input[j] = base_choices_[j] & (enc_input[j] ^ input); + } + + block enc_output = _mm_set_epi64x(0, 0); + for (std::size_t j = 0; j < threshhold; j++) { + enc_output ^= enc_input[j] ^ q_mat[idx][j] ^ _mm_set_epi64x(0, idx); + hash->compute(reinterpret_cast(&enc_output), sizeof(block), + reinterpret_cast(&enc_output), sizeof(block)); + } + output = enc_output; +} + +void KkrtNcoOtExtReceiver::set_base_ots(const std::vector>& base_send_ots) { + solo::PRNGFactory prng_factory(solo::PRNGScheme::AES_ECB_CTR); + for (std::size_t i = 0; i < base_send_ots.size(); i++) { + std::vector seed0(sizeof(block)); + std::vector seed1(sizeof(block)); + memcpy(seed0.data(), reinterpret_cast(const_cast(&base_send_ots[i][0])), sizeof(block)); + memcpy(seed1.data(), reinterpret_cast(const_cast(&base_send_ots[i][1])), sizeof(block)); + std::array, 2> values{prng_factory.create(seed0), prng_factory.create(seed1)}; + prng_.emplace_back(values); + } + return; +} + +void KkrtNcoOtExtReceiver::receive( + const std::shared_ptr& net, const std::vector& choices, std::vector& messages) { + if (base_ot_sizes_ % (sizeof(block) * 8) != 0) { + throw std::invalid_argument("OT base size is not supported."); + } + ext_ot_sizes_ = choices.size(); + if (ext_ot_sizes_ % (sizeof(block) * 8) != 0) { + ext_ot_sizes_ += sizeof(block) * 8 - (ext_ot_sizes_ % (sizeof(block) * 8)); + } + if (ext_ot_sizes_ % (sizeof(block) * 8) != 0) { + throw std::invalid_argument("OT extension size is not supported."); + } + + std::size_t rows = base_ot_sizes_; + std::size_t cols = ext_ot_sizes_ / (sizeof(block) * 8); + + std::vector> t0(rows, std::vector(cols)); + std::vector> t1(rows, std::vector(cols)); + + for (std::size_t i = 0; i < rows; i++) { + prng_[i][0]->generate(cols * sizeof(block), reinterpret_cast(&(t0[i][0]))); + prng_[i][1]->generate(cols * sizeof(block), reinterpret_cast(&(t1[i][0]))); + } + + std::size_t threshhold = rows / (sizeof(block) * 8); + std::vector input(sizeof(block) * 8); + std::vector output(sizeof(block) * 8); + + std::vector> row_mat0(ext_ot_sizes_, std::vector(threshhold)); + for (std::size_t i = 0; i < cols; i++) { + for (std::size_t j = 0; j < threshhold; j++) { + for (std::size_t k = 0; k < sizeof(block) * 8; k++) { + input[k] = t0[j * sizeof(block) * 8 + k][i]; + } + matrix_transpose(input, sizeof(block) * 8, sizeof(block) * 8, output); + + for (std::size_t k = 0; k < sizeof(block) * 8; k++) { + row_mat0[i * sizeof(block) * 8 + k][j] = output[k]; + } + } + } + + std::vector> row_mat1(ext_ot_sizes_, std::vector(threshhold)); + for (std::size_t i = 0; i < cols; i++) { + for (std::size_t j = 0; j < threshhold; j++) { + for (std::size_t k = 0; k < sizeof(block) * 8; k++) { + input[k] = t1[j * sizeof(block) * 8 + k][i]; + } + matrix_transpose(input, sizeof(block) * 8, sizeof(block) * 8, output); + + for (std::size_t k = 0; k < sizeof(block) * 8; k++) { + row_mat1[i * sizeof(block) * 8 + k][j] = output[k]; + } + } + } + + auto hash = solo::Hash::create(solo::HashScheme::SHA_256); + std::vector row_mat(ext_ot_sizes_ * threshhold); + for (std::size_t i = 0; i < ext_ot_sizes_; i++) { + for (std::size_t j = 0; j < threshhold; j++) { + if (i < choices.size()) { + auto hash_in = choices[i] ^ _mm_set_epi64x(0, j); + hash->compute(reinterpret_cast(&hash_in), sizeof(block), + reinterpret_cast(&row_mat[i * threshhold + j]), sizeof(block)); + row_mat[i * threshhold + j] ^= row_mat0[i][j] ^ row_mat1[i][j] ^ choices[i]; + } else { + auto hash_in = _mm_set_epi64x(0, j); + hash->compute(reinterpret_cast(&hash_in), sizeof(block), + reinterpret_cast(&row_mat[i * threshhold + j]), sizeof(block)); + row_mat[i * threshhold + j] ^= row_mat0[i][j] ^ row_mat1[i][j]; + } + } + } + + send_block(net, row_mat.data(), ext_ot_sizes_ * threshhold); + + messages.resize(choices.size()); + for (std::size_t i = 0; i < choices.size(); i++) { + block hash_in = _mm_set_epi64x(0, 0); + for (std::size_t j = 0; j < threshhold; j++) { + hash_in ^= row_mat0[i][j] ^ _mm_set_epi64x(0, i); + hash->compute(reinterpret_cast(&hash_in), sizeof(block), + reinterpret_cast(&hash_in), sizeof(block)); + } + messages[i] = hash_in; + } + + return; +} + +} // namespace verse +} // namespace petace diff --git a/src/verse/n-choose-one/kkrt/kkrt_nco_ot_ext.h b/src/verse/n-choose-one/kkrt/kkrt_nco_ot_ext.h new file mode 100644 index 0000000..807ce03 --- /dev/null +++ b/src/verse/n-choose-one/kkrt/kkrt_nco_ot_ext.h @@ -0,0 +1,129 @@ +// Copyright 2023 TikTok Pte. Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include + +#include "network/network.h" + +#include "verse/n-choose-one/nco_ot_ext_receiver.h" +#include "verse/n-choose-one/nco_ot_ext_sender.h" +#include "verse/util/defines.h" + +namespace petace { +namespace verse { + +/** + * @brief 1-out-of-n kkrt ot extension [sender]. + * + * @see Refer to README.md for more details. + * + * @par Example. + * Refer to example.cpp. + */ +class KkrtNcoOtExtSender : public NcoOtExtSender { +public: + explicit KkrtNcoOtExtSender(const std::size_t base_ot_sizes) : NcoOtExtSender(base_ot_sizes) { + } + + ~KkrtNcoOtExtSender() { + } + + /** + * @brief The sender sets the base ots that are used to extend. + * + * @param[in] choices The chosen bits in the base ot. + * @param[in] base_send_ots Base OTs that are used for kkrt ot extension. + */ + void set_base_ots(const std::vector& choices, const std::vector& base_recv_ots) override; + + /** + * @brief The sender gets the random keys in the kkrt ot extension protocol. + * + * @param[in] net The network interface (e.g., PETAce-Network interface). + * @param[in] ext_ot_sizes The size of kkrt 1-out-of-n ot. + * @throws std::invalid_argument. + */ + void send(const std::shared_ptr& net, const std::size_t ext_ot_sizes) override; + + /** + * @brief For the OT at index idx, the sender compute the OT with choice value input. + * + * @param[in] idx The OT index that should be encoded. Each OT index allows the sender to learn many messages. + * @param[in] input The choice value that should be encoded. + * @param[out] output The OT message encoding the input. + */ + void encode(const std::size_t idx, const block& input, block& output) override; + +private: + std::vector base_choices_{}; + + std::vector> prng_{}; + + std::vector> q_mat{}; +}; + +/** + * @brief 1-out-of-n kkrt ot extension [receiver]. + * + * @see Refer to README.md for more details. + * + * @par Example. + * Refer to example.cpp. + */ +class KkrtNcoOtExtReceiver : public NcoOtExtReceiver { +public: + explicit KkrtNcoOtExtReceiver(const std::size_t base_ot_sizes) : NcoOtExtReceiver(base_ot_sizes) { + } + + ~KkrtNcoOtExtReceiver() { + } + + /** + * @brief The receiver sets the base ots that are used to extend. + * + * @param[in] base_send_ots Base OTs that are used for kkrt ot extension. + */ + void set_base_ots(const std::vector>& base_send_ots) override; + + /** + * @brief The receiver gets chosen messages indexed by choices in the kkrt ot extension protocol. + * + * @param[in] net The network interface (e.g., PETAce-Network interface). + * @param[in] choices The receiver's chosen number, which is stored in 128 bits. + * @param[out] messages The chosen messages indexed by choices. + * @throws std::invalid_argument. + */ + void receive(const std::shared_ptr& net, const std::vector& choices, + std::vector& messages); + +private: + std::vector base_choices{}; + + std::vector, 2>> prng_{}; +}; + +inline std::unique_ptr create_kkrt_ext_sender(const VerseParams& params) { + return std::make_unique(params.base_ot_sizes); +} + +inline std::unique_ptr create_kkrt_ext_receiver(const VerseParams& params) { + return std::make_unique(params.base_ot_sizes); +} + +} // namespace verse +} // namespace petace diff --git a/src/verse/n-choose-one/nco_ot_ext_receiver.h b/src/verse/n-choose-one/nco_ot_ext_receiver.h new file mode 100644 index 0000000..138bf6d --- /dev/null +++ b/src/verse/n-choose-one/nco_ot_ext_receiver.h @@ -0,0 +1,69 @@ +// Copyright 2023 TikTok Pte. Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include +#include + +#include "network/network.h" + +#include "verse/util/defines.h" + +namespace petace { +namespace verse { + +/** + * @brief 1-out-of-n ot extension framework [receiver]. + * + * @see Refer to README.md for more details. + * + * @par Example. + * Refer to example.cpp. + */ +class NcoOtExtReceiver { +public: + explicit NcoOtExtReceiver(const std::size_t base_ot_sizes) : base_ot_sizes_(base_ot_sizes) { + } + + virtual ~NcoOtExtReceiver() { + } + + /** + * @brief The receiver sets the base ots that are used to extend. + * + * @param[in] base_send_ots Base OTs that are used for 1-out-of-n ot extension. + */ + virtual void set_base_ots(const std::vector>& base_send_ots) = 0; + + /** + * @brief The receiver gets chosen messages indexed by choices in the 1-out-of-n ot extension protocol. + * + * @param[in] net The network interface (e.g., PETAce-Network interface). + * @param[in] choices The receiver's chosen number, which is stored in 128 bits block. + * @param[out] messages The chosen messages indexed by choices. + * @throws std::invalid_argument. + */ + virtual void receive(const std::shared_ptr& net, const std::vector& choices, + std::vector& messages) = 0; + +protected: + std::size_t base_ot_sizes_ = 0; + + std::size_t ext_ot_sizes_ = 0; +}; + +} // namespace verse +} // namespace petace diff --git a/src/verse/n-choose-one/nco_ot_ext_sender.h b/src/verse/n-choose-one/nco_ot_ext_sender.h new file mode 100644 index 0000000..5dcd86b --- /dev/null +++ b/src/verse/n-choose-one/nco_ot_ext_sender.h @@ -0,0 +1,76 @@ +// Copyright 2023 TikTok Pte. Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include + +#include "network/network.h" + +#include "verse/util/defines.h" + +namespace petace { +namespace verse { + +/** + * @brief 1-out-of-n ot extension framework [sender]. + * + * @see Refer to README.md for more details. + * + * @par Example. + * Refer to example.cpp. + */ +class NcoOtExtSender { +public: + explicit NcoOtExtSender(const std::size_t base_ot_sizes) : base_ot_sizes_(base_ot_sizes) { + } + + virtual ~NcoOtExtSender() { + } + + /** + * @brief The sender sets the base ots that are used to extend. + * + * @param[in] choices The chosen bits in the base ot. + * @param[in] base_send_ots Base OTs that are used for 1-out-of-n ot extension. + */ + virtual void set_base_ots(const std::vector& choices, const std::vector& base_recv_ots) = 0; + + /** + * @brief The sender gets the random keys in the 1-out-of-n ot extension protocol. + * + * @param[in] net The network interface (e.g., PETAce-Network interface). + * @param[in] ext_ot_sizes The size of 1-out-of-n ot. + * @throws std::invalid_argument. + */ + virtual void send(const std::shared_ptr& net, const std::size_t ext_ot_sizes) = 0; + + /** + * @brief For the OT at index idx, the sender compute the OT with choice value input. + * + * @param[in] idx The OT index that should be encoded. Each OT index allows the sender to learn many messages. + * @param[in] input The choice value that should be encoded. + * @param[out] output The OT message encoding the input. + */ + virtual void encode(const std::size_t idx, const block& input, block& output) = 0; + +protected: + std::size_t base_ot_sizes_ = 0; + + std::size_t ext_ot_sizes_ = 0; +}; + +} // namespace verse +} // namespace petace diff --git a/src/verse/verse_factory.h b/src/verse/verse_factory.h index 2579f27..2fac340 100644 --- a/src/verse/verse_factory.h +++ b/src/verse/verse_factory.h @@ -23,6 +23,9 @@ #include "verse/base-ot/base_ot_receiver.h" #include "verse/base-ot/base_ot_sender.h" #include "verse/base-ot/naor-pinkas-ot/naor_pinkas_ot.h" +#include "verse/n-choose-one/kkrt/kkrt_nco_ot_ext.h" +#include "verse/n-choose-one/nco_ot_ext_receiver.h" +#include "verse/n-choose-one/nco_ot_ext_sender.h" #include "verse/two-choose-one/iknp/iknp_ot_ext.h" #include "verse/two-choose-one/ot_ext_receiver.h" #include "verse/two-choose-one/ot_ext_sender.h" @@ -30,7 +33,14 @@ namespace petace { namespace verse { -enum class OTScheme : std::uint32_t { NaorPinkasSender = 0, NaorPinkasReceiver = 1, IknpSender = 2, IknpReceiver = 3 }; +enum class OTScheme : std::uint32_t { + NaorPinkasSender = 0, + NaorPinkasReceiver = 1, + IknpSender = 2, + IknpReceiver = 3, + KkrtSender = 4, + KkrtReceiver = 5 +}; template using VerseCreator = std::function(const VerseParams& params)>; @@ -118,11 +128,17 @@ class VerseRegistrar { static VerseRegistrar registrar__iknp_sender__object(scheme, creator); #define REGISTER_VERSE_EXTOT_RECEIVER(scheme, creator) \ static VerseRegistrar registrar__iknp_receiver__object(scheme, creator); +#define REGISTER_VERSE_NEXTOT_SENDER(scheme, creator) \ + static VerseRegistrar registrar__kkrt_sender__object(scheme, creator); +#define REGISTER_VERSE_NEXTOT_RECEIVER(scheme, creator) \ + static VerseRegistrar registrar__kkrt_receiver__object(scheme, creator); REGISTER_VERSE_BASE_OT_SENDER(OTScheme::NaorPinkasSender, create_naor_pinkas_sender) REGISTER_VERSE_BASE_OT_RECEIVER(OTScheme::NaorPinkasReceiver, create_naor_pinkas_receiver) REGISTER_VERSE_EXTOT_SENDER(OTScheme::IknpSender, create_iknp_ext_sender) REGISTER_VERSE_EXTOT_RECEIVER(OTScheme::IknpReceiver, create_iknp_ext_receiver) +REGISTER_VERSE_NEXTOT_SENDER(OTScheme::KkrtSender, create_kkrt_ext_sender) +REGISTER_VERSE_NEXTOT_RECEIVER(OTScheme::KkrtReceiver, create_kkrt_ext_receiver) } // namespace verse } // namespace petace diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bb38e2e..bb6c70e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -14,13 +14,13 @@ cmake_minimum_required(VERSION 3.14) -project(VERSETest VERSION 0.1.0 LANGUAGES CXX C) +project(VERSETest VERSION 0.2.0 LANGUAGES CXX C) # If not called from root CMakeLists.txt if(NOT DEFINED VERSE_BUILD_TEST) set(VERSE_BUILD_TEST ON) - find_package(PETAce-Verse 0.1.0 EXACT REQUIRED) + find_package(PETAce-Verse 0.2.0 EXACT REQUIRED) # Must define these variables and include macros set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib) @@ -63,8 +63,9 @@ if(VERSE_BUILD_TEST) # Add source files to test set(VERSE_TEST_FILES ${CMAKE_CURRENT_LIST_DIR}/test_runner.cpp - ${CMAKE_CURRENT_LIST_DIR}/np_ot_test.cpp + ${CMAKE_CURRENT_LIST_DIR}/kkrt_ot_test.cpp ${CMAKE_CURRENT_LIST_DIR}/iknp_ot_test.cpp + ${CMAKE_CURRENT_LIST_DIR}/np_ot_test.cpp ) set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} -ldl -lrt") diff --git a/test/kkrt_ot_test.cpp b/test/kkrt_ot_test.cpp new file mode 100644 index 0000000..a5f7528 --- /dev/null +++ b/test/kkrt_ot_test.cpp @@ -0,0 +1,154 @@ +// Copyright 2023 TikTok Pte. Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include +#include +#include + +#include "gtest/gtest.h" + +#include "network/net_factory.h" +#include "solo/prng.h" + +#include "verse/base-ot/naor-pinkas-ot/naor_pinkas_ot.h" +#include "verse/n-choose-one/kkrt/kkrt_nco_ot_ext.h" +#include "verse/util/common.h" +#include "verse/util/defines.h" +#include "verse/verse_factory.h" + +class KkrtOtTest : public ::testing::Test { +public: + void kkrt_ot(bool is_sender, petace::verse::VerseParams& params) { + std::size_t ext_ot_size = 500; + + petace::network::NetParams net_params; + if (is_sender) { + net_params.remote_addr = "127.0.0.1"; + net_params.remote_port = 8890; + net_params.local_addr = "127.0.0.1"; + net_params.local_port = 8891; + } else { + net_params.remote_addr = "127.0.0.1"; + net_params.remote_port = 8891; + net_params.local_addr = "127.0.0.1"; + net_params.local_port = 8890; + } + + auto net = petace::network::NetFactory::get_instance().build(petace::network::NetScheme::SOCKET, net_params); + + std::vector base_recv_ots; + std::vector> base_send_ots; + for (std::size_t i = 0; i < 4; i++) { + base_choices_.emplace_back(petace::verse::read_block_from_dev_urandom()); + } + for (std::size_t i = 0; i < ext_ot_size; i++) { + ext_choices_.emplace_back(_mm_set_epi64x(ext_ot_size - i, i)); + } + + auto npot_receiver = petace::verse::VerseFactory::get_instance().build( + petace::verse::OTScheme::NaorPinkasReceiver, params); + auto kkrt_sender = petace::verse::VerseFactory::get_instance().build( + petace::verse::OTScheme::KkrtSender, params); + + auto npot_sender = petace::verse::VerseFactory::get_instance().build( + petace::verse::OTScheme::NaorPinkasSender, params); + auto kkrt_receiver = petace::verse::VerseFactory::get_instance().build( + petace::verse::OTScheme::KkrtReceiver, params); + + if (is_sender) { + npot_receiver->receive(net, base_choices_, base_recv_ots); + kkrt_sender->set_base_ots(base_choices_, base_recv_ots); + kkrt_sender->send(net, ext_ot_size); + msg0_.resize(ext_ot_size); + for (std::size_t i = 0; i < ext_ot_size; i++) { + kkrt_sender->encode(i, ext_choices_[i], msg0_[i]); + } + petace::verse::send_block(net, msg0_.data(), msg0_.size()); + } else { + npot_sender->send(net, base_send_ots); + kkrt_receiver->set_base_ots(base_send_ots); + kkrt_receiver->receive(net, ext_choices_, msg1_); + + msg0_.resize(ext_ot_size); + petace::verse::recv_block(net, msg0_.data(), msg0_.size()); + } + } + +public: + std::vector base_choices_; + std::vector ext_choices_; + std::vector msg0_; + std::vector msg1_; +}; + +TEST_F(KkrtOtTest, kkrt_ot) { + pid_t pid; + int status; + + pid = fork(); + if (pid < 0) { + status = -1; + exit(EXIT_FAILURE); + } else if (pid == 0) { + petace::verse::VerseParams params; + params.base_ot_sizes = 512; + kkrt_ot(true, params); + exit(EXIT_SUCCESS); + } else { + petace::verse::VerseParams params; + params.base_ot_sizes = 512; + kkrt_ot(false, params); + while (waitpid(pid, &status, 0) < 0) { + if (errno != EINTR) { + status = -1; + break; + } + } + for (std::size_t i = 0; i < msg0_.size(); i++) { + ASSERT_EQ(msg1_[i][0], msg0_[i][0]); + ASSERT_EQ(msg1_[i][1], msg0_[i][1]); + } + return; + } +} + +TEST_F(KkrtOtTest, kkrt_ot_except) { + pid_t pid; + int status; + + pid = fork(); + if (pid < 0) { + status = -1; + exit(EXIT_FAILURE); + } else if (pid == 0) { + petace::verse::VerseParams params; + params.base_ot_sizes = 500; + EXPECT_THROW(kkrt_ot(true, params), std::invalid_argument); + exit(EXIT_SUCCESS); + } else { + petace::verse::VerseParams params; + params.base_ot_sizes = 500; + EXPECT_THROW(kkrt_ot(false, params), std::invalid_argument); + while (waitpid(pid, &status, 0) < 0) { + if (errno != EINTR) { + status = -1; + break; + } + } + return; + } +}