├── tests ├── FileBase_Tests.h ├── MPSI_Tests.h ├── RsOprf_Tests.h ├── UnitTests.h ├── RsCpsi_Tests.h ├── RsPsi_Tests.h ├── Common.h ├── RsOpprf_Tests.h ├── CMakeLists.txt ├── GMW_Tests.h ├── Paxos_Tests.h ├── RsOprf_Tests.cpp ├── RsPsi_Tests.cpp ├── RsOpprf_Tests.cpp ├── UnitTests.cpp ├── RsCpsi_Tests.cpp └── FileBase_Tests.cpp ├── .gitignore ├── volepsi_misc ├── blazingFastPSI.pdf └── todo.txt ├── volePSI ├── config.h.in ├── RpmtPsu.h ├── Mpsi.h ├── GMW │ ├── Circuit.h │ ├── Circuit.cpp │ ├── SilentTripleGen.h │ └── Gmw.h ├── Defines.h ├── fileBased.h ├── RsPsi.h ├── CMakeLists.txt ├── RsOprf.h ├── SimpleIndex.h ├── RsCpsi.h ├── RsOpprf.h ├── RsOpprf.cpp ├── RsCpsi.cpp ├── RsPsi.cpp ├── RsOprf.cpp └── RpmtPsu.cpp ├── cmake ├── volePSIConfig.cmake ├── Config.cmake.in ├── install.cmake ├── findDependancies.cmake ├── preamble.cmake └── buildOptions.cmake ├── dockerfile ├── CMakeLists.txt ├── frontend ├── CMakeLists.txt ├── perf.h ├── networkSocketExample.h ├── main.cpp └── messagePassingExample.h ├── volepsi_LICENSE ├── LICENSE ├── thirdparty ├── fetch.cmake ├── getSparsehash.cmake └── getLibOTe.cmake ├── CMakePresets.json ├── volepsi_README.md └── README.md /tests/FileBase_Tests.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orzcy/BZS-MPSI/HEAD/tests/FileBase_Tests.h -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | .vscode/ 3 | out/ 4 | thirdparty/ 5 | tests/cmakeTests/ 6 | CMakeSettings.json 7 | ~/ 8 | -------------------------------------------------------------------------------- /volepsi_misc/blazingFastPSI.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orzcy/BZS-MPSI/HEAD/volepsi_misc/blazingFastPSI.pdf -------------------------------------------------------------------------------- /volePSI/config.h.in: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | // compile the library with GMW 5 | #cmakedefine VOLE_PSI_ENABLE_GMW @VOLE_PSI_ENABLE_GMW@ 6 | 7 | // compile the library with circuit psi 8 | #cmakedefine VOLE_PSI_ENABLE_CPSI @VOLE_PSI_ENABLE_CPSI@ 9 | 10 | 11 | // compile the library with OPPRF 12 | #cmakedefine VOLE_PSI_ENABLE_OPPRF @VOLE_PSI_ENABLE_OPPRF@ 13 | -------------------------------------------------------------------------------- /volepsi_misc/todo.txt: -------------------------------------------------------------------------------- 1 | 2 | - getGapCols in poly time. 3 | - compress hashes. 4 | - paxos doDense *only* iterates over used columns, as opposed to all of them. 5 | - baxos par solve, remove vector -> std::vector hashes_(mNumItems); 6 | - optimize/minimize threadBinSize 7 | 8 | - on decode, allow unordered output? 9 | 10 | - Research question: fewer AES rounds if we only want the first bit to be random? maybe the XOR of the bits? -------------------------------------------------------------------------------- /cmake/volePSIConfig.cmake: -------------------------------------------------------------------------------- 1 | # these are just pass through config file for the ones that are placed in the build directory. 2 | 3 | 4 | include("${CMAKE_CURRENT_LIST_DIR}/preamble.cmake") 5 | 6 | if(NOT EXISTS "${VOLEPSI_BUILD_DIR}") 7 | message(FATAL_ERROR "failed to find the volePSI build directory. Looked at VOLEPSI_BUILD_DIR: ${VOLEPSI_BUILD_DIR}\n Please set it manually.") 8 | endif() 9 | 10 | include("${VOLEPSI_BUILD_DIR}/volePSIConfig.cmake") -------------------------------------------------------------------------------- /dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y build-essential cmake git libtool iproute2 python3 sudo && \ 5 | rm -rf /var/lib/apt/lists/* 6 | 7 | WORKDIR /app 8 | 9 | RUN git clone https://github.com/orzcy/BZS-MPSI.git 10 | 11 | WORKDIR /app/BZS-MPSI 12 | 13 | RUN python3 build.py -DVOLE_PSI_ENABLE_BOOST=ON && \ 14 | rm -rf ./out/bitpolymul ./out/boost_1_86_0 ./out/coproto ./out/function2 \ 15 | ./out/libdivide ./out/libOTe ./out/libsodium ./out/macoro 16 | 17 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.15) 2 | 3 | project(volePSI VERSION 0.1.2) 4 | 5 | set(VOLEPSI_BUILD ON) 6 | 7 | # sets some variables 8 | include(cmake/preamble.cmake) 9 | 10 | # sets build option 11 | include(cmake/buildOptions.cmake) 12 | 13 | # find all the dependancies. 14 | include(cmake/findDependancies.cmake) 15 | 16 | # build volePSI 17 | add_subdirectory(volePSI) 18 | 19 | # build the tests. 20 | add_subdirectory(tests) 21 | 22 | # link the executable. 23 | add_subdirectory(frontend) 24 | 25 | # setup the install 26 | include(cmake/install.cmake) -------------------------------------------------------------------------------- /volePSI/RpmtPsu.h: -------------------------------------------------------------------------------- 1 | #include "volePSI/Defines.h" 2 | #include "volePSI/RsOprf.h" 3 | #include "volePSI/RsPsi.h" 4 | #include "sparsehash/dense_hash_map" 5 | #include "cryptoTools/Common/Timer.h" 6 | 7 | namespace volePSI 8 | { 9 | class RpmtPsu_User : public oc::TimerAdapter 10 | { 11 | public: 12 | size_t Comm = 0; 13 | size_t Size_Different = 0; 14 | std::vector Different; 15 | void run(bool My_Role, u64 Sender_Set_Size, u64 Receiver_Set_Size, u64 Lambda, u64 Thread_Num, block Seed, std::vector Inputs, Socket& Chl); 16 | }; 17 | } -------------------------------------------------------------------------------- /frontend/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | file(GLOB_RECURSE SRCS *.cpp) 3 | 4 | add_executable(frontend ${SRCS}) 5 | 6 | target_link_libraries(frontend volePSI_Tests) 7 | target_link_libraries(frontend MPSI_Tests) 8 | 9 | 10 | if(VOLE_PSI_NO_LTO) 11 | target_link_options(frontend PUBLIC "-fno-lto") 12 | endif() 13 | 14 | 15 | 16 | if(MSVC) 17 | target_compile_options(frontend PRIVATE $<$:/std:c++${VOLE_PSI_STD_VER}>) 18 | #target_compile_options(libOTe PRIVATE -openmp:experimental) 19 | else() 20 | target_compile_options(frontend PRIVATE $<$:-std=c++${VOLE_PSI_STD_VER}>) 21 | endif() -------------------------------------------------------------------------------- /volePSI/Mpsi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "volePSI/Defines.h" 4 | #include "volePSI/RsOprf.h" 5 | #include "volePSI/RsPsi.h" 6 | #include "volePSI/RsCpsi.h" 7 | #include "sparsehash/dense_hash_map" 8 | #include "cryptoTools/Common/Timer.h" 9 | 10 | namespace volePSI 11 | { 12 | class Mpsi_User : public oc::TimerAdapter 13 | { 14 | public: 15 | size_t Comm = 0; 16 | size_t Size_Intersection = 0; 17 | std::vector Multi_Intersection; 18 | RsCpsiSender::Sharing Sender_Cpsi_Results; 19 | RsCpsiReceiver::Sharing Receiver_Cpsi_Results; 20 | void run(u64 User_Num, u64 My_Id, u64 Set_Size[], u64 Lambda, u64 Thread_Num, block Seed, std::vector Inputs, std::vector Chl, bool PSI_CA = false, bool Circuit = false, bool broadcast = false, bool Mal = false); 21 | }; 22 | } -------------------------------------------------------------------------------- /tests/MPSI_Tests.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "cryptoTools/Common/CLP.h" 4 | 5 | void MPSI_3Party_Empty_Test(const oc::CLP&); 6 | void MPSI_3Party_Partial_Test(const oc::CLP&); 7 | void MPSI_3Party_Full_Test(const oc::CLP&); 8 | void MPSI_3Party_Mthreads_Test(const oc::CLP&); 9 | void MPSI_3Party_Cardinality_Test(const oc::CLP&); 10 | void MPSI_3Party_Circuit_Test(const oc::CLP&); 11 | void MPSI_3Party_Broadcast_Test(const oc::CLP&); 12 | void MPSI_3Party_Malicious_Test(const oc::CLP& cmd); 13 | 14 | void MPSI_5Party_Empty_Test(const oc::CLP&); 15 | void MPSI_5Party_Partial_Test(const oc::CLP&); 16 | void MPSI_5Party_Full_Test(const oc::CLP&); 17 | void MPSI_5Party_Mthreads_Test(const oc::CLP&); 18 | void MPSI_5Party_Cardinality_Test(const oc::CLP&); 19 | void MPSI_5Party_Circuit_Test(const oc::CLP&); 20 | void MPSI_5Party_Broadcast_Test(const oc::CLP&); 21 | void MPSI_5Party_Malicious_Test(const oc::CLP& cmd); -------------------------------------------------------------------------------- /volepsi_LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2022 Visa 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /cmake/Config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | 4 | set(VOLE_PSI_ENABLE_SSE @VOLE_PSI_ENABLE_SSE@) 5 | set(VOLE_PSI_PIC @VOLE_PSI_PIC@) 6 | set(VOLE_PSI_STD_VER @VOLE_PSI_STD_VER@) 7 | set(VOLE_PSI_ENABLE_GMW @VOLE_PSI_ENABLE_GMW@) 8 | set(VOLE_PSI_ENABLE_CPSI @VOLE_PSI_ENABLE_CPSI@) 9 | set(VOLE_PSI_ENABLE_OPPRF @VOLE_PSI_ENABLE_OPPRF@) 10 | set(VOLE_PSI_ENABLE_BOOST @VOLE_PSI_ENABLE_BOOST@) 11 | set(VOLE_PSI_ENABLE_OPENSSL @VOLE_PSI_ENABLE_OPENSSL@) 12 | set(VOLE_PSI_ENABLE_BITPOLYMUL @VOLE_PSI_ENABLE_BITPOLYMUL@) 13 | set(VOLE_PSI_ENABLE_SODIUM @VOLE_PSI_ENABLE_SODIUM@) 14 | set(VOLE_PSI_SODIUM_MONTGOMERY @VOLE_PSI_SODIUM_MONTGOMERY@) 15 | set(VOLE_PSI_ENABLE_RELIC @VOLE_PSI_ENABLE_RELIC@) 16 | 17 | include("${CMAKE_CURRENT_LIST_DIR}/volePSITargets.cmake") 18 | 19 | include("${CMAKE_CURRENT_LIST_DIR}/findDependancies.cmake") 20 | 21 | 22 | get_target_property(volePSI_INCLUDE_DIRS visa::volePSI INTERFACE_INCLUDE_DIRECTORIES) 23 | 24 | get_target_property(volePSI_LIBRARIES visa::volePSI LOCATION) 25 | 26 | message("volePSI_INCLUDE_DIRS=${volePSI_INCLUDE_DIRS}") 27 | message("volePSI_LIBRARIES=${volePSI_LIBRARIES}") 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 orzcy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tests/RsOprf_Tests.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // © 2022 Visa. 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | #include "cryptoTools/Common/CLP.h" 10 | 11 | 12 | void RsOprf_eval_test(const oc::CLP&); 13 | void RsOprf_mal_test(const oc::CLP&); 14 | void RsOprf_reduced_test(const oc::CLP&); -------------------------------------------------------------------------------- /tests/UnitTests.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // © 2022 Visa. 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | 10 | #include 11 | namespace volePSI_Tests 12 | { 13 | extern osuCrypto::TestCollection Tests; 14 | } 15 | namespace MPSI_Tests 16 | { 17 | extern osuCrypto::TestCollection Tests; 18 | } -------------------------------------------------------------------------------- /thirdparty/fetch.cmake: -------------------------------------------------------------------------------- 1 | 2 | 3 | function(RUN) 4 | cmake_parse_arguments( 5 | PARSED_ARGS # prefix of parameters 6 | "" # list of names of the boolean arguments (only defined ones will be true) 7 | "WD" # list of names of mono-valued arguments 8 | "CMD;NAME" # list of names of multi-valued arguments (output variables are lists) 9 | ${ARGN} # arguments of the function to parse, here we take the all original ones 10 | ) 11 | message("${PARSED_ARGS_NAME}") 12 | 13 | string (REPLACE "%" "\;" PARSED_ARGS_CMD_STR "${PARSED_ARGS_CMD}") 14 | 15 | execute_process( 16 | COMMAND ${PARSED_ARGS_CMD_STR} 17 | WORKING_DIRECTORY ${PARSED_ARGS_WD} 18 | RESULT_VARIABLE RESULT 19 | COMMAND_ECHO STDOUT 20 | ) 21 | if(RESULT) 22 | file(READ ${LOG_FILE} LOG_STRING) 23 | message(FATAL_ERROR "${PARSED_ARGS_NAME} failed (${RESULT}).") 24 | 25 | endif() 26 | endfunction() 27 | 28 | 29 | 30 | if(NOT MSVC AND SUDO_FETCH) 31 | set(SUDO "sudo ") 32 | endif() 33 | 34 | if(NOT DEFINED PARALLEL_FETCH) 35 | include(ProcessorCount) 36 | ProcessorCount(NUM_PROCESSORS) 37 | if(NOT NUM_PROCESSORS EQUAL 0) 38 | set(PARALLEL_FETCH ${NUM_PROCESSORS}) 39 | else() 40 | set(PARALLEL_FETCH 1) 41 | endif() 42 | endif() -------------------------------------------------------------------------------- /tests/RsCpsi_Tests.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // © 2022 Visa. 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | #include "cryptoTools/Common/CLP.h" 10 | #include "volePSI/config.h" 11 | 12 | void Cpsi_Rs_empty_test(const oc::CLP&); 13 | void Cpsi_Rs_partial_test(const oc::CLP&); 14 | void Cpsi_Rs_full_test(const oc::CLP&); 15 | void Cpsi_Rs_full_asym_test(const oc::CLP&); 16 | void Cpsi_Rs_full_add32_test(const oc::CLP&); 17 | -------------------------------------------------------------------------------- /tests/RsPsi_Tests.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // © 2022 Visa. 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | #include "cryptoTools/Common/CLP.h" 10 | #include "volePSI/Defines.h" 11 | 12 | void Psi_Rs_empty_test(const oc::CLP&); 13 | void Psi_Rs_partial_test(const oc::CLP&); 14 | void Psi_Rs_full_test(const oc::CLP&); 15 | void Psi_Rs_reduced_test(const oc::CLP&); 16 | void Psi_Rs_multiThrd_test(const oc::CLP&); 17 | void Psi_Rs_mal_test(const oc::CLP&); 18 | -------------------------------------------------------------------------------- /frontend/perf.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // © 2022 Visa. 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | // 6 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | // 8 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | 10 | #include "cryptoTools/Common/CLP.h" 11 | 12 | void overflow(oc::CLP& cmd); 13 | void perfMod(oc::CLP& cmd); 14 | 15 | void perfBaxos(oc::CLP& cmd); 16 | 17 | 18 | void perfBuildRow(oc::CLP& cmd); 19 | void perfPaxos(oc::CLP& cmd); 20 | void perfPSI(oc::CLP& cmd); 21 | void perfCPSI(oc::CLP& cmd); 22 | void perfMpsi_User(oc::CLP& cmd); 23 | 24 | void perf(oc::CLP& cmd); -------------------------------------------------------------------------------- /tests/Common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // © 2022 Visa. 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | #include "macoro/task.h" 10 | #include "macoro/sync_wait.h" 11 | #include "macoro/when_all.h" 12 | 13 | namespace 14 | { 15 | inline auto eval(macoro::task<>& t0, macoro::task<>& t1) 16 | { 17 | auto r = macoro::sync_wait(macoro::when_all_ready(std::move(t0), std::move(t1))); 18 | std::get<0>(r).result(); 19 | std::get<1>(r).result(); 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /tests/RsOpprf_Tests.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // © 2022 Visa. 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | #include "cryptoTools/Common/TestCollection.h" 10 | #include "volePSI/Defines.h" 11 | #include "volePSI/config.h" 12 | 13 | #ifdef VOLE_PSI_ENABLE_OPPRF 14 | 15 | 16 | void RsOpprf_eval_blk_test(const oc::CLP&); 17 | void RsOpprf_eval_blk_mtx_test(const oc::CLP&); 18 | 19 | void RsOpprf_eval_u8_test(const oc::CLP&); 20 | void RsOpprf_eval_u8_mtx_test(const oc::CLP&); 21 | #endif -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | ############################################# 4 | # Build volePSI_Tests # 5 | ############################################# 6 | 7 | 8 | set(SRCS 9 | "Paxos_Tests.cpp" 10 | "RsOprf_Tests.cpp" 11 | "RsPsi_Tests.cpp" 12 | "UnitTests.cpp" 13 | "FileBase_Tests.cpp" 14 | "MPSI_Tests.cpp" 15 | ) 16 | 17 | if(VOLE_PSI_ENABLE_GMW) 18 | list(APPEND SRCS 19 | "GMW_Tests.cpp" 20 | ) 21 | endif() 22 | 23 | if(VOLE_PSI_ENABLE_CPSI) 24 | list(APPEND SRCS 25 | "RsCpsi_Tests.cpp" 26 | ) 27 | endif() 28 | if(VOLE_PSI_ENABLE_OPPRF) 29 | list(APPEND SRCS 30 | "RsOpprf_Tests.cpp" 31 | ) 32 | endif() 33 | 34 | add_library(volePSI_Tests ${SRCS}) 35 | 36 | target_link_libraries(volePSI_Tests volePSI) 37 | 38 | 39 | if(MSVC) 40 | target_compile_options(volePSI_Tests PRIVATE $<$:/std:c++${VOLE_PSI_STD_VER}>) 41 | #target_compile_options(libOTe PRIVATE -openmp:experimental) 42 | else() 43 | target_compile_options(volePSI_Tests PRIVATE $<$:-std=c++${VOLE_PSI_STD_VER}>) 44 | endif() 45 | 46 | add_library(MPSI_Tests ${SRCS}) 47 | 48 | target_link_libraries(MPSI_Tests volePSI) 49 | 50 | 51 | if(MSVC) 52 | target_compile_options(MPSI_Tests PRIVATE $<$:/std:c++${VOLE_PSI_STD_VER}>) 53 | #target_compile_options(libOTe PRIVATE -openmp:experimental) 54 | else() 55 | target_compile_options(MPSI_Tests PRIVATE $<$:-std=c++${VOLE_PSI_STD_VER}>) 56 | endif() -------------------------------------------------------------------------------- /volePSI/GMW/Circuit.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // © 2022 Visa. 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | 10 | #include "volePSI/Defines.h" 11 | #include "volePSI/config.h" 12 | #ifdef VOLE_PSI_ENABLE_GMW 13 | #include "cryptoTools/Circuit/BetaCircuit.h" 14 | 15 | namespace volePSI 16 | { 17 | #ifndef ENABLE_CIRCUITS 18 | static_assert(0, "ENABLE_CIRCUITS not defined in cryptoTools"); 19 | #endif 20 | 21 | using BetaCircuit = oc::BetaCircuit; 22 | using BetaBundle = oc::BetaBundle; 23 | 24 | 25 | BetaCircuit isZeroCircuit(u64 bits); 26 | 27 | void isZeroCircuit_Test(); 28 | } 29 | 30 | #endif -------------------------------------------------------------------------------- /tests/GMW_Tests.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // © 2022 Visa. 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | #include "cryptoTools/Common/CLP.h" 10 | #include "volePSI/config.h" 11 | #ifdef VOLE_PSI_ENABLE_GMW 12 | 13 | void generateBase_test(); 14 | void SilentTripleGen_test(); 15 | //void IknpTripleGen_test(); 16 | 17 | 18 | 19 | void Gmw_half_test(const oc::CLP& cmd); 20 | void Gmw_basic_test(const oc::CLP& cmd); 21 | void Gmw_inOut_test(const oc::CLP& cmd); 22 | void Gmw_xor_test(const oc::CLP& cmd); 23 | void Gmw_and_test(const oc::CLP& cmd); 24 | void Gmw_na_and_test(const oc::CLP& cmd); 25 | void Gmw_or_test(const oc::CLP& cmd); 26 | void Gmw_xor_and_test(const oc::CLP& cmd); 27 | void Gmw_aa_na_and_test(const oc::CLP& cmd); 28 | 29 | void Gmw_add_test(const oc::CLP& cmd); 30 | void Gmw_noLevelize_test(const oc::CLP& cmd); 31 | 32 | #endif -------------------------------------------------------------------------------- /tests/Paxos_Tests.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // © 2022 Visa. 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | 10 | #include "cryptoTools/Common/CLP.h" 11 | 12 | void Paxos_buildRow_Test(const oc::CLP& cmd); 13 | void Paxos_solve_Test(const oc::CLP& cmd); 14 | void Paxos_solve_u8_Test(const oc::CLP& cmd); 15 | void Paxos_solve_mtx_Test(const oc::CLP& cmd); 16 | void Paxos_invE_Test(const oc::CLP& cmd); 17 | void Paxos_invE_g3_Test(const oc::CLP& cmd); 18 | void Paxos_solve_gap_Test(const oc::CLP& cmd); 19 | void Paxos_solve_rand_Test(const oc::CLP& cmd); 20 | void Paxos_solve_rand_gap_Test(const oc::CLP& cmd); 21 | 22 | void Baxos_solve_Test(const oc::CLP& cmd); 23 | void Baxos_solve_mtx_Test(const oc::CLP& cmd); 24 | void Baxos_solve_par_Test(const oc::CLP& cmd); 25 | void Baxos_solve_rand_Test(const oc::CLP& cmd); 26 | void Baxos_solve_rand_gap_Test(const oc::CLP& cmd); 27 | 28 | 29 | 30 | void Paxos_experiment(const oc::CLP& cmd); -------------------------------------------------------------------------------- /volePSI/Defines.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // © 2022 Visa. 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | #include "cryptoTools/Common/Defines.h" 10 | #include "cryptoTools/Common/Matrix.h" 11 | #include "cryptoTools/Common/BitVector.h" 12 | #include "cryptoTools/Crypto/PRNG.h" 13 | #include "coproto/coproto.h" 14 | 15 | namespace volePSI 16 | { 17 | 18 | using u64 = oc::u64; 19 | using u32 = oc::u32; 20 | using u16 = oc::u16; 21 | using u8 = oc::u8; 22 | 23 | using i64 = oc::i64; 24 | using i32 = oc::i32; 25 | using i16 = oc::i16; 26 | using i8 = oc::i8; 27 | 28 | using block = oc::block; 29 | 30 | template 31 | using span = oc::span; 32 | template 33 | using Matrix = oc::Matrix; 34 | template 35 | using MatrixView = oc::MatrixView; 36 | 37 | enum Mode { 38 | Sender = 1, 39 | Receiver = 2 40 | //Dual = 3 41 | }; 42 | 43 | struct RequiredBase 44 | { 45 | u64 mNumSend; 46 | oc::BitVector mRecvChoiceBits; 47 | }; 48 | 49 | 50 | using PRNG = oc::PRNG; 51 | using Socket = coproto::Socket; 52 | using Proto = coproto::task; 53 | 54 | } 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /volePSI/fileBased.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // � 2022 Visa. 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "Defines.h" 15 | #include "cryptoTools/Common/CLP.h" 16 | 17 | namespace volePSI 18 | { 19 | 20 | 21 | std::ifstream::pos_type filesize(std::ifstream& file); 22 | 23 | bool hasSuffix(std::string const& value, std::string const& ending); 24 | 25 | bool isHexBlock(const std::string& buff); 26 | block hexToBlock(const std::string& buff); 27 | 28 | enum class FileType 29 | { 30 | Bin, 31 | Csv, 32 | Unspecified 33 | }; 34 | 35 | enum class Role { 36 | Sender = 0, 37 | Receiver = 1, 38 | Invalid 39 | }; 40 | 41 | std::vector readSet(const std::string& path, FileType ft, bool debug); 42 | 43 | void doFilePSI(const oc::CLP& cmd); 44 | void doFileMPSI(const oc::CLP& cmd); 45 | void doFilePSU(const oc::CLP& cmd); 46 | 47 | inline 48 | bool exist(std::string path) 49 | { 50 | std::fstream stream; 51 | stream.open(path.c_str(), std::ios::in); 52 | return stream.is_open(); 53 | } 54 | 55 | } 56 | 57 | -------------------------------------------------------------------------------- /cmake/install.cmake: -------------------------------------------------------------------------------- 1 | 2 | 3 | ############################################# 4 | # Install # 5 | ############################################# 6 | 7 | 8 | configure_file("${CMAKE_CURRENT_LIST_DIR}/findDependancies.cmake" "findDependancies.cmake" COPYONLY) 9 | configure_file("${CMAKE_CURRENT_LIST_DIR}/preamble.cmake" "preamble.cmake" COPYONLY) 10 | 11 | # make cache variables for install destinations 12 | include(GNUInstallDirs) 13 | include(CMakePackageConfigHelpers) 14 | 15 | 16 | # generate the config file that is includes the exports 17 | configure_package_config_file( 18 | "${CMAKE_CURRENT_LIST_DIR}/Config.cmake.in" 19 | "${CMAKE_CURRENT_BINARY_DIR}/volePSIConfig.cmake" 20 | INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/volePSI 21 | NO_SET_AND_CHECK_MACRO 22 | NO_CHECK_REQUIRED_COMPONENTS_MACRO 23 | ) 24 | 25 | if(NOT DEFINED volePSI_VERSION_MAJOR) 26 | message("\n\n\n\n warning, volePSI_VERSION_MAJOR not defined ${volePSI_VERSION_MAJOR}") 27 | endif() 28 | 29 | set_property(TARGET volePSI PROPERTY VERSION ${volePSI_VERSION}) 30 | 31 | # generate the version file for the config file 32 | write_basic_package_version_file( 33 | "${CMAKE_CURRENT_BINARY_DIR}/volePSIConfigVersion.cmake" 34 | VERSION "${volePSI_VERSION_MAJOR}.${volePSI_VERSION_MINOR}.${volePSI_VERSION_PATCH}" 35 | COMPATIBILITY AnyNewerVersion 36 | ) 37 | 38 | # install the configuration file 39 | install(FILES 40 | "${CMAKE_CURRENT_BINARY_DIR}/volePSIConfig.cmake" 41 | "${CMAKE_CURRENT_BINARY_DIR}/volePSIConfigVersion.cmake" 42 | "${CMAKE_CURRENT_BINARY_DIR}/findDependancies.cmake" 43 | "${CMAKE_CURRENT_BINARY_DIR}/preamble.cmake" 44 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/volePSI 45 | ) 46 | 47 | # install library 48 | install( 49 | TARGETS volePSI 50 | DESTINATION ${CMAKE_INSTALL_LIBDIR} 51 | EXPORT volePSITargets) 52 | 53 | # install headers 54 | install( 55 | DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/../volePSI" 56 | DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/" 57 | FILES_MATCHING PATTERN "*.h") 58 | 59 | 60 | # install config 61 | install(EXPORT volePSITargets 62 | FILE volePSITargets.cmake 63 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/volePSI 64 | NAMESPACE visa:: 65 | ) 66 | export(EXPORT volePSITargets 67 | FILE "${CMAKE_CURRENT_BINARY_DIR}/volePSITargets.cmake" 68 | NAMESPACE visa:: 69 | ) -------------------------------------------------------------------------------- /volePSI/GMW/Circuit.cpp: -------------------------------------------------------------------------------- 1 | #include "Circuit.h" 2 | #include 3 | namespace volePSI 4 | { 5 | 6 | BetaCircuit isZeroCircuit(u64 bits) 7 | { 8 | BetaCircuit cd; 9 | 10 | BetaBundle a(bits); 11 | 12 | cd.addInputBundle(a); 13 | 14 | //for (u64 i = 1; i < bits; ++i) 15 | // cd.addGate(a.mWires[i], a.mWires[i], oc::GateType::Nxor, a.mWires[i]); 16 | auto ts = [](int s) {return std::to_string(s); }; 17 | u64 step = 1; 18 | 19 | for (u64 i = 0; i < bits; ++i) 20 | cd.addInvert(a[i]); 21 | 22 | while (step < bits) 23 | { 24 | //std::cout << "\n step " << step << std::endl; 25 | cd.addPrint("\n step " + ts(step) + "\n"); 26 | for (u64 i = 0; i + step < bits; i += step * 2) 27 | { 28 | cd.addPrint("a[" + ts(i) + "] & a[" + ts(i + step) + "] -> a[" + ts(i) + "]\n"); 29 | cd.addPrint(a.mWires[i]); 30 | cd.addPrint(" & "); 31 | cd.addPrint(a.mWires[i + step]); 32 | cd.addPrint(" -> "); 33 | cd.addPrint(a.mWires[i]); 34 | //cd.addPrint("a[" + ts(i)+ "] &= a[" +ts(i + step) + "]\n"); 35 | 36 | //std::cout << "a[" << i << "] &= a[" << (i + step) << "]" << std::endl; 37 | cd.addGate(a.mWires[i], a.mWires[i + step], oc::GateType::And, a.mWires[i]); 38 | } 39 | 40 | step *= 2; 41 | } 42 | //cd.addOutputBundle() 43 | a.mWires.resize(1); 44 | cd.mOutputs.push_back(a); 45 | 46 | cd.levelByAndDepth(); 47 | 48 | return cd; 49 | } 50 | 51 | void isZeroCircuit_Test() 52 | { 53 | u64 n = 128, tt = 100; 54 | auto cir = isZeroCircuit(n); 55 | 56 | { 57 | oc::BitVector bv(n), out(1); 58 | cir.evaluate({ &bv, 1 }, { &out,1 }, false); 59 | 60 | if (out[0] != 1) 61 | throw RTE_LOC; 62 | } 63 | 64 | oc::PRNG prng(oc::ZeroBlock); 65 | 66 | for (u64 i = 0; i < tt; ++i) 67 | { 68 | oc::BitVector bv(n), out(1); 69 | bv.randomize(prng); 70 | if (bv.hammingWeight() == 0) 71 | continue; 72 | 73 | cir.evaluate({ &bv, 1 }, { &out,1 }, false); 74 | 75 | if (out[0] != 0) 76 | throw RTE_LOC; 77 | } 78 | 79 | 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /volePSI/RsPsi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // © 2022 Visa. 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | 10 | #include "volePSI/Defines.h" 11 | #include "volePSI/RsOprf.h" 12 | #include "sparsehash/dense_hash_map" 13 | #include "cryptoTools/Common/Timer.h" 14 | 15 | namespace volePSI 16 | { 17 | namespace details 18 | { 19 | struct RsPsiBase 20 | { 21 | 22 | u64 mSenderSize = 0; 23 | u64 mRecverSize = 0; 24 | u64 mSsp = 0; 25 | PRNG mPrng; 26 | bool mMalicious = false; 27 | bool mCompress = true; 28 | u64 mNumThreads = 0; 29 | u64 mMaskSize = 0; 30 | bool mUseReducedRounds = false; 31 | bool mDebug = false; 32 | 33 | void init(u64 senderSize, u64 recverSize, u64 statSecParam, block seed, bool malicious, u64 numThreads, bool useReducedRounds = false); 34 | 35 | }; 36 | } 37 | 38 | class RsPsiSender : public details::RsPsiBase, public oc::TimerAdapter 39 | { 40 | public: 41 | 42 | RsOprfSender mSender; 43 | void setMultType(oc::MultType type) { mSender.setMultType(type); }; 44 | 45 | 46 | Proto run(span inputs, Socket& chl); 47 | }; 48 | 49 | 50 | class RsPsiReceiver : public details::RsPsiBase, public oc::TimerAdapter 51 | { 52 | public: 53 | RsOprfReceiver mRecver; 54 | void setMultType(oc::MultType type) { mRecver.setMultType(type); }; 55 | 56 | std::vector mIntersection; 57 | 58 | Proto run(span inputs, Socket& chl); 59 | }; 60 | } -------------------------------------------------------------------------------- /thirdparty/getSparsehash.cmake: -------------------------------------------------------------------------------- 1 | set(DEP_NAME sparsehash-c11) 2 | set(GIT_REPOSITORY https://github.com/sparsehash/sparsehash-c11.git) 3 | set(GIT_TAG "edd6f1180156e76facc1c0449da245208ab39503" ) 4 | 5 | set(CLONE_DIR "${CMAKE_CURRENT_LIST_DIR}/${DEP_NAME}") 6 | set(BUILD_DIR "${CLONE_DIR}/build/${VOLEPSI_CONFIG}") 7 | set(LOG_FILE "${CMAKE_CURRENT_LIST_DIR}/log-${DEP_NAME}.txt") 8 | 9 | 10 | include("${CMAKE_CURRENT_LIST_DIR}/fetch.cmake") 11 | 12 | if(NOT SPARSEHASH_FOUND) 13 | find_program(GIT git REQUIRED) 14 | set(DOWNLOAD_CMD ${GIT} clone ${GIT_REPOSITORY}) 15 | set(CHECKOUT_CMD ${GIT} checkout ${GIT_TAG}) 16 | 17 | message("============= Building ${DEP_NAME} =============") 18 | if(NOT EXISTS ${CLONE_DIR}) 19 | run(NAME "Cloning ${GIT_REPOSITORY}" CMD ${DOWNLOAD_CMD} WD ${CMAKE_CURRENT_LIST_DIR}) 20 | endif() 21 | 22 | run(NAME "Checkout ${GIT_TAG} " CMD ${CHECKOUT_CMD} WD ${CLONE_DIR}) 23 | file(COPY ${CLONE_DIR}/sparsehash DESTINATION ${VOLEPSI_THIRDPARTY_DIR}/include/) 24 | #if(MSVC) 25 | # message("Install") 26 | # file(COPY ${CLONE_DIR}/src/windows/sparsehash DESTINATION ${VOLEPSI_THIRDPARTY_DIR}/include/) 27 | #else() 28 | # file(COPY ${CLONE_DIR}/src/sparsehash DESTINATION ${VOLEPSI_THIRDPARTY_DIR}/include/) 29 | # #run("Configure" CMD ./configure --prefix=${VOLEPSI_THIRDPARTY_DIR} WD ${CLONE_DIR}) 30 | # #run("make" CMD make -j ${PARALLEL_FETCH} WD ${CLONE_DIR}) 31 | # #run("install" CMD make install WD ${CLONE_DIR}) 32 | #endif() 33 | message("log ${LOG_FILE}\n==========================================") 34 | else() 35 | message("${DEP_NAME} already fetched.") 36 | endif() 37 | 38 | 39 | install(CODE "message(\"sparsehash begin ------------------\")") 40 | install( 41 | DIRECTORY "${CLONE_DIR}/sparsehash" 42 | DESTINATION "include") 43 | 44 | install(CODE "message(\"sparsehash end ------------------\")") 45 | 46 | 47 | #install(CODE " 48 | # if(MSVC) 49 | # file(COPY ${CLONE_DIR}/src/sparsehash DESTINATION \${CMAKE_INSTALL_PREFIX}/include/) 50 | # file(COPY ${CLONE_DIR}/src/windows/sparsehash DESTINATION \${CMAKE_INSTALL_PREFIX}/include/) 51 | # else() 52 | # message(\"sparse hash install\") 53 | # execute_process( 54 | # COMMAND ./configure --prefix= 55 | # COMMAND make -j ${PARALLEL_FETCH} 56 | # COMMAND ${SUDO} make DESTDIR= install 57 | # WORKING_DIRECTORY ${CLONE_DIR} 58 | # RESULT_VARIABLE RESULT 59 | # COMMAND_ECHO STDOUT 60 | # ) 61 | # message(\"sparse hash install done\") 62 | # 63 | # endif() 64 | #") -------------------------------------------------------------------------------- /volePSI/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | configure_file(config.h.in "config.h" ) 3 | 4 | 5 | set(SRCS 6 | "RsOprf.cpp" 7 | "RsPsi.cpp" 8 | "SimpleIndex.cpp" 9 | "fileBased.cpp" 10 | "Mpsi.cpp" 11 | "RpmtPsu.cpp" 12 | ) 13 | 14 | if(VOLE_PSI_ENABLE_GMW) 15 | list(APPEND SRCS 16 | "GMW/Circuit.cpp" 17 | "GMW/Gmw.cpp" 18 | "GMW/SilentTripleGen.cpp" 19 | ) 20 | endif() 21 | 22 | if(VOLE_PSI_ENABLE_CPSI) 23 | list(APPEND SRCS 24 | "RsCpsi.cpp" 25 | ) 26 | endif() 27 | 28 | if(VOLE_PSI_ENABLE_OPPRF) 29 | list(APPEND SRCS 30 | "RsOpprf.cpp" 31 | ) 32 | endif() 33 | 34 | add_library(volePSI STATIC ${SRCS}) 35 | target_link_libraries(volePSI oc::libOTe sparsehash libdivide) 36 | 37 | if(APPLE) 38 | target_compile_options(volePSI PRIVATE 39 | "-std=c++${VOLE_PSI_STD_VER}" 40 | ) 41 | target_compile_options(volePSI PRIVATE 42 | "-Wno-pessimizing-move" 43 | "-Wno-delete-non-abstract-non-virtual-dtor" 44 | ) 45 | elseif(MSVC) 46 | set_target_properties(volePSI 47 | PROPERTIES 48 | CXX_STANDARD ${VOLE_PSI_STD_VER} 49 | CXX_STANDARD_REQUIRED YES 50 | CXX_EXTENSIONS NO 51 | ) 52 | 53 | if(VOLE_PSI_ENABLE_ASAN) 54 | message(WARNING "volepsi has ASAN enabled") 55 | target_compile_options(volePSI PUBLIC "/fsanitize=address") 56 | target_link_options(volePSI PUBLIC "/fsanitize=address") 57 | 58 | endif() 59 | else() 60 | target_compile_options(volePSI PUBLIC 61 | "-std=c++${VOLE_PSI_STD_VER}" 62 | ) 63 | 64 | if(VOLE_PSI_ENABLE_ASAN) 65 | message(WARNING "volepsi has ASAN enabled") 66 | target_compile_options(volePSI PUBLIC "-fsanitize=address")# "-ftime-report") 67 | target_link_options(volePSI PUBLIC "-fsanitize=address") 68 | endif() 69 | endif() 70 | 71 | if(MSVC) 72 | target_compile_definitions(volePSI PUBLIC "_ENABLE_EXTENDED_ALIGNED_STORAGE") 73 | else() 74 | 75 | if(VOLE_PSI_ENABLE_SSE) 76 | target_compile_options(volePSI PUBLIC -mavx) 77 | endif() 78 | 79 | if(VOLE_PSI_ENABLE_PIC) 80 | target_compile_options(volePSI PUBLIC "-fPIC") 81 | endif() 82 | endif() 83 | 84 | #target_compile_features(volePSI PUBLIC cxx_std_17) 85 | # make projects that include volePSI use this as an include folder 86 | target_include_directories(volePSI PUBLIC 87 | $ 88 | $) 89 | target_include_directories(volePSI PUBLIC 90 | $ 91 | $) 92 | 93 | -------------------------------------------------------------------------------- /volePSI/RsOprf.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // © 2022 Visa. 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | 10 | #include "volePSI/Defines.h" 11 | #include "volePSI/Paxos.h" 12 | #include "libOTe/Vole/Silent/SilentVoleSender.h" 13 | #include "libOTe/Vole/Silent/SilentVoleReceiver.h" 14 | 15 | namespace volePSI 16 | { 17 | 18 | class RsOprfSender : public oc::TimerAdapter 19 | { 20 | public: 21 | oc::SilentVoleSender mVoleSender; 22 | span mB; 23 | block mD; 24 | Baxos mPaxos; 25 | bool mMalicious = false; 26 | block mW; 27 | u64 mBinSize = 1 << 14; 28 | u64 mSsp = 40; 29 | bool mDebug = false; 30 | 31 | void setMultType(oc::MultType type) { mVoleSender.mMultType = type; }; 32 | 33 | Proto send(u64 n, PRNG& prng, Socket& chl, u64 mNumThreads = 0, bool reducedRounds = false); 34 | 35 | 36 | block eval(block v); 37 | 38 | 39 | void eval(span val, span output, u64 mNumThreads = 0); 40 | 41 | 42 | Proto genVole(PRNG& prng, Socket& chl, bool reducedRounds); 43 | }; 44 | 45 | 46 | 47 | class RsOprfReceiver : public oc::TimerAdapter 48 | { 49 | 50 | public: 51 | bool mMalicious = false; 52 | oc::SilentVoleReceiver mVoleRecver; 53 | u64 mBinSize = 1 << 14; 54 | u64 mSsp = 40; 55 | bool mDebug = false; 56 | 57 | void setMultType(oc::MultType type) { mVoleRecver.mMultType = type; }; 58 | 59 | Proto receive(span values, span outputs, PRNG& prng, Socket& chl, u64 mNumThreads = 0, bool reducedRounds = false); 60 | 61 | 62 | Proto genVole(u64 n, PRNG& prng, Socket& chl, bool reducedRounds); 63 | 64 | }; 65 | } -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "configurePresets": [ 4 | { 5 | "name": "linux", 6 | "displayName": "Linux", 7 | "description": "Target the Windows Subsystem for Linux (WSL) or a remote Linux system.", 8 | "generator": "Ninja", 9 | "binaryDir": "${sourceDir}/out/build/${presetName}", 10 | "cacheVariables": { 11 | "CMAKE_BUILD_TYPE": "Release", 12 | "FETCH_AUTO": true, 13 | "FETCH_SPARSEHASH": true, 14 | "FETCH_LIBDIVIDE": true, 15 | "VOLE_PSI_ENABLE_ASAN": true, 16 | "VOLE_PSI_ENABLE_BOOST": true, 17 | "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}" 18 | }, 19 | "vendor": { 20 | "microsoft.com/VisualStudioSettings/CMake/1.0": { "hostOS": [ "Linux" ] }, 21 | "microsoft.com/VisualStudioRemoteSettings/CMake/1.0": { "sourceDir": "$env{HOME}/.vs/$ms{projectDirName}" } 22 | } 23 | }, 24 | { 25 | "name": "x64-Debug", 26 | "displayName": "Windows x64 Debug", 27 | "description": "Target Windows with the Visual Studio development environment.", 28 | "generator": "Ninja", 29 | "binaryDir": "${sourceDir}/out/build/${presetName}", 30 | "architecture": { 31 | "value": "x64", 32 | "strategy": "external" 33 | }, 34 | "cacheVariables": { 35 | "CMAKE_BUILD_TYPE": "Debug", 36 | "FETCH_AUTO": true, 37 | "FETCH_SPARSEHASH": true, 38 | "VOLE_PSI_ENABLE_ASAN": false, 39 | "COPROTO_ENABLE_BOOST": true, 40 | "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}" 41 | }, 42 | "vendor": { "microsoft.com/VisualStudioSettings/CMake/1.0": { "hostOS": [ "Windows" ] } } 43 | }, 44 | { 45 | "name": "x64-Release", 46 | "displayName": "Windows x64 Release", 47 | "description": "Target Windows with the Visual Studio development environment.", 48 | "generator": "Ninja", 49 | "binaryDir": "${sourceDir}/out/build/${presetName}", 50 | "architecture": { 51 | "value": "x64", 52 | "strategy": "external" 53 | }, 54 | "cacheVariables": { 55 | "CMAKE_BUILD_TYPE": "RelWithDebInfo", 56 | "FETCH_AUTO": true, 57 | "VOLE_PSI_ENABLE_BOOST": true, 58 | "VOLE_PSI_ENABLE_BITPOLYMUL": false, 59 | "FETCH_LIBOTE": true, 60 | "FETCH_LIBDIVIDE": true, 61 | "FETCH_SPARSEHASH": true, 62 | "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}" 63 | }, 64 | "vendor": { "microsoft.com/VisualStudioSettings/CMake/1.0": { "hostOS": [ "Windows" ] } } 65 | }, 66 | { 67 | "name": "osx", 68 | "displayName": "Custom configure preset", 69 | "description": "Sets Ninja generator, build and install directory", 70 | "generator": "Unix Makefiles", 71 | "binaryDir": "${sourceDir}/out/build/${presetName}", 72 | "cacheVariables": { 73 | "FETCH_AUTO": true, 74 | "VOLE_PSI_PIC": true, 75 | "CMAKE_BUILD_TYPE": "Release", 76 | "CMAKE_PREFIX_PATH": "/usr/local/opt/openssl/", 77 | "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}" 78 | }, 79 | "vendor": { "microsoft.com/VisualStudioSettings/CMake/1.0": { "hostOS": [ "macOS" ] } } 80 | } 81 | ] 82 | } -------------------------------------------------------------------------------- /volePSI/SimpleIndex.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // © 2016 Peter Rindal. 3 | // © 2022 Visa. 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | // 6 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | // 8 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | 10 | #include "volePSI/Defines.h" 11 | #include "cryptoTools/Common/Defines.h" 12 | #include "cryptoTools/Common/BitVector.h" 13 | #include "cryptoTools/Common/Matrix.h" 14 | namespace volePSI 15 | { 16 | 17 | class SimpleIndex 18 | { 19 | public: 20 | 21 | 22 | struct Item 23 | { 24 | Item() :mVal(-1) {} 25 | 26 | Item& operator=(const Item&) = default; 27 | 28 | bool isEmpty() const { return mVal == u64(-1); } 29 | 30 | // The index is the index of the input that currently 31 | // occupies this bin position. The index is encode in the 32 | // first 7 bytes. 33 | u64 idx() const { return mVal & (u64(-1) >> 8); } 34 | 35 | // The index of the hash function that this item is 36 | // currently using. This in is encoded in the 8th byte. 37 | u64 hashIdx() const { return ((u8*)&mVal)[7]; } 38 | 39 | // Return true if this item was set with a collition. 40 | //bool isCollision() const { return (((u8*)&mVal)[7] >> 7) > 0; } 41 | 42 | // The this item to contain the index idx under the given hash index. 43 | // The collision value is also encoded. 44 | void set(u64 idx, u8 hashIdx) 45 | { 46 | mVal = idx; 47 | ((u8*)&mVal)[7] = hashIdx; 48 | } 49 | #ifdef THREAD_SAFE_SIMPLE_INDEX 50 | Item(const Item& b) : mVal(b.mVal.load(std::memory_order_relaxed)) {} 51 | Item(Item&& b) : mVal(b.mVal.load(std::memory_order_relaxed)) {} 52 | std::atomic mVal; 53 | #else 54 | Item(const Item& b) : mVal(b.mVal) {} 55 | Item(Item&& b) : mVal(b.mVal) {} 56 | u64 mVal; 57 | #endif 58 | }; 59 | 60 | u64 mMaxBinSize, mNumHashFunctions; 61 | 62 | // The current assignment of items to bins. Only 63 | // the index of the input item is stored in the bin, 64 | // not the actual item itself. 65 | Matrix mBins; 66 | u64 mNumBins; 67 | 68 | // numBalls x mNumHashFunctions matrix, (i,j) contains the i'th items 69 | // hash value under hash index j. 70 | Matrix mItemToBinMap; 71 | 72 | // The some of each bin. 73 | std::vector mBinSizes; 74 | 75 | block mHashSeed; 76 | void print() ; 77 | static u64 get_bin_size(u64 numBins, u64 numBalls, u64 statSecParam, bool approx = true); 78 | 79 | 80 | void init(u64 numBins, u64 numBalls, u64 statSecParam = 40, u64 numHashFunction = 3); 81 | void insertItems(span items, block hashingSeed); 82 | }; 83 | 84 | } 85 | -------------------------------------------------------------------------------- /tests/RsOprf_Tests.cpp: -------------------------------------------------------------------------------- 1 | #include "RsOprf_Tests.h" 2 | #include "volePSI/RsOprf.h" 3 | #include "volePSI/RsOpprf.h" 4 | #include "cryptoTools/Network/Channel.h" 5 | #include "cryptoTools/Network/Session.h" 6 | #include "cryptoTools/Network/IOService.h" 7 | #include 8 | #include "Common.h" 9 | 10 | using coproto::LocalAsyncSocket; 11 | using namespace volePSI; 12 | using namespace oc; 13 | 14 | void RsOprf_eval_test(const CLP&) 15 | { 16 | RsOprfSender sender; 17 | RsOprfReceiver recver; 18 | 19 | auto sockets = LocalAsyncSocket::makePair(); 20 | u64 n = 4000; 21 | PRNG prng0(block(0, 0)); 22 | PRNG prng1(block(0, 1)); 23 | 24 | std::vector vals(n), recvOut(n); 25 | 26 | prng0.get(vals.data(), n); 27 | 28 | auto p0 = sender.send(n, prng0, sockets[0]); 29 | auto p1 = recver.receive(vals, recvOut, prng1, sockets[1]); 30 | 31 | eval(p0, p1); 32 | 33 | std::vector vv(n); 34 | sender.eval(vals, vv); 35 | 36 | u64 count = 0; 37 | for (u64 i = 0; i < n; ++i) 38 | { 39 | auto v = sender.eval(vals[i]); 40 | if (recvOut[i] != v || recvOut[i] != vv[i]) 41 | { 42 | if (count < 10) 43 | std::cout << i << " " << recvOut[i] << " " < vals(n), recvOut(n); 69 | 70 | prng0.get(vals.data(), n); 71 | 72 | sender.mMalicious = true; 73 | recver.mMalicious = true; 74 | 75 | auto p0 = sender.send(n, prng0, sockets[0]); 76 | auto p1 = recver.receive(vals, recvOut, prng1, sockets[1]); 77 | 78 | eval(p0, p1); 79 | 80 | std::vector vv(n); 81 | sender.eval(vals, vv); 82 | 83 | u64 count = 0; 84 | for (u64 i = 0; i < n; ++i) 85 | { 86 | auto v = sender.eval(vals[i]); 87 | if (recvOut[i] != v || recvOut[i] != vv[i]) 88 | { 89 | if (count < 10) 90 | std::cout << i << " " << recvOut[i] << " " << v << " " << vv[i] << std::endl; 91 | else 92 | break; 93 | 94 | ++count; 95 | } 96 | } 97 | if (count) 98 | throw RTE_LOC; 99 | } 100 | 101 | 102 | void RsOprf_reduced_test(const CLP&) 103 | { 104 | RsOprfSender sender; 105 | RsOprfReceiver recver; 106 | 107 | auto sockets = LocalAsyncSocket::makePair(); 108 | 109 | u64 n = 4000; 110 | PRNG prng0(block(0, 0)); 111 | PRNG prng1(block(0, 1)); 112 | 113 | std::vector vals(n), recvOut(n); 114 | 115 | prng0.get(vals.data(), n); 116 | 117 | auto p0 = sender.send(n, prng0, sockets[0], 0, true); 118 | auto p1 = recver.receive(vals, recvOut, prng1, sockets[1], 0, true); 119 | 120 | eval(p0, p1); 121 | 122 | std::vector vv(n); 123 | sender.eval(vals, vv); 124 | 125 | u64 count = 0; 126 | for (u64 i = 0; i < n; ++i) 127 | { 128 | auto v = sender.eval(vals[i]); 129 | if (recvOut[i] != v || recvOut[i] != vv[i]) 130 | { 131 | if (count < 10) 132 | std::cout << i << " " << recvOut[i] << " " << v << " " << vv[i] << std::endl; 133 | else 134 | break; 135 | 136 | ++count; 137 | } 138 | } 139 | if (count) 140 | throw RTE_LOC; 141 | } 142 | 143 | 144 | -------------------------------------------------------------------------------- /cmake/findDependancies.cmake: -------------------------------------------------------------------------------- 1 | include(${CMAKE_CURRENT_LIST_DIR}/preamble.cmake) 2 | 3 | message(STATUS "VOLEPSI_THIRDPARTY_DIR=${VOLEPSI_THIRDPARTY_DIR}") 4 | 5 | 6 | set(PUSHED_CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH}) 7 | set(CMAKE_PREFIX_PATH "${VOLEPSI_THIRDPARTY_DIR};${CMAKE_PREFIX_PATH}") 8 | 9 | 10 | ####################################### 11 | # sparsehash 12 | 13 | macro(FIND_SPARSEHASH) 14 | set(ARGS ${ARGN}) 15 | 16 | #explicitly asked to fetch sparsehash 17 | if(FETCH_SPARSEHASH) 18 | list(APPEND ARGS NO_DEFAULT_PATH PATHS ${VOLEPSI_THIRDPARTY_DIR}) 19 | elseif(${NO_CMAKE_SYSTEM_PATH}) 20 | list(APPEND ARGS NO_CMAKE_SYSTEM_PATH) 21 | endif() 22 | 23 | find_path(SPARSEHASH_INCLUDE_DIRS "sparsehash/dense_hash_map" PATH_SUFFIXES "include" ${ARGS}) 24 | 25 | if(EXISTS ${SPARSEHASH_INCLUDE_DIRS}) 26 | set(SPARSEHASH_FOUND ON) 27 | else() 28 | set(SPARSEHASH_FOUND OFF) 29 | endif() 30 | endmacro() 31 | 32 | if(FETCH_SPARSEHASH_AUTO) 33 | FIND_SPARSEHASH(QUIET) 34 | include(${CMAKE_CURRENT_LIST_DIR}/../thirdparty/getSparsehash.cmake) 35 | endif() 36 | 37 | FIND_SPARSEHASH(REQUIRED) 38 | message("SPARSEHASH_INCLUDE_DIRS=${SPARSEHASH_INCLUDE_DIRS}") 39 | 40 | if(NOT TARGET sparsehash) 41 | add_library(sparsehash INTERFACE IMPORTED) 42 | 43 | target_include_directories(sparsehash INTERFACE 44 | $ 45 | $) 46 | endif() 47 | 48 | ####################################### 49 | # libOTe 50 | 51 | macro(FIND_LIBOTE) 52 | set(ARGS ${ARGN}) 53 | 54 | #explicitly asked to fetch libOTe 55 | if(FETCH_LIBOTE) 56 | list(APPEND ARGS NO_DEFAULT_PATH PATHS ${VOLEPSI_THIRDPARTY_DIR}) 57 | elseif(${VOLE_PSI_NO_SYSTEM_PATH}) 58 | list(APPEND ARGS NO_DEFAULT_PATH PATHS ${CMAKE_PREFIX_PATH}) 59 | endif() 60 | 61 | set(libOTe_options silentot silent_vole circuits) 62 | if(VOLE_PSI_ENABLE_SSE) 63 | set(libOTe_options ${libOTe_options} sse) 64 | else() 65 | set(libOTe_options ${libOTe_options} no_sse) 66 | endif() 67 | 68 | if(VOLE_PSI_ENABLE_BOOST) 69 | set(libOTe_options ${libOTe_options} boost) 70 | endif() 71 | if(VOLE_PSI_ENABLE_OPENSSL) 72 | set(libOTe_options ${libOTe_options} openssl) 73 | endif() 74 | 75 | if(VOLE_PSI_ENABLE_BITPOLYMUL) 76 | set(libOTe_options ${libOTe_options} bitpolymul) 77 | endif() 78 | 79 | if(VOLE_PSI_ENABLE_ASAN) 80 | set(libOTe_options ${libOTe_options} asan) 81 | else() 82 | set(libOTe_options ${libOTe_options} no_asan) 83 | endif() 84 | 85 | if(VOLE_PSI_ENABLE_PIC) 86 | set(libOTe_options ${libOTe_options} pic) 87 | else() 88 | set(libOTe_options ${libOTe_options} no_pic) 89 | endif() 90 | 91 | if(VOLE_PSI_ENABLE_SODIUM) 92 | set(libOTe_options ${libOTe_options} sodium) 93 | if(VOLE_PSI_SODIUM_MONTGOMERY) 94 | set(libOTe_options ${libOTe_options} sodium_montgomery) 95 | else() 96 | set(libOTe_options ${libOTe_options} no_sodium_montgomery) 97 | endif() 98 | endif() 99 | 100 | if(VOLE_PSI_ENABLE_RELIC) 101 | set(libOTe_options ${libOTe_options} relic) 102 | endif() 103 | message("\n\n\nlibOTe_options=${libOTe_options}") 104 | find_package(libOTe ${ARGS} COMPONENTS ${libOTe_options}) 105 | 106 | if(TARGET oc::libOTe) 107 | set(libOTe_FOUND ON) 108 | else() 109 | set(libOTe_FOUND OFF) 110 | endif() 111 | endmacro() 112 | 113 | if(FETCH_LIBOTE_AUTO) 114 | FIND_LIBOTE(QUIET) 115 | include(${CMAKE_CURRENT_LIST_DIR}/../thirdparty/getLibOTe.cmake) 116 | endif() 117 | 118 | FIND_LIBOTE(REQUIRED) 119 | 120 | # resort the previous prefix path 121 | set(CMAKE_PREFIX_PATH ${PUSHED_CMAKE_PREFIX_PATH}) 122 | -------------------------------------------------------------------------------- /cmake/preamble.cmake: -------------------------------------------------------------------------------- 1 | 2 | 3 | if("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}") 4 | 5 | ############################################ 6 | # If top level cmake # 7 | ############################################ 8 | if(MSVC) 9 | # optionally add the following to CMAKE_PREFIX_PATH 10 | #if(NOT DEFINED CMAKE_PREFIX_PATH AND NOT DEFINED NO_OC_DEFAULT_PREFIX) 11 | # set(CMAKE_PREFIX_PATH 12 | # "c:/libs" 13 | # "${CMAKE_CURRENT_SOURCE_DIR}/..;" 14 | # ) 15 | #endif() 16 | 17 | else() 18 | set(COMMON_FLAGS "-Wall -Wfatal-errors") 19 | 20 | if(NOT DEFINED NO_ARCH_NATIVE) 21 | set(COMMON_FLAGS "${COMMON_FLAGS} -march=native") 22 | endif() 23 | 24 | SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG") 25 | SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO " -O2 -g -ggdb") 26 | SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -ggdb") 27 | #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") 28 | 29 | endif() 30 | 31 | 32 | 33 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMMON_FLAGS}") 34 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMMON_FLAGS}") 35 | 36 | 37 | ############################################ 38 | # Build mode checks # 39 | ############################################ 40 | 41 | # Set a default build type for single-configuration 42 | # CMake generators if no build type is set. 43 | if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE) 44 | SET(CMAKE_BUILD_TYPE Release) 45 | endif() 46 | 47 | if( NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Release" 48 | AND NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Debug" 49 | AND NOT "${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo" ) 50 | 51 | message(WARNING ": Unknown build type - \${CMAKE_BUILD_TYPE}=${CMAKE_BUILD_TYPE}. Please use one of Debug, Release, or RelWithDebInfo. e.g. call\n\tcmake . -DCMAKE_BUILD_TYPE=Release\n" ) 52 | endif() 53 | endif() 54 | 55 | if(MSVC) 56 | set(VOLEPSI_CONFIG_NAME "${CMAKE_BUILD_TYPE}") 57 | if("${VOLEPSI_CONFIG_NAME}" STREQUAL "RelWithDebInfo" OR "${VOLEPSI_CONFIG_NAME}" STREQUAL "") 58 | set(VOLEPSI_CONFIG_NAME "Release") 59 | endif() 60 | set(VOLEPSI_CONFIG "x64-${VOLEPSI_CONFIG_NAME}") 61 | elseif(APPLE) 62 | set(VOLEPSI_CONFIG "osx") 63 | else() 64 | set(VOLEPSI_CONFIG "linux") 65 | endif() 66 | 67 | if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/install.cmake) 68 | set(VOLEPSI_IN_BUILD_TREE ON) 69 | else() 70 | set(VOLEPSI_IN_BUILD_TREE OFF) 71 | endif() 72 | 73 | # we are in the build tree. We might be building the library or 74 | # someone is consuming us from the build tree. 75 | if(VOLEPSI_IN_BUILD_TREE) 76 | 77 | set(VOLEPSI_BUILD_DIR "${CMAKE_CURRENT_LIST_DIR}/../out/build/${VOLEPSI_CONFIG}") 78 | get_filename_component(VOLEPSI_BUILD_DIR ${VOLEPSI_BUILD_DIR} ABSOLUTE) 79 | 80 | # true if we are actually building 81 | if(VOLEPSI_BUILD) 82 | # warn if we aren't using out/build// 83 | if(NOT (${CMAKE_BINARY_DIR} STREQUAL ${VOLEPSI_BUILD_DIR})) 84 | message(WARNING "unexpected build directory. \n\tCMAKE_BINARY_DIR=${CMAKE_BINARY_DIR}\nbut expect\n\tVOLEPSI_BUILD_DIR=${VOLEPSI_BUILD_DIR}") 85 | endif() 86 | set(VOLEPSI_BUILD_DIR ${CMAKE_BINARY_DIR}) 87 | else() 88 | endif() 89 | 90 | 91 | if(NOT DEFINED VOLEPSI_THIRDPARTY_DIR) 92 | set(VOLEPSI_THIRDPARTY_DIR "${CMAKE_CURRENT_LIST_DIR}/../out/install/${VOLEPSI_CONFIG}") 93 | get_filename_component(VOLEPSI_THIRDPARTY_DIR ${VOLEPSI_THIRDPARTY_DIR} ABSOLUTE) 94 | endif() 95 | else() 96 | # we currenty are in install tree, /lib/cmake/vole-psi 97 | if(NOT DEFINED VOLEPSI_THIRDPARTY_DIR) 98 | set(VOLEPSI_THIRDPARTY_DIR "${CMAKE_CURRENT_LIST_DIR}/../../..") 99 | get_filename_component(VOLEPSI_THIRDPARTY_DIR ${VOLEPSI_THIRDPARTY_DIR} ABSOLUTE) 100 | endif() 101 | endif() 102 | 103 | 104 | if(NOT VOLE_PSI_THIRDPARTY_CLONE_DIR) 105 | get_filename_component(VOLE_PSI_THIRDPARTY_CLONE_DIR "${CMAKE_CURRENT_LIST_DIR}/../out/" ABSOLUTE) 106 | endif() 107 | -------------------------------------------------------------------------------- /thirdparty/getLibOTe.cmake: -------------------------------------------------------------------------------- 1 | 2 | set(USER_NAME ) 3 | set(TOKEN ) 4 | set(GIT_REPOSITORY "https://github.com/osu-crypto/libOTe.git") 5 | set(GIT_TAG "d55867114c78272be7142bd67ebdcb346fec8621" ) 6 | 7 | set(DEP_NAME libOTe) 8 | set(CLONE_DIR "${VOLE_PSI_THIRDPARTY_CLONE_DIR}/${DEP_NAME}") 9 | set(BUILD_DIR "${CLONE_DIR}/out/build/${VOLEPSI_CONFIG}") 10 | set(LOG_FILE "${CMAKE_CURRENT_LIST_DIR}/log-${DEP_NAME}.txt") 11 | 12 | 13 | include("${CMAKE_CURRENT_LIST_DIR}/fetch.cmake") 14 | 15 | option(LIBOTE_DEV "always build libOTe" OFF) 16 | 17 | if(NOT ${DEP_NAME}_FOUND OR LIBOTE_DEV) 18 | 19 | string (REPLACE ";" "%" CMAKE_PREFIX_PATH_STR "${CMAKE_PREFIX_PATH}") 20 | 21 | find_program(GIT git REQUIRED) 22 | set(DOWNLOAD_CMD ${GIT} clone --recursive ${GIT_REPOSITORY}) 23 | set(CHECKOUT_CMD ${GIT} checkout ${GIT_TAG}) 24 | set(SUBMODULE_CMD ${GIT} submodule update --recursive) 25 | set(CONFIGURE_CMD ${CMAKE_COMMAND} -S ${CLONE_DIR} -B ${BUILD_DIR} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} 26 | -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH_STR} 27 | -DNO_SYSTEM_PATH=${VOLE_PSI_NO_SYSTEM_PATH} 28 | -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} 29 | -DFETCH_AUTO=${FETCH_AUTO} 30 | -DVERBOSE_FETCH=${VERBOSE_FETCH} 31 | -DENABLE_CIRCUITS=ON 32 | -DENABLE_MRR=ON 33 | -DENABLE_IKNP=ON 34 | -DENABLE_SOFTSPOKEN_OT=ON 35 | -DENABLE_BITPOLYMUL=${VOLE_PSI_ENABLE_BITPOLYMUL} 36 | -DENABLE_SILENTOT=ON 37 | -DENABLE_SILENT_VOLE=ON 38 | -DENABLE_SSE=${VOLE_PSI_ENABLE_SSE} 39 | -DENABLE_BOOST=${VOLE_PSI_ENABLE_BOOST} 40 | -DENABLE_OPENSSL=${VOLE_PSI_ENABLE_OPENSSL} 41 | -DLIBOTE_STD_VER=${VOLE_PSI_STD_VER} 42 | -DENABLE_PIC=${VOLE_PSI_ENABLE_PIC} 43 | -DENABLE_ASAN=${VOLE_PSI_ENABLE_ASAN} 44 | -DOC_THIRDPARTY_CLONE_DIR=${VOLE_PSI_THIRDPARTY_CLONE_DIR} 45 | -DOC_THIRDPARTY_INSTALL_PREFIX=${VOLEPSI_THIRDPARTY_DIR} 46 | -DENABLE_SODIUM=${VOLE_PSI_ENABLE_SODIUM} 47 | -DENABLE_RELIC=${VOLE_PSI_ENABLE_RELIC} 48 | -DSODIUM_MONTGOMERY=${VOLE_PSI_SODIUM_MONTGOMERY} 49 | ) 50 | set(BUILD_CMD ${CMAKE_COMMAND} --build ${BUILD_DIR} --config ${CMAKE_BUILD_TYPE}) 51 | set(INSTALL_CMD ${CMAKE_COMMAND} --install ${BUILD_DIR} --config ${CMAKE_BUILD_TYPE} --prefix ${VOLEPSI_THIRDPARTY_DIR}) 52 | 53 | 54 | message("============= Building ${DEP_NAME} =============") 55 | if(NOT EXISTS ${CLONE_DIR}) 56 | run(NAME "Cloning ${GIT_REPOSITORY}" CMD ${DOWNLOAD_CMD} WD ${VOLE_PSI_THIRDPARTY_CLONE_DIR}) 57 | endif() 58 | 59 | 60 | run(NAME "libOTe Checkout ${GIT_TAG} " CMD ${CHECKOUT_CMD} WD ${CLONE_DIR}) 61 | run(NAME "libOTe submodule" CMD ${SUBMODULE_CMD} WD ${CLONE_DIR}) 62 | run(NAME "libOTe Configure" CMD ${CONFIGURE_CMD} WD ${CLONE_DIR}) 63 | run(NAME "libOTe Build" CMD ${BUILD_CMD} WD ${CLONE_DIR}) 64 | run(NAME "libOTe Install" CMD ${INSTALL_CMD} WD ${CLONE_DIR}) 65 | 66 | message("log ${LOG_FILE}\n==========================================") 67 | else() 68 | message("${DEP_NAME} already fetched.") 69 | endif() 70 | 71 | install(CODE " 72 | if(NOT CMAKE_INSTALL_PREFIX STREQUAL \"${VOLE_PSI_THIRDPARTY_CLONE_DIR}\") 73 | execute_process( 74 | COMMAND ${SUDO} \${CMAKE_COMMAND} --install ${BUILD_DIR} --config ${CMAKE_BUILD_TYPE} --prefix \${CMAKE_INSTALL_PREFIX} 75 | WORKING_DIRECTORY ${CLONE_DIR} 76 | RESULT_VARIABLE RESULT 77 | COMMAND_ECHO STDOUT 78 | ) 79 | endif() 80 | ") 81 | -------------------------------------------------------------------------------- /volePSI/GMW/SilentTripleGen.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // © 2022 Visa. 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | 10 | #include "volePSI/Defines.h" 11 | #include "volePSI/config.h" 12 | #ifdef VOLE_PSI_ENABLE_GMW 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | namespace volePSI 19 | { 20 | 21 | 22 | Proto generateBase( 23 | RequiredBase base, 24 | u64 partyIdx, 25 | oc::PRNG& prng, 26 | coproto::Socket& chl, 27 | span recvMsg, 28 | span> sendMsg, 29 | oc::Timer* timer = nullptr); 30 | 31 | Proto extend( 32 | RequiredBase b, 33 | span> baseMsg, 34 | oc::PRNG& prng, 35 | coproto::Socket& chl, 36 | span recvMsgP, 37 | span> sendMsgP); 38 | 39 | Proto extend( 40 | RequiredBase b, 41 | oc::BitVector baseChoice, 42 | span baseMsg, 43 | oc::PRNG& prng, 44 | coproto::Socket& chl, 45 | span recvMsgP, 46 | span> sendMsgP); 47 | 48 | class SilentTripleGen : public oc::TimerAdapter 49 | { 50 | public: 51 | bool mHasBase = false; 52 | u64 mN, mBatchSize, mNumPer; 53 | Mode mMode; 54 | oc::PRNG mPrng; 55 | 56 | std::unique_ptr mBackingSenderOT; 57 | std::unique_ptr mBackingRecverOT; 58 | 59 | span mSenderOT; 60 | span mRecverOT; 61 | 62 | void init(u64 n, u64 batchSize, u64 numThreads, Mode mode, block seed); 63 | 64 | 65 | RequiredBase mBase; 66 | 67 | RequiredBase requiredBaseOts(); 68 | 69 | void setBaseOts(span recvOts, span> sendOts); 70 | 71 | Proto expand(coproto::Socket& chl); 72 | 73 | bool hasBaseOts() { return mHasBase; } 74 | 75 | 76 | Proto generateBaseOts(u64 partyIdx, oc::PRNG& prng, coproto::Socket& chl) 77 | { 78 | 79 | auto rMsg = std::vector{}; 80 | auto sMsg = std::vector>{}; 81 | auto b = RequiredBase{ }; 82 | 83 | setTimePoint("TripleGen::generateBaseOts begin"); 84 | b = requiredBaseOts(); 85 | 86 | if (b.mNumSend || b.mRecvChoiceBits.size()) 87 | { 88 | rMsg.resize(b.mRecvChoiceBits.size()); 89 | sMsg.resize(b.mNumSend); 90 | co_await (generateBase(b, partyIdx, prng, chl, rMsg, sMsg, mTimer)); 91 | setBaseOts(rMsg, sMsg); 92 | } 93 | setTimePoint("TripleGen::generateBaseOts end"); 94 | 95 | } 96 | 97 | 98 | // A * C = B + D 99 | span mMult, mAdd; 100 | std::vector mAVec, mBVec, mDVec; 101 | oc::BitVector mCBitVec; 102 | }; 103 | 104 | 105 | 106 | } 107 | #endif -------------------------------------------------------------------------------- /volePSI/RsCpsi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // © 2022 Visa. 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | 10 | #include "volePSI/Defines.h" 11 | #include "volePSI/config.h" 12 | #ifdef VOLE_PSI_ENABLE_CPSI 13 | 14 | #include "cryptoTools/Crypto/PRNG.h" 15 | #include "cryptoTools/Network/Channel.h" 16 | #include "cryptoTools/Common/CuckooIndex.h" 17 | #include "volePSI/RsOpprf.h" 18 | #include "volePSI/GMW/Gmw.h" 19 | #include "volePSI/SimpleIndex.h" 20 | #include "cryptoTools/Common/Timer.h" 21 | #include "cryptoTools/Common/BitVector.h" 22 | 23 | namespace volePSI 24 | { 25 | constexpr bool RsCpsiSenderDebug = false; 26 | 27 | enum ValueShareType 28 | { 29 | Xor, 30 | add32 31 | }; 32 | namespace details 33 | { 34 | 35 | struct RsCpsiBase 36 | { 37 | 38 | u64 mSenderSize = 0; 39 | u64 mRecverSize = 0; 40 | u64 mValueByteLength = 0; 41 | u64 mSsp = 0, mNumThreads = 0; 42 | PRNG mPrng; 43 | ValueShareType mType = ValueShareType::Xor; 44 | 45 | void init( 46 | u64 senderSize, 47 | u64 recverSize, 48 | u64 valueByteLength, 49 | u64 statSecParam, 50 | block seed, 51 | u64 numThreads, 52 | ValueShareType type = ValueShareType::Xor) 53 | { 54 | 55 | mSenderSize = senderSize; 56 | mRecverSize = recverSize; 57 | mValueByteLength = valueByteLength; 58 | mSsp = statSecParam; 59 | mPrng.SetSeed(seed); 60 | mNumThreads = numThreads; 61 | mType = type; 62 | } 63 | }; 64 | } 65 | 66 | class RsCpsiSender : public details::RsCpsiBase, public oc::TimerAdapter 67 | { 68 | public: 69 | struct Sharing 70 | { 71 | // The sender's share of the bit vector indicating that 72 | // the i'th row is a real row (1) or a row (0). 73 | oc::BitVector mFlagBits; 74 | 75 | // Secret share of the values associated with the output 76 | // elements. These values are from the sender. 77 | oc::Matrix mValues; 78 | 79 | // The mapping of the senders input rows to output rows. 80 | // Each input row might have been mapped to one of three 81 | // possible output rows. 82 | std::vector> mMapping; 83 | 84 | }; 85 | 86 | // perform the join with Y being the join keys with associated values. 87 | // The output is written to s. 88 | Proto send(span Y, oc::MatrixView values, Sharing& s, Socket& chl); 89 | 90 | }; 91 | 92 | 93 | class RsCpsiReceiver :public details::RsCpsiBase, public oc::TimerAdapter 94 | { 95 | public: 96 | 97 | struct Sharing 98 | { 99 | // The sender's share of the bit vector indicating that 100 | // the i'th row is a real row (1) or a row (0). 101 | oc::BitVector mFlagBits; 102 | 103 | // Secret share of the values associated with the output 104 | // elements. These values are from the sender. 105 | oc::Matrix mValues; 106 | 107 | // The mapping of the receiver's input rows to output rows. 108 | std::vector mMapping; 109 | 110 | }; 111 | 112 | // perform the join with X being the join keys. 113 | // The output is written to s. 114 | Proto receive(span X, Sharing& s, Socket& chl); 115 | 116 | }; 117 | 118 | } 119 | 120 | #endif -------------------------------------------------------------------------------- /tests/RsPsi_Tests.cpp: -------------------------------------------------------------------------------- 1 | #include "RsPsi_Tests.h" 2 | #include "volePSI/RsPsi.h" 3 | #include "volePSI/RsCpsi.h" 4 | #include "cryptoTools/Network/Channel.h" 5 | #include "cryptoTools/Network/Session.h" 6 | #include "cryptoTools/Network/IOService.h" 7 | #include "Common.h" 8 | using namespace oc; 9 | using namespace volePSI; 10 | using coproto::LocalAsyncSocket; 11 | 12 | namespace 13 | { 14 | std::vector run(PRNG& prng, std::vector& recvSet, std::vector &sendSet, bool mal, u64 nt = 1, bool reduced = false) 15 | { 16 | auto sockets = LocalAsyncSocket::makePair(); 17 | 18 | RsPsiReceiver recver; 19 | RsPsiSender sender; 20 | 21 | recver.init(sendSet.size(), recvSet.size(), 40, prng.get(), mal, nt, reduced); 22 | sender.init(sendSet.size(), recvSet.size(), 40, prng.get(), mal, nt, reduced); 23 | 24 | auto p0 = recver.run(recvSet, sockets[0]); 25 | auto p1 = sender.run(sendSet, sockets[1]); 26 | 27 | eval(p0, p1); 28 | 29 | return recver.mIntersection; 30 | } 31 | 32 | 33 | } 34 | 35 | void Psi_Rs_empty_test(const CLP& cmd) 36 | { 37 | u64 n = cmd.getOr("n", 13243); 38 | std::vector recvSet(n), sendSet(n); 39 | PRNG prng(ZeroBlock); 40 | prng.get(recvSet.data(), recvSet.size()); 41 | prng.get(sendSet.data(), sendSet.size()); 42 | 43 | auto inter = run(prng, recvSet, sendSet, false); 44 | 45 | if (inter.size()) 46 | throw RTE_LOC; 47 | } 48 | 49 | 50 | void Psi_Rs_partial_test(const CLP& cmd) 51 | { 52 | u64 n = cmd.getOr("n", 13243); 53 | std::vector recvSet(n), sendSet(n); 54 | PRNG prng(ZeroBlock); 55 | prng.get(recvSet.data(), recvSet.size()); 56 | prng.get(sendSet.data(), sendSet.size()); 57 | 58 | std::set exp; 59 | for (u64 i = 0; i < n; ++i) 60 | { 61 | if (prng.getBit()) 62 | { 63 | recvSet[i] = sendSet[(i + 312) % n]; 64 | exp.insert(i); 65 | } 66 | } 67 | 68 | auto inter = run(prng, recvSet, sendSet, false); 69 | std::set act(inter.begin(), inter.end()); 70 | if (act != exp) 71 | { 72 | std::cout << "exp size " << exp.size() << std::endl; 73 | std::cout << "act size " << act.size() << std::endl; 74 | throw RTE_LOC; 75 | } 76 | } 77 | 78 | 79 | void Psi_Rs_full_test(const CLP& cmd) 80 | { 81 | u64 n = cmd.getOr("n", 13243); 82 | std::vector recvSet(n), sendSet(n); 83 | PRNG prng(ZeroBlock); 84 | prng.get(recvSet.data(), recvSet.size()); 85 | sendSet = recvSet; 86 | 87 | std::set exp; 88 | for (u64 i = 0; i < n; ++i) 89 | exp.insert(i); 90 | 91 | auto inter = run(prng, recvSet, sendSet, false); 92 | std::set act(inter.begin(), inter.end()); 93 | if (act != exp) 94 | throw RTE_LOC; 95 | } 96 | 97 | 98 | 99 | void Psi_Rs_reduced_test(const CLP& cmd) 100 | { 101 | u64 n = cmd.getOr("n", 13243); 102 | std::vector recvSet(n), sendSet(n); 103 | PRNG prng(ZeroBlock); 104 | prng.get(recvSet.data(), recvSet.size()); 105 | sendSet = recvSet; 106 | 107 | std::set exp; 108 | for (u64 i = 0; i < n; ++i) 109 | exp.insert(i); 110 | 111 | auto inter = run(prng, recvSet, sendSet, false, 1, true); 112 | std::set act(inter.begin(), inter.end()); 113 | if (act != exp) 114 | throw RTE_LOC; 115 | } 116 | 117 | 118 | void Psi_Rs_multiThrd_test(const CLP& cmd) 119 | { 120 | u64 n = cmd.getOr("n", 13243); 121 | u64 nt = cmd.getOr("nt", 8); 122 | std::vector recvSet(n), sendSet(n); 123 | PRNG prng(ZeroBlock); 124 | prng.get(recvSet.data(), recvSet.size()); 125 | sendSet = recvSet; 126 | 127 | std::set exp; 128 | for (u64 i = 0; i < n; ++i) 129 | exp.insert(i); 130 | 131 | auto inter = run(prng, recvSet, sendSet, false, nt); 132 | std::set act(inter.begin(), inter.end()); 133 | if (act != exp) 134 | throw RTE_LOC; 135 | } 136 | 137 | 138 | void Psi_Rs_mal_test(const CLP& cmd) 139 | { 140 | u64 n = cmd.getOr("n", 13243); 141 | std::vector recvSet(n), sendSet(n); 142 | PRNG prng(ZeroBlock); 143 | prng.get(recvSet.data(), recvSet.size()); 144 | prng.get(sendSet.data(), sendSet.size()); 145 | 146 | std::set exp; 147 | for (u64 i = 0; i < n; ++i) 148 | { 149 | if (prng.getBit()) 150 | { 151 | recvSet[i] = sendSet[(i + 312) % n]; 152 | exp.insert(i); 153 | } 154 | } 155 | 156 | auto inter = run(prng, recvSet, sendSet, true); 157 | std::set act(inter.begin(), inter.end()); 158 | if (act != exp) 159 | throw RTE_LOC; 160 | } 161 | -------------------------------------------------------------------------------- /cmake/buildOptions.cmake: -------------------------------------------------------------------------------- 1 | 2 | macro(EVAL var) 3 | if(${ARGN}) 4 | set(${var} ON) 5 | else() 6 | set(${var} OFF) 7 | endif() 8 | endmacro() 9 | 10 | option(FETCH_AUTO "automaticly download and build dependancies" OFF) 11 | option(VERBOSE_FETCH "Verbose fetch" ON) 12 | 13 | 14 | if(DEFINED COPROTO_ENABLE_BOOST) 15 | message("warning, setting VOLE_PSI_ENABLE_BOOST as COPROTO_ENABLE_BOOST=${COPROTO_ENABLE_BOOST}") 16 | set(VOLE_PSI_ENABLE_BOOST ${COPROTO_ENABLE_BOOST}) 17 | unset(COPROTO_ENABLE_BOOST CACHE) 18 | endif() 19 | 20 | if(DEFINED COPROTO_ENABLE_OPENSSL) 21 | message("warning, setting VOLE_PSI_ENABLE_OPENSSL as COPROTO_ENABLE_OPENSSL=${COPROTO_ENABLE_OPENSSL}") 22 | set(VOLE_PSI_ENABLE_OPENSSL ${COPROTO_ENABLE_OPENSSL}) 23 | unset(COPROTO_ENABLE_OPENSSL CACHE) 24 | endif() 25 | 26 | if(DEFINED LIBOTE_ENABLE_BITPOLYMUL) 27 | message("warning, setting VOLE_PSI_ENABLE_BITPOLYMUL as LIBOTE_ENABLE_BITPOLYMUL=${LIBOTE_ENABLE_BITPOLYMUL}") 28 | set(VOLE_PSI_ENABLE_BITPOLYMUL ${LIBOTE_ENABLE_BITPOLYMUL}) 29 | unset(LIBOTE_ENABLE_BITPOLYMUL CACHE) 30 | endif() 31 | 32 | if(DEFINED VOLE_PSI_PIC) 33 | message("warning, setting VOLE_PSI_ENABLE_PIC as VOLE_PSI_PIC=${VOLE_PSI_PIC}") 34 | set(VOLE_PSI_ENABLE_PIC ${VOLE_PSI_PIC}) 35 | unset(VOLE_PSI_PIC CACHE) 36 | endif() 37 | 38 | #option(FETCH_SPARSEHASH "download and build sparsehash" OFF)) 39 | EVAL(FETCH_SPARSEHASH_AUTO 40 | (DEFINED FETCH_SPARSEHASH AND FETCH_SPARSEHASH) OR 41 | ((NOT DEFINED FETCH_SPARSEHASH) AND (FETCH_AUTO))) 42 | 43 | #option(FETCH_LIBOTE "download and build libOTe" OFF)) 44 | EVAL(FETCH_LIBOTE_AUTO 45 | (DEFINED FETCH_LIBOTE AND FETCH_LIBOTE) OR 46 | ((NOT DEFINED FETCH_LIBOTE) AND (FETCH_AUTO))) 47 | 48 | #option(FETCH_LIBDIVIDE "download and build libdivide" OFF)) 49 | EVAL(FETCH_LIBDIVIDE_AUTO 50 | (DEFINED FETCH_LIBDIVIDE AND FETCH_LIBDIVIDE) OR 51 | ((NOT DEFINED FETCH_LIBDIVIDE) AND (FETCH_AUTO))) 52 | 53 | 54 | if(NOT DEFINED VOLE_PSI_STD_VER) 55 | set(VOLE_PSI_STD_VER 20) 56 | endif() 57 | 58 | if(APPLE) 59 | set(VOLE_PSI_ENABLE_SODIUM_DEFAULT OFF) 60 | set(VOLE_PSI_ENABLE_RELIC_DEFAULT ON) 61 | else() 62 | set(VOLE_PSI_ENABLE_SODIUM_DEFAULT ON) 63 | set(VOLE_PSI_ENABLE_RELIC_DEFAULT OFF) 64 | endif() 65 | 66 | 67 | 68 | option(VOLE_PSI_ENABLE_SSE "build the library with SSE intrisics" ON) 69 | option(VOLE_PSI_ENABLE_GMW "compile the library with GMW" ON) 70 | option(VOLE_PSI_ENABLE_CPSI "compile the library with circuit PSI" ON) 71 | option(VOLE_PSI_ENABLE_OPPRF "compile the library with OPPRF" ON) 72 | option(VOLE_PSI_ENABLE_BOOST "build coproto with boost support" OFF) 73 | option(VOLE_PSI_ENABLE_OPENSSL "build coproto with boost openssl support" OFF) 74 | option(VOLE_PSI_ENABLE_PIC "build with PIC" OFF) 75 | option(VOLE_PSI_ENABLE_ASAN "build with ASAN" OFF) 76 | option(VOLE_PSI_ENABLE_SODIUM "Use the sodium crypto library." ${VOLE_PSI_ENABLE_SODIUM_DEFAULT}) 77 | option(VOLE_PSI_ENABLE_RELIC "Use the relic crypto library." ${VOLE_PSI_ENABLE_RELIC_DEFAULT}) 78 | option(VOLE_PSI_SODIUM_MONTGOMERY "request libOTe to use the modified sodium library (non-standard sodium)." ON) 79 | if(APPLE) 80 | option(VOLE_PSI_ENABLE_BITPOLYMUL "build libOTe with quasiCyclic support" OFF) 81 | else() 82 | option(VOLE_PSI_ENABLE_BITPOLYMUL "build libOTe with quasiCyclic support" ON) 83 | endif() 84 | 85 | 86 | if(VOLE_PSI_ENABLE_CPSI) 87 | set(VOLE_PSI_ENABLE_GMW ${VOLE_PSI_ENABLE_CPSI}) 88 | endif() 89 | if(VOLE_PSI_ENABLE_CPSI) 90 | set(VOLE_PSI_ENABLE_OPPRF ${VOLE_PSI_ENABLE_CPSI}) 91 | endif() 92 | 93 | 94 | 95 | message(STATUS "vole-psi options\n=======================================================") 96 | 97 | message(STATUS "Option: VOLE_PSI_NO_SYSTEM_PATH = ${VOLE_PSI_NO_SYSTEM_PATH}") 98 | message(STATUS "Option: CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}\n") 99 | message(STATUS "Option: FETCH_AUTO = ${FETCH_AUTO}") 100 | message(STATUS "Option: FETCH_SPARSEHASH = ${FETCH_SPARSEHASH}") 101 | message(STATUS "Option: FETCH_LIBOTE = ${FETCH_LIBOTE}") 102 | 103 | 104 | message("\n") 105 | message(STATUS "Option: VOLE_PSI_ENABLE_SSE = ${VOLE_PSI_ENABLE_SSE}") 106 | message(STATUS "Option: VOLE_PSI_ENABLE_PIC = ${VOLE_PSI_ENABLE_PIC}") 107 | message(STATUS "Option: VOLE_PSI_ENABLE_ASAN = ${VOLE_PSI_ENABLE_ASAN}") 108 | message(STATUS "Option: VOLE_PSI_STD_VER = ${VOLE_PSI_STD_VER}") 109 | 110 | message(STATUS "Option: VOLE_PSI_ENABLE_GMW = ${VOLE_PSI_ENABLE_GMW}") 111 | message(STATUS "Option: VOLE_PSI_ENABLE_CPSI = ${VOLE_PSI_ENABLE_CPSI}") 112 | message(STATUS "Option: VOLE_PSI_ENABLE_OPPRF = ${VOLE_PSI_ENABLE_OPPRF}\n") 113 | 114 | message(STATUS "Option: VOLE_PSI_ENABLE_BOOST = ${VOLE_PSI_ENABLE_BOOST}") 115 | message(STATUS "Option: VOLE_PSI_ENABLE_OPENSSL = ${VOLE_PSI_ENABLE_OPENSSL}") 116 | message(STATUS "Option: VOLE_PSI_ENABLE_BITPOLYMUL = ${VOLE_PSI_ENABLE_BITPOLYMUL}") 117 | message(STATUS "Option: VOLE_PSI_ENABLE_SODIUM = ${VOLE_PSI_ENABLE_SODIUM}") 118 | message(STATUS "Option: VOLE_PSI_SODIUM_MONTGOMERY = ${VOLE_PSI_SODIUM_MONTGOMERY}") 119 | message(STATUS "Option: VOLE_PSI_ENABLE_RELIC = ${VOLE_PSI_ENABLE_RELIC}") 120 | 121 | 122 | -------------------------------------------------------------------------------- /tests/RsOpprf_Tests.cpp: -------------------------------------------------------------------------------- 1 | #include "RsOpprf_Tests.h" 2 | #include "volePSI/RsOprf.h" 3 | #include "volePSI/RsOpprf.h" 4 | #include "cryptoTools/Network/Channel.h" 5 | #include "cryptoTools/Network/Session.h" 6 | #include "cryptoTools/Network/IOService.h" 7 | #include 8 | #include "Common.h" 9 | 10 | using namespace volePSI; 11 | using namespace oc; 12 | 13 | 14 | void RsOpprf_eval_blk_test(const CLP&) 15 | { 16 | RsOpprfSender sender; 17 | RsOpprfReceiver recver; 18 | 19 | 20 | auto sockets = cp::LocalAsyncSocket::makePair(); 21 | 22 | 23 | u64 n = 4000; 24 | PRNG prng0(block(0, 0)); 25 | PRNG prng1(block(0, 1)); 26 | 27 | std::vector vals(n), out(n), recvOut(n); 28 | 29 | prng0.get(vals.data(), n); 30 | prng0.get(out.data(), n); 31 | 32 | auto p0 = sender.send(n, vals, out, prng0, 1, sockets[0]); 33 | auto p1 = recver.receive(n, vals, recvOut, prng1, 1, sockets[1]); 34 | 35 | eval(p0, p1); 36 | 37 | u64 count = 0; 38 | for (u64 i = 0; i < n; ++i) 39 | { 40 | auto v = sender.eval(vals[i]); 41 | if (recvOut[i] != v || recvOut[i] != out[i]) 42 | { 43 | if (count < 10) 44 | std::cout << i << " recv= " << recvOut[i] << ", send = " << v << ", send* = " << out[i] << std::endl; 45 | else 46 | break; 47 | 48 | ++count; 49 | } 50 | } 51 | if (count) 52 | throw RTE_LOC; 53 | } 54 | 55 | template 56 | std::string hex(const Vec& v) 57 | { 58 | auto d = (u8*)v.data(); 59 | auto s = v.size() * sizeof(typename Vec::value_type); 60 | std::stringstream ss; 61 | for (u64 i = 0; i < s; ++i) 62 | ss << std::hex << std::setw(2) << std::setfill('0') << (int)d[i]; 63 | return ss.str(); 64 | } 65 | 66 | void RsOpprf_eval_blk_mtx_test(const CLP&) 67 | { 68 | RsOpprfSender sender; 69 | RsOpprfReceiver recver; 70 | 71 | auto sockets = cp::LocalAsyncSocket::makePair(); 72 | 73 | 74 | u64 n = 4000; 75 | u64 m = 7; 76 | PRNG prng0(block(0, 0)); 77 | PRNG prng1(block(0, 1)); 78 | 79 | std::vector vals(n); 80 | oc::Matrix out(n, m), out2(n, m), recvOut(n, m); 81 | 82 | prng0.get(vals.data(), n); 83 | prng0.get(out.data(), n); 84 | 85 | 86 | auto p0 = sender.send(n, vals, out, prng0, 1, sockets[0]); 87 | auto p1 = recver.receive(n, vals, recvOut, prng1, 1, sockets[1]); 88 | 89 | eval(p0, p1); 90 | 91 | sender.eval(vals, out2, 1); 92 | 93 | u64 count = 0; 94 | for (u64 i = 0; i < n; ++i) 95 | { 96 | auto c0 = memcmp(recvOut[i].data(), out[i].data(), m * sizeof(block)) != 0; 97 | auto c1 = memcmp(recvOut[i].data(), out2[i].data(), m * sizeof(block)) != 0; 98 | if (c0 || c1) 99 | { 100 | if (count < 10) 101 | std::cout << i << "\n\t " << hex(recvOut[i]) << "\n\t " << hex(out2[i]) << "\n\t " << hex(out[i]) << std::endl; 102 | else 103 | break; 104 | 105 | ++count; 106 | } 107 | } 108 | if (count) 109 | throw RTE_LOC; 110 | } 111 | 112 | void RsOpprf_eval_u8_test(const CLP&) 113 | { 114 | RsOpprfSender sender; 115 | RsOpprfReceiver recver; 116 | 117 | auto sockets = cp::LocalAsyncSocket::makePair(); 118 | 119 | u64 n = 4000; 120 | PRNG prng0(block(0, 0)); 121 | PRNG prng1(block(0, 1)); 122 | 123 | std::vector vals(n); 124 | std::vector out(n), recvOut(n); 125 | 126 | prng0.get(vals.data(), n); 127 | prng0.get(out.data(), n); 128 | 129 | auto p0 = sender.send(n, vals, out, prng0, 1, sockets[0]); 130 | auto p1 = recver.receive(n, vals, recvOut, prng1, 1, sockets[1]); 131 | 132 | eval(p0, p1); 133 | 134 | u64 count = 0; 135 | for (u64 i = 0; i < n; ++i) 136 | { 137 | auto v = sender.eval(vals[i]); 138 | if (recvOut[i] != v || recvOut[i] != out[i]) 139 | { 140 | if (count < 10) 141 | std::cout << i << " " << recvOut[i] << " " << v << " " << out[i] << std::endl; 142 | else 143 | break; 144 | 145 | ++count; 146 | } 147 | } 148 | if (count) 149 | throw RTE_LOC; 150 | } 151 | 152 | 153 | 154 | void RsOpprf_eval_u8_mtx_test(const CLP&) 155 | { 156 | RsOpprfSender sender; 157 | RsOpprfReceiver recver; 158 | 159 | auto sockets = cp::LocalAsyncSocket::makePair(); 160 | 161 | u64 n = 4000; 162 | u64 m = 7; 163 | PRNG prng0(block(0, 0)); 164 | PRNG prng1(block(0, 1)); 165 | 166 | std::vector vals(n); 167 | oc::Matrix out(n, m), out2(n, m), recvOut(n, m); 168 | 169 | prng0.get(vals.data(), n); 170 | prng0.get(out.data(), n); 171 | 172 | auto p0 = sender.send(n, vals, out, prng0, 1, sockets[0]); 173 | auto p1 = recver.receive(n, vals, recvOut, prng1, 1, sockets[1]); 174 | 175 | eval(p0, p1); 176 | 177 | 178 | sender.eval(vals, out2, 1); 179 | 180 | u64 count = 0; 181 | for (u64 i = 0; i < n; ++i) 182 | { 183 | auto c0 = memcmp(recvOut[i].data(), out[i].data(), m * sizeof(u8)) != 0; 184 | auto c1 = memcmp(recvOut[i].data(), out2[i].data(), m * sizeof(u8)) != 0; 185 | if (c0 || c1) 186 | { 187 | if (count < 10) 188 | std::cout << i << " " << hex(recvOut[i]) << " " << hex(out2[i]) << " " << hex(out[i]) << std::endl; 189 | else 190 | break; 191 | 192 | ++count; 193 | } 194 | } 195 | if (count) 196 | throw RTE_LOC; 197 | } 198 | -------------------------------------------------------------------------------- /tests/UnitTests.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "cryptoTools/Common/Log.h" 4 | #include 5 | #include "UnitTests.h" 6 | 7 | #include "Paxos_Tests.h" 8 | #include "RsOprf_Tests.h" 9 | #include "RsOpprf_Tests.h" 10 | #include "RsPsi_Tests.h" 11 | #include "RsCpsi_Tests.h" 12 | #include "GMW_Tests.h" 13 | #include "volePSI/GMW/Circuit.h" 14 | #include "FileBase_Tests.h" 15 | #include "MPSI_Tests.h" 16 | 17 | namespace volePSI_Tests 18 | { 19 | using namespace volePSI; 20 | 21 | oc::TestCollection Tests([](oc::TestCollection& t) { 22 | 23 | t.add("Paxos_buildRow_Test ", Paxos_buildRow_Test); 24 | t.add("Paxos_solve_Test ", Paxos_solve_Test); 25 | t.add("Paxos_solve_u8_Test ", Paxos_solve_u8_Test); 26 | t.add("Paxos_solve_mtx_Test ", Paxos_solve_mtx_Test); 27 | 28 | t.add("Paxos_invE_Test ", Paxos_invE_Test); 29 | t.add("Paxos_invE_g3_Test ", Paxos_invE_g3_Test); 30 | t.add("Paxos_solve_gap_Test ", Paxos_solve_gap_Test); 31 | t.add("Paxos_solve_rand_Test ", Paxos_solve_rand_Test); 32 | t.add("Paxos_solve_rand_gap_Test ", Paxos_solve_rand_gap_Test); 33 | 34 | t.add("Baxos_solve_Test ", Baxos_solve_Test); 35 | t.add("Baxos_solve_mtx_Test ", Baxos_solve_mtx_Test); 36 | t.add("Baxos_solve_par_Test ", Baxos_solve_par_Test); 37 | t.add("Baxos_solve_rand_Test ", Baxos_solve_rand_Test); 38 | 39 | #ifdef VOLE_PSI_ENABLE_GMW 40 | t.add("SilentTripleGen_test ", SilentTripleGen_test); 41 | //t.add("IknpTripleGen_test ", IknpTripleGen_test); 42 | t.add("generateBase_test ", generateBase_test); 43 | 44 | t.add("isZeroCircuit_Test ", isZeroCircuit_Test); 45 | t.add("Gmw_half_test ", Gmw_half_test); 46 | t.add("Gmw_basic_test ", Gmw_basic_test); 47 | t.add("Gmw_inOut_test ", Gmw_inOut_test); 48 | t.add("Gmw_xor_test ", Gmw_xor_test); 49 | t.add("Gmw_and_test ", Gmw_and_test); 50 | t.add("Gmw_or_test ", Gmw_or_test); 51 | t.add("Gmw_na_and_test ", Gmw_na_and_test); 52 | t.add("Gmw_xor_and_test ", Gmw_xor_and_test); 53 | t.add("Gmw_aa_na_and_test ", Gmw_aa_na_and_test); 54 | t.add("Gmw_noLevelize_test ", Gmw_noLevelize_test); 55 | t.add("Gmw_add_test ", Gmw_add_test); 56 | #endif 57 | 58 | t.add("RsOprf_eval_test ", RsOprf_eval_test); 59 | t.add("RsOprf_mal_test ", RsOprf_mal_test); 60 | t.add("RsOprf_reduced_test ", RsOprf_reduced_test); 61 | 62 | #ifdef VOLE_PSI_ENABLE_OPPRF 63 | t.add("RsOpprf_eval_blk_test ", RsOpprf_eval_blk_test); 64 | t.add("RsOpprf_eval_u8_test ", RsOpprf_eval_u8_test); 65 | 66 | t.add("RsOpprf_eval_blk_mtx_test ", RsOpprf_eval_blk_mtx_test); 67 | t.add("RsOpprf_eval_u8_mtx_test ", RsOpprf_eval_u8_mtx_test); 68 | #endif 69 | 70 | t.add("Psi_Rs_empty_test ", Psi_Rs_empty_test); 71 | t.add("Psi_Rs_partial_test ", Psi_Rs_partial_test); 72 | t.add("Psi_Rs_full_test ", Psi_Rs_full_test); 73 | t.add("Psi_Rs_reduced_test ", Psi_Rs_reduced_test); 74 | t.add("Psi_Rs_multiThrd_test ", Psi_Rs_multiThrd_test); 75 | t.add("Psi_Rs_mal_test ", Psi_Rs_mal_test); 76 | 77 | #ifdef VOLE_PSI_ENABLE_CPSI 78 | t.add("Cpsi_Rs_empty_test ", Cpsi_Rs_empty_test); 79 | t.add("Cpsi_Rs_partial_test ", Cpsi_Rs_partial_test); 80 | t.add("Cpsi_Rs_full_test ", Cpsi_Rs_full_test); 81 | t.add("Cpsi_Rs_full_asym_test ", Cpsi_Rs_full_asym_test); 82 | t.add("Cpsi_Rs_full_add32_test ", Cpsi_Rs_full_add32_test); 83 | #endif 84 | 85 | t.add("filebase_readSet_Test ", filebase_readSet_Test); 86 | t.add("filebase_psi_bin_Test ", filebase_psi_bin_Test); 87 | t.add("filebase_psi_csv_Test ", filebase_psi_csv_Test); 88 | t.add("filebase_psi_csvh_Test ", filebase_psi_csvh_Test); 89 | 90 | }); 91 | } 92 | 93 | namespace MPSI_Tests 94 | { 95 | using namespace volePSI; 96 | 97 | oc::TestCollection Tests([](oc::TestCollection& t) { 98 | 99 | t.add("MPSI_3Party_Empty_Test ", MPSI_3Party_Empty_Test); 100 | t.add("MPSI_3Party_Partial_Test ", MPSI_3Party_Partial_Test); 101 | t.add("MPSI_3Party_Full_Test ", MPSI_3Party_Full_Test); 102 | t.add("MPSI_3Party_Mthreads_Test ", MPSI_3Party_Mthreads_Test); 103 | t.add("MPSI_3Party_Cardinality_Test", MPSI_3Party_Cardinality_Test); 104 | t.add("MPSI_3Party_Circuit_Test ", MPSI_3Party_Circuit_Test); 105 | t.add("MPSI_3Party_Broadcast_Test ", MPSI_3Party_Broadcast_Test); 106 | t.add("MPSI_3Party_Malicious_Test ", MPSI_3Party_Malicious_Test); 107 | 108 | t.add("MPSI_5Party_Empty_Test ", MPSI_5Party_Empty_Test); 109 | t.add("MPSI_5Party_Partial_Test ", MPSI_5Party_Partial_Test); 110 | t.add("MPSI_5Party_Full_Test ", MPSI_5Party_Full_Test); 111 | t.add("MPSI_5Party_Mthreads_Test ", MPSI_5Party_Mthreads_Test); 112 | t.add("MPSI_5Party_Cardinality_Test", MPSI_5Party_Cardinality_Test); 113 | t.add("MPSI_5Party_Circuit_Test ", MPSI_5Party_Circuit_Test); 114 | t.add("MPSI_5Party_Broadcast_Test ", MPSI_5Party_Broadcast_Test); 115 | t.add("MPSI_5Party_Malicious_Test ", MPSI_5Party_Malicious_Test); 116 | 117 | }); 118 | } 119 | -------------------------------------------------------------------------------- /volepsi_README.md: -------------------------------------------------------------------------------- 1 | # Vole-PSI 2 | 3 | 4 | Vole-PSI implements the protocols described in [VOLE-PSI: Fast OPRF and Circuit-PSI from Vector-OLE](https://eprint.iacr.org/2021/266) and [Blazing Fast PSI from Improved OKVS and Subfield VOLE](misc/blazingFastPSI.pdf). The library implements standard [Private Set Intersection (PSI)](https://en.wikipedia.org/wiki/Private_set_intersection) along with a variant called Circuit PSI where the result is secret shared between the two parties. 5 | 6 | The library is cross platform (win,linux,mac) and depends on [libOTe](https://github.com/osu-crypto/libOTe), [sparsehash](https://github.com/sparsehash/sparsehash), [Coproto](https://github.com/Visa-Research/coproto). 7 | 8 | ### Build 9 | 10 | The library can be cloned and built with networking support as 11 | ``` 12 | git clone https://github.com/Visa-Research/volepsi.git 13 | cd volepsi 14 | python3 build.py -DVOLE_PSI_ENABLE_BOOST=ON 15 | ``` 16 | If TCP/IP support is not required, then a minimal version of the library can be build by calling `python3 build.py`. See below and the cmake/python output for additional options. 17 | The user can manually call cmake as well. 18 | 19 | The output library `volePSI` and executable `frontend` will be written to `out/build//`. The `frontend` can perform PSI based on files as input sets and communicate via sockets. See the output of `frontend` for details. There is also two example on how to perform [networking](https://github.com/Visa-Research/volepsi/blob/main/frontend/networkSocketExample.h#L7) or [manually](https://github.com/Visa-Research/volepsi/blob/main/frontend/messagePassingExample.h#L93) get & send the protocol messages. 20 | 21 | ##### Compile Options 22 | Options can be set as `-D NAME=VALUE`. For example, `-D VOLE_PSI_NO_SYSTEM_PATH=true`. See the output of the build for default/current value. Options include : 23 | * `VOLE_PSI_NO_SYSTEM_PATH`, values: `true,false`. When looking for dependencies, do not look in the system install. Instead use `CMAKE_PREFIX_PATH` and the internal dependency management. 24 | * `CMAKE_BUILD_TYPE`, values: `Debug,Release,RelWithDebInfo`. The build type. 25 | * `FETCH_AUTO`, values: `true,false`. If true, dependencies will first be searched for and if not found then automatically downloaded. 26 | * `FETCH_SPARSEHASH`, values: `true,false`. If true, the dependency sparsehash will always be downloaded. 27 | * `FETCH_LIBOTE`, values: `true,false`. If true, the dependency libOTe will always be downloaded. 28 | * `FETCH_LIBDIVIDE`, values: `true,false`. If true, the dependency libdivide will always be downloaded. 29 | * `VOLE_PSI_ENABLE_SSE`, values: `true,false`. If true, the library will be built with SSE intrinsics support. 30 | * `VOLE_PSI_ENABLE_PIC`, values: `true,false`. If true, the library will be built `-fPIC` for shared library support. 31 | * `VOLE_PSI_ENABLE_ASAN`, values: `true,false`. If true, the library will be built ASAN enabled. 32 | * `VOLE_PSI_ENABLE_GMW`, values: `true,false`. If true, the GMW protocol will be compiled. Only used for Circuit PSI. 33 | * `VOLE_PSI_ENABLE_CPSI`, values: `true,false`. If true, the circuit PSI protocol will be compiled. 34 | * `VOLE_PSI_ENABLE_OPPRF`, values: `true,false`. If true, the OPPRF protocol will be compiled. Only used for Circuit PSI. 35 | * `VOLE_PSI_ENABLE_BOOST`, values: `true,false`. If true, the library will be built with boost networking support. This support is managed by libOTe. 36 | * `VOLE_PSI_ENABLE_OPENSSL`, values: `true,false`. If true,the library will be built with OpenSSL networking support. This support is managed by libOTe. If enabled, it is the responsibility of the user to install openssl to the system or to a location contained in `CMAKE_PREFIX_PATH`. 37 | * `VOLE_PSI_ENABLE_BITPOLYMUL`, values: `true,false`. If true, the library will be built with quasicyclic codes for VOLE which are more secure than the alternative. This support is managed by libOTe. 38 | * `VOLE_PSI_ENABLE_SODIUM`, values: `true,false`. If true, the library will be built libSodium for doing elliptic curve operations. This or relic must be enabled. This support is managed by libOTe. 39 | * `VOLE_PSI_SODIUM_MONTGOMERY`, values: `true,false`. If true, the library will use a non-standard version of sodium that enables slightly better efficiency. 40 | * `VOLE_PSI_ENABLE_RELIC`, values: `true,false`. If true, the library will be built relic for doing elliptic curve operations. This or sodium must be enabled. This support is managed by libOTe. 41 | 42 | 43 | ### Installing 44 | 45 | The library and any fetched dependencies can be installed. 46 | ``` 47 | python3 build.py --install 48 | ``` 49 | or 50 | ``` 51 | python3 build.py --install=install/prefix/path 52 | ``` 53 | if a custom install prefix is perfected. Install can also be performed via cmake. 54 | 55 | ### Linking 56 | 57 | libOTe can be linked via cmake as 58 | ``` 59 | find_package(volepsi REQUIRED) 60 | target_link_libraries(myProject visa::volepsi) 61 | ``` 62 | To ensure that cmake can find volepsi, you can either install volepsi or build it locally and set `-D CMAKE_PREFIX_PATH=path/to/volepsi` or provide its location as a cmake `HINTS`, i.e. `find_package(volepsi HINTS path/to/volepsi)`. 63 | 64 | To link a non-cmake project you will need to link volepsi, libOTe,coproto, macoro, (sodium or relic), optionally boost and openss if enabled. These will be installed to the install location and staged to `./out/install/`. 65 | 66 | 67 | ### Dependency Management 68 | 69 | By default the dependencies are fetched automatically. This can be turned off by using cmake directly or adding `-D FETCH_AUTO=OFF`. For other options see the cmake output or that of `python build.py --help`. 70 | 71 | If the dependency is installed to the system, then cmake should automatically find it if `VOLE_PSI_NO_SYSTEM_PATH` is `false`. If they are installed to a specific location, then you call tell cmake about them as 72 | ``` 73 | python3 build.py -D CMAKE_PREFIX_PATH=install/prefix/path 74 | ``` 75 | 76 | -------------------------------------------------------------------------------- /volePSI/GMW/Gmw.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // © 2022 Visa. 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | #include "volePSI/Defines.h" 10 | #include "volePSI/config.h" 11 | 12 | #ifdef VOLE_PSI_ENABLE_GMW 13 | 14 | #include "volePSI/GMW/Circuit.h" 15 | #include "volePSI/GMW/SilentTripleGen.h" 16 | #include 17 | #include 18 | #include 19 | namespace volePSI 20 | { 21 | 22 | enum class OtExtType 23 | { 24 | IKNP, 25 | Silent, 26 | InsecureMock 27 | }; 28 | class Gmw : public oc::TimerAdapter 29 | { 30 | public: 31 | 32 | struct Debug 33 | { 34 | bool mDebug = false; 35 | std::vector mA, mB, mC, mD; 36 | std::list,2>> mU, mW; 37 | Matrix mVals; 38 | Matrix mWords; 39 | }; 40 | 41 | 42 | Debug mO; 43 | 44 | // allow the circuit to be reordered into levels 45 | // based on their AND depth. 46 | BetaCircuit::LevelizeType mLevelize = BetaCircuit::LevelizeType::Reorder; 47 | 48 | u64 mN = 0, mNumOts = 0, mIdx; 49 | OtExtType mOtExtType; 50 | //u64 mBitCount; 51 | Matrix mWords; 52 | u64 mRoundIdx = 0, mNumRounds; 53 | BetaCircuit mCir; 54 | span mGates; 55 | 56 | oc::PRNG mPrng, mPhiPrng; 57 | 58 | span mA, mB, mC, mC2, mD; 59 | 60 | u64 mDebugPrintIdx = -1; 61 | BetaCircuit::PrintIter mPrint; 62 | 63 | 64 | void init( 65 | u64 n, 66 | BetaCircuit& cir, 67 | u64 numThreads, 68 | u64 pIdx, 69 | block seed); 70 | 71 | void setTriples(span a, span b, span c, span d) 72 | { 73 | mA = a; 74 | mB = b; 75 | mC = c; 76 | mC2 = c; 77 | mD = d; 78 | } 79 | 80 | Proto generateTriple( 81 | u64 batchSize, 82 | u64 numThreads, 83 | coproto::Socket& chl); 84 | 85 | template 86 | void setInput(u64 i, oc::MatrixView input) 87 | { 88 | static_assert(std::is_trivially_copyable::value, "expecting trivial"); 89 | oc::MatrixView ii((u8*)input.data(), input.rows(), input.cols() * sizeof(T)); 90 | implSetInput(i, ii, sizeof(T)); 91 | } 92 | 93 | void setZeroInput(u64 i); 94 | 95 | Proto run(coproto::Socket& chl); 96 | 97 | template 98 | void getOutput(u64 i, oc::MatrixView out) 99 | { 100 | static_assert(std::is_trivially_copyable::value, "expecting trivial"); 101 | oc::MatrixView ii((u8*)out.data(), out.rows(), out.cols() * sizeof(T)); 102 | implGetOutput(i, ii, sizeof(T)); 103 | } 104 | 105 | 106 | void implSetInput(u64 i, oc::MatrixView input, u64 alignment); 107 | void implGetOutput(u64 i, oc::MatrixView out, u64 alignment); 108 | 109 | oc::MatrixView getInputView(u64 i); 110 | oc::MatrixView getOutputView(u64 i); 111 | oc::MatrixView getMemView(BetaBundle& wires); 112 | 113 | SilentTripleGen mSilent; 114 | //IknpTripleGen mIknp; 115 | 116 | u64 numRounds() 117 | { 118 | return mNumRounds; 119 | } 120 | 121 | Proto roundFunction(coproto::Socket& chl); 122 | 123 | 124 | Proto multSendP1(span x, coproto::Socket& chl, oc::GateType gt); 125 | Proto multSendP2(span x, coproto::Socket& chl, oc::GateType gt); 126 | 127 | 128 | Proto multRecvP1(span x, span z, coproto::Socket& chl, oc::GateType gt); 129 | Proto multRecvP2(span x, span z, coproto::Socket& chl); 130 | 131 | 132 | Proto multSend(span x, span y, coproto::Socket& chl, oc::GateType gt) 133 | { 134 | if (mIdx == 0) 135 | return multSendP1(x, y, chl, gt); 136 | else 137 | return multSendP2(x, y, chl); 138 | } 139 | Proto multSendP1(span x, span y, coproto::Socket& chl, oc::GateType gt); 140 | Proto multSendP2(span x, span y, coproto::Socket& chl); 141 | 142 | 143 | Proto multRecv(span x, span y, span z, coproto::Socket& chl, oc::GateType gt) 144 | { 145 | if (mIdx == 0) 146 | return multRecvP1(x, y, z, chl, gt); 147 | else 148 | return multRecvP2(x, y, z, chl); 149 | } 150 | 151 | Proto multRecvP1(span x, span y, span z, coproto::Socket& chl, oc::GateType gt); 152 | Proto multRecvP2(span x, span y, span z, coproto::Socket& chl); 153 | }; 154 | } 155 | #endif -------------------------------------------------------------------------------- /tests/RsCpsi_Tests.cpp: -------------------------------------------------------------------------------- 1 | #include "RsCpsi_Tests.h" 2 | #include "volePSI/RsPsi.h" 3 | #include "volePSI/RsCpsi.h" 4 | #include "cryptoTools/Network/Channel.h" 5 | #include "cryptoTools/Network/Session.h" 6 | #include "cryptoTools/Network/IOService.h" 7 | #include "Common.h" 8 | 9 | using coproto::LocalAsyncSocket; 10 | using namespace oc; 11 | using namespace volePSI; 12 | 13 | namespace 14 | { 15 | 16 | std::vector runCpsi( 17 | PRNG& prng, 18 | std::vector& recvSet, 19 | std::vector& sendSet, 20 | u64 nt = 1, 21 | ValueShareType type = ValueShareType::Xor) 22 | { 23 | auto sockets = LocalAsyncSocket::makePair(); 24 | 25 | 26 | RsCpsiReceiver recver; 27 | RsCpsiSender sender; 28 | 29 | auto byteLength = sizeof(block); 30 | oc::Matrix senderValues(sendSet.size(), sizeof(block)); 31 | std::memcpy(senderValues.data(), sendSet.data(), sendSet.size() * sizeof(block)); 32 | 33 | recver.init(sendSet.size(), recvSet.size(), byteLength, 40, prng.get(), nt); 34 | sender.init(sendSet.size(), recvSet.size(), byteLength, 40, prng.get(), nt); 35 | 36 | RsCpsiReceiver::Sharing rShare; 37 | RsCpsiSender::Sharing sShare; 38 | 39 | auto p0 = recver.receive(recvSet, rShare, sockets[0]); 40 | auto p1 = sender.send(sendSet, senderValues, sShare, sockets[1]); 41 | 42 | eval(p0, p1); 43 | 44 | bool failed = false; 45 | std::vector intersection; 46 | for (u64 i = 0; i < recvSet.size(); ++i) 47 | { 48 | auto k = rShare.mMapping[i]; 49 | 50 | if (rShare.mFlagBits[k] ^ sShare.mFlagBits[k]) 51 | { 52 | intersection.push_back(i); 53 | 54 | if (type == ValueShareType::Xor) 55 | { 56 | auto rv = *(block*)&rShare.mValues(k, 0); 57 | auto sv = *(block*)&sShare.mValues(k, 0); 58 | auto act = (rv ^ sv); 59 | if (recvSet[i] != act) 60 | { 61 | if(!failed) 62 | std::cout << i << " ext " << recvSet[i] << ", act " << act << " = " << rv << " " << sv << std::endl; 63 | failed = true; 64 | //throw RTE_LOC; 65 | } 66 | } 67 | else 68 | { 69 | 70 | for (u64 j = 0; j < 4; ++j) 71 | { 72 | auto rv = (u32*)&rShare.mValues(i, 0); 73 | auto sv = (u32*)&sShare.mValues(i, 0); 74 | 75 | if (recvSet[i].get(j) != (sv[j] + rv[j])) 76 | { 77 | throw RTE_LOC; 78 | } 79 | } 80 | } 81 | } 82 | } 83 | 84 | 85 | return intersection; 86 | } 87 | } 88 | 89 | 90 | void Cpsi_Rs_empty_test(const CLP& cmd) 91 | { 92 | u64 n = cmd.getOr("n", 133); 93 | std::vector recvSet(n), sendSet(n); 94 | PRNG prng(ZeroBlock); 95 | prng.get(recvSet.data(), recvSet.size()); 96 | prng.get(sendSet.data(), sendSet.size()); 97 | 98 | auto inter = runCpsi(prng, recvSet, sendSet); 99 | 100 | if (inter.size()) 101 | throw RTE_LOC; 102 | } 103 | 104 | 105 | void Cpsi_Rs_partial_test(const CLP& cmd) 106 | { 107 | u64 n = cmd.getOr("n", 128); 108 | std::vector recvSet(n), sendSet(n); 109 | PRNG prng(ZeroBlock); 110 | prng.get(recvSet.data(), recvSet.size()); 111 | prng.get(sendSet.data(), sendSet.size()); 112 | 113 | for (u64 i = 0; i < n; ++i) 114 | { 115 | sendSet[i].set(0, i); 116 | recvSet[i].set(0, i); 117 | } 118 | 119 | std::set exp; 120 | for (u64 i = 0; i < n; ++i) 121 | { 122 | if (prng.getBit()) 123 | { 124 | recvSet[i] = sendSet[(i + 312) % n]; 125 | exp.insert(i); 126 | } 127 | } 128 | 129 | auto inter = runCpsi(prng, recvSet, sendSet); 130 | std::set act(inter.begin(), inter.end()); 131 | if (act != exp) 132 | { 133 | auto rem = exp; 134 | for (auto a : act) 135 | rem.erase(a); 136 | 137 | std::cout << "missing " << *rem.begin() << " " << recvSet[*rem.begin()] << std::endl; 138 | throw RTE_LOC; 139 | } 140 | } 141 | 142 | 143 | void Cpsi_Rs_full_test(const CLP& cmd) 144 | { 145 | u64 n = cmd.getOr("n", 243); 146 | std::vector recvSet(n), sendSet(n); 147 | PRNG prng(ZeroBlock); 148 | prng.get(recvSet.data(), recvSet.size()); 149 | sendSet = recvSet; 150 | 151 | std::set exp; 152 | for (u64 i = 0; i < n; ++i) 153 | exp.insert(i); 154 | 155 | auto inter = runCpsi(prng, recvSet, sendSet); 156 | std::set act(inter.begin(), inter.end()); 157 | if (act != exp) 158 | throw RTE_LOC; 159 | } 160 | 161 | void Cpsi_Rs_full_asym_test(const CLP& cmd) 162 | { 163 | u64 ns = cmd.getOr("ns", 2432); 164 | u64 nr = cmd.getOr("nr", 212); 165 | std::vector recvSet(nr), sendSet(ns); 166 | PRNG prng(ZeroBlock); 167 | prng.get(recvSet.data(), recvSet.size()); 168 | prng.SetSeed(ZeroBlock); 169 | prng.get(sendSet.data(), sendSet.size()); 170 | 171 | std::set exp; 172 | for (u64 i = 0; i < std::min(ns,nr); ++i) 173 | exp.insert(i); 174 | 175 | auto inter = runCpsi(prng, recvSet, sendSet); 176 | std::set act(inter.begin(), inter.end()); 177 | if (act != exp) 178 | throw RTE_LOC; 179 | } 180 | 181 | 182 | 183 | 184 | void Cpsi_Rs_full_add32_test(const CLP& cmd) 185 | { 186 | //u64 n = cmd.getOr("n", 13243); 187 | //std::vector recvSet(n), sendSet(n); 188 | //PRNG prng(ZeroBlock); 189 | //prng.get(recvSet.data(), recvSet.size()); 190 | //sendSet = recvSet; 191 | 192 | //std::set exp; 193 | //for (u64 i = 0; i < n; ++i) 194 | // exp.insert(i); 195 | 196 | //auto inter = runCpsi(prng, recvSet, sendSet, 1, ValueShareType::add32); 197 | //std::set act(inter.begin(), inter.end()); 198 | //if (act != exp) 199 | // throw RTE_LOC; 200 | } -------------------------------------------------------------------------------- /frontend/networkSocketExample.h: -------------------------------------------------------------------------------- 1 | #include "cryptoTools/Common/CLP.h" 2 | #include "volePSI/RsPsi.h" 3 | #include 4 | #include "coproto/Socket/AsioSocket.h" 5 | #include "volePSI/fileBased.h" 6 | 7 | void networkSocketExampleRun(const oc::CLP& cmd) 8 | { 9 | try { 10 | auto recver = cmd.get("r"); 11 | bool client = !cmd.getOr("server", recver); 12 | auto ip = cmd.getOr("ip", "localhost:1212"); 13 | 14 | auto ns = cmd.getOr("senderSize", 100ull); 15 | auto nr = cmd.getOr("receiverSize", 100ull); 16 | 17 | // The statistical security parameter. 18 | auto ssp = cmd.getOr("ssp", 40ull); 19 | 20 | // Malicious Security. 21 | auto mal = cmd.isSet("malicious"); 22 | 23 | // The vole type, default to expand accumulate. 24 | auto type = oc::DefaultMultType; 25 | #ifdef ENABLE_INSECURE_SILVER 26 | type = cmd.isSet("useSilver") ? oc::MultType::slv5 : type; 27 | #endif 28 | #ifdef ENABLE_BITPOLYMUL 29 | type = cmd.isSet("useQC") ? oc::MultType::QuasiCyclic : type; 30 | #endif 31 | 32 | // use fewer rounds of communication but more computation. 33 | auto useReducedRounds = cmd.isSet("reducedRounds"); 34 | 35 | 36 | std::cout << "connecting as " << (client ? "client" : "server") << " at ip " << ip << std::endl; 37 | 38 | coproto::Socket sock; 39 | if (cmd.isSet("tls")) 40 | { 41 | std::string certDir = cmd.getOr("cert", "./thirdparty/libOTe/thirdparty/coproto/tests/cert/"); 42 | std::string CACert = cmd.getOr("CA", certDir + "/ca.cert.pem"); 43 | auto privateKey = cmd.getOr("sk", certDir + "/" + (client ? "client" : "server") + "-0.key.pem"); 44 | auto publicKey = cmd.getOr("pk", certDir + "/" + (client ? "client" : "server") + "-0.cert.pem"); 45 | 46 | if (!volePSI::exist(CACert) || !volePSI::exist(privateKey) || !volePSI::exist(privateKey)) 47 | { 48 | if (!volePSI::exist(CACert)) 49 | std::cout << "CA cert " << CACert << "does not exist" << std::endl; 50 | if (!volePSI::exist(privateKey)) 51 | std::cout << "private key " << privateKey << "does not exist" << std::endl; 52 | if (!volePSI::exist(privateKey)) 53 | std::cout << "public key " << publicKey << "does not exist" << std::endl; 54 | 55 | std::cout << "Please correctly set -CA= -sk= -pk= to the CA cert, user private key " 56 | << " and public key respectively. Or run the program from the volePSI root directory to use the " 57 | << oc::Color::Red << "insecure " << oc::Color::Default 58 | << " sample certs/keys that are provided by coproto. " << std::endl; 59 | } 60 | 61 | #ifdef COPROTO_ENABLE_OPENSSL 62 | boost::asio::ssl::context ctx(client ? 63 | boost::asio::ssl::context::tlsv13_client : 64 | boost::asio::ssl::context::tlsv13_server 65 | ); 66 | 67 | // Require that the both parties verify using their cert. 68 | ctx.set_verify_mode( 69 | boost::asio::ssl::verify_peer | 70 | boost::asio::ssl::verify_fail_if_no_peer_cert); 71 | ctx.load_verify_file(CACert); 72 | ctx.use_private_key_file(privateKey, boost::asio::ssl::context::file_format::pem); 73 | ctx.use_certificate_file(publicKey, boost::asio::ssl::context::file_format::pem); 74 | 75 | // Perform the TCP/IP and TLS handshake. 76 | sock = coproto::sync_wait( 77 | client ? 78 | macoro::make_task(coproto::AsioTlsConnect(ip, coproto::global_io_context(), ctx)) : 79 | macoro::make_task(coproto::AsioTlsAcceptor(ip, coproto::global_io_context(), ctx)) 80 | ); 81 | #else 82 | throw std::runtime_error("COPROTO_ENABLE_OPENSSL must be define (via cmake) to use TLS sockets. " COPROTO_LOCATION); 83 | #endif 84 | } 85 | else 86 | { 87 | #ifdef COPROTO_ENABLE_BOOST 88 | // Perform the TCP/IP. 89 | sock = coproto::asioConnect(ip, !client); 90 | #else 91 | throw std::runtime_error("COPROTO_ENABLE_BOOST must be define (via cmake) to use tcp sockets. " COPROTO_LOCATION); 92 | #endif 93 | } 94 | 95 | std::cout << "connected" << std::endl; 96 | std::vector set; 97 | if (!recver) 98 | { 99 | // Use dummy set {0,1,...} 100 | set.resize(ns); 101 | for (oc::u64 i = 0; i < ns; ++i) 102 | set[i] = oc::block(0, i); 103 | 104 | // configure 105 | volePSI::RsPsiSender sender; 106 | sender.setMultType(type); 107 | sender.init(ns, nr, ssp, oc::sysRandomSeed(), mal, 1, useReducedRounds); 108 | 109 | std::cout << "sender start\n"; 110 | auto start = std::chrono::system_clock::now(); 111 | 112 | // Run the protocol. 113 | macoro::sync_wait(sender.run(set, sock)); 114 | 115 | auto done = std::chrono::system_clock::now(); 116 | std::cout << "sender done, " << std::chrono::duration_cast(done-start).count() <<"ms" << std::endl; 117 | } 118 | else 119 | { 120 | // Use dummy set {0,1,...} 121 | set.resize(nr); 122 | for (oc::u64 i = 0; i < nr; ++i) 123 | set[i] = oc::block(0, i); 124 | 125 | // Configure. 126 | volePSI::RsPsiReceiver recevier; 127 | recevier.setMultType(type); 128 | recevier.init(ns, nr, ssp, oc::sysRandomSeed(), mal, 1, useReducedRounds); 129 | 130 | std::cout << "recver start\n"; 131 | auto start = std::chrono::system_clock::now(); 132 | 133 | // Run the protocol. 134 | macoro::sync_wait(recevier.run(set, sock)); 135 | 136 | auto done = std::chrono::system_clock::now(); 137 | std::cout << "sender done, " << std::chrono::duration_cast(done-start).count() <<"ms" << std::endl; 138 | } 139 | 140 | } 141 | catch (std::exception& e) 142 | { 143 | std::cout << e.what() << std::endl; 144 | } 145 | } 146 | 147 | 148 | void networkSocketExample(const oc::CLP& cmd) 149 | { 150 | // If the user specified -sender or -recver, then run that party. 151 | // Otherwisew run both parties. 152 | if (cmd.isSet("sender") || cmd.isSet("recver")) 153 | { 154 | networkSocketExampleRun(cmd); 155 | } 156 | else 157 | { 158 | auto s = cmd; 159 | s.set("sender"); 160 | s.set("server"); 161 | auto a = std::async([&]() {networkSocketExampleRun(s); }); 162 | networkSocketExampleRun(cmd); 163 | a.get(); 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /volePSI/RsOpprf.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // © 2022 Visa. 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | // 5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | 10 | #include "volePSI/Defines.h" 11 | #include "volePSI/config.h" 12 | #ifdef VOLE_PSI_ENABLE_OPPRF 13 | 14 | #include "volePSI/RsOprf.h" 15 | 16 | namespace volePSI 17 | { 18 | template 19 | struct SharedContainer 20 | { 21 | std::shared_ptr mBuffer; 22 | 23 | using value_type = typename T::value_type; 24 | using size_type = typename T::size_type; 25 | 26 | //SharedContainer() = default; 27 | SharedContainer(const SharedContainer&) = default; 28 | SharedContainer(SharedContainer&&) = default; 29 | SharedContainer& operator=(SharedContainer&&) = default; 30 | SharedContainer& operator=(const SharedContainer&) = default; 31 | 32 | template 33 | SharedContainer(Args... args) 34 | :mBuffer(std::make_shared(std::forward(args)...)) 35 | { } 36 | 37 | void resize(u64 s) { mBuffer->resize(s); } 38 | auto size() const { return mBuffer->size(); } 39 | auto data() { return mBuffer->data(); } 40 | auto data() const { return mBuffer->data(); } 41 | 42 | auto begin() { return mBuffer->begin(); } 43 | auto end() { return mBuffer->end(); } 44 | auto begin() const { return mBuffer->begin(); } 45 | auto end() const { return mBuffer->end(); } 46 | 47 | operator T&() { return *mBuffer; } 48 | operator const T&() const { return *mBuffer; } 49 | }; 50 | 51 | 52 | template 53 | struct BasicVector : public span 54 | { 55 | BasicVector() = default; 56 | BasicVector(BasicVector&& o) { asSpan() = o.asSpan(); o.asSpan() = {}; }; 57 | BasicVector& operator=(BasicVector&& o) { clear(); asSpan() = o.asSpan(); o.asSpan() = {}; return *this; }; 58 | 59 | span& asSpan() { return static_cast&>(*this); } 60 | operator span& () { return asSpan(); } 61 | 62 | BasicVector(u64 size) 63 | { 64 | resize(size); 65 | } 66 | 67 | auto clear() 68 | { 69 | if (asSpan().data()) 70 | delete[] asSpan().data(); 71 | } 72 | 73 | ~BasicVector() 74 | { 75 | clear(); 76 | } 77 | 78 | void resize(u64 size) 79 | { 80 | clear(); 81 | asSpan() = span(new T[size], size); 82 | } 83 | 84 | 85 | 86 | }; 87 | 88 | 89 | 90 | class RsOpprfSender : public oc::TimerAdapter 91 | { 92 | public: 93 | RsOprfSender mOprfSender; 94 | void setMultType(oc::MultType type) { mOprfSender.setMultType(type); }; 95 | 96 | //struct PP 97 | //{ 98 | // u8* mData = nullptr; 99 | // u64 mRows = 0; 100 | // u64 mCols = 0; 101 | 102 | // ~PP() 103 | // { 104 | // delete[] mData; 105 | // } 106 | 107 | // PP(u64 n, u64 m) 108 | // : mData(new u8[n * m]) 109 | // , mRows(n) 110 | // , mCols(m) 111 | // { } 112 | //}; 113 | 114 | //std::shared_ptr mPBacking; 115 | SharedContainer> mP; 116 | 117 | u64 mPaxosByteWidth = 0; 118 | Baxos mPaxos; 119 | 120 | Proto send(u64 recverSize, span X, span val, PRNG& prng, u64 numThreads, Socket& chl) 121 | { 122 | return send(recverSize, X, MatrixView((u8*)val.data(), val.size(), sizeof(block)), prng, numThreads, chl); 123 | } 124 | 125 | template 126 | Proto send(u64 recverSize, span X, MatrixView val, PRNG& prng, u64 numThreads, Socket& chl) 127 | { 128 | return send(recverSize, X, MatrixView((u8*)val.data(), val.rows(), val.cols() * sizeof(ValueType)), prng, numThreads, chl); 129 | } 130 | 131 | template 132 | Proto send(u64 recverSize, span X, span val, PRNG& prng, u64 numThreads, Socket& chl) 133 | { 134 | return send(recverSize, X, MatrixView((u8*)val.data(), val.size(), sizeof(ValueType)), prng, numThreads, chl); 135 | } 136 | 137 | 138 | template 139 | T eval(block v) 140 | { 141 | T r; 142 | MatrixView mm(&r, 1, 1); 143 | eval({ &v, 1 }, mm, 1); 144 | return r; 145 | //return mOprfSender.eval(v) ^ mPaxos.decode(v, mP); 146 | } 147 | 148 | void eval(span val, span output, u64 numThreads) 149 | { 150 | eval(val, MatrixView((u8*)output.data(), output.size(), sizeof(block)), numThreads); 151 | } 152 | 153 | 154 | template 155 | void eval(span val, MatrixView output, u64 numThreads) 156 | { 157 | eval(val, MatrixView((u8*)output.data(), output.rows(), output.cols() * sizeof(ValueType)), numThreads); 158 | } 159 | 160 | 161 | void oprfEval(span val, span out, span add, u64 stride, u64 numThreads); 162 | Proto send(u64 recverSize, span X, MatrixView val, PRNG& prng, u64 numThreads, Socket& chl); 163 | void eval(span val, MatrixView output, u64 numThreads); 164 | }; 165 | 166 | 167 | 168 | class RsOpprfReceiver : public oc::TimerAdapter 169 | { 170 | 171 | public: 172 | RsOprfReceiver mOprfReceiver; 173 | void setMultType(oc::MultType type) { mOprfReceiver.setMultType(type); }; 174 | 175 | Proto receive(u64 senderSize, span values, span outputs, PRNG& prng, u64 numThreads, Socket& chl) 176 | { 177 | return receive(senderSize, values, MatrixView((u8*)outputs.data(), outputs.size(), sizeof(block)), prng, numThreads, chl); 178 | } 179 | 180 | template 181 | Proto receive(u64 senderSize, span values, MatrixView outputs, PRNG& prng, u64 numThreads, Socket& chl) 182 | { 183 | return receive(senderSize, values, MatrixView((u8*)outputs.data(), outputs.rows(), outputs.cols() * sizeof(ValueType)), prng, numThreads, chl); 184 | } 185 | 186 | template 187 | Proto receive(u64 senderSize, span values, span outputs, PRNG& prng, u64 numThreads, Socket& chl) 188 | { 189 | return receive(senderSize, values, MatrixView((u8*)outputs.data(), outputs.size(), sizeof(ValueType)), prng, numThreads, chl); 190 | } 191 | 192 | 193 | Proto receive(u64 senderSize, span values, MatrixView outputs, PRNG& prng, u64 numThreads, Socket& chl); 194 | 195 | }; 196 | 197 | } 198 | #endif 199 | -------------------------------------------------------------------------------- /volePSI/RsOpprf.cpp: -------------------------------------------------------------------------------- 1 | #include "RsOpprf.h" 2 | 3 | 4 | namespace volePSI 5 | { 6 | void RsOpprfSender::oprfEval(span X, span out, span add, u64 m, u64 numThreads) 7 | { 8 | auto n = X.size(); 9 | auto nm = n * m; 10 | 11 | if (out.size() < nm) 12 | throw RTE_LOC; 13 | 14 | std::unique_ptr tempPtr; 15 | span oprfOutput; 16 | if (m == sizeof(block) && !(out.data() == add.data())) 17 | oprfOutput = span((block*)out.data(), n); 18 | else 19 | { 20 | tempPtr.reset(new u8[n * sizeof(block)]); 21 | oprfOutput = span((block*)tempPtr.get(), n); 22 | } 23 | 24 | mOprfSender.eval(X, oprfOutput, numThreads); 25 | 26 | if (m <= sizeof(block)) 27 | { 28 | // short string case 29 | for (u64 i = 0, ij = 0; i < n; ++i) 30 | { 31 | for (u64 j = 0; j < m; ++j, ++ij) 32 | { 33 | out[ij] = add[ij] ^ oprfOutput[i].get(j); 34 | } 35 | } 36 | } 37 | else if (m > sizeof(block)) 38 | { 39 | // long string case 40 | 41 | std::vector buffer(oc::divCeil(m, sizeof(block))); 42 | auto buffPtr = (u8*)buffer.data(); 43 | for (u64 i = 0, ij = 0; i < n; ++i) 44 | { 45 | oc::AES enc(oprfOutput[i]); 46 | enc.ecbEncCounterMode(0, buffer); 47 | for (u64 j = 0; j < m; ++j, ++ij) 48 | out[ij] = add[ij] ^ buffPtr[j]; 49 | } 50 | } 51 | } 52 | 53 | 54 | Proto RsOpprfSender::send(u64 recverSize, span X, MatrixView val, PRNG& prng, u64 numThreads, Socket& chl) 55 | { 56 | auto n = u64{}; 57 | auto m = u64{}; 58 | auto nm = u64{}; 59 | auto hashingSeed = block{}; 60 | auto type = PaxosParam::Binary; 61 | auto diffPtr = std::unique_ptr{}; 62 | auto diffU8 = span{}; 63 | 64 | setTimePoint("RsOpprfSender::send begin"); 65 | n = X.size(); 66 | m = val.cols(); 67 | nm = n * m; 68 | 69 | if (val.rows() != n) 70 | throw RTE_LOC; 71 | 72 | if (!n || !m) 73 | throw RTE_LOC; 74 | 75 | hashingSeed = prng.get(); 76 | co_await(chl.send(std::move(hashingSeed))); 77 | 78 | type = m % sizeof(block) ? PaxosParam::Binary : PaxosParam::GF128; 79 | mPaxos.init(n, 1 << 14, 3, 40, type, hashingSeed); 80 | 81 | if (mTimer) 82 | mOprfSender.setTimer(*mTimer); 83 | 84 | co_await(mOprfSender.send(recverSize, prng, chl, numThreads)); 85 | 86 | diffPtr.reset(new u8[nm]); 87 | diffU8 = span(diffPtr.get(), nm); 88 | 89 | if (diffU8.size() < val.size()) 90 | throw RTE_LOC; 91 | memset(diffU8.data(), 0, val.size()); 92 | oprfEval(X, diffU8, val, m, numThreads); 93 | 94 | mPaxosByteWidth = m; 95 | mP.resize(mPaxos.size() * m); 96 | 97 | setTimePoint("RsOpprfSender::send eval"); 98 | 99 | if (m == 16) 100 | { 101 | // special case for block. 102 | auto diff = span((block*)diffU8.data(), n); 103 | auto P = span((block*)mP.data(), mPaxos.size()); 104 | 105 | // double check the bounds. 106 | if ((u8*)(diff.data() + diff.size()) > diffU8.data() + diffU8.size()) 107 | throw RTE_LOC; 108 | if ((u8*)(mP.data() + mP.size()) > mP.data() + mP.size()) 109 | throw RTE_LOC; 110 | 111 | mPaxos.solve(X, diff, P, &prng, numThreads); 112 | } 113 | else 114 | { 115 | //throw RTE_LOC; 116 | auto diff = MatrixView(diffPtr.get(), n, m); 117 | auto P = MatrixView((u8*)mP.data(), mPaxos.size(), m); 118 | 119 | // double check the bounds. 120 | if (diff.data() + diff.size() > diffU8.data() + diffU8.size()) 121 | throw RTE_LOC; 122 | if (mP.data() + mP.size() > mP.data() + mP.size()) 123 | throw RTE_LOC; 124 | 125 | mPaxos.solve(X, diff, P, &prng, numThreads); 126 | } 127 | diffPtr.reset(); 128 | 129 | setTimePoint("RsOpprfSender::send paxos solve"); 130 | 131 | co_await(chl.send(coproto::copy(mP))); 132 | 133 | setTimePoint("RsOpprfSender::send end"); 134 | 135 | } 136 | 137 | void RsOpprfSender::eval(span val, MatrixView output, u64 numThreads) 138 | { 139 | auto m = output.cols(); 140 | 141 | if (mPaxosByteWidth != m) 142 | throw RTE_LOC; 143 | 144 | MatrixView P(mP.data(), mPaxos.size(), output.cols()); 145 | 146 | setTimePoint("RsOpprfSender::eval begin"); 147 | if (m == sizeof(block)) 148 | { 149 | // spacial case for block 150 | auto oo = span((block*)output.data(), output.rows()); 151 | auto pp = span((block*)P.data(), P.rows()); 152 | mPaxos.decode(val, oo, pp); 153 | } 154 | else 155 | { 156 | mPaxos.decode(val, output, P); 157 | } 158 | 159 | setTimePoint("RsOpprfSender::eval paxos decode"); 160 | 161 | // output += oprf(val) 162 | auto outU8 = span(output.data(), output.size()); 163 | oprfEval(val, outU8, outU8, m, numThreads); 164 | 165 | setTimePoint("RsOpprfSender::eval end"); 166 | 167 | } 168 | 169 | 170 | Proto RsOpprfReceiver::receive( 171 | u64 senderSize, 172 | span values, 173 | MatrixView outputs, 174 | PRNG& prng, 175 | u64 numThreads, 176 | Socket& chl) 177 | { 178 | auto n = u64{0}, m = u64{0}; 179 | auto paxos = Baxos{}; 180 | auto type = PaxosParam::Binary; 181 | auto temp = BasicVector{}; 182 | auto oprfOutput = span{}; 183 | auto p = Matrix{ }; 184 | 185 | setTimePoint("RsOpprfReceiver::receive begin"); 186 | 187 | if (values.size() != outputs.rows()) 188 | throw RTE_LOC; 189 | n = outputs.rows(); 190 | m = outputs.cols(); 191 | 192 | 193 | co_await chl.recv(paxos.mSeed); 194 | type = m % sizeof(block) ? PaxosParam::Binary : PaxosParam::GF128; 195 | paxos.init(senderSize, 1 << 14, 3, 40, type, paxos.mSeed); 196 | 197 | if (mTimer) 198 | mOprfReceiver.setTimer(*mTimer); 199 | 200 | if (outputs.cols() >= sizeof(block)) 201 | { 202 | // reuse memory. extra logic to make sure oprfOutput is properly aligned. 203 | auto ptr = outputs.data() + outputs.size(); 204 | auto offset = (u64)ptr % sizeof(block); 205 | if (offset) 206 | ptr -= offset; 207 | assert((((u64)ptr) % sizeof(block)) == 0); 208 | 209 | oprfOutput = span((block*)(ptr)-n, n); 210 | 211 | assert( 212 | (void*)(oprfOutput.data() + oprfOutput.size()) <= 213 | (void*)(outputs.data() + outputs.size())); 214 | } 215 | else 216 | { 217 | temp.resize(n); 218 | oprfOutput = temp; 219 | } 220 | 221 | co_await mOprfReceiver.receive(values, oprfOutput, prng, chl, numThreads); 222 | 223 | 224 | p.resize(paxos.size(), m, oc::AllocType::Uninitialized); 225 | co_await chl.recv(p); 226 | setTimePoint("RsOpprfReceiver::receive recv"); 227 | 228 | if (m == sizeof(block)) 229 | { 230 | auto v = span((block*)values.data(), n); 231 | auto o = span((block*)outputs.data(), n); 232 | auto pp = span((block*)p.data(), paxos.size()); 233 | 234 | paxos.mAddToDecode = true; 235 | paxos.decode(v, o, pp, numThreads); 236 | } 237 | else 238 | { 239 | if (m > sizeof(block)) 240 | { 241 | 242 | std::vector buffer(oc::divCeil(m, sizeof(block))); 243 | auto buffPtr = (u8*)buffer.data(); 244 | 245 | for (u64 i = 0; i < n; ++i) 246 | { 247 | oc::AES enc(oprfOutput[i]); 248 | enc.ecbEncCounterMode(0, buffer); 249 | memcpy(&outputs(i * m), buffPtr, m); 250 | } 251 | } 252 | else 253 | { 254 | for (u64 i = 0; i < n; ++i) 255 | memcpy(&outputs(i * m), &oprfOutput[i], m); 256 | } 257 | 258 | temp = {}; 259 | paxos.mAddToDecode = true; 260 | paxos.decode(values, outputs, p, numThreads); 261 | } 262 | temp = {}; 263 | 264 | setTimePoint("RsOpprfReceiver::receive end"); 265 | 266 | co_return; 267 | } 268 | } -------------------------------------------------------------------------------- /tests/FileBase_Tests.cpp: -------------------------------------------------------------------------------- 1 | #include "FileBase_Tests.h" 2 | 3 | #include "volePSI/fileBased.h" 4 | #include "cryptoTools/Crypto/RandomOracle.h" 5 | using namespace oc; 6 | using namespace volePSI; 7 | 8 | template 9 | std::vector setItersect(std::vector& v, std::vector& sub) 10 | { 11 | std::unordered_set ss(sub.begin(), sub.end()); 12 | 13 | std::vector r; 14 | for (u64 i = 0; i < v.size(); ++i) 15 | { 16 | if (ss.find(v[i]) != ss.end()) 17 | r.push_back(i); 18 | } 19 | 20 | return r; 21 | } 22 | 23 | std::vector writeFile(std::string path, u64 step, u64 size, FileType ft) 24 | { 25 | std::ofstream o; 26 | std::vector r; r.reserve(size); 27 | if (ft == FileType::Bin) 28 | { 29 | o.open(path, std::ios::trunc | std::ios::binary); 30 | 31 | if (o.is_open() == false) 32 | throw RTE_LOC; 33 | 34 | for (u64 i = 0; i < size; ++i) 35 | { 36 | auto v = i * step; 37 | block b(v, v); 38 | r.push_back(b); 39 | o.write((char*)&b, 16); 40 | } 41 | } 42 | else if(ft == FileType::Csv) 43 | { 44 | o.open(path, std::ios::trunc); 45 | 46 | if (o.is_open() == false) 47 | throw RTE_LOC; 48 | 49 | for (u64 i = 0; i < size; ++i) 50 | { 51 | auto v = i * step; 52 | block b(v, v); 53 | r.push_back(b); 54 | o << b << "\n"; 55 | } 56 | } 57 | else 58 | { 59 | o.open(path, std::ios::trunc); 60 | 61 | if (o.is_open() == false) 62 | throw RTE_LOC; 63 | 64 | for (u64 i = 0; i < size; ++i) 65 | { 66 | auto v = "prefix_" + std::to_string(i * step) + "\n"; 67 | 68 | oc::RandomOracle ro(16); 69 | ro.Update(v.data(), v.size()); 70 | block b; 71 | ro.Final(b); 72 | r.push_back(b); 73 | 74 | o << v; 75 | } 76 | } 77 | 78 | return r; 79 | } 80 | 81 | bool checkFile(std::string path,std::vector& exp, FileType ft) 82 | { 83 | 84 | if (ft == FileType::Bin) 85 | { 86 | std::ifstream o; 87 | o.open(path, std::ios::in | std::ios::binary); 88 | if (o.is_open() == false) 89 | throw std::runtime_error("failed to open file: " + path); 90 | 91 | auto size = static_cast(filesize(o)); 92 | if (size % sizeof(u64)) 93 | throw RTE_LOC; 94 | 95 | auto s = size / sizeof(u64); 96 | if (s != exp.size()) 97 | return false; 98 | 99 | std::vector vals(s); 100 | 101 | o.read((char*)vals.data(), size); 102 | 103 | std::unordered_set ss(vals.begin(), vals.end()); 104 | 105 | if (ss.size() != s) 106 | throw RTE_LOC; 107 | 108 | for (u64 i = 0; i < exp.size(); ++i) 109 | { 110 | if (ss.find(exp[i]) == ss.end()) 111 | return false; 112 | } 113 | } 114 | else 115 | { 116 | std::ifstream file(path, std::ios::in); 117 | if (file.is_open() == false) 118 | throw std::runtime_error("failed to open file: " + path); 119 | 120 | std::unordered_set ss; 121 | 122 | while (file.eof() == false) 123 | { 124 | u64 i = -1; 125 | file >> i; 126 | 127 | if (ss.find(i) != ss.end()) 128 | throw RTE_LOC; 129 | ss.insert(i); 130 | } 131 | 132 | for (u64 i = 0; i < exp.size(); ++i) 133 | { 134 | if (ss.find(exp[i]) == ss.end()) 135 | return false; 136 | } 137 | } 138 | 139 | return true; 140 | } 141 | 142 | void filebase_readSet_Test() 143 | { 144 | u64 ns = 34234; 145 | auto ft = FileType::Bin; 146 | std::string sFile = "./sFile_deleteMe"; 147 | auto s = writeFile(sFile, 1, ns, ft); 148 | 149 | auto s2 = readSet(sFile, ft, true); 150 | 151 | if (s != s2) 152 | throw RTE_LOC; 153 | } 154 | 155 | void filebase_psi_bin_Test() 156 | { 157 | #if defined(COPROTO_ENABLE_BOOST) 158 | 159 | u64 ns = 3124; 160 | u64 nr = 12352; 161 | auto ft = FileType::Bin; 162 | 163 | std::string sFile = "./sFile_deleteMe"; 164 | std::string rFile = "./rFile_deleteMe"; 165 | std::string oFile = "./oFile_deleteMe"; 166 | 167 | auto s = writeFile(sFile, 1, ns, ft); 168 | auto r = writeFile(rFile, 2, nr, ft); 169 | auto i = setItersect(r, s); 170 | 171 | CLP sCmd, rCmd; 172 | sCmd.setDefault("server", "0"); 173 | rCmd.setDefault("server", "1"); 174 | 175 | sCmd.setDefault("r", "0"); 176 | rCmd.setDefault("r", "1"); 177 | 178 | sCmd.set("indexSet"); 179 | rCmd.set("indexSet"); 180 | sCmd.set("quiet"); 181 | rCmd.set("quiet"); 182 | 183 | sCmd.set("bin"); 184 | rCmd.set("bin"); 185 | 186 | sCmd.set("debug"); 187 | rCmd.set("debug"); 188 | 189 | sCmd.setDefault("senderSize", ns); 190 | rCmd.setDefault("senderSize", ns); 191 | 192 | sCmd.setDefault("receiverSize", nr); 193 | rCmd.setDefault("receiverSize", nr); 194 | 195 | rCmd.setDefault("in", rFile); 196 | sCmd.setDefault("in", sFile); 197 | 198 | rCmd.setDefault("out", oFile); 199 | 200 | auto f0 = std::async([&]() { doFilePSI(sCmd); }); 201 | auto f1 = std::async([&]() { doFilePSI(rCmd); }); 202 | 203 | f0.get(); 204 | f1.get(); 205 | 206 | bool passed = checkFile(oFile, i, ft); 207 | 208 | std::remove(sFile.c_str()); 209 | std::remove(rFile.c_str()); 210 | std::remove(oFile.c_str()); 211 | 212 | if (!passed) 213 | throw RTE_LOC; 214 | 215 | #endif 216 | } 217 | 218 | void filebase_psi_csv_Test() 219 | { 220 | #if defined(COPROTO_ENABLE_BOOST) 221 | 222 | u64 ns = 34234; 223 | u64 nr = 24356; 224 | auto ft = FileType::Csv; 225 | 226 | std::string sFile = "./sFile_deleteMe"; 227 | std::string rFile = "./rFile_deleteMe"; 228 | std::string oFile = "./oFile_deleteMe"; 229 | 230 | auto s = writeFile(sFile, 1, ns, ft); 231 | auto r = writeFile(rFile, 2, nr, ft); 232 | auto i = setItersect(r, s); 233 | 234 | CLP sCmd, rCmd; 235 | sCmd.setDefault("server", "0"); 236 | rCmd.setDefault("server", "1"); 237 | 238 | sCmd.setDefault("r", "0"); 239 | rCmd.setDefault("r", "1"); 240 | 241 | sCmd.set("indexSet"); 242 | rCmd.set("indexSet"); 243 | sCmd.set("quiet"); 244 | rCmd.set("quiet"); 245 | 246 | sCmd.set("csv"); 247 | rCmd.set("csv"); 248 | 249 | sCmd.setDefault("senderSize", ns); 250 | rCmd.setDefault("senderSize", ns); 251 | 252 | sCmd.setDefault("receiverSize", nr); 253 | rCmd.setDefault("receiverSize", nr); 254 | 255 | rCmd.setDefault("in", rFile); 256 | sCmd.setDefault("in", sFile); 257 | 258 | rCmd.setDefault("out", oFile); 259 | 260 | auto f0 = std::async([&]() { doFilePSI(sCmd); }); 261 | auto f1 = std::async([&]() { doFilePSI(rCmd); }); 262 | 263 | f0.get(); 264 | f1.get(); 265 | 266 | bool passed = checkFile(oFile, i, ft); 267 | 268 | std::remove(sFile.c_str()); 269 | std::remove(rFile.c_str()); 270 | std::remove(oFile.c_str()); 271 | 272 | if (!passed) 273 | throw RTE_LOC; 274 | #endif 275 | } 276 | 277 | 278 | void filebase_psi_csvh_Test() 279 | { 280 | #if defined(COPROTO_ENABLE_BOOST) 281 | 282 | u64 ns = 34234; 283 | u64 nr = 24356; 284 | auto ft = FileType::Unspecified; 285 | 286 | std::string sFile = "./sFile_deleteMe"; 287 | std::string rFile = "./rFile_deleteMe"; 288 | std::string oFile = "./oFile_deleteMe"; 289 | 290 | auto s = writeFile(sFile, 1, ns, ft); 291 | auto r = writeFile(rFile, 2, nr, ft); 292 | auto i = setItersect(r, s); 293 | 294 | CLP sCmd, rCmd; 295 | sCmd.setDefault("server", "0"); 296 | rCmd.setDefault("server", "1"); 297 | 298 | sCmd.setDefault("r", "0"); 299 | rCmd.setDefault("r", "1"); 300 | 301 | sCmd.set("csv"); 302 | rCmd.set("csv"); 303 | 304 | sCmd.set("indexSet"); 305 | rCmd.set("indexSet"); 306 | sCmd.set("quiet"); 307 | rCmd.set("quiet"); 308 | 309 | sCmd.setDefault("senderSize", ns); 310 | rCmd.setDefault("senderSize", ns); 311 | 312 | sCmd.setDefault("receiverSize", nr); 313 | rCmd.setDefault("receiverSize", nr); 314 | 315 | rCmd.setDefault("in", rFile); 316 | sCmd.setDefault("in", sFile); 317 | 318 | rCmd.setDefault("out", oFile); 319 | 320 | auto f0 = std::async([&]() { doFilePSI(sCmd); }); 321 | auto f1 = std::async([&]() { doFilePSI(rCmd); }); 322 | 323 | f0.get(); 324 | f1.get(); 325 | 326 | bool passed = checkFile(oFile, i, FileType::Csv); 327 | 328 | std::remove(sFile.c_str()); 329 | std::remove(rFile.c_str()); 330 | std::remove(oFile.c_str()); 331 | 332 | if (!passed) 333 | throw RTE_LOC; 334 | 335 | #endif 336 | } 337 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BZS-MPSI 2 | 3 | BZS-MPSI implements the protocols described in our paper [**Efficient Scalable Multi-Party Private Set Intersection(-Variants) from Bicentric Zero-Sharing (ACM CCS 2024)**](https://dl.acm.org/doi/10.1145/3658644.3690245), which also gets the `Artifacts Evaluated` badge. 4 | 5 | When using BZS-MPSI to achieve the MPSI functionality, the part of two-party PSI being invoked is based on [Vole-PSI](https://github.com/Visa-Research/volepsi) from [VOLE-PSI: Fast OPRF and Circuit-PSI from Vector-OLE](https://eprint.iacr.org/2021/266) and [Blazing Fast PSI from Improved OKVS and Subfield VOLE](https://eprint.iacr.org/2022/320.pdf). And thanks to the recent updates and optimizations of Vole-PSI by its contributors, the communication cost of Leader and Pivot in BZS-MPSI will be reduced compared to that presented in Table 5 of our paper. 6 | 7 | ## Building the project 8 | 9 | The project can be built in a Linux system with networking support using the following instructions. The recommended versions are ``Ubuntu:22.04 LTS, g++ 11.4.0, and CMake 3.22.1`` or higher. Otherwise, we highly suggest using the dockerfile-based approach introduced later for better reproducibility. 10 | 11 | ```shell 12 | sudo apt-get update -y 13 | sudo apt-get install -y build-essential gcc g++ libtool libssl-dev git iproute2 python3 cmake=3.22.* 14 | 15 | git clone https://github.com/orzcy/BZS-MPSI.git 16 | cd BZS-MPSI 17 | python3 build.py -DVOLE_PSI_ENABLE_BOOST=ON 18 | ``` 19 | 20 | After the building process, the executable `frontend` will be located at `out/build/linux/frontend`. 21 | 22 | **We also provide some docker-based approaches to build the project.** 23 | 24 | The dockerfile-based building approach: 25 | ```shell 26 | git clone https://github.com/orzcy/BZS-MPSI.git 27 | cd BZS-MPSI 28 | docker build --no-cache -t [Your Image Name] . 29 | docker run -itd --net=host --name [Your Container Name] --cap-add=NET_ADMIN [Your Image Name(or ID)] /bin/bash 30 | docker exec -it [Your Container Name(or ID)] /bin/bash 31 | ``` 32 | 33 | The docker-image-based building approach: 34 | ```shell 35 | docker pull orzcy/bzs-di:latest 36 | docker run -itd --net=host --name [Your Container Name] --cap-add=NET_ADMIN orzcy/bzs-di:latest /bin/bash 37 | docker exec -it [Your Container Name(or ID)] /bin/bash 38 | ``` 39 | After the (docker-based) building process, the executable `frontend` will be located at `app/BZS-MPSI/out/build/linux/frontend` in the docker container. 40 | 41 | ## Running the code 42 | 43 | Use the following instruction in `frontend` to run a participant: 44 | 45 | ```shell 46 | ./frontend -mpsi [Parameters] 47 | ``` 48 | 49 | Required parameters: 50 | * `-in [value]`, value: the path to the party's set. The path should have a \".csv\" extension with one element with 32 char hex per row. 51 | * `-out [value]`, value: the output file path (default "in || .out"). 52 | * `-nu [value]`, value: the number of participants. 53 | * `-id [value]`, value: participant ID (the IDs of Clients range from 0 to nu-3, the ID of Pivot is nu-2, and the ID of Leader is nu-1). 54 | * `-ipp [value]`, value: IP address and base port of Pivot. 55 | * `-ipl [value]`, value: IP address and base port of Leader. 56 | 57 | Optional parameters: 58 | * `-nt [value]`, value: the number of threads allocated to the participant (default 1). 59 | * `-la [value]`, value: the statistical security parameter (default 40). 60 | * `-ca`, if this option appears, run MPSI-CA instead of MPSI (default false). 61 | * `-bc`, if this option appears, Leader broadcasts the result at the end (default false). 62 | 63 | There are some examples to illustrate how to run the code: 64 | 65 | ````shell 66 | # Enter out/build/linux/frontend 67 | 68 | cd out/build/linux/frontend 69 | 70 | # Run MPSI with 4 participants (in 4 different terminals) 71 | # The input files are P1~P4.csv 72 | # Pivot's IP address is 192.168.0.10, and the base port is 10000 73 | # Leader's IP address is 192.168.0.11, and the base port is 12000 74 | # Leader computes the intersection and writes it to O4.csv 75 | 76 | ./frontend -mpsi -nu 4 -id 0 -in P1.csv -ipp 192.168.0.10:10000 -ipl 192.168.0.11:12000 77 | ./frontend -mpsi -nu 4 -id 1 -in P2.csv -ipp 192.168.0.10:10000 -ipl 192.168.0.11:12000 78 | ./frontend -mpsi -nu 4 -id 2 -in P3.csv -ipp 192.168.0.10:10000 -ipl 192.168.0.11:12000 79 | ./frontend -mpsi -nu 4 -id 3 -in P4.csv -out O4.csv -ipp 192.168.0.10:10000 -ipl 192.168.0.11:12000 80 | 81 | # Run MPSI-CA with 4 participants (in 4 different terminals) 82 | # Allocate 4 threads for Pivot (ID = 3) and Leader (ID = 4) each 83 | # The input files are P1~P4.csv 84 | # Pivot's IP address is 192.168.0.10, and the base port is 10000 85 | # Leader's IP address is 192.168.0.11, and the base port is 12000 86 | # Leader computes the size of the intersection and broadcasts it to all participants 87 | # The output files are O1~O4.csv 88 | 89 | ./frontend -mpsi -nu 4 -id 0 -in P1.csv -out O1.csv -ipp 192.168.0.10:10000 -ipl 192.168.0.11:12000 -ca -bc 90 | ./frontend -mpsi -nu 4 -id 1 -in P2.csv -out O2.csv -ipp 192.168.0.10:10000 -ipl 192.168.0.11:12000 -ca -bc 91 | ./frontend -mpsi -nu 4 -id 2 -in P3.csv -out O3.csv -ipp 192.168.0.10:10000 -ipl 192.168.0.11:12000 -ca -bc -nt 4 92 | ./frontend -mpsi -nu 4 -id 3 -in P4.csv -out O4.csv -ipp 192.168.0.10:10000 -ipl 192.168.0.11:12000 -ca -bc -nt 4 93 | ```` 94 | 95 | **We also provide a benchmark based on a single machine, simulated networks, and random inputs.** 96 | 97 | Use the following instruction in `frontend` to run the unit tests: 98 | ```shell 99 | ./frontend -u -mpsi 100 | ``` 101 | 102 | And use the following instruction in `frontend` to run a participant in benchmark: 103 | ```shell 104 | ./frontend -perf -mpsi [Parameters] 105 | ``` 106 | 107 | Required parameters: 108 | * `-nu [value]`, value: the number of participants. 109 | * `-id [value]`, value: participant ID (the IDs of Clients range from 0 to nu-3, the ID of Pivot is nu-2, and the ID of Leader is nu-1). 110 | * `-nn [value]`, value: the log2 size of the set (default 10). In the benchmark, please enter the same `nn` for all participants. 111 | 112 | Optional parameters: 113 | * `-ts [value]`, value: the preset intersection size to verify the correctness (default 0.1*set size). 114 | * `-nt [value]`, value: the number of threads allocated to the participant (default 1). 115 | * `-la [value]`, value: the statistical security parameter (default 40). 116 | * `-ca`, if this option appears, run MPSI-CA instead of MPSI (default false). 117 | * `-bc`, if this option appears, Leader broadcasts the result at the end (default false). 118 | 119 | There are some examples to illustrate how to run the benchmark: 120 | 121 | ````shell 122 | # Enter out/build/linux/frontend 123 | 124 | cd out/build/linux/frontend 125 | 126 | # Run the unit tests 127 | 128 | ./frontend -u -mpsi 129 | 130 | # Run MPSI benchmark with 5 participants, 2^20 set size, and preset the intersection size as 1000 131 | 132 | ./frontend -perf -mpsi -nu 5 -id 0 -nn 20 -ts 1000 & 133 | ./frontend -perf -mpsi -nu 5 -id 1 -nn 20 -ts 1000 & 134 | ./frontend -perf -mpsi -nu 5 -id 2 -nn 20 -ts 1000 & 135 | ./frontend -perf -mpsi -nu 5 -id 3 -nn 20 -ts 1000 & 136 | ./frontend -perf -mpsi -nu 5 -id 4 -nn 20 -ts 1000 137 | 138 | # Run MPSI-CA benchmark with 5 participants, 2^16 set size 139 | # Allocate 4 threads for Pivot (ID = 3) and Leader (ID = 4) each, and preset the intersection size as 100 140 | 141 | ./frontend -perf -mpsi -nu 5 -id 0 -nn 16 -ts 100 -ca & 142 | ./frontend -perf -mpsi -nu 5 -id 1 -nn 16 -ts 100 -ca & 143 | ./frontend -perf -mpsi -nu 5 -id 2 -nn 16 -ts 100 -ca & 144 | ./frontend -perf -mpsi -nu 5 -id 3 -nn 16 -ts 100 -ca -nt 4 & 145 | ./frontend -perf -mpsi -nu 5 -id 4 -nn 16 -ts 100 -ca -nt 4 146 | ```` 147 | 148 | The program will output the running time and communication cost of Client (ID = nu-3), Pivot (ID = nu-2), and Leader (ID = nu-1), along with the resulting intersection size obtained by Leader on the terminal. 149 | 150 | In addition, we use `tc` command to set our LAN and WAN settings. 151 | 152 | ````shell 153 | # LAN setting: 20Gbps bandwidth, 0.01ms latency (i.e. 0.02ms round-trip latency) 154 | 155 | sudo tc qdisc add dev lo root netem rate 20Gbit delay 0.01ms 156 | 157 | # WAN setting: 200Mbps bandwidth, 48ms latency (i.e. 96ms round-trip latency) 158 | 159 | sudo tc qdisc add dev lo root netem rate 200Mbit delay 48ms 160 | 161 | # Delete all the limits on "lo" 162 | 163 | sudo tc qdisc del dev lo root 164 | ```` 165 | -------------------------------------------------------------------------------- /volePSI/RsCpsi.cpp: -------------------------------------------------------------------------------- 1 | #include "RsCpsi.h" 2 | 3 | #include 4 | 5 | namespace volePSI 6 | { 7 | 8 | Proto RsCpsiSender::send(span Y, oc::MatrixView values, Sharing& ret, Socket& chl) 9 | { 10 | auto cuckooSeed = block{}; 11 | auto params = oc::CuckooParam{}; 12 | auto numBins = u64{}; 13 | auto sIdx = SimpleIndex{}; 14 | auto keyBitLength = u64{}; 15 | auto keyByteLength = u64{}; 16 | auto hashers = std::array {}; 17 | auto Ty = std::vector{}; 18 | auto Tv = Matrix{}; 19 | auto r = Matrix{}; 20 | auto TyIter = std::vector::iterator{}; 21 | auto TvIter = Matrix::iterator{}; 22 | auto rIter = Matrix::iterator{}; 23 | auto opprf = std::make_unique(); 24 | auto cmp = std::make_unique(); 25 | auto cir = BetaCircuit{}; 26 | 27 | setTimePoint("RsCpsiSender::send begin"); 28 | if (mSenderSize != Y.size() || mValueByteLength != values.cols()) 29 | { 30 | co_await chl.close(); 31 | throw RTE_LOC; 32 | } 33 | 34 | co_await (chl.recv(cuckooSeed)); 35 | setTimePoint("RsCpsiSender::send recv"); 36 | 37 | params = oc::CuckooIndex<>::selectParams(mRecverSize, mSsp, 0, 3); 38 | numBins = params.numBins(); 39 | sIdx.init(numBins, mSenderSize, mSsp, 3); 40 | sIdx.insertItems(Y, cuckooSeed); 41 | 42 | setTimePoint("RsCpsiSender::send simpleHash"); 43 | 44 | 45 | keyBitLength = mSsp + oc::log2ceil(params.numBins()); 46 | keyByteLength = oc::divCeil(keyBitLength, 8); 47 | 48 | hashers[0].setKey(block(3242, 23423) ^ cuckooSeed); 49 | hashers[1].setKey(block(4534, 45654) ^ cuckooSeed); 50 | hashers[2].setKey(block(5677, 67867) ^ cuckooSeed); 51 | 52 | // The OPPRF input value of the i'th input under the j'th cuckoo 53 | // hash function. 54 | Ty.resize(Y.size() * 3); 55 | 56 | // The value associated with the k'th OPPRF input 57 | Tv.resize(Y.size() * 3, keyByteLength + values.cols(), oc::AllocType::Uninitialized); 58 | 59 | // The special value assigned to the i'th bin. 60 | r.resize(numBins, keyByteLength, oc::AllocType::Uninitialized); 61 | 62 | TyIter = Ty.begin(); 63 | TvIter = Tv.begin(); 64 | rIter = r.begin(); 65 | ret.mValues.resize(numBins, values.cols(), oc::AllocType::Uninitialized); 66 | mPrng.get(r); 67 | mPrng.get(ret.mValues); 68 | 69 | 70 | 71 | for (u64 i = 0; i < numBins; ++i) 72 | { 73 | auto bin = sIdx.mBins[i]; 74 | auto size = sIdx.mBinSizes[i]; 75 | 76 | for (u64 p = 0; p < size; ++p) 77 | { 78 | auto j = bin[p].hashIdx(); 79 | auto& hj = hashers[j]; 80 | auto b = bin[p].idx(); 81 | *TyIter = hj.hashBlock(Y[b]); 82 | memcpy(&*TvIter, &*rIter, keyByteLength); 83 | TvIter += keyByteLength; 84 | 85 | if (values.size()) 86 | { 87 | memcpy(&*TvIter, &values(b, 0), values.cols()); 88 | 89 | if (mType == ValueShareType::Xor) 90 | { 91 | for (u64 k = 0; k < values.cols(); ++k) 92 | { 93 | TvIter[k] ^= ret.mValues(i, k); 94 | } 95 | } 96 | else if (mType == ValueShareType::add32) 97 | { 98 | assert(values.cols() % sizeof(u32) == 0); 99 | auto ss = values.cols() / sizeof(u32); 100 | auto tv = (u32*)&*TvIter; 101 | auto rr = (u32*)&ret.mValues(i, 0); 102 | for (u64 k = 0; k < ss; ++k) 103 | tv[k] -= rr[k]; 104 | } 105 | else 106 | { 107 | co_await chl.close(); 108 | throw RTE_LOC; 109 | } 110 | TvIter += values.cols(); 111 | } 112 | 113 | ++TyIter; 114 | } 115 | rIter += keyByteLength; 116 | } 117 | 118 | while (TyIter != Ty.end()) 119 | { 120 | *TyIter = mPrng.get(); 121 | ++TyIter; 122 | } 123 | 124 | setTimePoint("RsCpsiSender::send setValues"); 125 | 126 | if (mTimer) 127 | opprf->setTimer(*mTimer); 128 | 129 | co_await (opprf->send(numBins, Ty, Tv, mPrng, mNumThreads, chl)); 130 | 131 | if (mTimer) 132 | cmp->setTimer(*mTimer); 133 | 134 | cir = isZeroCircuit(keyBitLength); 135 | cmp->init(r.rows(), cir, mNumThreads, 1, mPrng.get()); 136 | 137 | cmp->setInput(0, r); 138 | co_await (cmp->run(chl)); 139 | 140 | { 141 | 142 | auto ss = cmp->getOutputView(0); 143 | ret.mFlagBits.resize(numBins); 144 | std::copy(ss.begin(), ss.begin() + ret.mFlagBits.sizeBytes(), ret.mFlagBits.data()); 145 | } 146 | } 147 | 148 | Proto RsCpsiReceiver::receive(span X, Sharing& ret, Socket& chl) 149 | { 150 | auto cuckooSeed = block{}; 151 | auto cuckoo = oc::CuckooIndex<>{}; 152 | auto Tx = std::vector{}; 153 | auto hashers = std::array {}; 154 | auto numBins = u64{}; 155 | auto keyBitLength = u64{}; 156 | auto keyByteLength = u64{}; 157 | auto r = Matrix{}; 158 | auto opprf = std::make_unique(); 159 | auto cmp = std::make_unique(); 160 | auto cir = BetaCircuit{}; 161 | 162 | if (mRecverSize != X.size()) 163 | throw RTE_LOC; 164 | 165 | setTimePoint("RsCpsiReceiver::receive begin"); 166 | 167 | cuckooSeed = mPrng.get(); 168 | co_await (chl.send(std::move(cuckooSeed))); 169 | cuckoo.init(mRecverSize, mSsp, 0, 3); 170 | 171 | cuckoo.insert(X, cuckooSeed); 172 | Tx.resize(cuckoo.mNumBins); 173 | 174 | setTimePoint("RsCpsiReceiver::receive cuckoo"); 175 | 176 | hashers[0].setKey(block(3242, 23423) ^ cuckooSeed); 177 | hashers[1].setKey(block(4534, 45654) ^ cuckooSeed); 178 | hashers[2].setKey(block(5677, 67867) ^ cuckooSeed); 179 | 180 | ret.mMapping.resize(X.size(), ~u64(0)); 181 | numBins = cuckoo.mBins.size(); 182 | for (u64 i = 0; i < numBins; ++i) 183 | { 184 | auto& bin = cuckoo.mBins[i]; 185 | if (bin.isEmpty() == false) 186 | { 187 | auto j = bin.hashIdx(); 188 | auto b = bin.idx(); 189 | 190 | //j = oc::CuckooIndex<>::minCollidingHashIdx(i, cuckoo.mHashes[b], 3, numBins); 191 | 192 | auto& hj = hashers[j]; 193 | Tx[i] = hj.hashBlock(X[b]); 194 | ret.mMapping[b] = i; 195 | } 196 | else 197 | { 198 | Tx[i] = block(i, 0); 199 | } 200 | } 201 | setTimePoint("RsCpsiReceiver::receive values"); 202 | 203 | keyBitLength = mSsp + oc::log2ceil(Tx.size()); 204 | keyByteLength = oc::divCeil(keyBitLength, 8); 205 | 206 | r.resize(Tx.size(), keyByteLength + mValueByteLength, oc::AllocType::Uninitialized); 207 | 208 | if (mTimer) 209 | opprf->setTimer(*mTimer); 210 | 211 | co_await (opprf->receive(mSenderSize * 3, Tx, r, mPrng, mNumThreads, chl)); 212 | 213 | if (mTimer) 214 | cmp->setTimer(*mTimer); 215 | 216 | cir = isZeroCircuit(keyBitLength); 217 | cmp->init(r.rows(), cir, mNumThreads, 0, mPrng.get()); 218 | 219 | cmp->implSetInput(0, r, r.cols()); 220 | 221 | co_await (cmp->run(chl)); 222 | 223 | { 224 | auto ss = cmp->getOutputView(0); 225 | 226 | ret.mFlagBits.resize(numBins); 227 | std::copy(ss.begin(), ss.begin() + ret.mFlagBits.sizeBytes(), ret.mFlagBits.data()); 228 | 229 | if (mValueByteLength) 230 | { 231 | ret.mValues.resize(numBins, mValueByteLength); 232 | 233 | for (u64 i = 0; i < numBins; ++i) 234 | { 235 | std::memcpy(&ret.mValues(i, 0), &r(i, keyByteLength), mValueByteLength); 236 | } 237 | } 238 | } 239 | 240 | setTimePoint("RsCpsiReceiver::receive done"); 241 | } 242 | 243 | 244 | } -------------------------------------------------------------------------------- /volePSI/RsPsi.cpp: -------------------------------------------------------------------------------- 1 | #include "RsPsi.h" 2 | #include 3 | #include 4 | //#include "thirdparty/parallel-hashmap/parallel_hashmap/phmap.h" 5 | namespace volePSI 6 | { 7 | 8 | 9 | 10 | template 11 | struct Buffer : public span 12 | { 13 | std::unique_ptr mPtr; 14 | 15 | void resize(u64 s) 16 | { 17 | mPtr.reset(new T[s]); 18 | static_cast&>(*this) = span(mPtr.get(), s); 19 | } 20 | }; 21 | 22 | void details::RsPsiBase::init( 23 | u64 senderSize, 24 | u64 recverSize, 25 | u64 statSecParam, 26 | block seed, 27 | bool malicious, 28 | u64 numThreads, 29 | bool useReducedRounds) 30 | { 31 | mSenderSize = senderSize; 32 | mRecverSize = recverSize; 33 | mSsp = statSecParam; 34 | mPrng.SetSeed(seed); 35 | mMalicious = malicious; 36 | 37 | mMaskSize = malicious ? 38 | sizeof(block) : 39 | std::min(oc::divCeil(mSsp + oc::log2ceil(mSenderSize * mRecverSize), 8), sizeof(block)); 40 | mCompress = mMaskSize != sizeof(block); 41 | 42 | mNumThreads = numThreads; 43 | mUseReducedRounds = useReducedRounds; 44 | } 45 | 46 | Proto RsPsiSender::run(span inputs, Socket& chl) 47 | { 48 | 49 | auto hashes = Buffer{}; 50 | setTimePoint("RsPsiSender::run-begin"); 51 | 52 | if (mTimer) 53 | mSender.setTimer(getTimer()); 54 | 55 | mSender.mMalicious = mMalicious; 56 | mSender.mSsp = mSsp; 57 | mSender.mDebug = mDebug; 58 | 59 | co_await mSender.send(mRecverSize, mPrng, chl, mNumThreads, mUseReducedRounds); 60 | 61 | setTimePoint("RsPsiSender::run-opprf"); 62 | 63 | hashes.resize(inputs.size() * sizeof(block)); 64 | mSender.eval(inputs, span((block*)hashes.data(), inputs.size()), mNumThreads); 65 | 66 | setTimePoint("RsPsiSender::run-eval"); 67 | if (mCompress) 68 | { 69 | auto src = (block*)hashes.data(); 70 | auto dest = (u8*)hashes.data(); 71 | u64 i = 0; 72 | 73 | for (; i < std::min(mSenderSize, 100); ++i) 74 | { 75 | memmove(dest, src, mMaskSize); 76 | dest += mMaskSize; 77 | src += 1; 78 | } 79 | for (; i < mSenderSize; ++i) 80 | { 81 | memcpy(dest, src, mMaskSize); 82 | dest += mMaskSize; 83 | src += 1; 84 | } 85 | static_cast&>(hashes) = span((u8*)hashes.data(), dest); 86 | } 87 | 88 | co_await chl.send(std::move(hashes)); 89 | setTimePoint("RsPsiSender::run-sendHash"); 90 | 91 | } 92 | 93 | namespace { 94 | struct NoHash 95 | { 96 | inline size_t operator()(const block& v) const 97 | { 98 | return v.get(0); 99 | } 100 | }; 101 | } 102 | 103 | Proto RsPsiReceiver::run(span inputs, Socket& chl) 104 | { 105 | setTimePoint("RsPsiReceiver::run-enter"); 106 | static const u64 batchSize = 128; 107 | 108 | struct MultiThread 109 | { 110 | std::promise prom; 111 | std::shared_future fu; 112 | std::vector thrds; 113 | std::functionroutine; 114 | std::atomic numDone; 115 | std::promise hashingDoneProm; 116 | std::shared_future hashingDoneFu; 117 | std::mutex mMergeMtx; 118 | 119 | u64 numThreads; 120 | u64 binSize; 121 | libdivide::libdivide_u32_t divider; 122 | }; 123 | 124 | auto data = std::unique_ptr{}; 125 | auto myHashes = span{}; 126 | auto theirHashes = oc::MatrixView{}; 127 | auto map = google::dense_hash_map{}; 128 | auto i = u64{}; 129 | auto main = u64{}; 130 | auto hh = std::array, 128> {}; 131 | auto mt = std::unique_ptr{}; 132 | auto mask = block{}; 133 | 134 | setTimePoint("RsPsiReceiver::run-begin"); 135 | mIntersection.clear(); 136 | 137 | data = std::unique_ptr(new u8[ 138 | mSenderSize * mMaskSize + 139 | mRecverSize * sizeof(block)]); 140 | 141 | myHashes = span((block*)data.get(), mRecverSize); 142 | theirHashes = oc::MatrixView((u8*)((block*)data.get() + mRecverSize), mSenderSize, mMaskSize); 143 | 144 | setTimePoint("RsPsiReceiver::run-alloc"); 145 | 146 | if (mTimer) 147 | mRecver.setTimer(getTimer()); 148 | 149 | mRecver.mMalicious = mMalicious; 150 | mRecver.mSsp = mSsp; 151 | mRecver.mDebug = mDebug; 152 | 153 | // todo, parallelize these two 154 | co_await(mRecver.receive(inputs, myHashes, mPrng, chl, mNumThreads, mUseReducedRounds)); 155 | setTimePoint("RsPsiReceiver::run-opprf"); 156 | 157 | mask = oc::ZeroBlock; 158 | for (i = 0; i < mMaskSize; ++i) 159 | mask.set(i, ~0); 160 | 161 | if (mNumThreads < 2) 162 | { 163 | 164 | map.resize(myHashes.size()); 165 | setTimePoint("RsPsiReceiver::run-reserve"); 166 | map.set_empty_key(oc::ZeroBlock); 167 | setTimePoint("RsPsiReceiver::run-set_empty_key"); 168 | 169 | main = mRecverSize / batchSize * batchSize; 170 | 171 | if (!mCompress) 172 | { 173 | 174 | for (i = 0; i < main; i += batchSize) 175 | { 176 | for (u64 j = 0; j < batchSize; ++j) 177 | hh[j] = { myHashes[i + j], i + j }; 178 | 179 | map.insert(hh.begin(), hh.end()); 180 | } 181 | for (; i < mRecverSize; ++i) 182 | map.insert({ myHashes[i], i }); 183 | } 184 | else 185 | { 186 | 187 | for (i = 0; i < main; i += batchSize) 188 | { 189 | for (u64 j = 0; j < batchSize; ++j) 190 | hh[j] = { myHashes[i + j] & mask, i + j }; 191 | 192 | map.insert(hh.begin(), hh.end()); 193 | } 194 | for (; i < mRecverSize; ++i) 195 | map.insert({ myHashes[i] & mask, i }); 196 | } 197 | 198 | setTimePoint("RsPsiReceiver::run-insert"); 199 | 200 | co_await(chl.recv(theirHashes)); 201 | 202 | setTimePoint("RsPsiReceiver::run-recv"); 203 | 204 | { 205 | block h = oc::ZeroBlock; 206 | auto iter = theirHashes.data(); 207 | for (i = 0; i < mSenderSize; ++i) 208 | { 209 | memcpy(&h, iter, mMaskSize); 210 | iter += mMaskSize; 211 | 212 | auto iter = map.find(h); 213 | if (iter != map.end()) 214 | { 215 | mIntersection.push_back(iter->second); 216 | } 217 | } 218 | } 219 | 220 | setTimePoint("RsPsiReceiver::run-find"); 221 | } 222 | else 223 | { 224 | mt.reset(new MultiThread); 225 | 226 | mt->fu = mt->prom.get_future().share(); 227 | 228 | setTimePoint("RsPsiReceiver::run-reserve"); 229 | 230 | mt->numDone = 0; 231 | mt->hashingDoneFu = mt->hashingDoneProm.get_future().share(); 232 | 233 | mt->numThreads = std::max(1, mNumThreads); 234 | mt->binSize = Baxos::getBinSize(mNumThreads, mRecverSize, mSsp); 235 | mt->divider = libdivide::libdivide_u32_gen(mt->numThreads); 236 | 237 | mt->routine = [&](u64 thrdIdx) 238 | { 239 | if (!thrdIdx) 240 | setTimePoint("RsPsiReceiver::run-threadBegin"); 241 | 242 | auto& divider = mt->divider; 243 | google::dense_hash_map map(mt->binSize); 244 | map.set_empty_key(oc::ZeroBlock); 245 | 246 | if (!thrdIdx) 247 | setTimePoint("RsPsiReceiver::run-set_empty_key_par"); 248 | 249 | u64 i = 0; 250 | std::array, batchSize> hh; 251 | for (; i < myHashes.size();) 252 | { 253 | u64 j = 0; 254 | while (j != batchSize && i < myHashes.size()) 255 | { 256 | auto v = myHashes[i].get(0); 257 | auto k = libdivide::libdivide_u32_do(v, ÷r); 258 | v -= k * mNumThreads; 259 | if (v == thrdIdx) 260 | { 261 | hh[j] = { myHashes[i] & mask, i }; 262 | ++j; 263 | } 264 | ++i; 265 | } 266 | map.insert(hh.begin(), hh.begin() + j); 267 | } 268 | 269 | if (++mt->numDone == mt->numThreads) 270 | mt->hashingDoneProm.set_value(); 271 | else 272 | mt->hashingDoneFu.get(); 273 | 274 | if (!thrdIdx) 275 | setTimePoint("RsPsiReceiver::run-insert_par"); 276 | 277 | mt->fu.get(); 278 | if (!thrdIdx) 279 | setTimePoint("RsPsiReceiver::run-recv_par"); 280 | 281 | auto begin = thrdIdx * myHashes.size() / mNumThreads; 282 | u64 intersectionSize = 0; 283 | u64* intersection = (u64*)&myHashes[begin]; 284 | 285 | { 286 | block h = oc::ZeroBlock; 287 | auto iter = theirHashes.data(); 288 | for (i = 0; i < mSenderSize; ++i) 289 | { 290 | memcpy(&h, iter, mMaskSize); 291 | iter += mMaskSize; 292 | 293 | auto v = h.get(0); 294 | auto k = libdivide::libdivide_u32_do(v, ÷r); 295 | v -= k * mNumThreads; 296 | if (v == thrdIdx) 297 | { 298 | auto iter = map.find(h); 299 | if (iter != map.end()) 300 | { 301 | intersection[intersectionSize] = iter->second; 302 | ++intersectionSize; 303 | } 304 | } 305 | } 306 | } 307 | 308 | if (!thrdIdx) 309 | setTimePoint("RsPsiReceiver::run-find_par"); 310 | if (intersectionSize) 311 | { 312 | std::lock_guard lock(mt->mMergeMtx); 313 | mIntersection.insert(mIntersection.end(), intersection, intersection + intersectionSize); 314 | } 315 | }; 316 | 317 | 318 | mt->thrds.resize(mt->numThreads); 319 | for (i = 0; i < mt->thrds.size(); ++i) 320 | mt->thrds[i] = std::thread(mt->routine, i); 321 | co_await(chl.recv(theirHashes)); 322 | mt->prom.set_value(); 323 | 324 | for (i = 0; i < mt->thrds.size(); ++i) 325 | mt->thrds[i].join(); 326 | 327 | setTimePoint("RsPsiReceiver::run-done"); 328 | 329 | } 330 | } 331 | 332 | } -------------------------------------------------------------------------------- /frontend/main.cpp: -------------------------------------------------------------------------------- 1 | #include "tests/UnitTests.h" 2 | #include "perf.h" 3 | 4 | #include "messagePassingExample.h" 5 | #include "networkSocketExample.h" 6 | #include "volePSI/fileBased.h" 7 | #include "tests/Paxos_Tests.h" 8 | 9 | int main(int argc, char** argv) 10 | { 11 | oc::CLP cmd(argc, argv); 12 | 13 | //std::ofstream file("./set.csv"); 14 | //for (oc::u64 i = 0; i < 10000000; ++i) 15 | // file << std::setfill('0') << std::setw(32) << i << "\n"; 16 | //return 0; 17 | if (cmd.isSet("in")) 18 | { 19 | if (cmd.isSet("mpsi")) 20 | { 21 | volePSI::doFileMPSI(cmd); 22 | } 23 | else if (cmd.isSet("psu")) 24 | { 25 | volePSI::doFilePSU(cmd); 26 | } 27 | else 28 | { 29 | volePSI::doFilePSI(cmd); 30 | } 31 | } 32 | else if (cmd.isSet("messagePassing")) 33 | { 34 | messagePassingExample(cmd); 35 | } 36 | else if (cmd.isSet("net")) 37 | { 38 | networkSocketExample(cmd); 39 | } 40 | else if (cmd.isSet("exp")) 41 | { 42 | Paxos_experiment(cmd); 43 | } 44 | else if (cmd.isSet("perf")) 45 | { 46 | perf(cmd); 47 | } 48 | else if (cmd.isSet("balls")) 49 | { 50 | overflow(cmd); 51 | } 52 | else if(cmd.isSet("u")) 53 | { 54 | if (cmd.isSet("mpsi")) 55 | { 56 | auto r = MPSI_Tests::Tests.runIf(cmd); 57 | return r == oc::TestCollection::Result::failed; 58 | } 59 | else 60 | { 61 | auto r = volePSI_Tests::Tests.runIf(cmd); 62 | return r == oc::TestCollection::Result::failed; 63 | } 64 | 65 | } 66 | else 67 | { 68 | std::cout << oc::Color::Yellow << "BZS-MPSI\n" << oc::Color::Default 69 | << oc::Color::Green << "File-based MPSI Parameters:\n" << oc::Color::Default 70 | << "./frontend -mpsi [parameters] : Run a participant with the following parameters.\n" 71 | << " Required parameters\n:" 72 | << " -in : the path to the party's set. The path should have a \".csv\" extension with one element with 32 char hex per row.\n" 73 | << " -out : the output file path (default \"in || .out\").\n" 74 | << " -nu : the number of participants.\n" 75 | << " -id : participant ID (the IDs of Clients range from 0 to nu-3, the ID of Pivot is nu-2, and the ID of Leader is nu-1).\n" 76 | << " -ipp : IP address and base port of Pivot.\n" 77 | << " -ipl : IP address and base port of Leader.\n" 78 | << " Optional parameters:\n" 79 | << " -nt : the number of threads allocated to the participant (default 1).\n" 80 | << " -la : the statistical security parameter (default 40).\n" 81 | << " -ca, if this option appears, run MPSI-CA instead of MPSI (default false).\n" 82 | << " -bc, if this option appears, Leader broadcasts the result at the end (default false).\n" 83 | << oc::Color::Green << "MPSI Benchmark Parameters:\n" << oc::Color::Default 84 | << " Required parameters:\n" 85 | << " -nu : the number of participants.\n" 86 | << " -id : participant ID (the IDs of Clients range from 0 to nu-3, the ID of Pivot is nu-2, and the ID of Leader is nu-1).\n" 87 | << " -nn : the log2 size of the set (default 10). In the benchmark, please enter the same \"nn\" for all participants.\n" 88 | << " Optional parameters:\n" 89 | << " -ts : the preset intersection size to verify the correctness (default 0.1*set size).\n" 90 | << " -nt : the number of threads allocated to the participant (default 1).\n" 91 | << " -la : the statistical security parameter (default 40).\n" 92 | << " -ca, if this option appears, run MPSI-CA instead of MPSI (default false).\n" 93 | << " -bc, if this option appears, Leader broadcasts the result at the end (default false).\n\n" 94 | 95 | ; 96 | 97 | 98 | std::cout << oc::Color::Yellow << "volepsi\n" << oc::Color::Default 99 | << "./frontend -perf -mpsi [parameters] : Run a participant with the following parameters.\n" 100 | << oc::Color::Green << "File based PSI Parameters:\n" << oc::Color::Default 101 | << " -in : The path to the party's set. Should either be a binary file containing 16 byte elements with a .bin extension. " 102 | << "Otherwise the path should have a .csv extension and have one element per row, 32 char hex rows are preferred. \n" 103 | 104 | << " -r : value should be in { 0, 1 } where 0 means PSI sender.\n" 105 | 106 | << " -out : The output file path. Will be written in the same format as the input. (Default = in || \".out\")\n" 107 | << " -quiet: print less info.\n" 108 | << " -v: print more info.\n" 109 | << " -indexSet: output the index set of the intersection instead of the set element itself\n" 110 | << " -noSort: do not require the output to be in the same order and the input (slightly faster)." 111 | << " -malicious: run the protocol with malicious security\n" 112 | << " -useSilver: run the protocol with the Silver Vole encoder (experimental, default is expand accumulate)\n" 113 | << " -useQC: run the protocol with the QuasiCyclic Vole encoder (default is expand accumulate)\n" 114 | << " -ssp: Statistical Security parameter, default = 40.\n\n" 115 | 116 | << " -ip : IP address and port of the server = PSI receiver. (Default = localhost:1212)\n" 117 | << " -server : Value should be in {0, 1} and indicates if this party should be the IP server. (Default = r)\n" 118 | << " -tls: run the protocol with TLS. Must also set -CA,-sk,-pk\n" 119 | << " -CA : if tls, then this must be the path to the CA cert file in pem format\n" 120 | << " -pk : if tls, then this must be the path to this parties public key cert file in pem format\n" 121 | << " -sk : if tls, then this must be the path to this parties private key file in pem format\n\n" 122 | 123 | << " -bin: Optional flag to always interpret the input file as binary.\n" 124 | << " -csv: Optional flag to always interpret the input file as a CSV.\n" 125 | << " -receiverSize : An optional parameter to specify the receiver's set size.\n" 126 | << " -senderSize : An optional parameter to specify the sender's set size.\n\n" 127 | 128 | ; 129 | 130 | 131 | std::cout << oc::Color::Green << "Example programs: \n" << oc::Color::Default 132 | << " -messagePassing: Runs the message passing example program. This example shows how to manually pass messages between the PSI parties. Same parameters as File base PSI can be used.\n" 133 | << " -net: Run the network socket (TCP/IP or TLS) example program. This example shows how to run the protocol on the coproto network socket. Same parameters as File base PSI can be used.\n\n" 134 | 135 | ; 136 | 137 | 138 | std::cout << oc::Color::Green << "Benchmark programs: \n" << oc::Color::Default 139 | << " -perf: required flag to run benchmarking\n" 140 | << " -psi: Run the PSI benchmark.\n" 141 | << " -nn : the log2 size of the sets.\n" 142 | << " -t : the number of trials.\n" 143 | << " -malicious: run with malicious security.\n" 144 | << " -v: verbose.\n" 145 | << " -nt: number of threads.\n" 146 | << " -fakeBase: use fake base OTs.\n" 147 | << " -nc: do not compress the OPRF outputs.\n" 148 | << " -useSilver: run the protocol with the Silver Vole encoder (experimental, default is expand accumulate)\n" 149 | << " -useQC: run the protocol with the QuasiCyclic Vole encoder (default is expand accumulate)\n" 150 | << " -bs: the okvs bin size.\n" 151 | << " -cpsi: Run the circuit psi benchmark.\n" 152 | << " -nn : the log2 size of the sets.\n" 153 | << " -t : the number of trials.\n" 154 | << " -v: verbose.\n" 155 | << " -nt: number of threads.\n" 156 | << " -paxos: Run the okvs benchmark.\n" 157 | << " -n : The set size. Can also set n using -nn wher n=2^nn.\n" 158 | << " -t : the number of trials.\n" 159 | << " -b : The bitcount of the index type. Must by a multiple of 8 and greater than 1.3*n.\n" 160 | << " -v: verbose.\n" 161 | << " -w : The okvs weight.\n" 162 | << " -ssp : statistical security parameter.\n" 163 | << " -binary: binary okvs dense columns.\n" 164 | << " -cols: The size of the okvs elemenst in multiples of 16 bytes. default = 1.\n" 165 | << " -baxos: The the bin okvs benchmark. Same parameters as -paxos plus.\n" 166 | << " -lbs : the log2 bin size.\n" 167 | << " -nt: number of threads.\n" 168 | 169 | ; 170 | 171 | std::cout << oc::Color::Green << "Unit tests: \n" << oc::Color::Default 172 | << " -u: Run all of the unit tests.\n" 173 | << " -u -list: List run all of the unit tests.\n" 174 | << " -u 10 15: Run unit test 10 and 15.\n" 175 | << " -u 10..15: Run unit test 10 to 15 (exclusive).\n" 176 | << " -u psi: Run unit test that contain \"psi\" is the title.\n\n" 177 | ; 178 | } 179 | 180 | return 0; 181 | } -------------------------------------------------------------------------------- /frontend/messagePassingExample.h: -------------------------------------------------------------------------------- 1 | #include "cryptoTools/Common/CLP.h" 2 | #include "coproto/Socket/BufferingSocket.h" 3 | #include "volePSI/RsPsi.h" 4 | #include 5 | 6 | // This example demonstates how one can get and manually send the protocol messages 7 | // that are generated. This communicate method is one possible way of doing this. 8 | // It takes a protocol that has been started and coproto buffering socket as input. 9 | // It alternates between "sending" and "receiving" protocol messages. Instead of 10 | // sending the messages on a socket, this program writes them to a file and the other 11 | // party reads that file to get the message. In a real program the communication could 12 | // handled in any way the user decides. 13 | auto communicate( 14 | macoro::eager_task<>& protocol, 15 | bool sender, 16 | coproto::BufferingSocket& sock, 17 | bool verbose) 18 | { 19 | 20 | int s = 0, r = 0; 21 | std::string me = sender ? "sender" : "recver"; 22 | std::string them = !sender ? "sender" : "recver"; 23 | 24 | // write any outgoing data to a file me_i.bin where i in the message index. 25 | auto write = [&]() 26 | { 27 | // the the outbound messages that the protocol has generated. 28 | // This will consist of all the outbound messages that can be 29 | // generated without receiving the next inbound message. 30 | auto b = sock.getOutbound(); 31 | 32 | // If we do have outbound messages, then lets write them to a file. 33 | if (b && b->size()) 34 | { 35 | std::ofstream message; 36 | auto temp = me + ".tmp"; 37 | auto file = me + "_" + std::to_string(s) + ".bin"; 38 | message.open(temp, std::ios::binary | std::ios::trunc); 39 | message.write((char*)b->data(), b->size()); 40 | message.close(); 41 | 42 | if (verbose) 43 | { 44 | // optional for debug purposes. 45 | oc::RandomOracle hash(16); 46 | hash.Update(b->data(), b->size()); 47 | oc::block h; hash.Final(h); 48 | 49 | std::cout << me << " write " << std::to_string(s) << " " << h << "\n"; 50 | } 51 | 52 | if (rename(temp.c_str(), file.c_str()) != 0) 53 | std::cout << me << " file renamed failed\n"; 54 | else if (verbose) 55 | std::cout << me << " file renamed successfully\n"; 56 | 57 | ++s; 58 | } 59 | 60 | }; 61 | 62 | // write incoming data from a file them_i.bin where i in the message index. 63 | auto read = [&]() { 64 | 65 | std::ifstream message; 66 | auto file = them + "_" + std::to_string(r) + ".bin"; 67 | while (message.is_open() == false) 68 | { 69 | message.open(file, std::ios::binary); 70 | if ((message.is_open() == false)) 71 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); 72 | } 73 | 74 | auto fsize = message.tellg(); 75 | message.seekg(0, std::ios::end); 76 | fsize = message.tellg() - fsize; 77 | message.seekg(0, std::ios::beg); 78 | std::vector buff(fsize); 79 | message.read((char*)buff.data(), fsize); 80 | message.close(); 81 | std::remove(file.c_str()); 82 | 83 | if (verbose) 84 | { 85 | oc::RandomOracle hash(16); 86 | hash.Update(buff.data(), buff.size()); 87 | oc::block h; hash.Final(h); 88 | 89 | std::cout << me << " read " << std::to_string(r) << " " << h << "\n"; 90 | } 91 | ++r; 92 | 93 | // This gives this socket the message which forwards it to the protocol and 94 | // run the protocol forward, possibly generating more outbound protocol 95 | // messages. 96 | sock.processInbound(buff); 97 | }; 98 | 99 | // The sender we generate the first message. 100 | if (sender) 101 | write(); 102 | 103 | // While the protocol is not done we alternate between reading and writing messages. 104 | while (protocol.is_ready() == false) 105 | { 106 | read(); 107 | write(); 108 | } 109 | } 110 | 111 | void messagePassingExampleRun(oc::CLP& cmd) 112 | { 113 | auto receiver = cmd.get("r"); 114 | 115 | // The sender set size. 116 | auto ns = cmd.getOr("senderSize", 100ull); 117 | 118 | // The receiver set size. 119 | auto nr = cmd.getOr("receiverSize", 100ull); 120 | auto verbose = cmd.isSet("v"); 121 | 122 | // The statistical security parameter. 123 | auto ssp = cmd.getOr("ssp", 40); 124 | 125 | // Malicious Security. 126 | auto mal = cmd.isSet("malicious"); 127 | 128 | // The vole type, default to expand accumulate. 129 | auto type = oc::DefaultMultType; 130 | #ifdef ENABLE_INSECURE_SILVER 131 | type = cmd.isSet("useSilver") ? oc::MultType::slv5 : type; 132 | #endif 133 | #ifdef ENABLE_BITPOLYMUL 134 | type = cmd.isSet("useQC") ? oc::MultType::QuasiCyclic : type; 135 | #endif 136 | 137 | // use fewer rounds of communication but more computation. 138 | auto useReducedRounds = cmd.isSet("reducedRounds"); 139 | 140 | // A buffering socket. This socket type internally buffers the 141 | // protocol messages. It is then up to the user to manually send 142 | // and receive messages via the getOutbond(...) and processInbount(...) 143 | // methods. 144 | coproto::BufferingSocket sock; 145 | 146 | // Sets are always represented as 16 byte values. To support longer elements one can hash them. 147 | std::vector set; 148 | if (!receiver) 149 | { 150 | volePSI::RsPsiSender sender; 151 | set.resize(ns); 152 | 153 | // in this example we use the set {0,1,...}. 154 | for (oc::u64 i = 0; i < ns; ++i) 155 | set[i] = oc::block(0, i); 156 | 157 | sender.setMultType(type); 158 | sender.init(ns, nr, ssp, oc::sysRandomSeed(), mal, 1, useReducedRounds); 159 | 160 | if (verbose) 161 | std::cout << "sender start\n"; 162 | 163 | // Eagerly start the protocol. This will run the protocol up to the point 164 | // that it need to receive a message from the other party. 165 | auto protocol = sender.run(set, sock) | macoro::make_eager(); 166 | 167 | // Perform the communication and complete the protocol. 168 | communicate(protocol, true, sock, verbose); 169 | 170 | std::cout << "sender done\n"; 171 | } 172 | else 173 | { 174 | // in this example we use the set {0,1,...}. 175 | set.resize(nr); 176 | for (oc::u64 i = 0; i < nr; ++i) 177 | set[i] = oc::block(0, i); 178 | 179 | volePSI::RsPsiReceiver recevier; 180 | recevier.setMultType(type); 181 | recevier.init(ns, nr, ssp, oc::sysRandomSeed(), mal, 1, useReducedRounds); 182 | 183 | if (verbose) 184 | std::cout << "recver start\n"; 185 | 186 | 187 | // Eagerly start the protocol. This will run the protocol up to the point 188 | // that it need to receive a message from the other party. 189 | auto protocol = recevier.run(set, sock) | macoro::make_eager(); 190 | 191 | // Perform the communication and complete the protocol. 192 | communicate(protocol, false, sock, verbose); 193 | 194 | std::cout << "recver done " << recevier.mIntersection.size() << " \n"; 195 | } 196 | } 197 | 198 | // This sample is how to run both parties in single program. 199 | void messagePassingExampleBoth(oc::CLP& cmd) 200 | { 201 | // The sender set size. 202 | auto ns = cmd.getOr("senderSize", 100); 203 | 204 | // The receiver set size. 205 | auto nr = cmd.getOr("receiverSize", 100); 206 | auto verbose = cmd.isSet("v"); 207 | 208 | // The statistical security parameter. 209 | auto ssp = cmd.getOr("ssp", 40); 210 | 211 | // Malicious Security. 212 | auto mal = cmd.isSet("malicious"); 213 | 214 | // The vole type, default to expand accumulate. 215 | auto type = oc::DefaultMultType; 216 | #ifdef ENABLE_INSECURE_SILVER 217 | type = cmd.isSet("useSilver") ? oc::MultType::slv5 : type; 218 | #endif 219 | #ifdef ENABLE_BITPOLYMUL 220 | type = cmd.isSet("useQC") ? oc::MultType::QuasiCyclic : type; 221 | #endif 222 | 223 | // use fewer rounds of communication but more computation. 224 | auto useReducedRounds = cmd.isSet("reducedRounds"); 225 | 226 | // A buffering socket. This socket type internally buffers the 227 | // protocol messages. It is then up to the user to manually send 228 | // and receive messages via the getOutbond(...) and processInbount(...) 229 | // methods. 230 | coproto::BufferingSocket senderSock, recverSock; 231 | 232 | // Sets are always represented as 16 byte values. To support longer elements one can hash them. 233 | std::vector senderSet, recverSet; 234 | volePSI::RsPsiSender sender; 235 | senderSet.resize(ns); 236 | 237 | // in this example we use the set {0,1,...}. 238 | for (oc::u64 i = 0; i < ns; ++i) 239 | senderSet[i] = oc::block(0, i); 240 | 241 | sender.setMultType(type); 242 | sender.init(ns, nr, ssp, oc::sysRandomSeed(), mal, 1, useReducedRounds); 243 | 244 | if (verbose) 245 | std::cout << "sender start\n"; 246 | 247 | // Eagerly start the protocol. This will run the protocol up to the point 248 | // that it need to receive a message from the other party. 249 | coproto::optional> senderProto = 250 | sender.run(senderSet, senderSock) | macoro::make_eager(); 251 | 252 | 253 | // in this example we use the set {0,1,...}. 254 | recverSet.resize(nr); 255 | for (oc::u64 i = 0; i < nr; ++i) 256 | recverSet[i] = oc::block(0, i); 257 | 258 | volePSI::RsPsiReceiver recevier; 259 | recevier.setMultType(type); 260 | recevier.init(ns, nr, ssp, oc::sysRandomSeed(), mal, 1, useReducedRounds); 261 | 262 | if (verbose) 263 | std::cout << "recver start\n"; 264 | 265 | 266 | // Eagerly start the protocol. This will run the protocol up to the point 267 | // that it need to receive a message from the other party. 268 | coproto::optional> recverProto = 269 | recevier.run(recverSet, recverSock) | macoro::make_eager(); 270 | 271 | // pass messages between the parties until they are done. 272 | try 273 | { 274 | while (recverProto || senderProto) 275 | { 276 | if (recverProto && recverProto->is_ready()) 277 | { 278 | // get the result of the protocol. Might throw. 279 | coproto::sync_wait(*recverProto); 280 | std::cout << "recver done " << recevier.mIntersection.size() << " \n"; 281 | recverProto.reset(); 282 | } 283 | 284 | if (senderProto && senderProto->is_ready()) 285 | { 286 | // get the result of the protocol. Might throw. 287 | coproto::sync_wait(*senderProto); 288 | std::cout << "sender done " << " \n"; 289 | senderProto.reset(); 290 | } 291 | coproto::optional> recverMsg = recverSock.getOutbound(); 292 | if (recverMsg.has_value()) 293 | senderSock.processInbound(*recverMsg); 294 | 295 | coproto::optional> senderMsg = senderSock.getOutbound(); 296 | if (senderMsg) 297 | recverSock.processInbound(*senderMsg); 298 | } 299 | 300 | } 301 | catch (std::exception& e) 302 | { 303 | std::cout << "Exception: " << e.what() << std::endl; 304 | } 305 | } 306 | 307 | 308 | void messagePassingExample(oc::CLP& cmd) 309 | { 310 | if (cmd.isSet("both")) 311 | { 312 | 313 | messagePassingExampleBoth(cmd); 314 | } 315 | else 316 | { 317 | 318 | 319 | // If the user specified -r, then run that party. 320 | // Otherwisew run both parties. 321 | if (cmd.hasValue("r")) 322 | { 323 | messagePassingExampleRun(cmd); 324 | } 325 | else 326 | { 327 | auto s = cmd; 328 | s.setDefault("r", 0); 329 | cmd.setDefault("r", 1); 330 | auto a = std::async([&]() {messagePassingExampleRun(s); }); 331 | messagePassingExampleRun(cmd); 332 | a.get(); 333 | } 334 | } 335 | } 336 | 337 | -------------------------------------------------------------------------------- /volePSI/RsOprf.cpp: -------------------------------------------------------------------------------- 1 | #include "RsOprf.h" 2 | 3 | namespace volePSI 4 | { 5 | Proto RsOprfSender::send(u64 n, PRNG& prng, Socket& chl, u64 numThreads, bool reducedRounds) 6 | { 7 | auto ws = block{}; 8 | auto hBuff = std::array {}; 9 | auto ro = oc::RandomOracle(32); 10 | auto pPtr = std::unique_ptr{}; 11 | auto pp = span{}; 12 | auto subPp = span{}; 13 | auto remB = span{}; 14 | auto subB = span{}; 15 | auto fu = macoro::eager_task{}; 16 | auto recvIdx = u64{ 0 }; 17 | auto fork = Socket{}; 18 | 19 | setTimePoint("RsOprfSender::send-begin"); 20 | ws = prng.get(); 21 | 22 | mPaxos.init(n, mBinSize, 3, mSsp, PaxosParam::GF128, oc::ZeroBlock); 23 | 24 | mD = prng.get(); 25 | 26 | if (mMalicious) 27 | { 28 | mVoleSender.mMalType = oc::SilentSecType::Malicious; 29 | ro.Update(ws); 30 | ro.Final(hBuff); 31 | co_await(chl.send(std::move(hBuff))); 32 | } 33 | 34 | if (mTimer) 35 | mVoleSender.setTimer(*mTimer); 36 | 37 | numThreads = std::max(1, numThreads); 38 | //mVoleSender.mNumThreads = numThreads; 39 | // a + b = c * d 40 | fork = chl.fork(); 41 | fu = genVole(prng, fork, reducedRounds) 42 | | macoro::make_eager(); 43 | 44 | co_await(chl.recv(mPaxos.mSeed)); 45 | setTimePoint("RsOprfSender::recv-seed"); 46 | co_await(fu); 47 | mB = mVoleSender.mB; 48 | setTimePoint("RsOprfSender::send-vole"); 49 | 50 | 51 | 52 | 53 | if (mMalicious) 54 | { 55 | co_await(chl.recv(mW)); 56 | co_await(chl.send(std::move(ws))); 57 | mW = mW ^ ws; 58 | setTimePoint("RsOprfSender::recv-mal"); 59 | } 60 | 61 | pPtr.reset(new block[mPaxos.size()]); 62 | pp = span(pPtr.get(), mPaxos.size()); 63 | 64 | setTimePoint("RsOprfSender::alloc "); 65 | 66 | if (0) 67 | { 68 | co_await(chl.recv(pp)); 69 | 70 | setTimePoint("RsOprfSender::send-recv"); 71 | { 72 | 73 | auto main = mB.size() / 8 * 8; 74 | auto b = mB.data(); 75 | auto p = pp.data(); 76 | for (u64 i = 0; i < main; i += 8) 77 | { 78 | b[0] = b[0] ^ mD.gf128Mul(p[0]); 79 | b[1] = b[1] ^ mD.gf128Mul(p[1]); 80 | b[2] = b[2] ^ mD.gf128Mul(p[2]); 81 | b[3] = b[3] ^ mD.gf128Mul(p[3]); 82 | b[4] = b[4] ^ mD.gf128Mul(p[4]); 83 | b[5] = b[5] ^ mD.gf128Mul(p[5]); 84 | b[6] = b[6] ^ mD.gf128Mul(p[6]); 85 | b[7] = b[7] ^ mD.gf128Mul(p[7]); 86 | 87 | b += 8; 88 | p += 8; 89 | } 90 | 91 | for (u64 i = main; i < mB.size(); ++i) 92 | { 93 | mB[i] = mB[i] ^ mD.gf128Mul(pp[i]); 94 | } 95 | } 96 | setTimePoint("RsOprfSender::send-gf128Mul"); 97 | } 98 | else 99 | { 100 | remB = mB; 101 | 102 | while (pp.size()) 103 | { 104 | 105 | subPp = pp.subspan(0, std::min(pp.size(), 1 << 28)); 106 | pp = pp.subspan(subPp.size()); 107 | 108 | subB = remB.subspan(0, subPp.size()); 109 | remB = remB.subspan(subPp.size()); 110 | 111 | setTimePoint("RsOprfSender::pre*-" + std::to_string(recvIdx)); 112 | co_await chl.recv(subPp); 113 | setTimePoint("RsOprfSender::recv-" + std::to_string(recvIdx)); 114 | 115 | { 116 | 117 | auto main = subB.size() / 8 * 8; 118 | auto b = subB.data(); 119 | auto p = subPp.data(); 120 | for (u64 i = 0; i < main; i += 8) 121 | { 122 | b[0] = b[0] ^ mD.gf128Mul(p[0]); 123 | b[1] = b[1] ^ mD.gf128Mul(p[1]); 124 | b[2] = b[2] ^ mD.gf128Mul(p[2]); 125 | b[3] = b[3] ^ mD.gf128Mul(p[3]); 126 | b[4] = b[4] ^ mD.gf128Mul(p[4]); 127 | b[5] = b[5] ^ mD.gf128Mul(p[5]); 128 | b[6] = b[6] ^ mD.gf128Mul(p[6]); 129 | b[7] = b[7] ^ mD.gf128Mul(p[7]); 130 | 131 | b += 8; 132 | p += 8; 133 | } 134 | 135 | for (u64 i = main; i < subB.size(); ++i, ++b, ++p) 136 | { 137 | *b = *b ^ mD.gf128Mul(*p); 138 | } 139 | } 140 | setTimePoint("RsOprfSender::gf128Mul-" + std::to_string(recvIdx)); 141 | 142 | ++recvIdx; 143 | 144 | } 145 | } 146 | } 147 | 148 | block RsOprfSender::eval(block v) 149 | { 150 | block o; 151 | eval({ &v,1 }, { &o,1 }, 1); 152 | return o; 153 | } 154 | void RsOprfSender::eval(span val, span output, u64 numThreads) 155 | { 156 | setTimePoint("RsOprfSender::eval-begin"); 157 | 158 | mPaxos.decode(val, output, mB, numThreads); 159 | 160 | setTimePoint("RsOprfSender::eval-decode"); 161 | 162 | auto main = val.size() / 8 * 8; 163 | auto o = output.data(); 164 | auto v = val.data(); 165 | std::array h; 166 | 167 | // todo, parallelize this. 168 | if (mMalicious) 169 | { 170 | oc::MultiKeyAES<8> hasher; 171 | 172 | //main = 0; 173 | for (u64 i = 0; i < main; i += 8) 174 | { 175 | oc::mAesFixedKey.hashBlocks<8>(v, h.data()); 176 | o[0] = o[0] ^ mD.gf128Mul(h[0]); 177 | o[1] = o[1] ^ mD.gf128Mul(h[1]); 178 | o[2] = o[2] ^ mD.gf128Mul(h[2]); 179 | o[3] = o[3] ^ mD.gf128Mul(h[3]); 180 | o[4] = o[4] ^ mD.gf128Mul(h[4]); 181 | o[5] = o[5] ^ mD.gf128Mul(h[5]); 182 | o[6] = o[6] ^ mD.gf128Mul(h[6]); 183 | o[7] = o[7] ^ mD.gf128Mul(h[7]); 184 | 185 | 186 | o[0] = o[0] ^ mW; 187 | o[1] = o[1] ^ mW; 188 | o[2] = o[2] ^ mW; 189 | o[3] = o[3] ^ mW; 190 | o[4] = o[4] ^ mW; 191 | o[5] = o[5] ^ mW; 192 | o[6] = o[6] ^ mW; 193 | o[7] = o[7] ^ mW; 194 | 195 | hasher.setKeys({ o, 8 }); 196 | hasher.hashNBlocks(v, o); 197 | 198 | o += 8; 199 | v += 8; 200 | } 201 | for (u64 i = main; i < val.size(); ++i) 202 | { 203 | auto h = oc::mAesFixedKey.hashBlock(val[i]); 204 | output[i] = output[i] ^ mD.gf128Mul(h); 205 | 206 | output[i] = output[i] ^ mW; 207 | output[i] = oc::AES(output[i]).hashBlock(val[i]); 208 | } 209 | } 210 | else 211 | { 212 | 213 | for (u64 i = 0; i < main; i += 8) 214 | { 215 | oc::mAesFixedKey.hashBlocks<8>(v, h.data()); 216 | //auto h = v; 217 | 218 | o[0] = o[0] ^ mD.gf128Mul(h[0]); 219 | o[1] = o[1] ^ mD.gf128Mul(h[1]); 220 | o[2] = o[2] ^ mD.gf128Mul(h[2]); 221 | o[3] = o[3] ^ mD.gf128Mul(h[3]); 222 | o[4] = o[4] ^ mD.gf128Mul(h[4]); 223 | o[5] = o[5] ^ mD.gf128Mul(h[5]); 224 | o[6] = o[6] ^ mD.gf128Mul(h[6]); 225 | o[7] = o[7] ^ mD.gf128Mul(h[7]); 226 | 227 | oc::mAesFixedKey.hashBlocks<8>(o, o); 228 | 229 | o += 8; 230 | v += 8; 231 | } 232 | 233 | 234 | 235 | for (u64 i = main; i < val.size(); ++i) 236 | { 237 | auto h = oc::mAesFixedKey.hashBlock(val[i]); 238 | output[i] = output[i] ^ mD.gf128Mul(h); 239 | output[i] = oc::mAesFixedKey.hashBlock(output[i]); 240 | } 241 | } 242 | 243 | setTimePoint("RsOprfSender::eval-hash"); 244 | 245 | } 246 | 247 | Proto RsOprfSender::genVole(PRNG& prng, Socket& chl, bool reduceRounds) 248 | { 249 | if (reduceRounds) 250 | mVoleSender.configure(mPaxos.size(), oc::SilentBaseType::Base); 251 | 252 | return mVoleSender.silentSendInplace(mD, mPaxos.size(), prng, chl); 253 | } 254 | 255 | struct UninitVec : span 256 | { 257 | std::unique_ptr ptr; 258 | 259 | void resize(u64 s) 260 | { 261 | ptr.reset(new block[s]); 262 | static_cast&>(*this) = span(ptr.get(), s); 263 | } 264 | }; 265 | 266 | Proto RsOprfReceiver::receive(span values, span outputs, PRNG& prng, Socket& chl, u64 numThreads, bool reducedRounds) 267 | { 268 | 269 | auto hashingSeed = block{}; 270 | auto wr = block{}; 271 | auto ws = block{}; 272 | auto Hws = std::array {}; 273 | auto paxos = Baxos{}; 274 | auto hPtr = std::unique_ptr{}; 275 | auto h = span{}; 276 | auto p = UninitVec{}; 277 | auto subP = span{}; 278 | auto subC = span{}; 279 | auto a = span{}; 280 | auto c = span{}; 281 | auto fu = macoro::eager_task{}; 282 | auto ii = u64{ 0 }; 283 | auto fork = Socket{}; 284 | 285 | setTimePoint("RsOprfReceiver::receive-begin"); 286 | 287 | if (values.size() != outputs.size()) 288 | throw RTE_LOC; 289 | 290 | hashingSeed = prng.get(), wr = prng.get(); 291 | paxos.mDebug = mDebug; 292 | paxos.init(values.size(), mBinSize, 3, mSsp, PaxosParam::GF128, hashingSeed); 293 | 294 | co_await(chl.send(std::move(hashingSeed))); 295 | 296 | if (mMalicious) 297 | { 298 | mVoleRecver.mMalType = oc::SilentSecType::Malicious; 299 | co_await(chl.recv(Hws)); 300 | } 301 | 302 | if (mTimer) 303 | mVoleRecver.setTimer(*mTimer); 304 | 305 | fork = chl.fork(); 306 | fu = genVole(paxos.size(), prng, fork, reducedRounds) 307 | | macoro::make_eager(); 308 | 309 | 310 | 311 | hPtr.reset(new block[values.size()]); 312 | h = span(hPtr.get(), values.size()); 313 | 314 | oc::mAesFixedKey.hashBlocks(values, h); 315 | setTimePoint("RsOprfReceiver::receive-hash"); 316 | 317 | //auto pPtr = std::make_shared>(paxos.size()); 318 | //span p = *pPtr; 319 | 320 | p.resize(paxos.size()); 321 | 322 | setTimePoint("RsOprfReceiver::receive-alloc"); 323 | 324 | paxos.solve(values, h, p, nullptr, numThreads); 325 | setTimePoint("RsOprfReceiver::receive-solve"); 326 | co_await(fu); 327 | 328 | // a + b = c * d 329 | a = mVoleRecver.mA; 330 | c = mVoleRecver.mC; 331 | 332 | setTimePoint("RsOprfReceiver::receive-vole"); 333 | 334 | 335 | if (mMalicious) 336 | { 337 | co_await(chl.send(std::move(wr))); 338 | } 339 | 340 | 341 | //if (numThreads > 1) 342 | // thrd.join(); 343 | if (0) 344 | { 345 | { 346 | auto main = (p.size() / 8) * 8; 347 | block* __restrict pp = p.data(); 348 | block* __restrict cc = c.data(); 349 | for (u64 i = 0; i < main; i += 8) 350 | { 351 | pp[0] = pp[0] ^ cc[0]; 352 | pp[1] = pp[1] ^ cc[1]; 353 | pp[2] = pp[2] ^ cc[2]; 354 | pp[3] = pp[3] ^ cc[3]; 355 | pp[4] = pp[4] ^ cc[4]; 356 | pp[5] = pp[5] ^ cc[5]; 357 | pp[6] = pp[6] ^ cc[6]; 358 | pp[7] = pp[7] ^ cc[7]; 359 | 360 | pp += 8; 361 | cc += 8; 362 | } 363 | for (u64 i = main; i < p.size(); ++i) 364 | p[i] = p[i] ^ c[i]; 365 | } 366 | 367 | setTimePoint("RsOprfReceiver::receive-xor"); 368 | 369 | // send c ^ p 370 | co_await(chl.send(std::move(p))); 371 | } 372 | else 373 | { 374 | ii = 0; 375 | 376 | while (c.size()) 377 | { 378 | 379 | subP = p.subspan(0, std::min(p.size(), 1 << 28)); 380 | subC = c.subspan(0, subP.size()); 381 | 382 | if (p.size() != subP.size()) 383 | static_cast&>(p) = p.subspan(subP.size()); 384 | c = c.subspan(subP.size()); 385 | 386 | { 387 | 388 | auto main = (subP.size() / 8) * 8; 389 | block* __restrict pp = subP.data(); 390 | block* __restrict cc = subC.data(); 391 | for (u64 i = 0; i < main; i += 8) 392 | { 393 | pp[0] = pp[0] ^ cc[0]; 394 | pp[1] = pp[1] ^ cc[1]; 395 | pp[2] = pp[2] ^ cc[2]; 396 | pp[3] = pp[3] ^ cc[3]; 397 | pp[4] = pp[4] ^ cc[4]; 398 | pp[5] = pp[5] ^ cc[5]; 399 | pp[6] = pp[6] ^ cc[6]; 400 | pp[7] = pp[7] ^ cc[7]; 401 | 402 | pp += 8; 403 | cc += 8; 404 | } 405 | for (u64 i = main; i < p.size(); ++i, ++pp, ++cc) 406 | *pp = *pp ^ *cc; 407 | } 408 | 409 | setTimePoint("RsOprfReceiver::receive-xor"); 410 | 411 | if (p.size() != subP.size()) 412 | co_await(chl.send(std::move(subP))); 413 | else 414 | co_await(chl.send(std::move(p))); 415 | 416 | setTimePoint("RsOprfReceiver::receive-send"); 417 | 418 | ++ii; 419 | } 420 | 421 | } 422 | 423 | paxos.decode(values, outputs, a, numThreads); 424 | 425 | setTimePoint("RsOprfReceiver::receive-decode"); 426 | 427 | if (mMalicious) 428 | { 429 | co_await(chl.recv(ws)); 430 | 431 | { 432 | std::array Hws2; 433 | oc::RandomOracle ro(32); 434 | ro.Update(ws); 435 | ro.Final(Hws2); 436 | if (Hws != Hws2) 437 | throw RTE_LOC; 438 | 439 | auto w = ws ^ wr; 440 | 441 | // todo, parallelize this. 442 | 443 | // compute davies-meyer F 444 | // F(x) = H( Decode(x, a) + w, x) 445 | // where 446 | // H(u,v) = AES_u(v) ^ v 447 | 448 | oc::MultiKeyAES<8> hasher; 449 | auto main = outputs.size() / 8 * 8; 450 | auto o = outputs.data(); 451 | auto v = values.data(); 452 | for (u64 i = 0; i < main; i += 8) 453 | { 454 | o[0] = o[0] ^ w; 455 | o[1] = o[1] ^ w; 456 | o[2] = o[2] ^ w; 457 | o[3] = o[3] ^ w; 458 | o[4] = o[4] ^ w; 459 | o[5] = o[5] ^ w; 460 | o[6] = o[6] ^ w; 461 | o[7] = o[7] ^ w; 462 | 463 | // o = H(o, v) 464 | hasher.setKeys({ o, 8 }); 465 | hasher.hashNBlocks(v, o); 466 | 467 | o += 8; 468 | v += 8; 469 | } 470 | 471 | for (u64 i = main; i < outputs.size(); ++i) 472 | { 473 | outputs[i] = outputs[i] ^ w; 474 | outputs[i] = oc::AES(outputs[i]).hashBlock(values[i]); 475 | } 476 | } 477 | } 478 | else 479 | { 480 | // todo, parallelize this. 481 | 482 | // compute davies-meyer-Oseas F 483 | // F(x) = H(Decode(x, a)) 484 | // where 485 | // H(u) = AES_fixed(u) ^ u 486 | oc::mAesFixedKey.hashBlocks(outputs, outputs); 487 | } 488 | 489 | setTimePoint("RsOprfReceiver::receive-hash"); 490 | } 491 | 492 | Proto RsOprfReceiver::genVole(u64 n, PRNG& prng, Socket& chl, bool reducedRounds) 493 | { 494 | if (reducedRounds) 495 | mVoleRecver.configure(n, oc::SilentBaseType::Base); 496 | return mVoleRecver.silentReceiveInplace(n, prng, chl); 497 | } 498 | 499 | } -------------------------------------------------------------------------------- /volePSI/RpmtPsu.cpp: -------------------------------------------------------------------------------- 1 | #include "RpmtPsu.h" 2 | #include "volePSI/RsPsi.h" 3 | #include "volePSI/RsOprf.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "volePSI/SimpleIndex.h" 10 | #include "libdivide.h" 11 | #include "coproto/Socket/AsioSocket.h" 12 | #include "libOTe/Tools/DefaultCurve.h" 13 | #include 14 | #include 15 | #include "libOTe/Base/BaseOT.h" 16 | #include "libOTe/Base/SimplestOT.h" 17 | #include "libOTe/TwoChooseOne/Iknp/IknpOtExtReceiver.h" 18 | #include "libOTe/TwoChooseOne/Iknp/IknpOtExtSender.h" 19 | 20 | namespace volePSI 21 | { 22 | 23 | void RpmtPsu_User::run(bool My_Role, u64 Sender_Set_Size, u64 Receiver_Set_Size, u64 Lambda, u64 Thread_Num, block Seed, std::vector Inputs, Socket& Chl){ 24 | 25 | if (My_Role == 1){ 26 | 27 | // DH-Based RPMT 28 | 29 | PRNG Prng(Seed); 30 | oc::RandomOracle hash(sizeof(block)); 31 | std::vector Inputs_DH(Receiver_Set_Size); 32 | 33 | for (u64 i = 0ull; i < Receiver_Set_Size; i++) 34 | { 35 | hash.Reset(); 36 | hash.Update(Inputs[i].data(), sizeof(block)); 37 | hash.Final(Inputs_DH[i]); 38 | } 39 | 40 | std::vector Se_point(Sender_Set_Size),Re_point(Receiver_Set_Size); 41 | osuCrypto::Sodium::Scalar25519 G = osuCrypto::Sodium::Scalar25519(Prng); 42 | 43 | if (Thread_Num > 1){ 44 | 45 | std::vector Y_beta(Thread_Num); 46 | 47 | for (u64 i = 0ull; i < Thread_Num; i++){ 48 | Y_beta[i] = std::thread([&, i]() { 49 | unsigned char Th_point_bytes[32]; 50 | memset(Th_point_bytes,0,32); 51 | u64 Th_Begin = i * Receiver_Set_Size / Thread_Num, Th_End = (i+1) * Receiver_Set_Size / Thread_Num; 52 | for (u64 j = Th_Begin; j < Th_End; j++){ 53 | unsigned char* block_bytes = Inputs_DH[j].data(); 54 | memcpy(Th_point_bytes, block_bytes, 16); 55 | Re_point[j].fromBytes(Th_point_bytes); 56 | Re_point[j] = G * Re_point[j]; 57 | } 58 | return ; 59 | }); 60 | } 61 | 62 | for (auto& thrd : Y_beta) thrd.join(); 63 | 64 | coproto::sync_wait(Chl.recv(Se_point)); 65 | coproto::sync_wait(Chl.send(Re_point)); 66 | 67 | std::vector X_alpha_beta(Thread_Num); 68 | 69 | for (u64 i = 0ull; i < Thread_Num; i++){ 70 | X_alpha_beta[i] = std::thread([&, i]() { 71 | u64 Th_Begin = i * Sender_Set_Size / Thread_Num, Th_End = (i+1) * Sender_Set_Size / Thread_Num; 72 | for (u64 j = Th_Begin; j < Th_End; j++) 73 | Se_point[j] = G * Se_point[j]; 74 | return ; 75 | }); 76 | } 77 | 78 | for (auto& thrd : X_alpha_beta) thrd.join(); 79 | 80 | coproto::sync_wait(Chl.recv(Re_point)); 81 | 82 | } 83 | else { 84 | 85 | unsigned char point_bytes[32]; 86 | memset(point_bytes,0,32); 87 | 88 | for (u64 i = 0ull; i < Receiver_Set_Size; i++){ 89 | unsigned char* block_bytes = Inputs_DH[i].data(); 90 | memcpy(point_bytes, block_bytes, 16); 91 | Re_point[i].fromBytes(point_bytes); 92 | Re_point[i] = G * Re_point[i]; 93 | } 94 | 95 | coproto::sync_wait(Chl.recv(Se_point)); 96 | coproto::sync_wait(Chl.send(Re_point)); 97 | 98 | for (u64 i = 0; i < Sender_Set_Size; i++) 99 | Se_point[i] = G * Se_point[i]; 100 | 101 | coproto::sync_wait(Chl.recv(Re_point)); 102 | 103 | } 104 | 105 | unsigned char point_bytes[32]; 106 | memset(point_bytes,0,32); 107 | std::vector Se_block(Sender_Set_Size), Re_block(Receiver_Set_Size); 108 | 109 | for (u64 i = 0ull; i < Sender_Set_Size; i++){ 110 | Se_point[i].toBytes(point_bytes); 111 | std::memcpy(Se_block[i].data(),point_bytes,16); 112 | } 113 | for (u64 i = 0ull; i < Receiver_Set_Size; i++){ 114 | Re_point[i].toBytes(point_bytes); 115 | std::memcpy(Re_block[i].data(),point_bytes,16); 116 | } 117 | 118 | std::unordered_set Re_set; 119 | 120 | for (u64 i = 0; i < Receiver_Set_Size; i++) 121 | Re_set.insert(Re_block[i]); 122 | 123 | std::vector Se_check(Sender_Set_Size); 124 | 125 | for (u64 i = 0; i < Sender_Set_Size; i++) 126 | Se_check[i] = (Re_set.find(Se_block[i]) != Re_set.end()); 127 | 128 | // OT Receiver 129 | 130 | std::vector recvMsg(Sender_Set_Size); 131 | 132 | if(Sender_Set_Size <= 128) // using libOTe-CO15 133 | { 134 | PRNG prng(oc::block(oc::sysRandomSeed())); 135 | osuCrypto::DefaultBaseOT baseOTs; 136 | std::vector mask(Sender_Set_Size); 137 | std::vector maskMsg(Sender_Set_Size); 138 | 139 | osuCrypto::BitVector choices; 140 | choices.resize(Sender_Set_Size); 141 | for(u64 i = 0; i < Sender_Set_Size; i++) 142 | choices[i] = 1 - Se_check[i]; 143 | 144 | // random OT 145 | auto p = baseOTs.receive(choices, mask, prng, Chl); 146 | auto r = macoro::sync_wait(macoro::when_all_ready(std::move(p))); 147 | std::get<0>(r).result(); 148 | 149 | // random OT -> OT 150 | coproto::sync_wait(Chl.recv(maskMsg)); 151 | for(u64 i = 0; i < Sender_Set_Size; i++) 152 | recvMsg[i] = maskMsg[i] ^ mask[i]; 153 | } 154 | else // IKNP 155 | { 156 | PRNG prng(oc::block(oc::sysRandomSeed())); 157 | oc::DefaultBaseOT baseOTs; 158 | std::vector mask(Sender_Set_Size); 159 | std::vector maskMsg(Sender_Set_Size); 160 | std::vector> baseSend(128); // kappa == 128 161 | 162 | prng.get((u8*)baseSend.data()->data(), sizeof(oc::block) * 2 * baseSend.size()); 163 | auto p = baseOTs.send(baseSend, prng, Chl); 164 | auto r = macoro::sync_wait(macoro::when_all_ready(std::move(p))); 165 | std::get<0>(r).result(); 166 | 167 | oc::IknpOtExtReceiver recv; 168 | recv.setBaseOts(baseSend); 169 | 170 | osuCrypto::BitVector choices; 171 | choices.resize(Sender_Set_Size); 172 | for(u64 i = 0; i < Sender_Set_Size; i++) { 173 | choices[i] = 1 - Se_check[i]; 174 | } 175 | 176 | auto proto = recv.receive(choices, mask, prng, Chl); 177 | auto result = macoro::sync_wait(macoro::when_all_ready(std::move(proto))); 178 | std::get<0>(result).result(); 179 | 180 | // random OT -> OT 181 | coproto::sync_wait(Chl.recv(maskMsg)); 182 | for(u64 i = 0; i < Sender_Set_Size; i++) 183 | recvMsg[i] = maskMsg[i] ^ mask[i]; 184 | } 185 | for (u64 i = 0; i < Sender_Set_Size; i++) 186 | if (Se_check[i] == 0){ 187 | Size_Different++; Different.push_back(recvMsg[i]); 188 | } 189 | } 190 | else { 191 | 192 | // DH-Based RPMT 193 | 194 | PRNG Prng(Seed); 195 | oc::RandomOracle hash(sizeof(block)); 196 | std::vector Inputs_DH(Sender_Set_Size); 197 | 198 | for (u64 i = 0ull; i < Sender_Set_Size; i++) 199 | { 200 | hash.Reset(); 201 | hash.Update(Inputs[i].data(), sizeof(block)); 202 | hash.Final(Inputs_DH[i]); 203 | } 204 | 205 | std::vector Se_point(Sender_Set_Size),Re_point(Receiver_Set_Size); 206 | osuCrypto::Sodium::Scalar25519 G = osuCrypto::Sodium::Scalar25519(Prng); 207 | 208 | if (Thread_Num > 1){ 209 | 210 | std::vector X_alpha(Thread_Num); 211 | 212 | for (u64 i = 0ull; i < Thread_Num; i++){ 213 | X_alpha[i] = std::thread([&, i]() { 214 | unsigned char Th_point_bytes[32]; 215 | memset(Th_point_bytes,0,32); 216 | u64 Th_Begin = i * Sender_Set_Size / Thread_Num, Th_End = (i+1) * Sender_Set_Size / Thread_Num; 217 | for (u64 j = Th_Begin; j < Th_End; j++){ 218 | unsigned char* block_bytes = Inputs_DH[j].data(); 219 | memcpy(Th_point_bytes, block_bytes, 16); 220 | Se_point[j].fromBytes(Th_point_bytes); 221 | Se_point[j] = G * Se_point[j]; 222 | } 223 | return ; 224 | }); 225 | } 226 | 227 | for (auto& thrd : X_alpha) thrd.join(); 228 | 229 | coproto::sync_wait(Chl.send(Se_point)); 230 | coproto::sync_wait(Chl.recv(Re_point)); 231 | 232 | std::vector Y_alpha_beta(Thread_Num); 233 | 234 | for (u64 i = 0ull; i < Thread_Num; i++){ 235 | Y_alpha_beta[i] = std::thread([&, i]() { 236 | u64 Th_Begin = i * Receiver_Set_Size / Thread_Num, Th_End = (i+1) * Receiver_Set_Size / Thread_Num; 237 | for (u64 j = Th_Begin; j < Th_End; j++){ 238 | Re_point[j] = G * Re_point[j]; 239 | } 240 | return ; 241 | }); 242 | } 243 | 244 | for (auto& thrd : Y_alpha_beta) thrd.join(); 245 | 246 | std::shuffle(Re_point.begin(),Re_point.end(),Prng); 247 | coproto::sync_wait(Chl.send(Re_point)); 248 | 249 | setTimePoint("DH-Based RPMT Finish"); 250 | 251 | } 252 | else { 253 | 254 | setTimePoint("DH-Based RPMT Begin"); 255 | 256 | unsigned char point_bytes[32]; 257 | memset(point_bytes,0,32); 258 | 259 | for (u64 i = 0ull; i < Sender_Set_Size; i++){ 260 | unsigned char* block_bytes = Inputs_DH[i].data(); 261 | memcpy(point_bytes, block_bytes, 16); 262 | Se_point[i].fromBytes(point_bytes); 263 | Se_point[i] = G * Se_point[i]; 264 | } 265 | 266 | coproto::sync_wait(Chl.send(Se_point)); 267 | coproto::sync_wait(Chl.recv(Re_point)); 268 | 269 | for (u64 i = 0; i < Receiver_Set_Size; i++) 270 | Re_point[i] = G * Re_point[i]; 271 | 272 | std::shuffle(Re_point.begin(),Re_point.end(),Prng); 273 | coproto::sync_wait(Chl.send(Re_point)); 274 | } 275 | 276 | // OT Sender 277 | 278 | std::vector Rand_Num(Sender_Set_Size); 279 | Prng.get(Rand_Num); 280 | 281 | if(Sender_Set_Size <= 128) // using libOTe-CO15 282 | { 283 | // config basic messages 284 | osuCrypto::DefaultBaseOT baseOTs; 285 | PRNG prng(oc::block(oc::sysRandomSeed())); 286 | std::vector half_sendMsg(Sender_Set_Size); 287 | std::vector> randMsg(Sender_Set_Size); 288 | 289 | // generate random OT 290 | auto p = baseOTs.send(randMsg, prng, Chl); 291 | auto r = macoro::sync_wait(macoro::when_all_ready(std::move(p))); 292 | std::get<0>(r).result(); 293 | 294 | // random OT -> OT 295 | for(u64 i = 0; i < Sender_Set_Size; i++) 296 | { 297 | half_sendMsg[i] = Inputs[i] ^ randMsg[i][1]; 298 | } 299 | coproto::sync_wait(Chl.send(half_sendMsg)); 300 | } 301 | else // IKNP 302 | { 303 | // configure 304 | oc::DefaultBaseOT baseOTs; 305 | PRNG prng(oc::block(oc::sysRandomSeed())); 306 | std::vector half_sendMsg(Sender_Set_Size); 307 | std::vector> randMsg(Sender_Set_Size); 308 | 309 | // set base random messages 310 | std::vector baseRecv(128); // kappa == 128 311 | osuCrypto::BitVector baseChoice(128); // kappa == 128 312 | 313 | baseChoice.randomize(prng); 314 | 315 | // random OT (base) 316 | auto p = baseOTs.receive(baseChoice, baseRecv, prng, Chl); 317 | auto r = macoro::sync_wait(macoro::when_all_ready(std::move(p))); 318 | std::get<0>(r).result(); 319 | 320 | // execute extension 321 | osuCrypto::IknpOtExtSender sender; 322 | sender.setBaseOts(baseRecv, baseChoice); 323 | auto proto = sender.send(randMsg, prng, Chl); 324 | auto result = macoro::sync_wait(macoro::when_all_ready(std::move(proto))); 325 | std::get<0>(result).result(); 326 | 327 | // random OT -> OT 328 | for(u64 i = 0; i < Sender_Set_Size; i++) 329 | { 330 | half_sendMsg[i] = Inputs[i] ^ randMsg[i][1]; 331 | } 332 | coproto::sync_wait(Chl.send(half_sendMsg)); 333 | } 334 | 335 | } 336 | 337 | return ; 338 | 339 | } 340 | } --------------------------------------------------------------------------------