├── ABY_example └── dectree │ ├── CMakeLists.txt │ ├── common │ ├── garbledBP.h │ ├── auxiliary-functions.h │ ├── selection_blocks │ │ ├── selection_block.h │ │ ├── e_SelectionBlock.h │ │ ├── e_SelectionBlock.cpp │ │ ├── permutation_network.h │ │ ├── t_SelectionBlock.h │ │ ├── permutation_network.cpp │ │ └── t_SelectionBlock.cpp │ ├── crypto_party │ │ ├── crypto_party.h │ │ ├── paillier_party.h │ │ ├── dgk_party.h │ │ ├── paillier.cpp │ │ ├── paillier.h │ │ ├── dgk_party.cpp │ │ └── paillier_party.cpp │ ├── auxiliary-functions.cpp │ ├── sndrcv.h │ ├── sndrcv.cpp │ ├── decision-tree-circuit.h │ ├── dectree.h │ ├── selection-functions.cpp │ ├── dectree.cpp │ └── decision-tree-circuit.cpp │ ├── UCI_dectrees │ ├── iris │ ├── wine │ ├── breast │ └── linnerud │ └── decision_tree_test.cpp ├── LICENSE ├── UCI_dectrees ├── iris ├── wine ├── breast └── linnerud ├── README.md └── XCMP_files └── benchmark_gt ├── dectree.hpp └── hhh.cpp /ABY_example/dectree/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_executable(decision_tree_test decision_tree_test.cpp common/dectree.cpp common/decision-tree-circuit.cpp common/auxiliary-functions.cpp common/sndrcv.cpp common/selection-functions.cpp common/crypto_party/dgk_party.cpp common/crypto_party/paillier_party.cpp common/crypto_party/paillier.cpp common/selection_blocks/e_SelectionBlock.cpp common/selection_blocks/t_SelectionBlock.cpp common/selection_blocks/permutation_network.cpp) 3 | target_link_libraries(decision_tree_test ABY::aby ENCRYPTO_utils::encrypto_utils) 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 ENCRYPTO 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. -------------------------------------------------------------------------------- /ABY_example/dectree/common/garbledBP.h: -------------------------------------------------------------------------------- 1 | /** 2 | \file garbledBP.h 3 | \author masoud.naderpour@helsinki.fi 4 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 5 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | ABY is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Lesser General Public License for more details. 14 | You should have received a copy of the GNU Lesser General Public License 15 | along with this program. If not, see . 16 | \brief Garbled node 17 | */ 18 | 19 | #ifndef __Garbled_BP_H_ 20 | #define __Garbled_BP_H_ 21 | 22 | struct garbldNode{ 23 | uint8_t *rnode, *lnode; 24 | }; 25 | 26 | #endif /* __Garbled_BP_H_ */ 27 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/auxiliary-functions.h: -------------------------------------------------------------------------------- 1 | /** 2 | \file auxiliary-functions.h 3 | \author masoud.naderpour@helsinki.fi 4 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 5 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | ABY is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Lesser General Public License for more details. 14 | You should have received a copy of the GNU Lesser General Public License 15 | along with this program. If not, see . 16 | \brief Auxiliary functions 17 | */ 18 | 19 | #ifndef __AUX_FUNCTIONS_H_ 20 | #define __AUX_FUNCTIONS_H_ 21 | 22 | #include 23 | #include 24 | 25 | void print(uint8_t* s, int size); 26 | 27 | uint8_t* Xor(uint8_t* a, uint8_t* b, int size); 28 | 29 | double time_diff(struct timeval x , struct timeval y); 30 | 31 | double time_diff_microsec(struct timeval x , struct timeval y); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /UCI_dectrees/iris: -------------------------------------------------------------------------------- 1 | digraph Tree { 2 | node [shape=box] ; 3 | 0 [label="X[1] <= 2.45\ngini = 0.667\nsamples = 150\nvalue = [50, 50, 50]"] ; 4 | 1 [label="gini = 0.0\nsamples = 50\nvalue = [50, 0, 0]"] ; 5 | 0 -> 1 [labeldistance=2.5, labelangle=45, headlabel="True"] ; 6 | 2 [label="X[2] <= 1.75\ngini = 0.5\nsamples = 100\nvalue = [0, 50, 50]"] ; 7 | 0 -> 2 [labeldistance=2.5, labelangle=-45, headlabel="False"] ; 8 | 3 [label="X[1] <= 4.95\ngini = 0.168\nsamples = 54\nvalue = [0, 49, 5]"] ; 9 | 2 -> 3 ; 10 | 4 [label="X[2] <= 1.65\ngini = 0.041\nsamples = 48\nvalue = [0, 47, 1]"] ; 11 | 3 -> 4 ; 12 | 5 [label="gini = 0.0\nsamples = 47\nvalue = [0, 47, 0]"] ; 13 | 4 -> 5 ; 14 | 6 [label="gini = 0.0\nsamples = 1\nvalue = [0, 0, 1]"] ; 15 | 4 -> 6 ; 16 | 7 [label="X[2] <= 1.55\ngini = 0.444\nsamples = 6\nvalue = [0, 2, 4]"] ; 17 | 3 -> 7 ; 18 | 8 [label="gini = 0.0\nsamples = 3\nvalue = [0, 0, 3]"] ; 19 | 7 -> 8 ; 20 | 9 [label="X[1] <= 5.45\ngini = 0.444\nsamples = 3\nvalue = [0, 2, 1]"] ; 21 | 7 -> 9 ; 22 | 10 [label="gini = 0.0\nsamples = 2\nvalue = [0, 2, 0]"] ; 23 | 9 -> 10 ; 24 | 11 [label="gini = 0.0\nsamples = 1\nvalue = [0, 0, 1]"] ; 25 | 9 -> 11 ; 26 | 12 [label="X[1] <= 4.85\ngini = 0.043\nsamples = 46\nvalue = [0, 1, 45]"] ; 27 | 2 -> 12 ; 28 | 13 [label="X[0] <= 5.95\ngini = 0.444\nsamples = 3\nvalue = [0, 1, 2]"] ; 29 | 12 -> 13 ; 30 | 14 [label="gini = 0.0\nsamples = 1\nvalue = [0, 1, 0]"] ; 31 | 13 -> 14 ; 32 | 15 [label="gini = 0.0\nsamples = 2\nvalue = [0, 0, 2]"] ; 33 | 13 -> 15 ; 34 | 16 [label="gini = 0.0\nsamples = 43\nvalue = [0, 0, 43]"] ; 35 | 12 -> 16 ; 36 | } 37 | -------------------------------------------------------------------------------- /ABY_example/dectree/UCI_dectrees/iris: -------------------------------------------------------------------------------- 1 | digraph Tree { 2 | node [shape=box] ; 3 | 0 [label="X[1] <= 2.45\ngini = 0.667\nsamples = 150\nvalue = [50, 50, 50]"] ; 4 | 1 [label="gini = 0.0\nsamples = 50\nvalue = [50, 0, 0]"] ; 5 | 0 -> 1 [labeldistance=2.5, labelangle=45, headlabel="True"] ; 6 | 2 [label="X[2] <= 1.75\ngini = 0.5\nsamples = 100\nvalue = [0, 50, 50]"] ; 7 | 0 -> 2 [labeldistance=2.5, labelangle=-45, headlabel="False"] ; 8 | 3 [label="X[1] <= 4.95\ngini = 0.168\nsamples = 54\nvalue = [0, 49, 5]"] ; 9 | 2 -> 3 ; 10 | 4 [label="X[2] <= 1.65\ngini = 0.041\nsamples = 48\nvalue = [0, 47, 1]"] ; 11 | 3 -> 4 ; 12 | 5 [label="gini = 0.0\nsamples = 47\nvalue = [0, 47, 0]"] ; 13 | 4 -> 5 ; 14 | 6 [label="gini = 0.0\nsamples = 1\nvalue = [0, 0, 1]"] ; 15 | 4 -> 6 ; 16 | 7 [label="X[2] <= 1.55\ngini = 0.444\nsamples = 6\nvalue = [0, 2, 4]"] ; 17 | 3 -> 7 ; 18 | 8 [label="gini = 0.0\nsamples = 3\nvalue = [0, 0, 3]"] ; 19 | 7 -> 8 ; 20 | 9 [label="X[1] <= 5.45\ngini = 0.444\nsamples = 3\nvalue = [0, 2, 1]"] ; 21 | 7 -> 9 ; 22 | 10 [label="gini = 0.0\nsamples = 2\nvalue = [0, 2, 0]"] ; 23 | 9 -> 10 ; 24 | 11 [label="gini = 0.0\nsamples = 1\nvalue = [0, 0, 1]"] ; 25 | 9 -> 11 ; 26 | 12 [label="X[1] <= 4.85\ngini = 0.043\nsamples = 46\nvalue = [0, 1, 45]"] ; 27 | 2 -> 12 ; 28 | 13 [label="X[0] <= 5.95\ngini = 0.444\nsamples = 3\nvalue = [0, 1, 2]"] ; 29 | 12 -> 13 ; 30 | 14 [label="gini = 0.0\nsamples = 1\nvalue = [0, 1, 0]"] ; 31 | 13 -> 14 ; 32 | 15 [label="gini = 0.0\nsamples = 2\nvalue = [0, 0, 2]"] ; 33 | 13 -> 15 ; 34 | 16 [label="gini = 0.0\nsamples = 43\nvalue = [0, 0, 43]"] ; 35 | 12 -> 16 ; 36 | } 37 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/selection_blocks/selection_block.h: -------------------------------------------------------------------------------- 1 | /** 2 | \file SelectionBlock.h 3 | \author masoud.naderpour@helsinki.fi 4 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 5 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | ABY is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Lesser General Public License for more details. 14 | You should have received a copy of the GNU Lesser General Public License 15 | along with this program. If not, see . 16 | \brief Implementation of WaksmanPermutation and SelectionBlock 17 | */ 18 | 19 | #ifndef __ABY_SELECTIONBLOCK_H_ 20 | #define __ABY_SELECTIONBLOCK_H_ 21 | 22 | #include 23 | #include 24 | #include "stdio.h" 25 | #include 26 | #include "../../../../abycore/circuit/booleancircuits.h" 27 | 28 | class SelectionBlock { 29 | public: 30 | virtual void SelectionBlockProgram(uint32_t *p) = 0; 31 | virtual void SetControlBits() = 0; 32 | virtual std::vector > buildSelectionBlockCircuit(std::vector >& input) = 0; 33 | }; 34 | 35 | #endif /* __ABY_SELECTIONBLOCK_H_ */ 36 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/crypto_party/crypto_party.h: -------------------------------------------------------------------------------- 1 | /** 2 | \file crypto_party.h 3 | \author masoud.naderpour@helsinki.fi 4 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 5 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | ABY is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Lesser General Public License for more details. 14 | You should have received a copy of the GNU Lesser General Public License 15 | along with this program. If not, see . 16 | \brief Crypto functions 17 | */ 18 | 19 | #ifndef __CRYPTO_PARTY_H__ 20 | #define __CRYPTO_PARTY_H__ 21 | 22 | #include 23 | #include "../../../..//abycore/ABY_utils/ABYconstants.h" 24 | #include 25 | 26 | using namespace std; 27 | 28 | // Super class 29 | class cryptoParty { 30 | public: 31 | 32 | virtual void generateKey() = 0; 33 | 34 | virtual void keyExchange(channel* &chan) = 0; 35 | 36 | virtual bool readKey() = 0; 37 | 38 | virtual void storeKey() = 0; 39 | 40 | virtual bool encrypt(vector &plaintexts, BYTE* &ciphertextsBuf) = 0; 41 | 42 | virtual void encSndRcvVec(e_role role, vector &plaintexts, mpz_t* &ciphertexts, channel* &chan) = 0; 43 | 44 | virtual void mskSndRcvVec(e_role role, mpz_t* &CTs, mpz_t* &RndMsks, vector &Mapping, mpz_t* &inputs, channel* &chan) = 0; 45 | 46 | protected: 47 | 48 | //GMP PRNG 49 | gmp_randstate_t m_randstate; 50 | }; 51 | 52 | 53 | #endif //__CRYPTO_PARTY_H__ 54 | -------------------------------------------------------------------------------- /UCI_dectrees/wine: -------------------------------------------------------------------------------- 1 | digraph Tree { 2 | node [shape=box] ; 3 | 0 [label="X[6] <= 755.0\ngini = 0.658\nsamples = 178\nvalue = [59, 71, 48]"] ; 4 | 1 [label="X[5] <= 2.115\ngini = 0.492\nsamples = 111\nvalue = [2, 67, 42]"] ; 5 | 0 -> 1 [labeldistance=2.5, labelangle=45, headlabel="True"] ; 6 | 2 [label="X[4] <= 0.935\ngini = 0.227\nsamples = 46\nvalue = [0, 6, 40]"] ; 7 | 1 -> 2 ; 8 | 3 [label="X[2] <= 1.58\ngini = 0.049\nsamples = 40\nvalue = [0, 1, 39]"] ; 9 | 2 -> 3 ; 10 | 4 [label="gini = 0.0\nsamples = 39\nvalue = [0, 0, 39]"] ; 11 | 3 -> 4 ; 12 | 5 [label="gini = 0.0\nsamples = 1\nvalue = [0, 1, 0]"] ; 13 | 3 -> 5 ; 14 | 6 [label="X[1] <= 2.395\ngini = 0.278\nsamples = 6\nvalue = [0, 5, 1]"] ; 15 | 2 -> 6 ; 16 | 7 [label="gini = 0.0\nsamples = 5\nvalue = [0, 5, 0]"] ; 17 | 6 -> 7 ; 18 | 8 [label="gini = 0.0\nsamples = 1\nvalue = [0, 0, 1]"] ; 19 | 6 -> 8 ; 20 | 9 [label="X[2] <= 0.795\ngini = 0.117\nsamples = 65\nvalue = [2, 61, 2]"] ; 21 | 1 -> 9 ; 22 | 10 [label="gini = 0.0\nsamples = 2\nvalue = [0, 0, 2]"] ; 23 | 9 -> 10 ; 24 | 11 [label="X[0] <= 13.175\ngini = 0.061\nsamples = 63\nvalue = [2, 61, 0]"] ; 25 | 9 -> 11 ; 26 | 12 [label="gini = 0.0\nsamples = 58\nvalue = [0, 58, 0]"] ; 27 | 11 -> 12 ; 28 | 13 [label="X[0] <= 13.365\ngini = 0.48\nsamples = 5\nvalue = [2, 3, 0]"] ; 29 | 11 -> 13 ; 30 | 14 [label="gini = 0.0\nsamples = 2\nvalue = [2, 0, 0]"] ; 31 | 13 -> 14 ; 32 | 15 [label="gini = 0.0\nsamples = 3\nvalue = [0, 3, 0]"] ; 33 | 13 -> 15 ; 34 | 16 [label="X[2] <= 2.165\ngini = 0.265\nsamples = 67\nvalue = [57, 4, 6]"] ; 35 | 0 -> 16 [labeldistance=2.5, labelangle=-45, headlabel="False"] ; 36 | 17 [label="X[4] <= 0.803\ngini = 0.375\nsamples = 8\nvalue = [0, 2, 6]"] ; 37 | 16 -> 17 ; 38 | 18 [label="gini = 0.0\nsamples = 6\nvalue = [0, 0, 6]"] ; 39 | 17 -> 18 ; 40 | 19 [label="gini = 0.0\nsamples = 2\nvalue = [0, 2, 0]"] ; 41 | 17 -> 19 ; 42 | 20 [label="X[3] <= 3.435\ngini = 0.065\nsamples = 59\nvalue = [57, 2, 0]"] ; 43 | 16 -> 20 ; 44 | 21 [label="gini = 0.0\nsamples = 2\nvalue = [0, 2, 0]"] ; 45 | 20 -> 21 ; 46 | 22 [label="gini = 0.0\nsamples = 57\nvalue = [57, 0, 0]"] ; 47 | 20 -> 22 ; 48 | } 49 | -------------------------------------------------------------------------------- /ABY_example/dectree/UCI_dectrees/wine: -------------------------------------------------------------------------------- 1 | digraph Tree { 2 | node [shape=box] ; 3 | 0 [label="X[6] <= 755.0\ngini = 0.658\nsamples = 178\nvalue = [59, 71, 48]"] ; 4 | 1 [label="X[5] <= 2.115\ngini = 0.492\nsamples = 111\nvalue = [2, 67, 42]"] ; 5 | 0 -> 1 [labeldistance=2.5, labelangle=45, headlabel="True"] ; 6 | 2 [label="X[4] <= 0.935\ngini = 0.227\nsamples = 46\nvalue = [0, 6, 40]"] ; 7 | 1 -> 2 ; 8 | 3 [label="X[2] <= 1.58\ngini = 0.049\nsamples = 40\nvalue = [0, 1, 39]"] ; 9 | 2 -> 3 ; 10 | 4 [label="gini = 0.0\nsamples = 39\nvalue = [0, 0, 39]"] ; 11 | 3 -> 4 ; 12 | 5 [label="gini = 0.0\nsamples = 1\nvalue = [0, 1, 0]"] ; 13 | 3 -> 5 ; 14 | 6 [label="X[1] <= 2.395\ngini = 0.278\nsamples = 6\nvalue = [0, 5, 1]"] ; 15 | 2 -> 6 ; 16 | 7 [label="gini = 0.0\nsamples = 5\nvalue = [0, 5, 0]"] ; 17 | 6 -> 7 ; 18 | 8 [label="gini = 0.0\nsamples = 1\nvalue = [0, 0, 1]"] ; 19 | 6 -> 8 ; 20 | 9 [label="X[2] <= 0.795\ngini = 0.117\nsamples = 65\nvalue = [2, 61, 2]"] ; 21 | 1 -> 9 ; 22 | 10 [label="gini = 0.0\nsamples = 2\nvalue = [0, 0, 2]"] ; 23 | 9 -> 10 ; 24 | 11 [label="X[0] <= 13.175\ngini = 0.061\nsamples = 63\nvalue = [2, 61, 0]"] ; 25 | 9 -> 11 ; 26 | 12 [label="gini = 0.0\nsamples = 58\nvalue = [0, 58, 0]"] ; 27 | 11 -> 12 ; 28 | 13 [label="X[0] <= 13.365\ngini = 0.48\nsamples = 5\nvalue = [2, 3, 0]"] ; 29 | 11 -> 13 ; 30 | 14 [label="gini = 0.0\nsamples = 2\nvalue = [2, 0, 0]"] ; 31 | 13 -> 14 ; 32 | 15 [label="gini = 0.0\nsamples = 3\nvalue = [0, 3, 0]"] ; 33 | 13 -> 15 ; 34 | 16 [label="X[2] <= 2.165\ngini = 0.265\nsamples = 67\nvalue = [57, 4, 6]"] ; 35 | 0 -> 16 [labeldistance=2.5, labelangle=-45, headlabel="False"] ; 36 | 17 [label="X[4] <= 0.803\ngini = 0.375\nsamples = 8\nvalue = [0, 2, 6]"] ; 37 | 16 -> 17 ; 38 | 18 [label="gini = 0.0\nsamples = 6\nvalue = [0, 0, 6]"] ; 39 | 17 -> 18 ; 40 | 19 [label="gini = 0.0\nsamples = 2\nvalue = [0, 2, 0]"] ; 41 | 17 -> 19 ; 42 | 20 [label="X[3] <= 3.435\ngini = 0.065\nsamples = 59\nvalue = [57, 2, 0]"] ; 43 | 16 -> 20 ; 44 | 21 [label="gini = 0.0\nsamples = 2\nvalue = [0, 2, 0]"] ; 45 | 20 -> 21 ; 46 | 22 [label="gini = 0.0\nsamples = 57\nvalue = [57, 0, 0]"] ; 47 | 20 -> 22 ; 48 | } 49 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/auxiliary-functions.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | \file auxiliary-functions.cpp 3 | \author masoud.naderpour@helsinki.fi 4 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 5 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | ABY is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Lesser General Public License for more details. 14 | You should have received a copy of the GNU Lesser General Public License 15 | along with this program. If not, see . 16 | \brief Auxiliary functions 17 | */ 18 | 19 | #include 20 | #include 21 | #include "auxiliary-functions.h" 22 | 23 | void print(uint8_t* s, int size){ 24 | for(int i = 0; i < size; i++) 25 | std::cout<< std::hex << std::setw(2) << std::setfill('0') << int(s[i]); 26 | std::cout << std::endl; 27 | } 28 | 29 | uint8_t* Xor(uint8_t* a, uint8_t* b, int size){ 30 | for(int i = 0; i < size; i++) 31 | a[i] ^= b[i]; 32 | return a; 33 | } 34 | 35 | double time_diff(struct timeval x , struct timeval y){ 36 | double x_ms , y_ms , diff; 37 | 38 | x_ms = (double)x.tv_sec*1000 + (double)(x.tv_usec / 1000); 39 | y_ms = (double)y.tv_sec*1000 + (double)(y.tv_usec / 1000); 40 | 41 | diff = (double)y_ms - (double)x_ms; 42 | 43 | return diff; 44 | } 45 | 46 | double time_diff_microsec(struct timeval x , struct timeval y){ 47 | double x_ms , y_ms , diff; 48 | 49 | x_ms = (double)x.tv_sec*1000000 + (double)(x.tv_usec); 50 | y_ms = (double)y.tv_sec*1000000 + (double)(y.tv_usec); 51 | 52 | diff = (double)y_ms - (double)x_ms; 53 | 54 | return diff; 55 | } 56 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/sndrcv.h: -------------------------------------------------------------------------------- 1 | /** 2 | \file sndrcv.h 3 | \author masoud.naderpour@helsinki.fi 4 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 5 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | ABY is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Lesser General Public License for more details. 14 | You should have received a copy of the GNU Lesser General Public License 15 | along with this program. If not, see . 16 | \brief Send and receive garbled DT 17 | */ 18 | 19 | #ifndef __SNDRCV_H__ 20 | #define __SNDRCV_H__ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "auxiliary-functions.h" 29 | #include "../../../abycore/ABY_utils/ABYconstants.h" 30 | #include 31 | #include 32 | #include 33 | 34 | #define PROGRAM_MAIN_CHANNEL 0x01 35 | 36 | class NetConnection { 37 | public: 38 | BOOL EstConnection(e_role role); 39 | BOOL PartyConnect(); 40 | BOOL PartyListen(); 41 | NetConnection(const std::string addr, uint16_t port); 42 | 43 | channel* commChannel; 44 | 45 | private: 46 | std::string ipaddress; 47 | uint16_t port; 48 | std::unique_ptr m_pSocket; 49 | std::unique_ptr snd_thread; 50 | std::unique_ptr rcv_thread; 51 | std::unique_ptr commlock; 52 | }; 53 | 54 | 55 | BOOL sendGarbledDT(channel* chan, const int16_t &numNodes, const int16_t &nodeSize, uint8_t* serialized_garbledDT ); 56 | BOOL receiveGarbledDT(channel* chan, const int16_t &numNodes, const int16_t &nodeSize, uint8_t* rcvBuff); 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/crypto_party/paillier_party.h: -------------------------------------------------------------------------------- 1 | /** 2 | \file paillier_party.h 3 | \author masoud.naderpour@helsinki.fi 4 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 5 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | ABY is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Lesser General Public License for more details. 14 | You should have received a copy of the GNU Lesser General Public License 15 | along with this program. If not, see . 16 | \brief Paillier crypto 17 | */ 18 | 19 | 20 | #ifndef __Paillier_Party_H__ 21 | #define __Paillier_Party_H__ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "paillier.h" 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "crypto_party.h" 34 | 35 | using namespace std; 36 | 37 | class PaillierParty: public cryptoParty { 38 | public: 39 | PaillierParty(uint32_t PaillierBits, uint32_t readkey); 40 | ~PaillierParty(); 41 | 42 | void generateKey(); 43 | 44 | void keyExchange(channel* &chan); 45 | 46 | bool readKey(); 47 | 48 | void storeKey(); 49 | 50 | bool encrypt(vector &plaintexts, BYTE* &ciphertextsBuf); 51 | 52 | void encSndRcvVec(e_role role, vector &plaintexts, mpz_t* &ciphertexts, channel* &chan); 53 | 54 | void mskSndRcvVec(e_role role, mpz_t* &CTs, mpz_t* &RndMsks, vector &Mapping, mpz_t* &MaskedInputsVec, channel* &chan); 55 | 56 | private: 57 | uint32_t m_nPaillierBits; 58 | uint16_t m_nShareLength; 59 | uint32_t m_nBuflen; 60 | 61 | paillier_pubkey_t *m_localpub, *m_remotepub; 62 | paillier_prvkey_t *m_prv; 63 | 64 | void sendmpz_t(mpz_t t, channel* chan, BYTE * buf); 65 | void receivempz_t(mpz_t t, channel* chan, BYTE * buf); 66 | 67 | void sendmpz_t(mpz_t t, channel* chan); 68 | void receivempz_t(mpz_t t, channel* chan); 69 | 70 | void printBuf(BYTE* b, uint32_t l); 71 | }; 72 | 73 | #endif //__Paillier_Party_H__ 74 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/crypto_party/dgk_party.h: -------------------------------------------------------------------------------- 1 | /** 2 | \file dgk_party.h 3 | \author masoud.naderpour@helsinki.fi 4 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 5 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | ABY is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Lesser General Public License for more details. 14 | You should have received a copy of the GNU Lesser General Public License 15 | along with this program. If not, see . 16 | \brief DGK crypto 17 | */ 18 | 19 | 20 | #ifndef __DGK_PAR_H__ 21 | #define __DGK_PAR_H__ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "crypto_party.h" 32 | 33 | using namespace std; 34 | 35 | class DGK: public cryptoParty { 36 | public: 37 | DGK(uint32_t DGKbits, uint32_t sharelen, uint32_t readkey); 38 | DGK(uint32_t DGKbits, uint32_t sharelen, channel* chan, uint32_t readkey); 39 | ~DGK(); 40 | 41 | void generateKey(); 42 | 43 | void keyExchange(channel* &chan); 44 | 45 | bool readKey(); 46 | 47 | void storeKey(); 48 | 49 | bool encrypt(vector &plaintexts, BYTE* &ciphertextsBuf); 50 | 51 | void encSndRcvVec(e_role role, vector &plaintexts, mpz_t* &ciphertexts, channel* &chan); 52 | 53 | void mskSndRcvVec(e_role role, mpz_t* &CTs, mpz_t* &RndMsks, vector &Mapping, mpz_t* &inputs, channel* &chan); 54 | 55 | private: 56 | uint16_t m_nNumMTThreads; 57 | uint16_t m_nShareLength; 58 | uint32_t m_nDGKbits; 59 | uint32_t m_nBuflen; 60 | 61 | dgk_pubkey_t *m_localpub, *m_remotepub; 62 | dgk_prvkey_t *m_prv; 63 | 64 | void sendmpz_t(mpz_t t, channel* chan, BYTE * buf); 65 | void receivempz_t(mpz_t t, channel* chan, BYTE * buf); 66 | 67 | void sendmpz_t(mpz_t t, channel* chan); 68 | void receivempz_t(mpz_t t, channel* chan); 69 | 70 | void printBuf(BYTE* b, uint32_t l); 71 | 72 | }; 73 | 74 | #endif //__DGK_PAR_H__ 75 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/sndrcv.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | \file sndrcv.h 3 | \author masoud.naderpour@helsinki.fi 4 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 5 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | ABY is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Lesser General Public License for more details. 14 | You should have received a copy of the GNU Lesser General Public License 15 | along with this program. If not, see . 16 | \brief Send and receive garbled DT 17 | */ 18 | 19 | #include "sndrcv.h" 20 | 21 | BOOL NetConnection::EstConnection(e_role role) 22 | { 23 | BOOL success = true; 24 | if (role == SERVER) { 25 | m_pSocket = Listen(ipaddress, port); 26 | if (!m_pSocket) 27 | success = false; 28 | } else { //CLIENT 29 | m_pSocket = Connect(ipaddress, port); 30 | if (!m_pSocket) 31 | success = false; 32 | } 33 | if (!success) { 34 | std::cout << "connection failed!" << std::endl; 35 | return false; 36 | } 37 | 38 | commlock = std::make_unique(); 39 | snd_thread = std::make_unique(m_pSocket.get(), commlock.get()); 40 | rcv_thread = std::make_unique(m_pSocket.get(), commlock.get()); 41 | snd_thread->Start(); 42 | rcv_thread->Start(); 43 | 44 | commChannel = new channel(PROGRAM_MAIN_CHANNEL, rcv_thread.get(), snd_thread.get()); 45 | 46 | return success; 47 | } 48 | 49 | NetConnection::NetConnection(const std::string addr, uint16_t port) { 50 | NetConnection::port = port; 51 | NetConnection::ipaddress = addr; 52 | } 53 | 54 | BOOL sendGarbledDT(channel* chan, const int16_t &numNodes, const int16_t &nodeSize, uint8_t* serialized_garbledDT ) { 55 | chan->send(serialized_garbledDT, numNodes * nodeSize * 2); 56 | return TRUE; 57 | } 58 | 59 | BOOL receiveGarbledDT(channel* chan, const int16_t &numNodes, const int16_t &nodeSize, uint8_t* rcvBuff) { 60 | 61 | timeval tbegin, tend; 62 | 63 | gettimeofday(&tbegin, NULL); 64 | chan->blocking_receive(rcvBuff, numNodes * nodeSize * 2); 65 | gettimeofday(&tend, NULL); 66 | std::cout << " Garbled tree transfer time: " << time_diff_microsec(tbegin, tend) << "us" << std::endl; 67 | return TRUE; 68 | } 69 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/decision-tree-circuit.h: -------------------------------------------------------------------------------- 1 | /** 2 | \file decision-tree-circuit.h 3 | \author masoud.naderpour@helsinki.fi 4 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 5 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | ABY is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Lesser General Public License for more details. 14 | You should have received a copy of the GNU Lesser General Public License 15 | along with this program. If not, see . 16 | \brief Private decision tree evaluation 17 | */ 18 | 19 | #ifndef __DECISION_TREE_H_ 20 | #define __DECISION_TREE_H_ 21 | 22 | #include "../../../abycore/circuit/circuit.h" 23 | #include "../../../abycore/aby/abyparty.h" 24 | #include "../../../abycore/sharing/yaoserversharing.h" 25 | #include "selection_blocks/selection_block.h" 26 | #include "crypto_party/crypto_party.h" 27 | #include "crypto_party/dgk_party.h" 28 | #include "crypto_party/paillier_party.h" 29 | #include "dectree.h" 30 | 31 | #include 32 | #include 33 | 34 | #define RANDOM_TESTCASE 35 | #define MaskBitLen 104 36 | //#define BP_DEBUG 37 | 38 | enum e_sel_alg{ SEL_HE = 0, SEL_GC = 1}; 39 | enum e_eval_alg{ EVAL_HE = 0, EVAL_GC = 1}; 40 | enum e_HE_crypto_party { e_DGK = 0, e_PAILLIER = 1}; 41 | 42 | void selction_HE(e_role role, channel* channel, vector &featureVec, seclvl seclvl, uint64_t NumDecisionNodes, uint16_t* permutation, BooleanCircuit* &Circ, share** &CircOut); 43 | 44 | void selction_GC(vector &featureVec, uint64_t numDecisionNodes, uint16_t* permutation, BooleanCircuit* &Circ, share** &CircOut); 45 | 46 | int pri_eval_decision_tree(e_role role, char* address, uint16_t port, seclvl seclvl, uint32_t nthreads, e_mt_gen_alg mt_alg, e_sharing comparesharing, e_sel_alg sel_alg, uint64_t numNodes, uint64_t dimension, DecTree &tree); 47 | 48 | uint8_t* create_garbled_tree(DecTree &dectree, seclvl seclvl, uint8_t** pointerKey, uint8_t* binPermute, uint16_t* permute); 49 | 50 | int Eval_garbled_tree(uint8_t *glbp, uint8_t **keys, uint16_t d, uint32_t keysize, uint32_t msgsize, seclvl seclvl); 51 | 52 | //void verify(vector const &featureVec, BranchingProgram* BP); 53 | 54 | #endif /* __DECISION_TREE_H_ */ 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Private Decision Tree Evaluation (PDTE) Protocols 2 | 3 | By *Ágnes Kiss* ([ENCRYPTO](http://www.encrypto.de), TU Darmstadt), *Masoud Naderpour* (University of Helsinki), *Jian Liu* (University of California, Berkeley), *N. Asokan* (Aalto University) and *Thomas Schneider* ([ENCRYPTO](http://www.encrypto.de), TU Darmstadt) in [PoPETs'19(2)](https://petsymposium.org/2019/). Paper available [here](http://encrypto.de/papers/KNLAS19.pdf) 4 | 5 | ### Features 6 | --- 7 | 8 | Our implementation for private decision tree evaluation protocols includes the protocols HHH, HGH, GGH, GGG and HGG (it can also be used to benchmark the last and most inefficient protocol HHG). The implementation of (SelH+)CompH and PathH is based on the mcl library (https://github.com/herumi/mcl) that implements efficient lifted ElGamal encryption over elliptic curves, more specifically on the XCMP protocol implementation which implements the DGK comparison protocol (https://github.com/fionser/XCMP). The implementation of SelH, SelG, CompG and PathG are based on the ABY framework (https://github.com/encryptogroup/ABY) which provides an efficient implementation of Yao's garbled circuit protocol as well as of the Paillier homomorphic encryption scheme. 9 | 10 | This code is provided as a experimental implementation for testing purposes and should not be used in a productive environment. We cannot guarantee security and correctness. 11 | 12 | ### Requirements 13 | --- 14 | The requirements are the same as that of https://github.com/fionser/XCMP and https://github.com/encryptogroup/ABY. 15 | 16 | ### PDTE Implementation 17 | --- 18 | 19 | 1. Clone a copy of the main PDTE git repository by running: 20 | ``` 21 | git clone --recursive git://github.com/encryptogroup/PDTE 22 | ``` 23 | 2. Enter the UC directory: `cd PDTE` 24 | 25 | #### (SelH+)CompH and PathH Implementation 26 | 3. Clone/download the XCMP repository in the PDTE folder 27 | 4. Place/replace the files from XCMP_files into the respective location in the XCMP folder 28 | 5. Add the following lines at the enf of XCMP/benchmark_gt/CMakeLists.txt: 29 | ``` 30 | add_executable(hhh hhh.cpp) 31 | target_link_libraries(hhh boost_system pthread ${ECC_LIB}) 32 | ``` 33 | 6. Run the following commands: 34 | ``` 35 | cd benchmark_gt 36 | mkdir build & cd build 37 | cmake .. -DCMAKE_BUILD_TYPE=Release & make 38 | ``` 39 | 7. In two separate terminals, run ```./hhh 0``` and ```./hhh 1``` for the server and client applications. You can configure the DT and PROT variables in the beginning of the file benchmark_dt/hhh.cpp for running different protocol parts and decision trees. 40 | 41 | #### SelG, SelH, CompG and PathG Implementation 42 | 8. Clone/download the ABY repository 43 | 9. Place the dectree folder from ABY_example in ABY/src/examples and add the line 44 | ``` 45 | add_subdirectory(dectree) 46 | ``` 47 | in ABY/src/examples/CMakeLists.txt. 48 | 10. Add the following line in ABY/src/abycore/sharing/yaoserversharing.h in line 74: 49 | ``` 50 | CBitVector get_R(){ return m_vR;} 51 | ``` 52 | 11. Add the following lines in ABY/src/abycore/circuit/booleancircuits.h in line 474: 53 | ``` 54 | BYTE* GetEvaluatedKey(uint32_t gateid) { return m_vGates[gateid].gs.yval; }; 55 | BYTE* GetServerRandomKey(uint32_t gateid) {return m_vGates[gateid].gs.yinput.outKey; }; 56 | BYTE* GetPi(uint32_t gateid) {return m_vGates[gateid].gs.yinput.pi; }; 57 | ``` 58 | 12. Build ABY with the examples as indicated at https://github.com/encryptogroup/ABY. 59 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/selection_blocks/e_SelectionBlock.h: -------------------------------------------------------------------------------- 1 | /** 2 | \file e_SelectionBlock.h 3 | \author masoud.naderpour@helsinki.fi 4 | \author michael.zohner@ec-spride.de 5 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 6 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Lesser General Public License as published 9 | by the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | ABY is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | You should have received a copy of the GNU Lesser General Public License 16 | along with this program. If not, see . 17 | \brief Implementation of extended SelectionBlock 18 | */ 19 | #ifndef __ABY_E_SELECTIONBLOCK_H_ 20 | #define __ABY_E_SELECTIONBLOCK_H_ 21 | 22 | #include 23 | #include 24 | #include "stdio.h" 25 | #include 26 | #include "../../../../abycore/circuit/booleancircuits.h" 27 | #include "selection_block.h" 28 | #include "permutation_network.h" 29 | 30 | using namespace std; 31 | 32 | //TODO: Generate destructor methods 33 | 34 | class e_SelectionBlock : public SelectionBlock { 35 | //private: 36 | public: // TODO: Fix this! 37 | PermutationNetwork *m_Pblock1,*m_Pblock2; 38 | uint32_t m_nNumInputs, m_nNumOutputs; 39 | vector m_vYgatesProgram; 40 | vector m_vYGates; 41 | BooleanCircuit* m_cBoolCirc; 42 | //public: 43 | e_SelectionBlock (uint32_t numInputs, uint32_t numOutputs, BooleanCircuit* circ){ 44 | m_nNumInputs = numInputs; 45 | m_nNumOutputs = numOutputs; 46 | m_vYgatesProgram.resize(m_nNumOutputs-1); 47 | m_vYGates.resize(m_nNumOutputs-1); 48 | m_Pblock1 = new PermutationNetwork(numInputs, numOutputs, circ); // Extended PermutationNetwork(u,v) [v>u] 49 | m_Pblock2 = new PermutationNetwork(numOutputs, numOutputs, circ);// PermutationNetwork(v,v) 50 | m_cBoolCirc = circ; 51 | } 52 | 53 | void SelectionBlockProgram(uint32_t *p); 54 | uint32_t getYGateAt(uint32_t idx) { 55 | return m_vYGates[idx]; 56 | } 57 | void setYProgram(uint32_t idx, bool val) { 58 | m_vYgatesProgram[idx] = val; 59 | } 60 | void setYGates() { 61 | uint32_t val; 62 | for (uint32_t i = 0; i < m_nNumOutputs-1 ; i++){ 63 | val = (uint32_t) m_vYgatesProgram[i]; 64 | m_vYGates[i] = (m_cBoolCirc->PutSIMDINGate(1,val,1,SERVER))->get_wire_id(0); 65 | } 66 | } 67 | void SetControlBits(){ 68 | m_Pblock1->setPermutationGates(); 69 | setYGates(); 70 | m_Pblock2->setPermutationGates(); 71 | } 72 | vector > buildSelectionBlockCircuit(vector >& input); 73 | vector PutCondYGate(vector& a, vector& b, uint32_t s) { 74 | return {m_cBoolCirc->PutCombinerGate(m_cBoolCirc->PutMUXGate(m_cBoolCirc->PutSplitterGate(b[0]), m_cBoolCirc->PutSplitterGate(a[0]), s, true))}; 75 | //return m_cBoolCirc->PutCondYGate(a, b, s, true); 76 | //return m_cBoolCirc->PutMUXGate(b, a, s, true); 77 | } 78 | 79 | }; 80 | 81 | #endif /* __ABY_E_SELECTIONBLOCK_H_ */ 82 | -------------------------------------------------------------------------------- /UCI_dectrees/breast: -------------------------------------------------------------------------------- 1 | digraph Tree { 2 | node [shape=box] ; 3 | 0 [label="X[5] <= 16.795\ngini = 0.468\nsamples = 569\nvalue = [212, 357]"] ; 4 | 1 [label="X[10] <= 0.136\ngini = 0.159\nsamples = 379\nvalue = [33, 346]"] ; 5 | 0 -> 1 [labeldistance=2.5, labelangle=45, headlabel="True"] ; 6 | 2 [label="X[4] <= 0.009\ngini = 0.03\nsamples = 333\nvalue = [5, 328]"] ; 7 | 1 -> 2 ; 8 | 3 [label="gini = 0.0\nsamples = 1\nvalue = [1, 0]"] ; 9 | 2 -> 3 ; 10 | 4 [label="X[2] <= 38.605\ngini = 0.024\nsamples = 332\nvalue = [4, 328]"] ; 11 | 2 -> 4 ; 12 | 5 [label="X[3] <= 0.003\ngini = 0.012\nsamples = 319\nvalue = [2, 317]"] ; 13 | 4 -> 5 ; 14 | 6 [label="X[9] <= 0.195\ngini = 0.245\nsamples = 7\nvalue = [1, 6]"] ; 15 | 5 -> 6 ; 16 | 7 [label="gini = 0.0\nsamples = 6\nvalue = [0, 6]"] ; 17 | 6 -> 7 ; 18 | 8 [label="gini = 0.0\nsamples = 1\nvalue = [1, 0]"] ; 19 | 6 -> 8 ; 20 | 9 [label="X[6] <= 33.27\ngini = 0.006\nsamples = 312\nvalue = [1, 311]"] ; 21 | 5 -> 9 ; 22 | 10 [label="gini = 0.0\nsamples = 292\nvalue = [0, 292]"] ; 23 | 9 -> 10 ; 24 | 11 [label="X[6] <= 33.56\ngini = 0.095\nsamples = 20\nvalue = [1, 19]"] ; 25 | 9 -> 11 ; 26 | 12 [label="gini = 0.0\nsamples = 1\nvalue = [1, 0]"] ; 27 | 11 -> 12 ; 28 | 13 [label="gini = 0.0\nsamples = 19\nvalue = [0, 19]"] ; 29 | 11 -> 13 ; 30 | 14 [label="X[4] <= 0.016\ngini = 0.26\nsamples = 13\nvalue = [2, 11]"] ; 31 | 4 -> 14 ; 32 | 15 [label="gini = 0.0\nsamples = 1\nvalue = [1, 0]"] ; 33 | 14 -> 15 ; 34 | 16 [label="X[10] <= 0.117\ngini = 0.153\nsamples = 12\nvalue = [1, 11]"] ; 35 | 14 -> 16 ; 36 | 17 [label="gini = 0.0\nsamples = 11\nvalue = [0, 11]"] ; 37 | 16 -> 17 ; 38 | 18 [label="gini = 0.0\nsamples = 1\nvalue = [1, 0]"] ; 39 | 16 -> 18 ; 40 | 19 [label="X[6] <= 25.67\ngini = 0.476\nsamples = 46\nvalue = [28, 18]"] ; 41 | 1 -> 19 ; 42 | 20 [label="X[7] <= 810.3\ngini = 0.332\nsamples = 19\nvalue = [4, 15]"] ; 43 | 19 -> 20 ; 44 | 21 [label="X[8] <= 0.179\ngini = 0.124\nsamples = 15\nvalue = [1, 14]"] ; 45 | 20 -> 21 ; 46 | 22 [label="gini = 0.0\nsamples = 14\nvalue = [0, 14]"] ; 47 | 21 -> 22 ; 48 | 23 [label="gini = 0.0\nsamples = 1\nvalue = [1, 0]"] ; 49 | 21 -> 23 ; 50 | 24 [label="X[3] <= 0.005\ngini = 0.375\nsamples = 4\nvalue = [3, 1]"] ; 51 | 20 -> 24 ; 52 | 25 [label="gini = 0.0\nsamples = 1\nvalue = [0, 1]"] ; 53 | 24 -> 25 ; 54 | 26 [label="gini = 0.0\nsamples = 3\nvalue = [3, 0]"] ; 55 | 24 -> 26 ; 56 | 27 [label="X[1] <= 0.054\ngini = 0.198\nsamples = 27\nvalue = [24, 3]"] ; 57 | 19 -> 27 ; 58 | 28 [label="X[0] <= 20.455\ngini = 0.5\nsamples = 6\nvalue = [3, 3]"] ; 59 | 27 -> 28 ; 60 | 29 [label="gini = 0.0\nsamples = 3\nvalue = [0, 3]"] ; 61 | 28 -> 29 ; 62 | 30 [label="gini = 0.0\nsamples = 3\nvalue = [3, 0]"] ; 63 | 28 -> 30 ; 64 | 31 [label="gini = 0.0\nsamples = 21\nvalue = [21, 0]"] ; 65 | 27 -> 31 ; 66 | 32 [label="X[0] <= 16.11\ngini = 0.109\nsamples = 190\nvalue = [179, 11]"] ; 67 | 0 -> 32 [labeldistance=2.5, labelangle=-45, headlabel="False"] ; 68 | 33 [label="X[1] <= 0.066\ngini = 0.498\nsamples = 17\nvalue = [8, 9]"] ; 69 | 32 -> 33 ; 70 | 34 [label="gini = 0.0\nsamples = 9\nvalue = [0, 9]"] ; 71 | 33 -> 34 ; 72 | 35 [label="gini = 0.0\nsamples = 8\nvalue = [8, 0]"] ; 73 | 33 -> 35 ; 74 | 36 [label="X[8] <= 0.088\ngini = 0.023\nsamples = 173\nvalue = [171, 2]"] ; 75 | 32 -> 36 ; 76 | 37 [label="gini = 0.0\nsamples = 1\nvalue = [0, 1]"] ; 77 | 36 -> 37 ; 78 | 38 [label="X[9] <= 0.18\ngini = 0.012\nsamples = 172\nvalue = [171, 1]"] ; 79 | 36 -> 38 ; 80 | 39 [label="X[11] <= 0.242\ngini = 0.375\nsamples = 4\nvalue = [3, 1]"] ; 81 | 38 -> 39 ; 82 | 40 [label="gini = 0.0\nsamples = 1\nvalue = [0, 1]"] ; 83 | 39 -> 40 ; 84 | 41 [label="gini = 0.0\nsamples = 3\nvalue = [3, 0]"] ; 85 | 39 -> 41 ; 86 | 42 [label="gini = 0.0\nsamples = 168\nvalue = [168, 0]"] ; 87 | 38 -> 42 ; 88 | } 89 | -------------------------------------------------------------------------------- /ABY_example/dectree/UCI_dectrees/breast: -------------------------------------------------------------------------------- 1 | digraph Tree { 2 | node [shape=box] ; 3 | 0 [label="X[5] <= 16.795\ngini = 0.468\nsamples = 569\nvalue = [212, 357]"] ; 4 | 1 [label="X[10] <= 0.136\ngini = 0.159\nsamples = 379\nvalue = [33, 346]"] ; 5 | 0 -> 1 [labeldistance=2.5, labelangle=45, headlabel="True"] ; 6 | 2 [label="X[4] <= 0.009\ngini = 0.03\nsamples = 333\nvalue = [5, 328]"] ; 7 | 1 -> 2 ; 8 | 3 [label="gini = 0.0\nsamples = 1\nvalue = [1, 0]"] ; 9 | 2 -> 3 ; 10 | 4 [label="X[2] <= 38.605\ngini = 0.024\nsamples = 332\nvalue = [4, 328]"] ; 11 | 2 -> 4 ; 12 | 5 [label="X[3] <= 0.003\ngini = 0.012\nsamples = 319\nvalue = [2, 317]"] ; 13 | 4 -> 5 ; 14 | 6 [label="X[9] <= 0.195\ngini = 0.245\nsamples = 7\nvalue = [1, 6]"] ; 15 | 5 -> 6 ; 16 | 7 [label="gini = 0.0\nsamples = 6\nvalue = [0, 6]"] ; 17 | 6 -> 7 ; 18 | 8 [label="gini = 0.0\nsamples = 1\nvalue = [1, 0]"] ; 19 | 6 -> 8 ; 20 | 9 [label="X[6] <= 33.27\ngini = 0.006\nsamples = 312\nvalue = [1, 311]"] ; 21 | 5 -> 9 ; 22 | 10 [label="gini = 0.0\nsamples = 292\nvalue = [0, 292]"] ; 23 | 9 -> 10 ; 24 | 11 [label="X[6] <= 33.56\ngini = 0.095\nsamples = 20\nvalue = [1, 19]"] ; 25 | 9 -> 11 ; 26 | 12 [label="gini = 0.0\nsamples = 1\nvalue = [1, 0]"] ; 27 | 11 -> 12 ; 28 | 13 [label="gini = 0.0\nsamples = 19\nvalue = [0, 19]"] ; 29 | 11 -> 13 ; 30 | 14 [label="X[4] <= 0.016\ngini = 0.26\nsamples = 13\nvalue = [2, 11]"] ; 31 | 4 -> 14 ; 32 | 15 [label="gini = 0.0\nsamples = 1\nvalue = [1, 0]"] ; 33 | 14 -> 15 ; 34 | 16 [label="X[10] <= 0.117\ngini = 0.153\nsamples = 12\nvalue = [1, 11]"] ; 35 | 14 -> 16 ; 36 | 17 [label="gini = 0.0\nsamples = 11\nvalue = [0, 11]"] ; 37 | 16 -> 17 ; 38 | 18 [label="gini = 0.0\nsamples = 1\nvalue = [1, 0]"] ; 39 | 16 -> 18 ; 40 | 19 [label="X[6] <= 25.67\ngini = 0.476\nsamples = 46\nvalue = [28, 18]"] ; 41 | 1 -> 19 ; 42 | 20 [label="X[7] <= 810.3\ngini = 0.332\nsamples = 19\nvalue = [4, 15]"] ; 43 | 19 -> 20 ; 44 | 21 [label="X[8] <= 0.179\ngini = 0.124\nsamples = 15\nvalue = [1, 14]"] ; 45 | 20 -> 21 ; 46 | 22 [label="gini = 0.0\nsamples = 14\nvalue = [0, 14]"] ; 47 | 21 -> 22 ; 48 | 23 [label="gini = 0.0\nsamples = 1\nvalue = [1, 0]"] ; 49 | 21 -> 23 ; 50 | 24 [label="X[3] <= 0.005\ngini = 0.375\nsamples = 4\nvalue = [3, 1]"] ; 51 | 20 -> 24 ; 52 | 25 [label="gini = 0.0\nsamples = 1\nvalue = [0, 1]"] ; 53 | 24 -> 25 ; 54 | 26 [label="gini = 0.0\nsamples = 3\nvalue = [3, 0]"] ; 55 | 24 -> 26 ; 56 | 27 [label="X[1] <= 0.054\ngini = 0.198\nsamples = 27\nvalue = [24, 3]"] ; 57 | 19 -> 27 ; 58 | 28 [label="X[0] <= 20.455\ngini = 0.5\nsamples = 6\nvalue = [3, 3]"] ; 59 | 27 -> 28 ; 60 | 29 [label="gini = 0.0\nsamples = 3\nvalue = [0, 3]"] ; 61 | 28 -> 29 ; 62 | 30 [label="gini = 0.0\nsamples = 3\nvalue = [3, 0]"] ; 63 | 28 -> 30 ; 64 | 31 [label="gini = 0.0\nsamples = 21\nvalue = [21, 0]"] ; 65 | 27 -> 31 ; 66 | 32 [label="X[0] <= 16.11\ngini = 0.109\nsamples = 190\nvalue = [179, 11]"] ; 67 | 0 -> 32 [labeldistance=2.5, labelangle=-45, headlabel="False"] ; 68 | 33 [label="X[1] <= 0.066\ngini = 0.498\nsamples = 17\nvalue = [8, 9]"] ; 69 | 32 -> 33 ; 70 | 34 [label="gini = 0.0\nsamples = 9\nvalue = [0, 9]"] ; 71 | 33 -> 34 ; 72 | 35 [label="gini = 0.0\nsamples = 8\nvalue = [8, 0]"] ; 73 | 33 -> 35 ; 74 | 36 [label="X[8] <= 0.088\ngini = 0.023\nsamples = 173\nvalue = [171, 2]"] ; 75 | 32 -> 36 ; 76 | 37 [label="gini = 0.0\nsamples = 1\nvalue = [0, 1]"] ; 77 | 36 -> 37 ; 78 | 38 [label="X[9] <= 0.18\ngini = 0.012\nsamples = 172\nvalue = [171, 1]"] ; 79 | 36 -> 38 ; 80 | 39 [label="X[11] <= 0.242\ngini = 0.375\nsamples = 4\nvalue = [3, 1]"] ; 81 | 38 -> 39 ; 82 | 40 [label="gini = 0.0\nsamples = 1\nvalue = [0, 1]"] ; 83 | 39 -> 40 ; 84 | 41 [label="gini = 0.0\nsamples = 3\nvalue = [3, 0]"] ; 85 | 39 -> 41 ; 86 | 42 [label="gini = 0.0\nsamples = 168\nvalue = [168, 0]"] ; 87 | 38 -> 42 ; 88 | } 89 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/dectree.h: -------------------------------------------------------------------------------- 1 | /** 2 | \file dectree.cpp 3 | \author kiss@encrypto.cs.tu-darmstadt.de 4 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 5 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | ABY is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Lesser General Public License for more details. 14 | You should have received a copy of the GNU Lesser General Public License 15 | along with this program. If not, see . 16 | \brief Decision tree implementation 17 | */ 18 | 19 | #ifndef DECTREE_H_INCLUDED 20 | #define DECTREE_H_INCLUDED 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include /* pow */ 34 | 35 | using namespace std; 36 | 37 | class DecTree { 38 | public: 39 | struct Node { 40 | // Pointer to the first child node 41 | Node* left; 42 | // Pointer to the second child node 43 | Node* right; 44 | // Pointer to the first parent node 45 | Node* parent; 46 | // True if the edges coming into the node are already colored 47 | uint32_t level; 48 | // True if the node is a leaf 49 | bool leaf; 50 | // Threshold in decision node to compare with 51 | uint64_t threshold; 52 | // Threshold in decision node to compare with 53 | uint64_t classification; 54 | // Attribute index to compare with, -1 if undefined 55 | uint32_t attribute_index; 56 | 57 | Node(); 58 | Node(const Node&); 59 | }; 60 | // Vector of nodes that belong to the Gamma1 graph 61 | vector node_vec; 62 | // Vector of decision nodes that belong to the Gamma1 graph 63 | vector decnode_vec; 64 | //Node** node_array; 65 | // Vector of all attributes used for comparison with their occurrence 66 | vector attributes; 67 | // Vector of all thresholds used for comparison with their occurrence 68 | vector thresholds; 69 | 70 | //STATISTICS FOR DECISION TREES 71 | //number of attributes 72 | uint32_t num_attributes; 73 | //number of decision nodes 74 | uint32_t num_dec_nodes; 75 | //depth = largest level of leaves 76 | uint32_t depth; 77 | //number of leaves 78 | uint32_t num_of_leaves; 79 | //dummy in our case 80 | uint32_t dummy_non_full; 81 | 82 | DecTree(); 83 | DecTree(const DecTree&); 84 | 85 | void add_node(Node*); 86 | void add_decnode(Node*); 87 | void add_edge(Node*, Node*); 88 | void read_from_file(string); 89 | void evaluate(vector inputs); 90 | void depthPad(); 91 | void fullTree(uint32_t num_att, uint32_t depth); 92 | 93 | ~DecTree(); 94 | }; 95 | 96 | void tokenize(const std::string&, std::vector&); 97 | void eraseSubStr(std::string &, const std::string &); 98 | 99 | #endif // DECTREE_H_INCLUDED 100 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/selection_blocks/e_SelectionBlock.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | \file e_SelectionBlock.cpp 3 | \author masoud.naderpour@helsinki.fi 4 | \author michael.zohner@ec-spride.de 5 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 6 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Lesser General Public License as published 9 | by the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | ABY is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | You should have received a copy of the GNU Lesser General Public License 16 | along with this program. If not, see . 17 | \brief Implementation of extended SelectionBlock 18 | */ 19 | #include "e_SelectionBlock.h" 20 | #include "permutation_network.h" 21 | 22 | void e_SelectionBlock::SelectionBlockProgram(uint32_t *p){ 23 | uint32_t *prog1, *programm; 24 | 25 | if(m_nNumInputs==1) return; 26 | 27 | // count number of occurrences 28 | vector c; 29 | c.resize(m_nNumInputs); 30 | 31 | for(uint32_t i=0; i=0 && p[i] upos, dummy; 40 | upos.resize(m_nNumInputs); 41 | dummy.resize(m_nNumOutputs); // list of dummy outputs 42 | 43 | for(uint32_t i=0; i0) { 45 | prog1[i]=sum; 46 | upos[i]=sum; 47 | if(sum>0) { 48 | setYProgram(sum-1, true); 49 | //m_vYgatesProgram[sum-1] = true; 50 | } 51 | for(uint32_t j = sum+1; j < sum+c[i]; j++) { 52 | setYProgram(j-1, false); 53 | //m_vYgatesProgram[j-1] = false; 54 | dummy[ndummys++]=j; 55 | } 56 | sum+=c[i]; 57 | } 58 | } 59 | 60 | // program dummys 61 | uint32_t nextdummy=0; 62 | for(uint32_t i=0; iProgramPermutationNetwork(prog1); 68 | 69 | // program b2 70 | 71 | vector prog2; 72 | prog2.resize(m_nNumOutputs); 73 | for(uint32_t i=0; iProgramPermutationNetwork(programm); 83 | } 84 | 85 | vector > e_SelectionBlock::buildSelectionBlockCircuit(vector >& inputs){ 86 | uint32_t rep = inputs[0].size(); 87 | vector > out_p1,out_g, outputs; 88 | 89 | if(m_nNumInputs==1) { 90 | for(uint32_t i=0; ibuildPermutationCircuit(inputs); 99 | 100 | out_g.resize(m_nNumOutputs); 101 | out_g[0]=out_p1[0]; 102 | for(uint32_t i=1; ibuildPermutationCircuit(out_g); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /ABY_example/dectree/decision_tree_test.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | \file decision_tree_test.cpp 3 | \author masoud.naderpour@helsinki.fi 4 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 5 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | ABY is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Lesser General Public License for more details. 14 | You should have received a copy of the GNU Lesser General Public License 15 | along with this program. If not, see . 16 | \brief Private decision tree evaluation 17 | */ 18 | 19 | //Utility libs 20 | #include 21 | #include 22 | //ABY Party class 23 | #include "../../abycore/aby/abyparty.h" 24 | #include "common/decision-tree-circuit.h" 25 | #include "common/dectree.h" 26 | #include 27 | 28 | int32_t read_test_options(int32_t* argcp, char*** argvp, e_role* role, uint32_t* bitlen, string* filename, uint32_t* depth, uint32_t* dim, uint64_t* numNodes, uint32_t* secparam, string* address, uint16_t* port, int32_t* test_op) { 29 | 30 | uint32_t int_role = 0, int_port = 0; 31 | bool useffc = false; 32 | 33 | parsing_ctx options[] = { { (void*) &int_role, T_NUM, "r", "Role: 0/1", true, false }, 34 | { (void*) filename, T_STR, "f", "Input file, e.g. wine, boston, ... (provide either an input file or depth & dimension)", false, false }, 35 | { (void*) depth, T_NUM, "d", "Depth of tree, default: 4", false, false }, 36 | { (void*) dim, T_NUM, "n", "Dimension of feature vector, default: 8", false, false }, 37 | { (void*) numNodes, T_NUM, "m", "Number of Decision Nodes, default: 15", false, false }, 38 | { (void*) bitlen, T_NUM, "b", "Bit-length, default 32", false, false }, 39 | { (void*) secparam, T_NUM, "s", "Symmetric Security Bits, default: 128", false, false }, 40 | { (void*) address, T_STR, "a", "IP-address, default: localhost", false, false }, 41 | { (void*) &int_port, T_NUM, "p", "Port, default: 7766", false, false }, 42 | { (void*) test_op, T_NUM, "t", "Single test (leave out for all operations), default: off", false, false } }; 43 | 44 | if (!parse_options(argcp, argvp, options, sizeof(options) / sizeof(parsing_ctx))) { 45 | print_usage(*argvp[0], options, sizeof(options) / sizeof(parsing_ctx)); 46 | cout << "Exiting" << endl; 47 | exit(0); 48 | } 49 | 50 | assert(int_role < 2); 51 | *role = (e_role) int_role; 52 | 53 | if (int_port != 0) { 54 | assert(int_port < 1 << (sizeof(uint16_t) * 8)); 55 | *port = (uint16_t) int_port; 56 | } 57 | 58 | cout << endl; 59 | 60 | //delete options; 61 | 62 | return 1; 63 | } 64 | 65 | int main(int argc, char** argv) { 66 | 67 | e_role role; 68 | uint32_t bitlen, secparam = 128, nthreads = 1; 69 | seclvl seclvl = get_sec_lvl(secparam); 70 | uint16_t nodeSize, port = 7760; 71 | string address = "127.0.0.1"; 72 | int32_t test_op = -1; 73 | e_mt_gen_alg mt_alg = MT_OT; 74 | e_sel_alg sel_alg = SEL_GC; 75 | timeval tbegin, tend; 76 | 77 | //----Tree Params------ 78 | uint32_t featureVecDimension = 8, depth = 4; //defaults 79 | uint64_t numNodes = (1 << depth) - 1; // number of decision nodes 80 | string dectree_rootdir = "../../src/examples/dectree/UCI_dectrees/"; 81 | string dectree_filename = "wine"; 82 | 83 | read_test_options(&argc, &argv, &role, &bitlen, &dectree_filename, &depth, &featureVecDimension, &numNodes, &secparam, &address, &port, &test_op); 84 | 85 | DecTree tree; 86 | tree.read_from_file(dectree_rootdir + dectree_filename); 87 | tree.depthPad(); 88 | //tree.fullTree(featureVecDimension, depth); 89 | featureVecDimension = tree.num_attributes; numNodes = tree.num_dec_nodes; //Setting new values if reading from file 90 | 91 | cout << "Testing GGG & HGG protocols..." << endl; 92 | cout << "Number of decision nodes: " << numNodes << "\tFeature vector dimension: " << featureVecDimension << endl; 93 | cout << "\n----------------GGG Protocol----------------" << endl; 94 | 95 | /* ===GGG=== */ 96 | pri_eval_decision_tree(role, (char*) address.c_str(), port, seclvl, nthreads, mt_alg, S_YAO,sel_alg, numNodes, featureVecDimension, tree); 97 | 98 | cout << "\n----------------HGG Protocol----------------" << endl; 99 | 100 | /* ===HGG=== */ 101 | sel_alg = SEL_HE; 102 | pri_eval_decision_tree(role, (char*) address.c_str(), port, seclvl, nthreads, mt_alg, S_YAO, sel_alg, numNodes, featureVecDimension, tree); 103 | 104 | return 0; 105 | } 106 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/selection_blocks/permutation_network.h: -------------------------------------------------------------------------------- 1 | /** 2 | \file permutation_network.cpp 3 | \author masoud.naderpour@helsinki.fi 4 | \author michael.zohner@ec-spride.de 5 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 6 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Lesser General Public License as published 9 | by the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | ABY is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | You should have received a copy of the GNU Lesser General Public License 16 | along with this program. If not, see . 17 | \brief Implementation of WaksmanPermutation 18 | */ 19 | 20 | 21 | #ifndef __ABY_PN_H_ 22 | #define __ABY_PN_H_ 23 | 24 | #include "../../../../abycore/circuit/booleancircuits.h" 25 | 26 | //Some default output that is used if no output is written to 27 | static std::vector > NON_INIT_DEF_OUTPUT; 28 | 29 | uint32_t estimateGates(uint32_t u, uint32_t v); 30 | 31 | class PermutationNetwork { 32 | //double linked list; node n is head 33 | class TodoList { 34 | uint32_t* nextu; 35 | uint32_t* prevu; 36 | uint32_t n; 37 | 38 | public: 39 | void remove(uint32_t x) { 40 | nextu[prevu[x]] = nextu[x]; 41 | prevu[nextu[x]] = prevu[x]; 42 | } 43 | 44 | uint32_t next() { 45 | uint32_t ret = nextu[n]; 46 | if (ret == n) 47 | return -1; 48 | else 49 | return ret; 50 | } 51 | 52 | TodoList(uint32_t num) { 53 | n = num; 54 | nextu = (uint32_t*) malloc(sizeof(uint32_t) * (n + 1)); //new uint32_t[n+1]; 55 | prevu = (uint32_t*) malloc(sizeof(uint32_t) * (n + 1)); //new uint32_t[n+1]; 56 | for (uint32_t i = 0; i < n + 1; i++) { 57 | nextu[i] = (i + 1) % (n + 1); 58 | prevu[i] = (i + n) % (n + 1); 59 | } 60 | } 61 | }; 62 | 63 | class WaksmanPermutation { 64 | public: 65 | WaksmanPermutation* b1; 66 | WaksmanPermutation* b2; 67 | 68 | uint32_t m_nNumInputs; 69 | uint32_t m_nNumOutputs; 70 | uint32_t m_nSizeB2; 71 | 72 | WaksmanPermutation(uint32_t numgates, uint32_t numoutputs, PermutationNetwork* pm); 73 | virtual ~WaksmanPermutation(); 74 | //Program the permutation 75 | void program(uint32_t* perm); 76 | void program_rec(uint32_t in, uint32_t block, uint32_t* p1, uint32_t* p2, uint32_t* rows, uint32_t* cols); 77 | std::vector > generateCircuit(std::vector > inputs, std::vector > outputs); 78 | 79 | std::vector s1, s2; 80 | TodoList* Todo; 81 | PermutationNetwork* m_PM; 82 | }; 83 | 84 | public: 85 | PermutationNetwork(uint32_t numInputs, uint32_t numOutputs, BooleanCircuit* circ) { 86 | m_nNumIn = numInputs; 87 | m_nNumOut = numOutputs; 88 | gatebuildcounter = 0; 89 | m_cBoolCirc = circ; 90 | m_vSwitchGateProgram.resize(estimateGates(numInputs, numOutputs)); 91 | wm = new WaksmanPermutation(numInputs, numOutputs, this); 92 | } 93 | 94 | uint32_t nextGate() { 95 | return gatebuildcounter++; 96 | } 97 | uint32_t getSwapGateAt(uint32_t idx) { 98 | return m_vSwapGates[idx]; 99 | } 100 | void setSwitchProgram(uint32_t idx, bool val) { 101 | m_vSwitchGateProgram[idx] = val; 102 | } 103 | 104 | /*void setPermutationGates(std::vector& gates) { 105 | m_vSwapGates = gates; 106 | }*/ 107 | void setPermutationGates() { 108 | uint32_t val; 109 | m_vSwapGates.resize(m_vSwitchGateProgram.size()); 110 | for (uint32_t i = 0; i < m_vSwitchGateProgram.size(); i++) { 111 | val = (uint32_t) m_vSwitchGateProgram[i]; 112 | m_vSwapGates[i] = (m_cBoolCirc->PutSIMDINGate(1,val,1,SERVER))->get_wire_id(0); 113 | } 114 | } 115 | std::vector > buildPermutationCircuit(std::vector >& input) { 116 | return wm->generateCircuit(input, NON_INIT_DEF_OUTPUT); 117 | } 118 | std::vector > PutCondSwapGate(std::vector& a, std::vector& b, uint32_t s) { 119 | return m_cBoolCirc->PutCondSwapGate(a, b, s, true); 120 | } 121 | std::vector ProgramPermutationNetwork(uint32_t* permutation) { 122 | wm->program(permutation); 123 | return m_vSwitchGateProgram; 124 | } 125 | private: 126 | uint32_t gatebuildcounter; 127 | uint32_t m_nNumIn; 128 | uint32_t m_nNumOut; 129 | std::vector m_vSwitchGateProgram; //contains the actual program for the swapgates to achieve the output permutation 130 | std::vector m_vSwapGates; //contains the gate addresses of the swapgates 131 | WaksmanPermutation* wm; 132 | BooleanCircuit* m_cBoolCirc; 133 | 134 | }; 135 | 136 | #endif /* __ABY_PN_H_ */ 137 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/selection_blocks/t_SelectionBlock.h: -------------------------------------------------------------------------------- 1 | /** 2 | \file t_SelectionBlock.h 3 | \author masoud.naderpour@helsinki.fi 4 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 5 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | ABY is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Lesser General Public License for more details. 14 | You should have received a copy of the GNU Lesser General Public License 15 | along with this program. If not, see . 16 | \brief Implementation of truncated SelectionBlock 17 | */ 18 | #ifndef __ABY_T_SELECTIONBLOCK_H_ 19 | #define __ABY_T_SELECTIONBLOCK_H_ 20 | 21 | #include 22 | #include 23 | #include "stdio.h" 24 | #include 25 | #include "../../../../abycore/circuit/booleancircuits.h" 26 | #include "selection_block.h" 27 | #include "permutation_network.h" 28 | 29 | using namespace std; 30 | 31 | //TODO: Generate destructor methods 32 | 33 | class Truncated_PN{ 34 | //double linked list; node n is head 35 | class TodoList { 36 | uint32_t* nextu; 37 | uint32_t* prevu; 38 | uint32_t n; 39 | 40 | public: 41 | void remove(uint32_t x) { 42 | nextu[prevu[x]] = nextu[x]; 43 | prevu[nextu[x]] = prevu[x]; 44 | } 45 | 46 | uint32_t next() { 47 | uint32_t ret = nextu[n]; 48 | if (ret == n) 49 | return -1; 50 | else 51 | return ret; 52 | } 53 | 54 | TodoList(uint32_t num) { 55 | n = num; 56 | nextu = (uint32_t*) malloc(sizeof(uint32_t) * (n + 1)); //new uint32_t[n+1]; 57 | prevu = (uint32_t*) malloc(sizeof(uint32_t) * (n + 1)); //new uint32_t[n+1]; 58 | for (uint32_t i = 0; i < n + 1; i++) { 59 | nextu[i] = (i + 1) % (n + 1); 60 | prevu[i] = (i + n) % (n + 1); 61 | } 62 | } 63 | }; 64 | 65 | class WaksmanPermutation { 66 | public: 67 | WaksmanPermutation* b1; 68 | WaksmanPermutation* b2; 69 | 70 | uint32_t m_nNumInputs; 71 | uint32_t m_nNumOutputs; 72 | uint32_t m_nSizeB2; 73 | 74 | WaksmanPermutation(uint32_t numgates, uint32_t numoutputs, Truncated_PN* pm); 75 | virtual ~WaksmanPermutation(); 76 | //Program the permutation 77 | void program(uint32_t* perm); 78 | void program_rec(uint32_t out, uint32_t block, uint32_t* p1, uint32_t* p2, uint32_t* rows, uint32_t* cols); 79 | vector > generateCircuit(vector > inputs, vector > outputs); 80 | 81 | vector s1, s2; 82 | vector m_vYGates; 83 | vector m_vYgatesProgram; 84 | TodoList* Todo; 85 | Truncated_PN* m_PM; 86 | }; 87 | 88 | public: 89 | Truncated_PN(uint32_t numInputs, uint32_t numOutputs, BooleanCircuit* circ) { 90 | m_nNumIn = numInputs; 91 | m_nNumOut = numOutputs; 92 | gatebuildcounter = 0; 93 | m_cBoolCirc = circ; 94 | m_vSwitchGateProgram.resize(numInputs-1); 95 | m_vSwitchGateProgram.resize(estimateGates(numInputs, numOutputs)); 96 | wm = new WaksmanPermutation(numInputs, numOutputs, this); 97 | } 98 | 99 | uint32_t nextGate() { 100 | return gatebuildcounter++; 101 | } 102 | uint32_t getSwapGateAt(uint32_t idx) { 103 | return m_vSwapGates[idx]; 104 | } 105 | void setSwitchProgram(uint32_t idx, bool val) { 106 | m_vSwitchGateProgram[idx] = val; 107 | } 108 | 109 | /*void setPermutationGates(vector& gates) { 110 | m_vSwapGates = gates; 111 | }*/ 112 | void setPermutationGates() { 113 | uint32_t val; 114 | m_vSwapGates.resize(m_vSwitchGateProgram.size()); 115 | for (uint32_t i = 0; i < m_vSwitchGateProgram.size(); i++) { 116 | val = (uint32_t) m_vSwitchGateProgram[i]; 117 | m_vSwapGates[i] = (m_cBoolCirc->PutSIMDINGate(1,val,1,SERVER))->get_wire_id(0); 118 | } 119 | } 120 | vector > buildPermutationCircuit(vector >& input) { 121 | return wm->generateCircuit(input, NON_INIT_DEF_OUTPUT); 122 | } 123 | vector > PutCondSwapGate(vector& a, vector& b, uint32_t s) { 124 | return m_cBoolCirc->PutCondSwapGate(a, b, s, true); 125 | } 126 | vector PutCondYGate(vector& a, vector& b, uint32_t s) { 127 | //return m_cBoolCirc->PutCondYGate(a, b, s, true); 128 | return m_cBoolCirc->PutMUXGate(b, a, s); 129 | } 130 | vector ProgramPermutationNetwork(uint32_t* permutation) { 131 | wm->program(permutation); 132 | return m_vSwitchGateProgram; 133 | } 134 | private: 135 | uint32_t gatebuildcounter; 136 | uint32_t m_nNumIn; 137 | uint32_t m_nNumOut; 138 | vector m_vSwitchGateProgram; 139 | vector m_vSwapGates; //gate addresses of the swapgates 140 | WaksmanPermutation* wm; 141 | BooleanCircuit* m_cBoolCirc; 142 | 143 | }; 144 | 145 | class t_SelectionBlock : public SelectionBlock { 146 | //private: 147 | public: 148 | Truncated_PN *m_Pblock1; 149 | PermutationNetwork *m_Pblock2; 150 | uint32_t m_nNumInputs, m_nNumOutputs; 151 | vector m_vYgatesProgram; 152 | vector m_vYGates; 153 | BooleanCircuit* m_cBoolCirc; 154 | //public: 155 | t_SelectionBlock (uint32_t numInputs, uint32_t numOutputs, BooleanCircuit* circ){ 156 | m_nNumInputs = numInputs; 157 | m_nNumOutputs = numOutputs; 158 | m_vYgatesProgram.resize(m_nNumOutputs-1); 159 | m_vYGates.resize(m_nNumOutputs-1); 160 | m_Pblock1 = new Truncated_PN(numInputs, numOutputs, circ); // Truncated PermutationNetwork(u,v) [v>u] 161 | m_Pblock2 = new PermutationNetwork(numOutputs, numOutputs, circ);// PermutationNetwork(v,v) 162 | m_cBoolCirc = circ; 163 | } 164 | 165 | void SelectionBlockProgram(uint32_t *p); 166 | uint32_t getYGateAt(uint32_t idx) { 167 | return m_vYGates[idx]; 168 | } 169 | void setYProgram(uint32_t idx, bool val) { 170 | m_vYgatesProgram[idx] = val; 171 | } 172 | void setYGates() { 173 | uint32_t val; 174 | for (uint32_t i = 0; i < m_nNumOutputs-1 ; i++){ 175 | val = (uint32_t) m_vYgatesProgram[i]; 176 | m_vYGates[i] = (m_cBoolCirc->PutSIMDINGate(1,val,1,SERVER))->get_wire_id(0); 177 | } 178 | } 179 | void SetControlBits(){ 180 | m_Pblock1->setPermutationGates(); 181 | setYGates(); 182 | m_Pblock2->setPermutationGates(); 183 | } 184 | vector > buildSelectionBlockCircuit(vector >& input); 185 | vector PutCondYGate(vector& a, vector& b, uint32_t s) { 186 | //return m_cBoolCirc->PutCondYGate(a, b, s, true); 187 | return {m_cBoolCirc->PutCombinerGate(m_cBoolCirc->PutMUXGate(m_cBoolCirc->PutSplitterGate(b[0]), m_cBoolCirc->PutSplitterGate(a[0]), s, true))}; 188 | } 189 | 190 | }; 191 | #endif /* __ABY_T_SELECTIONBLOCK_H_ */ 192 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/selection_blocks/permutation_network.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | \file permutation_network.cpp 3 | \author masoud.naderpour@helsinki.fi 4 | \author michael.zohner@ec-spride.de 5 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 6 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Lesser General Public License as published 9 | by the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | ABY is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Lesser General Public License for more details. 15 | You should have received a copy of the GNU Lesser General Public License 16 | along with this program. If not, see . 17 | \brief Implementation of WaksmanPermutation 18 | */ 19 | 20 | #include "permutation_network.h" 21 | 22 | uint32_t estimateGates(uint32_t u, uint32_t v) { 23 | if (u == 1) 24 | return 0; 25 | else { 26 | uint32_t s1count = u/2; 27 | uint32_t s2count = (u % 2 == 0 && v % 2 == 0) ? v/2-1 : v/2; 28 | return (s1count + s2count) + estimateGates(u/2, v/2) + estimateGates(u-(u/2), v-(v/2)); 29 | } 30 | } 31 | 32 | PermutationNetwork::WaksmanPermutation::~WaksmanPermutation() { 33 | // TODO Auto-generated destructor stub 34 | } 35 | 36 | void PermutationNetwork::WaksmanPermutation::program_rec(uint32_t in, uint32_t block, uint32_t* p1, uint32_t* p2, uint32_t* rows, uint32_t* cols) { 37 | uint32_t out = rows[in]; 38 | 39 | if ((in ^ 1) < m_nNumInputs && rows[in ^ 1] != -1) { 40 | m_PM->setSwitchProgram(s1[in / 2], (block == 0) != (in % 2 == 0)); 41 | Todo->remove(in / 2); 42 | } 43 | 44 | if (block == 1) { 45 | p2[in / 2] = out / 2; 46 | if (out / 2 < m_nSizeB2) { 47 | m_PM->setSwitchProgram(s2[out / 2], out % 2 == 0); 48 | } 49 | } else { // block==0 50 | p1[in / 2] = out / 2; 51 | if (out / 2 < m_nSizeB2) { 52 | m_PM->setSwitchProgram(s2[out / 2], out % 2 == 1); 53 | } 54 | } 55 | rows[in] = -1; 56 | cols[out] = -1; 57 | 58 | uint32_t newout = out ^ 1; 59 | if (newout < m_nNumOutputs && cols[newout] != -1) { 60 | uint32_t newin = cols[newout]; 61 | cols[newout] = -1; 62 | program_rec(newin, block ^ 1, p1, p2, rows, cols); 63 | } 64 | 65 | if ((in ^ 1) < m_nNumInputs && rows[in ^ 1] != -1) { 66 | program_rec(in ^ 1, block ^ 1, p1, p2, rows, cols); 67 | } 68 | } 69 | 70 | void PermutationNetwork::WaksmanPermutation::program(uint32_t* perm) { 71 | if (m_nNumInputs == 1) 72 | return; 73 | 74 | uint32_t* rows = perm; 75 | 76 | uint32_t* cols = (uint32_t*) malloc(sizeof(uint32_t) * m_nNumOutputs); //new uint32_t[v]; 77 | for (uint32_t i = 0; i < m_nNumOutputs; i++) cols[i] = -1; 78 | for (uint32_t i = 0; i < m_nNumInputs; i++) { 79 | uint32_t x = perm[i]; 80 | assert(x>=0 && xnext(); n != -1; n = Todo->next()) { 101 | program_rec(2 * n, 0, p1, p2, rows, cols); 102 | } 103 | 104 | // program sub-blocks 105 | b1->program(p1); 106 | b2->program(p2); 107 | } 108 | 109 | PermutationNetwork::WaksmanPermutation::WaksmanPermutation(uint32_t numinputs, uint32_t numoutputs, PermutationNetwork* pm) { 110 | assert(numoutputs >= numinputs); 111 | m_nNumInputs = numinputs; 112 | m_nNumOutputs = numoutputs; 113 | m_PM = pm; 114 | 115 | if (numinputs != 1) { 116 | // first row X 117 | s1.resize(m_nNumInputs / 2); 118 | 119 | for (uint32_t i = 0; i < m_nNumInputs / 2; i++) 120 | s1[i] = pm->nextGate(); 121 | 122 | //assign wires to X gates and permute them 123 | 124 | // B1 125 | b1 = new WaksmanPermutation(numinputs / 2, numoutputs / 2, pm); 126 | 127 | // B2 128 | b2 = new WaksmanPermutation(numinputs - (numinputs / 2), numoutputs - (numoutputs / 2), pm); 129 | 130 | // last row X 131 | m_nSizeB2 = (numinputs % 2 == 0 && numoutputs % 2 ==0) ? numoutputs / 2 - 1 : numoutputs / 2; 132 | s2.resize(m_nSizeB2); 133 | for (uint32_t i = 0; i < m_nSizeB2; i++) 134 | s2[i] = pm->nextGate(); 135 | 136 | } 137 | 138 | } 139 | 140 | std::vector > PermutationNetwork::WaksmanPermutation::generateCircuit(std::vector > inputs, std::vector > outputs) { 141 | uint32_t rep = inputs[0].size(); 142 | if (outputs == NON_INIT_DEF_OUTPUT) { 143 | outputs.resize(m_nNumOutputs); 144 | for (uint32_t i = 0; i < m_nNumOutputs; i++) { 145 | outputs[i].resize(rep); 146 | } 147 | } 148 | // wire input to all outputs 149 | if (m_nNumInputs == 1) { 150 | for (uint32_t i = 0; i < m_nNumOutputs; i++){ 151 | for (uint32_t j = 0; j < rep; j++){ 152 | outputs[i][j] = inputs[0][j]; 153 | } 154 | } 155 | return outputs; 156 | } 157 | 158 | uint32_t sizeB2 = m_nNumInputs - (m_nNumInputs / 2); 159 | std::vector > in_p1(m_nNumInputs / 2); 160 | std::vector > in_p2(sizeB2); 161 | 162 | //uint64_t s = 1; 163 | //share *shr_s = m_PM->m_cBoolCirc->PutINGate(1, s, 1, SERVER); 164 | 165 | 166 | 167 | // first row X 168 | std::vector > outtmp(2); 169 | 170 | 171 | 172 | for (uint32_t i = 0; i < s1.size(); i++) { 173 | in_p1[i].resize(rep); 174 | in_p2[i].resize(rep); 175 | //in_p1[i] = inputs[2 * i + m_PM->m_vSwitchGateProgram[s1[i]]]; 176 | //in_p2[i] = inputs[2 * i + !(m_PM->m_vSwitchGateProgram[s1[i]])]; 177 | outtmp = m_PM->PutCondSwapGate(inputs[2 * i], inputs[2 * i + 1], m_PM->m_vSwapGates[s1[i]]); 178 | for (uint32_t j = 0; j < rep; j++) { 179 | in_p1[i][j] = outtmp[0][j]; 180 | in_p2[i][j] = outtmp[1][j]; 181 | } 182 | 183 | } 184 | 185 | if (m_nNumInputs % 2 == 1) { 186 | in_p2[sizeB2 - 1].resize(rep); 187 | for (uint32_t i = 0; i < rep; i++) 188 | in_p2[sizeB2 - 1][i] = inputs[m_nNumInputs - 1][i]; 189 | } 190 | 191 | std::vector > out_p1 = b1->generateCircuit(in_p1, NON_INIT_DEF_OUTPUT); 192 | std::vector > out_p2 = b2->generateCircuit(in_p2, NON_INIT_DEF_OUTPUT); 193 | 194 | // last row X 195 | for (uint32_t i = 0; i < s2.size(); i++) { 196 | 197 | outtmp = m_PM->PutCondSwapGate(out_p1[i], out_p2[i], m_PM->m_vSwapGates[s2[i]]); 198 | for (uint32_t j = 0; j < rep; j++) { 199 | outputs[2 * i][j] = outtmp[0][j]; 200 | outputs[2 * i + 1][j] = outtmp[1][j]; 201 | } 202 | 203 | 204 | } 205 | 206 | if(m_nNumOutputs % 2 == 1) { 207 | for (uint32_t i = 0; i < rep; i++){ 208 | outputs[m_nNumOutputs - 1][i] = out_p2[out_p2.size()-1][i]; 209 | } 210 | } else if (m_nNumInputs % 2 == 0){ 211 | for (uint32_t i = 0; i < rep; i++){ 212 | 213 | outputs[m_nNumOutputs - 1][i] = out_p2[out_p2.size()-1][i]; 214 | outputs[m_nNumOutputs - 2][i] = out_p1[out_p1.size()-1][i]; 215 | } 216 | } 217 | 218 | return outputs; 219 | } 220 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/selection-functions.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | \file selection-functions.cpp 3 | \author masoud.naderpour@helsinki.fi 4 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 5 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | ABY is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Lesser General Public License for more details. 14 | You should have received a copy of the GNU Lesser General Public License 15 | along with this program. If not, see . 16 | \brief Selection with HE or GC 17 | */ 18 | 19 | #include "decision-tree-circuit.h" 20 | #include "selection_blocks/e_SelectionBlock.h" 21 | #include "selection_blocks/t_SelectionBlock.h" 22 | 23 | #define HE_SCHEME 1 //enum e_HE_crypto_party { e_DGK = 0, e_PAILLIER = 1}; 24 | 25 | /** 26 | * Selection function (homomorphic encryption) 27 | */ 28 | void selction_HE(e_role role, channel* channel, vector &featureVec, seclvl seclvl, uint64_t numDecisionNodes, uint16_t* permutation, BooleanCircuit* &Circ, share** &CircOut){ 29 | 30 | struct timespec start, end, clientOnline; 31 | uint32_t dimension = featureVec.size(); 32 | uint32_t m_nStatisticalParamBits = 40; // statistical param 33 | uint32_t m_nFeatureSize = 64; // param t 34 | uint32_t m_nPlaintextSize = m_nFeatureSize + m_nStatisticalParamBits; 35 | 36 | /* Initilization */ 37 | cryptoParty* cryptoPraty; 38 | 39 | switch(HE_SCHEME) { 40 | case e_DGK: { 41 | cryptoPraty = new DGK(seclvl.ifcbits, (uint32_t) m_nPlaintextSize, 1); // ifcbits = 3072 bits for LT security 42 | } 43 | break; 44 | 45 | case e_PAILLIER: 46 | default: { 47 | cryptoPraty = new PaillierParty(2048, 1); // ifcbits = 3072 bits for LT security 48 | } 49 | break; 50 | } 51 | cryptoPraty->keyExchange(channel); 52 | 53 | gmp_randstate_t m_randstate; 54 | gmp_randinit_default(m_randstate); 55 | gmp_randseed_ui(m_randstate, rand()); 56 | 57 | mpz_t *m_pRandomdMasks = (mpz_t*) calloc(numDecisionNodes, sizeof(mpz_t)); // random masks vector 58 | vector m_nRandomMasksVec; 59 | vector m_vSelection; // feature selection function (mapping) 60 | 61 | uint64_t lo, hi; 62 | mpz_t tmp; 63 | mpz_init( tmp ); 64 | 65 | for(int i=0; i < numDecisionNodes; i++){ 66 | mpz_init(m_pRandomdMasks[i]); 67 | mpz_urandomb (m_pRandomdMasks[i], m_randstate, MaskBitLen); // MaskBitLen 104 68 | m_vSelection.push_back(rand() % dimension); // dummy selection function 69 | 70 | //truncating random masks to sizeof uint64_t 71 | mpz_mod_2exp( tmp, m_pRandomdMasks[i], 64 ); /* tmp = (lower 64 bits of m_pRandomdMasks[i]) */ 72 | lo = mpz_get_ui( tmp ); /* lo = tmp & 0xffffffff */ 73 | mpz_div_2exp( tmp, tmp, 32 ); /* tmp >>= 32 */ 74 | hi = mpz_get_ui( tmp ); /* hi = tmp & 0xffffffff */ 75 | m_nRandomMasksVec.push_back((hi << 32) + lo); 76 | } 77 | 78 | mpz_t *m_pEncFeatureVec, *m_pBlindedFeatureVec; 79 | 80 | //--------client encrypts the feature vec and sends it to server---------- 81 | clock_gettime(CLOCK_MONOTONIC, &start); 82 | cryptoPraty->encSndRcvVec(role, featureVec, m_pEncFeatureVec, channel); 83 | 84 | //--------server selects & sends the inputs to subtraction circuit---------- 85 | cryptoPraty->mskSndRcvVec(role, m_pEncFeatureVec, m_pRandomdMasks, m_vSelection, m_pBlindedFeatureVec, channel); // decrypts the inputs internally 86 | clock_gettime(CLOCK_MONOTONIC, &end); 87 | printf("client online runtime: %.0lf ms \n", getMillies(start, end)); 88 | 89 | vector m_vTruncBlindedFeatureVec(numDecisionNodes, 0); 90 | // Truncating client inputs to garbled circuit 91 | if(role == CLIENT){ 92 | for(int i= 0; i < numDecisionNodes; i++){ 93 | mpz_mod_2exp( tmp, m_pBlindedFeatureVec[i], 64 ); /* tmp = (lower 64 bits of m_pBlindedFeatureVec[i]) */ 94 | lo = mpz_get_ui( tmp ); 95 | mpz_div_2exp( tmp, tmp, 32 ); 96 | hi = mpz_get_ui( tmp ); 97 | m_vTruncBlindedFeatureVec[i] = (hi << 32) + lo; 98 | } 99 | cout << "CLIENT: Input truncation done." << endl; 100 | } else { 101 | //SleepMiliSec(10); 102 | } 103 | mpz_clear( tmp ); 104 | 105 | 106 | uint64_t maxbitlen = 64; 107 | vector tresholdVec; 108 | share **tresholdShr, **featureVecShr, **rndMasksVecShr; 109 | 110 | //----------------Settign server input ---------------- 111 | tresholdShr = (share**) malloc(sizeof(share*) * numDecisionNodes); 112 | for(int i = 0; i < numDecisionNodes; i++) { 113 | tresholdVec.push_back(rand()); 114 | tresholdShr[permutation[i]] = Circ->PutSIMDINGate(1, tresholdVec[i], maxbitlen, SERVER); 115 | } 116 | rndMasksVecShr = (share**) malloc(sizeof(share*) * numDecisionNodes); 117 | for(int i = 0; i < numDecisionNodes; i++) { 118 | rndMasksVecShr[i] = Circ->PutSIMDINGate(1, m_nRandomMasksVec[i], maxbitlen, SERVER); 119 | } 120 | //----------------Setting client input------------- 121 | featureVecShr = (share**) malloc(sizeof(share*) * numDecisionNodes); 122 | for(int i = 0; i < numDecisionNodes; i++) { 123 | featureVecShr[i] = Circ->PutSIMDINGate(1, m_vTruncBlindedFeatureVec[i], maxbitlen, CLIENT); 124 | } 125 | //----------------Subtraction & comparison ciruit-------------- 126 | CircOut = (share**) malloc(sizeof(share*) * numDecisionNodes); 127 | assert(Circ->GetCircuitType() == C_BOOLEAN); 128 | 129 | for(int i = 0; i < numDecisionNodes; i++) { 130 | CircOut[i] = Circ->PutSUBGate(featureVecShr[i], rndMasksVecShr[i]); 131 | CircOut[i] = Circ->PutGTGate(CircOut[i], tresholdShr[i]); 132 | } 133 | } 134 | 135 | /** 136 | * Selection function (garbled circuit) 137 | */ 138 | void selction_GC(vector &featureVec, uint64_t numDecisionNodes, uint16_t* permutation, BooleanCircuit* &Circ, share** &CircOut) { 139 | 140 | uint16_t dim = featureVec.size(); 141 | uint16_t m_numNodes = numDecisionNodes; 142 | uint64_t maxbitlen = 64; 143 | 144 | //---- init selectionBlcok --------------- 145 | SelectionBlock *selBlock; 146 | if (m_numNodes >= dim){ 147 | selBlock = new e_SelectionBlock(dim, m_numNodes, Circ); // extended SelectionBlock 148 | } else { 149 | selBlock = new t_SelectionBlock(dim, m_numNodes, Circ); // truncated SelectionBlock 150 | } 151 | 152 | //-----------Output Program (Mapping) of Selection Block -------------- 153 | uint32_t *m_nMapping = (uint32_t*) malloc(sizeof(uint32_t) * m_numNodes); 154 | for(int i = 0; i < m_numNodes; i++){ 155 | m_nMapping[permutation[i]] = rand() % dim; 156 | } 157 | selBlock->SelectionBlockProgram(m_nMapping); 158 | selBlock->SetControlBits(); 159 | 160 | vector tresholdVec; 161 | share **tresholdShr, **featureVecShr; 162 | 163 | //----------------Settign server input ---------------- 164 | tresholdShr = (share**) malloc(sizeof(share*) * m_numNodes); 165 | for(int i = 0; i < m_numNodes; i++) { 166 | tresholdVec.push_back(rand()); 167 | tresholdShr[permutation[i]] = Circ->PutSIMDINGate(1, tresholdVec[i], maxbitlen, SERVER); 168 | } 169 | 170 | //----------------Setting client input------------- 171 | featureVecShr = (share**) malloc(sizeof(share*) * dim); 172 | for(int j = 0; j < dim; j++) { 173 | featureVecShr[j] = Circ->PutSIMDINGate(1, featureVec[j], maxbitlen, CLIENT); 174 | } 175 | 176 | //---------------Building selection circuit-------------- 177 | share **out, *cmp, *tmp; 178 | 179 | CircOut = (share**) malloc(sizeof(share*) * m_numNodes); 180 | assert(Circ->GetCircuitType() == C_BOOLEAN); 181 | 182 | vector > Inputs(dim); 183 | for(int i = 0; i < dim; i++){ 184 | Inputs[i].resize(1); 185 | Inputs[i][0] = Circ->PutCombinerGate(featureVecShr[i]->get_wires()); 186 | } 187 | 188 | vector > tempvec(m_numNodes); 189 | tempvec = selBlock->buildSelectionBlockCircuit(Inputs); 190 | 191 | share **SelectionBlockOutput = (share**) malloc(sizeof(share*) * m_numNodes); 192 | for (int i = 0; i < tempvec.size(); i++){ 193 | SelectionBlockOutput[i] = new boolshare(Circ->PutSplitterGate(tempvec[i][0]), Circ); 194 | } 195 | 196 | for (int i=0; i < m_numNodes; i++) { 197 | CircOut[i] = Circ->PutGTGate(SelectionBlockOutput[i], tresholdShr[i]); 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /UCI_dectrees/linnerud: -------------------------------------------------------------------------------- 1 | digraph Tree { 2 | node [shape=box] ; 3 | 0 [label="X[1] <= 103.0\ngini = 0.895\nsamples = 20\nvalue = [[1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 1, 1]\n[1, 1, 4, 3, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0]\n[2, 3, 3, 2, 3, 1, 1, 2, 1, 1, 1, 0, 0, 0, 0, 0]]"] ; 4 | 1 [label="X[1] <= 65.0\ngini = 0.759\nsamples = 6\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 2, 0, 1, 1]\n[0, 0, 0, 0, 0, 2, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0]\n[1, 1, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 5 | 0 -> 1 [labeldistance=2.5, labelangle=45, headlabel="True"] ; 6 | 2 [label="X[0] <= 2.5\ngini = 0.5\nsamples = 2\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1]\n[0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 7 | 1 -> 2 ; 8 | 3 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]\n[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 9 | 2 -> 3 ; 10 | 4 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 11 | 2 -> 4 ; 12 | 5 [label="X[0] <= 7.0\ngini = 0.583\nsamples = 4\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 1, 0]\n[0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]\n[1, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 13 | 1 -> 5 ; 14 | 6 [label="X[0] <= 5.0\ngini = 0.333\nsamples = 2\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0]\n[0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 15 | 5 -> 6 ; 16 | 7 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 17 | 6 -> 7 ; 18 | 8 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]\n[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 19 | 6 -> 8 ; 20 | 9 [label="X[2] <= 69.5\ngini = 0.333\nsamples = 2\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0]\n[0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 21 | 5 -> 9 ; 22 | 10 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0]\n[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 23 | 9 -> 10 ; 24 | 11 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]\n[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 25 | 9 -> 11 ; 26 | 12 [label="X[0] <= 13.5\ngini = 0.867\nsamples = 14\nvalue = [[1, 2, 1, 1, 1, 1, 1, 1, 1, 0, 2, 1, 0, 1, 0, 0]\n[1, 1, 4, 3, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[1, 2, 3, 1, 1, 0, 1, 2, 1, 1, 1, 0, 0, 0, 0, 0]]"] ; 27 | 0 -> 12 [labeldistance=2.5, labelangle=-45, headlabel="False"] ; 28 | 13 [label="X[2] <= 59.0\ngini = 0.823\nsamples = 9\nvalue = [[1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 2, 1, 0, 1, 0, 0]\n[0, 1, 2, 1, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[1, 1, 3, 0, 0, 0, 1, 2, 0, 1, 0, 0, 0, 0, 0, 0]]"] ; 29 | 12 -> 13 ; 30 | 14 [label="X[0] <= 9.0\ngini = 0.708\nsamples = 4\nvalue = [[1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0]\n[0, 0, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0]]"] ; 31 | 13 -> 14 ; 32 | 15 [label="X[1] <= 117.5\ngini = 0.5\nsamples = 2\nvalue = [[1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0]]"] ; 33 | 14 -> 15 ; 34 | 16 [label="gini = 0.0\nsamples = 1\nvalue = [[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]]"] ; 35 | 15 -> 16 ; 36 | 17 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 37 | 15 -> 17 ; 38 | 18 [label="X[0] <= 12.5\ngini = 0.333\nsamples = 2\nvalue = [[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 39 | 14 -> 18 ; 40 | 19 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 41 | 18 -> 19 ; 42 | 20 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 43 | 18 -> 20 ; 44 | 21 [label="X[2] <= 117.5\ngini = 0.693\nsamples = 5\nvalue = [[0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0]\n[0, 1, 1, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 45 | 13 -> 21 ; 46 | 22 [label="X[2] <= 70.0\ngini = 0.625\nsamples = 4\nvalue = [[0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0]\n[0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 47 | 21 -> 22 ; 48 | 23 [label="X[1] <= 136.0\ngini = 0.5\nsamples = 2\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 49 | 22 -> 23 ; 50 | 24 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 51 | 23 -> 24 ; 52 | 25 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 53 | 23 -> 25 ; 54 | 26 [label="X[1] <= 220.0\ngini = 0.333\nsamples = 2\nvalue = [[0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 55 | 22 -> 26 ; 56 | 27 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 57 | 26 -> 27 ; 58 | 28 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 59 | 26 -> 28 ; 60 | 29 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0]\n[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 61 | 21 -> 29 ; 62 | 30 [label="X[1] <= 220.0\ngini = 0.72\nsamples = 5\nvalue = [[0, 2, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0]\n[1, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0]]"] ; 63 | 12 -> 30 ; 64 | 31 [label="X[0] <= 14.5\ngini = 0.593\nsamples = 3\nvalue = [[0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0]\n[1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0]]"] ; 65 | 30 -> 31 ; 66 | 32 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]]"] ; 67 | 31 -> 32 ; 68 | 33 [label="X[2] <= 39.0\ngini = 0.5\nsamples = 2\nvalue = [[0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0]\n[1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]]"] ; 69 | 31 -> 33 ; 70 | 34 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 71 | 33 -> 34 ; 72 | 35 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]\n[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]]"] ; 73 | 33 -> 35 ; 74 | 36 [label="X[2] <= 161.5\ngini = 0.333\nsamples = 2\nvalue = [[0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 75 | 30 -> 36 ; 76 | 37 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 77 | 36 -> 37 ; 78 | 38 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 79 | 36 -> 38 ; 80 | } 81 | -------------------------------------------------------------------------------- /ABY_example/dectree/UCI_dectrees/linnerud: -------------------------------------------------------------------------------- 1 | digraph Tree { 2 | node [shape=box] ; 3 | 0 [label="X[1] <= 103.0\ngini = 0.895\nsamples = 20\nvalue = [[1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 1, 1]\n[1, 1, 4, 3, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0]\n[2, 3, 3, 2, 3, 1, 1, 2, 1, 1, 1, 0, 0, 0, 0, 0]]"] ; 4 | 1 [label="X[1] <= 65.0\ngini = 0.759\nsamples = 6\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 2, 0, 1, 1]\n[0, 0, 0, 0, 0, 2, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0]\n[1, 1, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 5 | 0 -> 1 [labeldistance=2.5, labelangle=45, headlabel="True"] ; 6 | 2 [label="X[0] <= 2.5\ngini = 0.5\nsamples = 2\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1]\n[0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 7 | 1 -> 2 ; 8 | 3 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]\n[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 9 | 2 -> 3 ; 10 | 4 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 11 | 2 -> 4 ; 12 | 5 [label="X[0] <= 7.0\ngini = 0.583\nsamples = 4\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 1, 0]\n[0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]\n[1, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 13 | 1 -> 5 ; 14 | 6 [label="X[0] <= 5.0\ngini = 0.333\nsamples = 2\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0]\n[0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 15 | 5 -> 6 ; 16 | 7 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 17 | 6 -> 7 ; 18 | 8 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]\n[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 19 | 6 -> 8 ; 20 | 9 [label="X[2] <= 69.5\ngini = 0.333\nsamples = 2\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0]\n[0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 21 | 5 -> 9 ; 22 | 10 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0]\n[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 23 | 9 -> 10 ; 24 | 11 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]\n[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 25 | 9 -> 11 ; 26 | 12 [label="X[0] <= 13.5\ngini = 0.867\nsamples = 14\nvalue = [[1, 2, 1, 1, 1, 1, 1, 1, 1, 0, 2, 1, 0, 1, 0, 0]\n[1, 1, 4, 3, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[1, 2, 3, 1, 1, 0, 1, 2, 1, 1, 1, 0, 0, 0, 0, 0]]"] ; 27 | 0 -> 12 [labeldistance=2.5, labelangle=-45, headlabel="False"] ; 28 | 13 [label="X[2] <= 59.0\ngini = 0.823\nsamples = 9\nvalue = [[1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 2, 1, 0, 1, 0, 0]\n[0, 1, 2, 1, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[1, 1, 3, 0, 0, 0, 1, 2, 0, 1, 0, 0, 0, 0, 0, 0]]"] ; 29 | 12 -> 13 ; 30 | 14 [label="X[0] <= 9.0\ngini = 0.708\nsamples = 4\nvalue = [[1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0]\n[0, 0, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0]]"] ; 31 | 13 -> 14 ; 32 | 15 [label="X[1] <= 117.5\ngini = 0.5\nsamples = 2\nvalue = [[1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0]]"] ; 33 | 14 -> 15 ; 34 | 16 [label="gini = 0.0\nsamples = 1\nvalue = [[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]]"] ; 35 | 15 -> 16 ; 36 | 17 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 37 | 15 -> 17 ; 38 | 18 [label="X[0] <= 12.5\ngini = 0.333\nsamples = 2\nvalue = [[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 39 | 14 -> 18 ; 40 | 19 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 41 | 18 -> 19 ; 42 | 20 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 43 | 18 -> 20 ; 44 | 21 [label="X[2] <= 117.5\ngini = 0.693\nsamples = 5\nvalue = [[0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0]\n[0, 1, 1, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 45 | 13 -> 21 ; 46 | 22 [label="X[2] <= 70.0\ngini = 0.625\nsamples = 4\nvalue = [[0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0]\n[0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 47 | 21 -> 22 ; 48 | 23 [label="X[1] <= 136.0\ngini = 0.5\nsamples = 2\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 49 | 22 -> 23 ; 50 | 24 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 51 | 23 -> 24 ; 52 | 25 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 53 | 23 -> 25 ; 54 | 26 [label="X[1] <= 220.0\ngini = 0.333\nsamples = 2\nvalue = [[0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 55 | 22 -> 26 ; 56 | 27 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 57 | 26 -> 27 ; 58 | 28 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 59 | 26 -> 28 ; 60 | 29 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0]\n[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 61 | 21 -> 29 ; 62 | 30 [label="X[1] <= 220.0\ngini = 0.72\nsamples = 5\nvalue = [[0, 2, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0]\n[1, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0]]"] ; 63 | 12 -> 30 ; 64 | 31 [label="X[0] <= 14.5\ngini = 0.593\nsamples = 3\nvalue = [[0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0]\n[1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0]]"] ; 65 | 30 -> 31 ; 66 | 32 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]]"] ; 67 | 31 -> 32 ; 68 | 33 [label="X[2] <= 39.0\ngini = 0.5\nsamples = 2\nvalue = [[0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0]\n[1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]]"] ; 69 | 31 -> 33 ; 70 | 34 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 71 | 33 -> 34 ; 72 | 35 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]\n[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]]"] ; 73 | 33 -> 35 ; 74 | 36 [label="X[2] <= 161.5\ngini = 0.333\nsamples = 2\nvalue = [[0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 75 | 30 -> 36 ; 76 | 37 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 77 | 36 -> 37 ; 78 | 38 [label="gini = 0.0\nsamples = 1\nvalue = [[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]"] ; 79 | 36 -> 38 ; 80 | } 81 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/selection_blocks/t_SelectionBlock.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | \file t_SelectionBlock.cpp 3 | \author masoud.naderpour@helsinki.fi 4 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 5 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | ABY is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Lesser General Public License for more details. 14 | You should have received a copy of the GNU Lesser General Public License 15 | along with this program. If not, see . 16 | \brief Implementation of truncated SelectionBlock 17 | */ 18 | #include "t_SelectionBlock.h" 19 | #include "permutation_network.h" 20 | 21 | Truncated_PN::WaksmanPermutation::~WaksmanPermutation() { 22 | // TODO Auto-generated destructor stub 23 | } 24 | 25 | void Truncated_PN::WaksmanPermutation::program_rec(uint32_t out, uint32_t block, uint32_t* p1, uint32_t* p2, uint32_t* rows, uint32_t* cols) { 26 | uint32_t in = cols[out]; 27 | 28 | if ((out^1) < m_nNumOutputs && cols[out^1] != -1 && out/2 < s2.size()) { 29 | m_PM->setSwitchProgram(s2[out/2],(block==0)!=(out%2==0)); 30 | Todo->remove(out/2); 31 | } 32 | 33 | if (block == 1) { 34 | p2[out/2] = in / 2; 35 | if(in / 2 < s1.size()) { 36 | m_PM->setSwitchProgram(s1[in/2], in % 2 == 0); 37 | } 38 | } else { // block==0 39 | p1[out / 2] = in / 2; 40 | if (in / 2 < s1.size()) { 41 | m_PM->setSwitchProgram(s1[in/2], in % 2 == 1); 42 | } 43 | } 44 | cols[out] = -1; 45 | rows[in] = -1; 46 | 47 | uint32_t newin = in^1; 48 | if (newin < m_nNumInputs && rows[newin]!=-1) { 49 | uint32_t newout = rows[newin]; 50 | rows[newin] = -1; 51 | program_rec(newout,block^1,p1,p2,rows,cols); 52 | } 53 | 54 | if ((out^1) < m_nNumOutputs && cols[out^1] != -1 && out/2 < s2.size()) { 55 | program_rec(out^1,block^1,p1,p2,rows,cols); 56 | } 57 | } 58 | 59 | void Truncated_PN::WaksmanPermutation::program(uint32_t* perm) { 60 | if (m_nNumOutputs == 1){ 61 | if(m_nNumInputs == 1) {return;} 62 | m_vYgatesProgram.resize(m_nNumInputs - 1); 63 | for(int i=0; i < m_nNumInputs-1; i++) { 64 | if(i + 1 == perm[0]) m_vYgatesProgram[i] = true; 65 | else m_vYgatesProgram[i] = false; 66 | } 67 | return; 68 | } 69 | 70 | uint32_t* cols = perm; 71 | 72 | uint32_t* rows = (uint32_t*) malloc(sizeof(uint32_t) * m_nNumInputs); //new uint32_t[u]; 73 | for (uint32_t i = 0; i < m_nNumInputs; i++) rows[i] = -1; 74 | for (uint32_t i = 0; i < m_nNumOutputs; i++) { 75 | uint32_t x = perm[i]; 76 | assert(x>=0 && xnext(); n != -1; n = Todo->next()) { 97 | program_rec(2 * n, 0, p1, p2, rows, cols); 98 | } 99 | 100 | // program sub-blocks 101 | b1->program(p1); 102 | b2->program(p2); 103 | } 104 | 105 | Truncated_PN::WaksmanPermutation::WaksmanPermutation(uint32_t numinputs, uint32_t numoutputs, Truncated_PN* pm) { 106 | assert(numoutputs <= numinputs); 107 | m_nNumInputs = numinputs; 108 | m_nNumOutputs = numoutputs; 109 | m_PM = pm; 110 | 111 | if (numoutputs != 1) { 112 | // first row X 113 | s1.resize(m_nNumInputs / 2); 114 | 115 | for (uint32_t i = 0; i < m_nNumInputs / 2; i++) 116 | s1[i] = pm->nextGate(); 117 | 118 | //assign wires to X gates and permute them 119 | 120 | // B1PermutationNetwork 121 | b1 = new WaksmanPermutation(numinputs / 2, numoutputs / 2, pm); 122 | 123 | // B2 124 | b2 = new WaksmanPermutation(numinputs - (numinputs / 2), numoutputs - (numoutputs / 2), pm); 125 | 126 | // last row X 127 | m_nSizeB2 = (numinputs % 2 == 0 && numoutputs % 2 ==0) ? numoutputs / 2 - 1 : numoutputs / 2; 128 | s2.resize(m_nSizeB2); 129 | for (uint32_t i = 0; i < m_nSizeB2; i++) 130 | s2[i] = pm->nextGate(); 131 | 132 | } 133 | 134 | } 135 | 136 | vector > Truncated_PN::WaksmanPermutation::generateCircuit(vector > inputs, vector > outputs) { 137 | uint32_t rep = inputs[0].size(); 138 | if (outputs == NON_INIT_DEF_OUTPUT) { 139 | outputs.resize(m_nNumOutputs); 140 | for (uint32_t i = 0; i < m_nNumOutputs; i++) { 141 | outputs[i].resize(rep); 142 | } 143 | } 144 | if (m_nNumOutputs == 1) { 145 | if(m_nNumInputs == 1) { 146 | for (uint32_t j = 0; j < rep; j++){ 147 | outputs[0][j] = inputs[0][j]; 148 | return outputs; 149 | } 150 | } 151 | vector > outtmp(1); 152 | outtmp[0] = m_PM->PutCondYGate(inputs[0], inputs[1],(m_PM->m_cBoolCirc->PutSIMDINGate(1,(uint32_t) m_vYgatesProgram[0],1,SERVER))->get_wire_id(0)); 153 | for(uint32_t i = 1;i < m_nNumInputs - 1; i++) { 154 | outtmp[0] = m_PM->PutCondYGate(outtmp[0], inputs[i+1], (m_PM->m_cBoolCirc->PutSIMDINGate(1,(uint32_t) m_vYgatesProgram[i],1,SERVER))->get_wire_id(0)); 155 | } 156 | outputs[0] = outtmp [0]; 157 | return outputs; 158 | } 159 | 160 | uint32_t sizeB2 = m_nNumInputs - (m_nNumInputs / 2); 161 | vector > in_p1(m_nNumInputs / 2); 162 | vector > in_p2(sizeB2); 163 | 164 | // first row X 165 | vector > outtmp(2); 166 | for (uint32_t i = 0; i < s1.size(); i++) { 167 | in_p1[i].resize(rep); 168 | in_p2[i].resize(rep); 169 | //in_p1[i] = inputs[2 * i + m_PM->m_vSwitchGateProgram[s1[i]]]; 170 | //in_p2[i] = inputs[2 * i + !(m_PM->m_vSwitchGateProgram[s1[i]])]; 171 | outtmp = m_PM->PutCondSwapGate(inputs[2 * i], inputs[2 * i + 1], m_PM->m_vSwapGates[s1[i]]); 172 | for (uint32_t j = 0; j < rep; j++) { 173 | in_p1[i][j] = outtmp[0][j]; 174 | in_p2[i][j] = outtmp[1][j]; 175 | } 176 | 177 | } 178 | 179 | if (m_nNumInputs % 2 == 1) { 180 | in_p2[sizeB2 - 1].resize(rep); 181 | for (uint32_t i = 0; i < rep; i++) 182 | in_p2[sizeB2 - 1][i] = inputs[m_nNumInputs - 1][i]; 183 | } 184 | 185 | vector > out_p1 = b1->generateCircuit(in_p1, NON_INIT_DEF_OUTPUT); 186 | vector > out_p2 = b2->generateCircuit(in_p2, NON_INIT_DEF_OUTPUT); 187 | 188 | // last row X 189 | for (uint32_t i = 0; i < s2.size(); i++) { 190 | 191 | outtmp = m_PM->PutCondSwapGate(out_p1[i], out_p2[i], m_PM->m_vSwapGates[s2[i]]); 192 | for (uint32_t j = 0; j < rep; j++) { 193 | outputs[2 * i][j] = outtmp[0][j]; 194 | outputs[2 * i + 1][j] = outtmp[1][j]; 195 | } 196 | 197 | 198 | } 199 | 200 | if(m_nNumOutputs % 2 == 1) { 201 | for (uint32_t i = 0; i < rep; i++){ 202 | outputs[m_nNumOutputs - 1][i] = out_p2[out_p2.size()-1][i]; 203 | } 204 | } else if (m_nNumInputs % 2 == 0){ 205 | for (uint32_t i = 0; i < rep; i++){ 206 | 207 | outputs[m_nNumOutputs - 1][i] = out_p2[out_p2.size()-1][i]; 208 | outputs[m_nNumOutputs - 2][i] = out_p1[out_p1.size()-1][i]; 209 | } 210 | } 211 | 212 | return outputs; 213 | } 214 | 215 | void t_SelectionBlock::SelectionBlockProgram(uint32_t *p){ 216 | uint32_t *prog1, *programm; 217 | 218 | if(m_nNumInputs==1) return; 219 | 220 | // count number of occurrences 221 | vector c; 222 | c.resize(m_nNumInputs); 223 | for(uint32_t i=0; i=0 && p[i] upos, dummy; 232 | upos.resize(m_nNumInputs); 233 | dummy.resize(m_nNumInputs); // list of dummy outputs 234 | 235 | for(uint32_t i=0; i0) { 237 | prog1[sum] = i; 238 | upos[i] = sum; 239 | if(sum>0) { 240 | setYProgram(sum-1, true); 241 | //m_vYgatesProgram[sum-1] = true; 242 | } 243 | for(uint32_t j = sum + 1; j < sum+c[i]; j++) { 244 | setYProgram(j-1, false); 245 | //m_vYgatesProgram[j-1] = false; 246 | prog1[j] = -1; 247 | } 248 | sum+=c[i]; 249 | } 250 | else{ 251 | dummy[ndummys++] = i; 252 | } 253 | } 254 | 255 | // program dummys 256 | uint32_t nextdummy=0; 257 | for(uint32_t i=0; i < m_nNumOutputs; i++) { 258 | if(prog1[i]==-1) { 259 | prog1[i]=dummy[nextdummy++]; 260 | } 261 | } 262 | m_Pblock1->ProgramPermutationNetwork(prog1); 263 | 264 | // program b2 265 | uint32_t* prog2 = (uint32_t*) malloc(sizeof(uint32_t) * m_nNumOutputs); 266 | for(uint32_t i=0; i < m_nNumOutputs; i++) { 267 | prog2[i]=upos[p[i]]++; 268 | } 269 | m_Pblock2->ProgramPermutationNetwork(prog2); 270 | } 271 | 272 | vector > t_SelectionBlock::buildSelectionBlockCircuit(vector >& inputs){ 273 | uint32_t rep = inputs[0].size(); 274 | vector > out_p1,out_g, outputs; 275 | 276 | out_p1 = m_Pblock1->buildPermutationCircuit(inputs); 277 | out_g.resize(m_nNumOutputs); 278 | out_g[0]=out_p1[0]; 279 | for(uint32_t i=1; ibuildPermutationCircuit(out_g); 283 | } 284 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/crypto_party/paillier.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | libpaillier - A library implementing the Paillier cryptosystem. 3 | 4 | Copyright (C) 2006 SRI International. 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, but 12 | WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | General Public License for more details. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "paillier.h" 22 | 23 | void 24 | init_rand( gmp_randstate_t rand, paillier_get_rand_t get_rand, int bytes ) 25 | { 26 | void* buf; 27 | mpz_t s; 28 | 29 | buf = malloc(bytes); 30 | get_rand(buf, bytes); 31 | 32 | gmp_randinit_default(rand); 33 | mpz_init(s); 34 | mpz_import(s, bytes, 1, 1, 0, 0, buf); 35 | gmp_randseed(rand, s); 36 | mpz_clear(s); 37 | 38 | free(buf); 39 | } 40 | 41 | void 42 | complete_pubkey( paillier_pubkey_t* pub ) 43 | { 44 | mpz_mul(pub->n_squared, pub->n, pub->n); 45 | mpz_add_ui(pub->n_plusone, pub->n, 1); 46 | } 47 | 48 | void 49 | complete_prvkey( paillier_prvkey_t* prv, paillier_pubkey_t* pub ) 50 | { 51 | mpz_powm(prv->x, pub->n_plusone, prv->lambda, pub->n_squared); 52 | mpz_sub_ui(prv->x, prv->x, 1); 53 | mpz_div(prv->x, prv->x, pub->n); 54 | mpz_invert(prv->x, prv->x, pub->n); 55 | } 56 | 57 | void 58 | paillier_keygen( int modulusbits, 59 | paillier_pubkey_t** pub, 60 | paillier_prvkey_t** prv, 61 | paillier_get_rand_t get_rand ) 62 | { 63 | mpz_t p; 64 | mpz_t q; 65 | gmp_randstate_t rand; 66 | 67 | /* allocate the new key structures */ 68 | 69 | *pub = (paillier_pubkey_t*) malloc(sizeof(paillier_pubkey_t)); 70 | *prv = (paillier_prvkey_t*) malloc(sizeof(paillier_prvkey_t)); 71 | 72 | /* initialize our integers */ 73 | 74 | mpz_init((*pub)->n); 75 | mpz_init((*pub)->n_squared); 76 | mpz_init((*pub)->n_plusone); 77 | mpz_init((*prv)->lambda); 78 | mpz_init((*prv)->x); 79 | mpz_init(p); 80 | mpz_init(q); 81 | 82 | /* pick random (modulusbits/2)-bit primes p and q */ 83 | 84 | init_rand(rand, get_rand, modulusbits / 8 + 1); 85 | do 86 | { 87 | do 88 | mpz_urandomb(p, rand, modulusbits / 2); 89 | while( !mpz_probab_prime_p(p, 10) ); 90 | 91 | do 92 | mpz_urandomb(q, rand, modulusbits / 2); 93 | while( !mpz_probab_prime_p(q, 10) ); 94 | 95 | /* compute the public modulus n = p q */ 96 | 97 | mpz_mul((*pub)->n, p, q); 98 | } while( !mpz_tstbit((*pub)->n, modulusbits - 1) ); 99 | complete_pubkey(*pub); 100 | (*pub)->bits = modulusbits; 101 | 102 | /* compute the private key lambda = lcm(p-1,q-1) */ 103 | 104 | mpz_sub_ui(p, p, 1); 105 | mpz_sub_ui(q, q, 1); 106 | mpz_lcm((*prv)->lambda, p, q); 107 | complete_prvkey(*prv, *pub); 108 | 109 | /* clear temporary integers and randstate */ 110 | 111 | mpz_clear(p); 112 | mpz_clear(q); 113 | gmp_randclear(rand); 114 | } 115 | 116 | paillier_ciphertext_t* 117 | paillier_enc( paillier_ciphertext_t* res, 118 | paillier_pubkey_t* pub, 119 | paillier_plaintext_t* pt, 120 | paillier_get_rand_t get_rand ) 121 | { 122 | mpz_t r; 123 | gmp_randstate_t rand; 124 | mpz_t x; 125 | 126 | /* pick random blinding factor */ 127 | 128 | mpz_init(r); 129 | gmp_randinit_mt(rand); 130 | do 131 | mpz_urandomb(r, rand, pub->bits); 132 | while( mpz_cmp(r, pub->n) >= 0 ); 133 | 134 | /* compute ciphertext */ 135 | 136 | if( !res ) 137 | { 138 | res = (paillier_ciphertext_t*) malloc(sizeof(paillier_ciphertext_t)); 139 | mpz_init(res->c); 140 | } 141 | 142 | mpz_init(x); 143 | mpz_powm(res->c, pub->n_plusone, pt->m, pub->n_squared); 144 | mpz_powm(x, r, pub->n, pub->n_squared); 145 | 146 | mpz_mul(res->c, res->c, x); 147 | mpz_mod(res->c, res->c, pub->n_squared); 148 | 149 | mpz_clear(x); 150 | mpz_clear(r); 151 | gmp_randclear(rand); 152 | 153 | return res; 154 | } 155 | 156 | paillier_plaintext_t* 157 | paillier_dec( paillier_plaintext_t* res, 158 | paillier_pubkey_t* pub, 159 | paillier_prvkey_t* prv, 160 | paillier_ciphertext_t* ct ) 161 | { 162 | if( !res ) 163 | { 164 | res = (paillier_plaintext_t*) malloc(sizeof(paillier_plaintext_t)); 165 | mpz_init(res->m); 166 | } 167 | 168 | mpz_powm(res->m, ct->c, prv->lambda, pub->n_squared); 169 | mpz_sub_ui(res->m, res->m, 1); 170 | mpz_div(res->m, res->m, pub->n); 171 | mpz_mul(res->m, res->m, prv->x); 172 | mpz_mod(res->m, res->m, pub->n); 173 | 174 | return res; 175 | } 176 | 177 | void 178 | paillier_mul( paillier_pubkey_t* pub, 179 | paillier_ciphertext_t* res, 180 | paillier_ciphertext_t* ct0, 181 | paillier_ciphertext_t* ct1 ) 182 | { 183 | mpz_mul(res->c, ct0->c, ct1->c); 184 | mpz_mod(res->c, res->c, pub->n_squared); 185 | } 186 | 187 | void 188 | paillier_exp( paillier_pubkey_t* pub, 189 | paillier_ciphertext_t* res, 190 | paillier_ciphertext_t* ct, 191 | paillier_plaintext_t* pt ) 192 | { 193 | mpz_powm(res->c, ct->c, pt->m, pub->n_squared); 194 | } 195 | 196 | paillier_plaintext_t* 197 | paillier_plaintext_from_ui( unsigned long int x ) 198 | { 199 | paillier_plaintext_t* pt; 200 | 201 | pt = (paillier_plaintext_t*) malloc(sizeof(paillier_plaintext_t)); 202 | mpz_init_set_ui(pt->m, x); 203 | 204 | return pt; 205 | } 206 | 207 | paillier_plaintext_t* 208 | paillier_plaintext_from_bytes( void* m, int len ) 209 | { 210 | paillier_plaintext_t* pt; 211 | 212 | pt = (paillier_plaintext_t*) malloc(sizeof(paillier_plaintext_t)); 213 | mpz_init(pt->m); 214 | mpz_import(pt->m, len, 1, 1, 0, 0, m); 215 | 216 | return pt; 217 | } 218 | 219 | void* 220 | paillier_plaintext_to_bytes( int len, paillier_plaintext_t* pt ) 221 | { 222 | void* buf0; 223 | void* buf1; 224 | size_t written; 225 | 226 | buf0 = mpz_export(0, &written, 1, 1, 0, 0, pt->m); 227 | 228 | if( written == len ) 229 | return buf0; 230 | 231 | buf1 = malloc(len); 232 | memset(buf1, 0, len); 233 | 234 | if( written == 0 ) 235 | /* no need to copy anything, pt->m = 0 and buf0 was not allocated */ 236 | return buf1; 237 | else if( written < len ) 238 | /* pad with leading zeros */ 239 | memcpy(buf1 + (len - written), buf0, written); 240 | else 241 | /* truncate leading garbage */ 242 | memcpy(buf1, buf0 + (written - len), len); 243 | 244 | free(buf0); 245 | 246 | return buf1; 247 | } 248 | 249 | paillier_plaintext_t* 250 | paillier_plaintext_from_str( char* str ) 251 | { 252 | return paillier_plaintext_from_bytes(str, strlen(str)); 253 | } 254 | 255 | char* 256 | paillier_plaintext_to_str( paillier_plaintext_t* pt ) 257 | { 258 | char* buf; 259 | size_t len; 260 | 261 | buf = (char*) mpz_export(0, &len, 1, 1, 0, 0, pt->m); 262 | buf = (char*) realloc(buf, len + 1); 263 | buf[len] = 0; 264 | 265 | return buf; 266 | } 267 | 268 | paillier_ciphertext_t* 269 | paillier_ciphertext_from_bytes( void* c, int len ) 270 | { 271 | paillier_ciphertext_t* ct; 272 | 273 | ct = (paillier_ciphertext_t*) malloc(sizeof(paillier_ciphertext_t)); 274 | mpz_init(ct->c); 275 | mpz_import(ct->c, len, 1, 1, 0, 0, c); 276 | 277 | return ct; 278 | } 279 | 280 | void* 281 | paillier_ciphertext_to_bytes( int len, paillier_ciphertext_t* ct ) 282 | { 283 | void* buf; 284 | int cur_len; 285 | 286 | cur_len = mpz_sizeinbase(ct->c, 2); 287 | cur_len = PAILLIER_BITS_TO_BYTES(cur_len); 288 | buf = malloc(len); 289 | memset(buf, 0, len); 290 | mpz_export(buf + (len - cur_len), 0, 1, 1, 0, 0, ct->c); 291 | 292 | return buf; 293 | } 294 | 295 | char* 296 | paillier_pubkey_to_hex( paillier_pubkey_t* pub ) 297 | { 298 | return mpz_get_str(0, 16, pub->n); 299 | } 300 | 301 | char* 302 | paillier_prvkey_to_hex( paillier_prvkey_t* prv ) 303 | { 304 | return mpz_get_str(0, 16, prv->lambda); 305 | } 306 | 307 | paillier_pubkey_t* 308 | paillier_pubkey_from_hex( char* str ) 309 | { 310 | paillier_pubkey_t* pub; 311 | 312 | pub = (paillier_pubkey_t*) malloc(sizeof(paillier_pubkey_t)); 313 | mpz_init_set_str(pub->n, str, 16); 314 | pub->bits = mpz_sizeinbase(pub->n, 2); 315 | mpz_init(pub->n_squared); 316 | mpz_init(pub->n_plusone); 317 | complete_pubkey(pub); 318 | 319 | return pub; 320 | } 321 | 322 | paillier_prvkey_t* 323 | paillier_prvkey_from_hex( char* str, paillier_pubkey_t* pub ) 324 | { 325 | paillier_prvkey_t* prv; 326 | 327 | prv = (paillier_prvkey_t*) malloc(sizeof(paillier_prvkey_t)); 328 | mpz_init_set_str(prv->lambda, str, 16); 329 | mpz_init(prv->x); 330 | complete_prvkey(prv, pub); 331 | 332 | return prv; 333 | } 334 | 335 | void 336 | paillier_freepubkey( paillier_pubkey_t* pub ) 337 | { 338 | mpz_clear(pub->n); 339 | mpz_clear(pub->n_squared); 340 | mpz_clear(pub->n_plusone); 341 | free(pub); 342 | } 343 | 344 | void 345 | paillier_freeprvkey( paillier_prvkey_t* prv ) 346 | { 347 | mpz_clear(prv->lambda); 348 | mpz_clear(prv->x); 349 | free(prv); 350 | } 351 | 352 | void 353 | paillier_freeplaintext( paillier_plaintext_t* pt ) 354 | { 355 | mpz_clear(pt->m); 356 | // free(pt); 357 | } 358 | 359 | void 360 | paillier_freeciphertext( paillier_ciphertext_t* ct ) 361 | { 362 | mpz_clear(ct->c); 363 | // free(ct); 364 | } 365 | 366 | void 367 | paillier_get_rand_file( void* buf, int len, char* file ) 368 | { 369 | FILE* fp; 370 | void* p; 371 | 372 | fp = fopen(file, "r"); 373 | 374 | p = buf; 375 | while( len ) 376 | { 377 | size_t s; 378 | s = fread(p, 1, len, fp); 379 | p += s; 380 | len -= s; 381 | } 382 | 383 | fclose(fp); 384 | } 385 | 386 | void 387 | paillier_get_rand_devrandom( void* buf, int len ) 388 | { 389 | paillier_get_rand_file(buf, len, "/dev/random"); 390 | } 391 | 392 | void 393 | paillier_get_rand_devurandom( void* buf, int len ) 394 | { 395 | paillier_get_rand_file(buf, len, "/dev/urandom"); 396 | } 397 | 398 | paillier_ciphertext_t* 399 | paillier_create_enc_zero() 400 | { 401 | paillier_ciphertext_t* ct; 402 | 403 | /* make a NON-RERANDOMIZED encryption of zero for the purposes of 404 | homomorphic computation */ 405 | 406 | /* note that this is just the number 1 */ 407 | 408 | ct = (paillier_ciphertext_t*) malloc(sizeof(paillier_ciphertext_t)); 409 | mpz_init_set_ui(ct->c, 1); 410 | 411 | return ct; 412 | } 413 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/crypto_party/paillier.h: -------------------------------------------------------------------------------- 1 | /* 2 | libpaillier - A library implementing the Paillier cryptosystem. 3 | 4 | Copyright (C) 2006 SRI International. 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, but 12 | WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | General Public License for more details. 15 | */ 16 | 17 | /* 18 | Include gmp.h before including this file. 19 | */ 20 | 21 | /* 22 | IMPORTANT SECURITY NOTES: 23 | 24 | On paillier_keygen and strong primes: 25 | 26 | When selecting a modulus n = p q, we do not bother ensuring that p 27 | and q are strong primes. While this was at one point considered 28 | important (e.g., it is required by ANSI X9.31), modern factoring 29 | algorithms make any advantage of strong primes doubtful [1]. RSA 30 | Laboratories no longer recommends the practice [2]. 31 | 32 | On memory handling: 33 | 34 | At no point is any special effort made to securely "shred" sensitive 35 | memory or prevent it from being paged out to disk. This means that 36 | it is important that functions dealing with private keys and 37 | plaintexts (e.g., paillier_keygen and paillier_enc) only be run on 38 | trusted machines. The resulting ciphertexts and public keys, 39 | however, may of course be handled in an untrusted manner. 40 | 41 | [1] Are "strong" primes needed for RSA? Ron Rivest and Robert 42 | Silverman. Cryptology ePrint Archive, Report 2001/007, 2001. 43 | 44 | [2] RSA Laboratories' Frequently Asked Questions About Today's 45 | Cryptography, Version 4.1, Section 3.1.4. 46 | */ 47 | 48 | /****** 49 | TYPES 50 | *******/ 51 | 52 | /* 53 | This represents a Paillier public key, which is basically just the 54 | modulus n. The other values should be considered private. 55 | */ 56 | typedef struct 57 | { 58 | int bits; /* e.g., 1024 */ 59 | mpz_t n; /* public modulus n = p q */ 60 | mpz_t n_squared; /* cached to avoid recomputing */ 61 | mpz_t n_plusone; /* cached to avoid recomputing */ 62 | } paillier_pubkey_t; 63 | 64 | /* 65 | This represents a Paillier private key; it needs to be used with a 66 | paillier_pubkey_t to be meaningful. It only includes the Carmichael 67 | function (lambda) of the modulus. The other value is kept for 68 | efficiency and should be considered private. 69 | */ 70 | typedef struct 71 | { 72 | mpz_t lambda; /* lambda(n), i.e., lcm(p-1,q-1) */ 73 | mpz_t x; /* cached to avoid recomputing */ 74 | } paillier_prvkey_t; 75 | 76 | /* 77 | This is a (semantic rather than structural) type for plaintexts. 78 | These can be converted to and from ASCII strings and byte arrays. 79 | */ 80 | typedef struct 81 | { 82 | mpz_t m; 83 | } paillier_plaintext_t; 84 | 85 | /* 86 | This is a (semantic rather than structural) type for ciphertexts. 87 | These can also be converted to or from byte arrays (for example in 88 | order to store them in a file). 89 | */ 90 | typedef struct 91 | { 92 | mpz_t c; 93 | } paillier_ciphertext_t; 94 | 95 | /* 96 | This is the type of the callback functions used to obtain the 97 | randomness needed by the probabilistic algorithms. The functions 98 | paillier_get_rand_devrandom and paillier_get_rand_devurandom 99 | (documented later) may be passed to any library function requiring a 100 | paillier_get_rand_t, or you may implement your own. If you implement 101 | your own such function, it should fill in "len" random bytes in the 102 | array "buf". 103 | */ 104 | typedef void (*paillier_get_rand_t) ( void* buf, int len ); 105 | 106 | /***************** 107 | BASIC OPERATIONS 108 | *****************/ 109 | 110 | /* 111 | Generate a keypair of length modulusbits using randomness from the 112 | provided get_rand function. Space will be allocated for each of the 113 | keys, and the given pointers will be set to point to the new 114 | paillier_pubkey_t and paillier_prvkey_t structures. The functions 115 | paillier_get_rand_devrandom and paillier_get_rand_devurandom may be 116 | passed as the final argument. 117 | */ 118 | void paillier_keygen( int modulusbits, 119 | paillier_pubkey_t** pub, 120 | paillier_prvkey_t** prv, 121 | paillier_get_rand_t get_rand ); 122 | 123 | /* 124 | Encrypt the given plaintext with the given public key using 125 | randomness from get_rand for blinding. If res is not null, its 126 | contents will be overwritten with the result. Otherwise, a new 127 | paillier_ciphertext_t will be allocated and returned. 128 | */ 129 | paillier_ciphertext_t* paillier_enc( paillier_ciphertext_t* res, 130 | paillier_pubkey_t* pub, 131 | paillier_plaintext_t* pt, 132 | paillier_get_rand_t get_rand ); 133 | 134 | /* 135 | Decrypt the given ciphertext with the given key pair. If res is not 136 | null, its contents will be overwritten with the result. Otherwise, a 137 | new paillier_plaintext_t will be allocated and returned. 138 | */ 139 | paillier_plaintext_t* paillier_dec( paillier_plaintext_t* res, 140 | paillier_pubkey_t* pub, 141 | paillier_prvkey_t* prv, 142 | paillier_ciphertext_t* ct ); 143 | 144 | /***************************** 145 | USE OF ADDITIVE HOMOMORPHISM 146 | *****************************/ 147 | 148 | /* 149 | Multiply the two ciphertexts assuming the modulus in the given 150 | public key and store the result in the contents of res, which is 151 | assumed to have already been allocated. 152 | */ 153 | void paillier_mul( paillier_pubkey_t* pub, 154 | paillier_ciphertext_t* res, 155 | paillier_ciphertext_t* ct0, 156 | paillier_ciphertext_t* ct1 ); 157 | 158 | /* 159 | Raise the given ciphertext to power pt and store the result in res, 160 | which is assumed to be already allocated. If ct is an encryption of 161 | x, then res will become an encryption of x * pt mod n, where n is 162 | the modulus in pub. 163 | */ 164 | void paillier_exp( paillier_pubkey_t* pub, 165 | paillier_ciphertext_t* res, 166 | paillier_ciphertext_t* ct, 167 | paillier_plaintext_t* pt ); 168 | 169 | /**************************** 170 | PLAINTEXT IMPORT AND EXPORT 171 | ****************************/ 172 | 173 | /* 174 | Allocate and initialize a paillier_plaintext_t from an unsigned long 175 | integer, an array of bytes, or a null terminated string. 176 | */ 177 | paillier_plaintext_t* paillier_plaintext_from_ui( unsigned long int x ); 178 | paillier_plaintext_t* paillier_plaintext_from_bytes( void* m, int len ); 179 | paillier_plaintext_t* paillier_plaintext_from_str( char* str ); 180 | 181 | /* 182 | Export a paillier_plaintext_t as a null terminated string or an 183 | array of bytes. In either case the result is allocated for the 184 | caller and the original paillier_plaintext_t is unchanged. 185 | */ 186 | char* paillier_plaintext_to_str( paillier_plaintext_t* pt ); 187 | void* paillier_plaintext_to_bytes( int len, paillier_plaintext_t* pt ); 188 | 189 | /***************************** 190 | CIPHERTEXT IMPORT AND EXPORT 191 | *****************************/ 192 | 193 | /* 194 | Import or export a paillier_ciphertext_t from or to an array of 195 | bytes. These behave like the corresponding functions for 196 | paillier_plaintext_t's. 197 | */ 198 | paillier_ciphertext_t* paillier_ciphertext_from_bytes( void* c, int len ); 199 | void* paillier_ciphertext_to_bytes( int len, paillier_ciphertext_t* ct ); 200 | 201 | /********************** 202 | KEY IMPORT AND EXPORT 203 | **********************/ 204 | 205 | /* 206 | Import or export public and private keys from or to hexadecimal, 207 | ASCII strings, which are suitable for I/O. Note that the 208 | corresponding public key is necessary to initialize a private key 209 | from a hex string. In all cases, the returned value is allocated for 210 | the caller and the values passed are unchanged. 211 | */ 212 | char* paillier_pubkey_to_hex( paillier_pubkey_t* pub ); 213 | char* paillier_prvkey_to_hex( paillier_prvkey_t* prv ); 214 | paillier_pubkey_t* paillier_pubkey_from_hex( char* str ); 215 | paillier_prvkey_t* paillier_prvkey_from_hex( char* str, 216 | paillier_pubkey_t* pub ); 217 | 218 | /******** 219 | CLEANUP 220 | ********/ 221 | 222 | /* 223 | These free the structures allocated and returned by various 224 | functions within library and should be used when the structures are 225 | no longer needed. 226 | */ 227 | void paillier_freepubkey( paillier_pubkey_t* pub ); 228 | void paillier_freeprvkey( paillier_prvkey_t* prv ); 229 | void paillier_freeplaintext( paillier_plaintext_t* pt ); 230 | void paillier_freeciphertext( paillier_ciphertext_t* ct ); 231 | 232 | /*********** 233 | MISC STUFF 234 | ***********/ 235 | 236 | /* 237 | These functions may be passed to the paillier_keygen and 238 | paillier_enc functions to provide a source of random numbers. The 239 | first reads bytes from /dev/random. On Linux, this device 240 | exclusively returns entropy gathered from environmental noise and 241 | therefore frequently blocks when not enough is available. The second 242 | returns bytes from /dev/urandom. On Linux, this device also returns 243 | environmental noise, but augments it with a pseudo-random number 244 | generator when not enough is available. The latter is probably the 245 | better choice unless you have a specific reason to believe it is 246 | insufficient. 247 | */ 248 | void paillier_get_rand_devrandom( void* buf, int len ); 249 | void paillier_get_rand_devurandom( void* buf, int len ); 250 | 251 | /* 252 | This function just allocates and returns a paillier_ciphertext_t 253 | which is a valid, _unblinded_ encryption of zero (which may actually 254 | be done without knowledge of a public key). Note that this 255 | encryption is UNBLINDED, so don't use it unless you want anyone who 256 | sees it to know it is an encryption of zero. This function is 257 | sometimes handy to get some homomorphic computations started or 258 | quickly allocate a paillier_ciphertext_t in which to place some 259 | later result. 260 | */ 261 | paillier_ciphertext_t* paillier_create_enc_zero(); 262 | 263 | /* 264 | Just a utility used internally when we need round a number of bits 265 | up the number of bytes necessary to hold them. 266 | */ 267 | 268 | void complete_pubkey( paillier_pubkey_t* pub ); 269 | 270 | 271 | #define PAILLIER_BITS_TO_BYTES(n) ((n) % 8 ? (n) / 8 + 1 : (n) / 8) 272 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/dectree.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | \file dectree.cpp 3 | \author kiss@encrypto.cs.tu-darmstadt.de 4 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 5 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | ABY is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Lesser General Public License for more details. 14 | You should have received a copy of the GNU Lesser General Public License 15 | along with this program. If not, see . 16 | \brief Decision tree implementation 17 | */ 18 | 19 | #include "dectree.h" 20 | /** 21 | * Node constructor that takes its number num, by default it has no children 22 | * and parents, is not colored. 23 | * @param num the number that identifies the node 24 | */ 25 | DecTree::Node::Node() 26 | : left(0) 27 | , right(0) 28 | , parent(0) 29 | , level(0) 30 | , leaf(false) 31 | , threshold(0) 32 | , attribute_index(0) 33 | , classification(0) 34 | {} 35 | 36 | DecTree::Node::Node(const Node& other){ 37 | left = new Node(*(other.left)); 38 | right = new Node(*(other.right)); 39 | parent = new Node(*(other.parent)); 40 | level = other.level; 41 | leaf = other.leaf; 42 | threshold = other.threshold; 43 | attribute_index = other.attribute_index; 44 | classification = other.classification; 45 | } 46 | 47 | /** 48 | * Gamma2 constructor that creates a Gamma2 graph with specified number of Nodes 49 | * @param num the number specifying the number of Nodes 50 | */ 51 | DecTree::DecTree() 52 | { 53 | num_attributes = 0; 54 | num_dec_nodes = 0; 55 | depth = 0; 56 | num_of_leaves = 0; 57 | dummy_non_full = 0; 58 | } 59 | 60 | DecTree::DecTree(const DecTree& other){ 61 | node_vec = other.node_vec; 62 | decnode_vec = other.decnode_vec; 63 | attributes = other.attributes; 64 | thresholds = other.thresholds; 65 | num_attributes = other.num_attributes; 66 | num_dec_nodes = other.num_dec_nodes; 67 | depth = other.depth; 68 | num_of_leaves = other.num_of_leaves; 69 | dummy_non_full = other.dummy_non_full; 70 | } 71 | 72 | /** 73 | * Add a node 74 | * @param node the Node to be added to the tree 75 | */ 76 | void DecTree::add_node(DecTree::Node* node){ 77 | node_vec.push_back(node); 78 | } 79 | 80 | /** 81 | * Add a decision node 82 | * @param node the Node to be added to the tree 83 | */ 84 | void DecTree::add_decnode(DecTree::Node* node){ 85 | decnode_vec.push_back(node); 86 | } 87 | 88 | /** 89 | * Add an edge between two nodes 90 | * @param n1 the starting Node of the edge 91 | * @param n2 the ending Node of the edge 92 | */ 93 | void DecTree::add_edge(DecTree::Node* n1, DecTree::Node* n2){ 94 | n2->parent = n1; 95 | n2->level = n1->level + 1; 96 | if(n1->left == NULL){ 97 | n1->left = n2; 98 | } 99 | else{ 100 | n1->right = n2; 101 | } 102 | } 103 | 104 | /** 105 | * Takes a string in the Format "i i i ..." separated by ' ' 106 | * @param str the string to tokenize 107 | * @param tokens the result vector of wire id 108 | */ 109 | void tokenize(const std::string& str, std::vector& tokens) { 110 | tokens.clear(); 111 | std::size_t prev = 0, pos; 112 | while ((pos = str.find_first_of(" []", prev)) != std::string::npos) 113 | { 114 | if (pos > prev) 115 | tokens.push_back(str.substr(prev, pos-prev)); 116 | prev = pos+1; 117 | } 118 | if (prev < str.length()) 119 | tokens.push_back(str.substr(prev, std::string::npos)); 120 | } 121 | 122 | /** 123 | * Erase First Occurrence of given substring from main string. 124 | */ 125 | void eraseSubStr(std::string & mainStr, const std::string & toErase) 126 | { 127 | // Search for the substring in string 128 | size_t pos = mainStr.find(toErase); 129 | 130 | if (pos != std::string::npos) 131 | { 132 | // If found then erase it from string 133 | mainStr.erase(pos, toErase.length()); 134 | } 135 | } 136 | 137 | class SearchFunction { 138 | public: 139 | SearchFunction(uint32_t item): item_(item) {} 140 | bool operator()(uint64_t const & ref) { 141 | return ref == item_; 142 | } 143 | private: 144 | uint32_t item_; 145 | }; 146 | 147 | //root node will be in decnode_vec[0] and node_vec[0] 148 | void DecTree::read_from_file(string string_file){ 149 | const char* filename = string_file.c_str(); 150 | ifstream file; 151 | file.open(filename); 152 | cout << "Reading from " << filename << endl; 153 | 154 | //ofstream file2; 155 | //file2.open("dectree.txt", std::ios_base::app); 156 | 157 | uint32_t node1; 158 | uint32_t node2; 159 | 160 | DecTree::Node* node; 161 | uint32_t index; 162 | string line; 163 | vector tokens; 164 | vector::iterator it; 165 | float thres; 166 | while (getline(file, line)){ 167 | tokenize(line, tokens); 168 | if(tokens[1] == "label=\"gini"){ 169 | node1 = atoi(tokens[0].c_str()); 170 | this->add_node(new DecTree::Node()); 171 | this->node_vec[node1]->leaf = true; 172 | this->num_of_leaves++; 173 | this->node_vec[node1]->classification = rand() % 100; 174 | } 175 | else if(tokens[1] == "label=\"X"){ 176 | node1 = atoi(tokens[0].c_str()); 177 | //cout << node1 << endl; 178 | node = new DecTree::Node(); 179 | index = atoi(tokens[2].c_str()); 180 | node->attribute_index = index; 181 | //cout << index << endl; 182 | string str_cleaned = tokens[4]; 183 | eraseSubStr(str_cleaned, "\\ngini"); 184 | thres = atof(str_cleaned.c_str()); 185 | node->threshold = thres*1000; 186 | //cout << node->threshold << endl; //Thresholds are converted so that we only compare integers 187 | this->num_dec_nodes++; 188 | this->add_node(node); 189 | this->add_decnode(node); 190 | 191 | it = find_if(this->attributes.begin(), this->attributes.end(), SearchFunction(index)); 192 | if(it == this->attributes.end()){ 193 | this->num_attributes++; 194 | } 195 | this->attributes.push_back(index); 196 | this->thresholds.push_back(node->threshold); 197 | } 198 | else if(tokens[1] == "->"){ 199 | node1 = atoi(tokens[0].c_str()); 200 | node2 = atoi(tokens[2].c_str()); 201 | this->add_edge(this->node_vec[node1], this->node_vec[node2]); 202 | } 203 | } 204 | for(uint32_t i = 0; i < this->node_vec.size(); ++i){ 205 | node = this->node_vec[i]; 206 | if(node->leaf){ //Right is also 0 in this case 207 | if(node->level > this->depth){ 208 | this->depth = node->level; 209 | } 210 | } 211 | } 212 | //cout << "Total number of attributes " << this->num_attributes << endl; 213 | //cout << "Depth of the tree " << this->depth << endl; 214 | //cout << "Total number of decision nodes " << this->num_dec_nodes << endl; 215 | //cout << "Total number of leaves " << this->num_of_leaves << endl; 216 | 217 | for(uint32_t i = 0; i < this->node_vec.size(); ++i){ 218 | node = this->node_vec[i]; 219 | if(node->leaf){ 220 | this->dummy_non_full += this->depth - node->level; 221 | } 222 | } 223 | //cout << "Total number of dummy nodes in non-full tree " << this->dummy_non_full << endl; 224 | 225 | uint32_t total_number_of_edges = 0; 226 | for(uint32_t i = 0; i < this->node_vec.size(); ++i){ 227 | node = this->node_vec[i]; 228 | if(node->leaf){ 229 | total_number_of_edges += node->level; 230 | } 231 | } 232 | //cout << "Total number of edges " << total_number_of_edges << endl; 233 | file.close(); 234 | //file2.close(); 235 | } 236 | 237 | 238 | void DecTree::fullTree(uint32_t num_att, uint32_t tree_depth){ 239 | this->num_attributes = num_att; 240 | this->num_dec_nodes = pow(2.0, num_att); 241 | this->depth = tree_depth; 242 | this->num_of_leaves = pow(2.0, num_att + 1); 243 | vector attr(num_att, 0); 244 | vector thres(this->num_dec_nodes, 0); 245 | this->attributes = attr; 246 | this->thresholds = thres; 247 | 248 | for(uint32_t i = 0; i < this->num_dec_nodes + this->num_of_leaves; ++i){ 249 | DecTree::Node* newNode = new DecTree::Node(); 250 | if(i == 0){ 251 | newNode->parent = NULL; 252 | newNode->level = 0; 253 | } 254 | else if(i%2 == 0){ 255 | this->node_vec[i/2 - 1]->right = newNode; 256 | newNode->parent = this->node_vec[i/2 - 1]; 257 | newNode->level = newNode->parent->level + 1; 258 | } 259 | else if(i%2 == 1){ //odd case 260 | this->node_vec[i/2]->left = newNode; 261 | newNode->parent = this->node_vec[i/2]; 262 | newNode->level = newNode->parent->level + 1; 263 | } 264 | 265 | if(i < this->num_dec_nodes){ 266 | this->decnode_vec.push_back(newNode); 267 | } 268 | else{ 269 | newNode->leaf = true; 270 | } 271 | this->node_vec.push_back(newNode); 272 | } 273 | } 274 | 275 | void DecTree::depthPad(){ 276 | DecTree::Node* tmp; 277 | for(uint32_t i = 0; i < this->node_vec.size(); ++i){ 278 | if(this->node_vec[i]->leaf){ 279 | if(this->node_vec[i]->level != this->depth){ 280 | tmp = this->node_vec[i]; 281 | this->node_vec[i] = new DecTree::Node(); 282 | this->node_vec[i]->parent = tmp->parent; 283 | this->node_vec[i]->level = tmp->level; //leaf is false, threshold is 0, attribute_index is 0 284 | this->decnode_vec.push_back(this->node_vec[i]); 285 | this->attributes.push_back(this->node_vec[i]->attribute_index); 286 | this->thresholds.push_back(this->node_vec[i]->threshold); 287 | this->num_dec_nodes++; 288 | 289 | tmp->level++; 290 | tmp->parent = this->node_vec[i]; 291 | this->node_vec[i]->left = tmp; 292 | this->node_vec[i]->right = tmp; 293 | this->node_vec.push_back(tmp); 294 | } 295 | } 296 | } 297 | //cout << "Number of decision nodes " << this->num_dec_nodes << endl; 298 | } 299 | 300 | void DecTree::evaluate(vector inputs){ 301 | DecTree::Node* this_node = this->node_vec[0]; 302 | while(!(this_node->leaf)){ 303 | //cout << inputs[this_node->attribute_index] << endl; 304 | //cout << this_node->threshold << endl; 305 | if(inputs[this_node->attribute_index] <= this_node->threshold){ 306 | this_node = this_node->left; 307 | } 308 | else{ 309 | this_node = this_node->right; 310 | } 311 | } 312 | } 313 | 314 | /** 315 | * Destructor DecTree 316 | */ 317 | DecTree::~DecTree(){ 318 | node_vec.clear(); 319 | } 320 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/crypto_party/dgk_party.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | \file dgk_party.cpp 3 | \author masoud.naderpour@helsinki.fi 4 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 5 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | ABY is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Lesser General Public License for more details. 14 | You should have received a copy of the GNU Lesser General Public License 15 | along with this program. If not, see . 16 | \brief DGK crypto 17 | */ 18 | 19 | 20 | 21 | #include "dgk_party.h" 22 | 23 | #define CHECKCOMM 0 24 | #define DEBUG 0 25 | #define NETDEBUG 0 26 | #define WINDOWSIZE 50000 //maximum size of a network packet in Byte 27 | 28 | /** 29 | * initializes a DGK_Party with the asymmetric security parameter and the sharelength and exchanges public keys. 30 | * @param mode - 0 = generate new key; 1 = read key 31 | */ 32 | DGK::DGK(uint32_t DGKbits, uint32_t sharelen, channel* chan, uint32_t readkey) { 33 | 34 | m_nShareLength = sharelen; 35 | m_nDGKbits = DGKbits; 36 | m_nBuflen = DGKbits / 8 + 1; //size of one ciphertext to send via network. DGK uses n bits == n/8 bytes 37 | 38 | #if DEBUG 39 | std::cout << "Created party with " << DGKbits << " key bits and" << sharelen << " bit shares" << std::endl; 40 | #endif 41 | 42 | gmp_randinit_default(m_randstate); 43 | srand(time(0)); 44 | gmp_randseed_ui(m_randstate, rand()); 45 | 46 | if (readkey) { 47 | readKey(); 48 | } else { 49 | generateKey(); 50 | } 51 | 52 | keyExchange(chan); 53 | } 54 | 55 | /** 56 | * initializes a DGK_Party with the asymmetric security parameter and the sharelength. 57 | * @param mode - 0 = generate new key; 1 = read key 58 | * Public keys must be exchanged manually when using this constructor! 59 | */ 60 | DGK::DGK(uint32_t DGKbits, uint32_t sharelen, uint32_t readkey) { 61 | 62 | m_nShareLength = sharelen; 63 | m_nDGKbits = DGKbits; 64 | m_nBuflen = DGKbits / 8; //size of one ciphertext to send via network. DGK uses n bits == n/8 bytes 65 | 66 | #if DEBUG 67 | std::cout << "Created party with " << DGKbits << " key bits and" << sharelen << " bit shares" << std::endl; 68 | #endif 69 | 70 | gmp_randinit_default(m_randstate); 71 | gmp_randseed_ui(m_randstate, rand()); 72 | 73 | if (readkey) { 74 | if (!readKey()){ 75 | std::cout << "No DGK key file found! Generating a new DGK key." << std::endl; 76 | generateKey(); 77 | storeKey(); 78 | } 79 | } else { 80 | generateKey(); 81 | } 82 | } 83 | 84 | bool DGK::readKey() { 85 | #if DEBUG 86 | std::cout << "KeyGen" << std::endl; 87 | #endif 88 | dgk_readkey(m_nDGKbits, m_nShareLength, &m_localpub, &m_prv); 89 | #if DEBUG 90 | std::cout << "key read." << std::endl; 91 | #endif 92 | return true; 93 | } 94 | 95 | void DGK::storeKey(){ 96 | 97 | dgk_storekey(m_nDGKbits, m_nShareLength, m_localpub, m_prv); 98 | } 99 | 100 | void DGK::generateKey() { 101 | #if DEBUG 102 | std::cout << "KeyGen" << std::endl; 103 | #endif 104 | dgk_keygen(m_nDGKbits, m_nShareLength, &m_localpub, &m_prv); 105 | 106 | #if DEBUG 107 | std::cout << "key generated." << std::endl; 108 | #endif 109 | } 110 | 111 | /** 112 | * deletes party and frees keys and randstate 113 | */ 114 | DGK::~DGK() { 115 | #if DEBUG 116 | std::cout << "Deleting DGK..." << std::endl; 117 | #endif 118 | gmp_randclear(m_randstate); 119 | dgk_freeprvkey(m_prv); 120 | dgk_freepubkey(m_localpub); 121 | dgk_freepubkey(m_remotepub); 122 | 123 | } 124 | 125 | /** 126 | * encrypts PTs in the given Vec 127 | */ 128 | bool DGK::encrypt(vector &plaintexts, BYTE* &ciphertexts){ 129 | 130 | mpz_t tmp, tmp2, res; 131 | mpz_inits(tmp, tmp2, res, NULL); 132 | 133 | for(int i = 0;i < plaintexts.size();i++){ 134 | 135 | //mpz_set_ui(tmp, plaintexts[i]); 136 | mpz_set_ui(tmp, 123456); //Testing with a fixed val for debugging 137 | 138 | dgk_encrypt_crt(res, m_localpub, m_prv, tmp); 139 | //dgk_encrypt_plain(res, m_localpub, tmp); 140 | //mpz_mod(res,res, m_localpub->n); //res % modulus n (TODO: remove this) 141 | 142 | mpz_set_ui(res, plaintexts[i]); 143 | mpz_export(ciphertexts + i * m_nBuflen, NULL, -1, 1, 1, 0, res); 144 | 145 | dgk_decrypt(tmp2, m_localpub, m_prv, res); 146 | gmp_printf ("feature%d (%Zd) decryption is (%Zd)\n", i, tmp, tmp2); //TODO: solve the problem with decryption :( 147 | 148 | if (mpz_cmp(tmp, tmp2)) { 149 | printf("ERROR!\n"); 150 | break; //exit(0); 151 | } 152 | } 153 | 154 | return 1; 155 | } 156 | 157 | /** 158 | * encrypts & sends a Vec of plaintexts 159 | */ 160 | void DGK::encSndRcvVec(e_role role, vector &plaintexts, mpz_t* &ciphertexts, channel* &chan){ 161 | 162 | 163 | struct timespec start, end; 164 | uint32_t shareBytes = m_nShareLength / 8; 165 | uint32_t offset = 0; 166 | 167 | clock_gettime(CLOCK_MONOTONIC, &start); 168 | 169 | BYTE *m_encSndBuf, *m_encRcvBuf; 170 | m_encSndBuf = (BYTE*) calloc(plaintexts.size() * m_nBuflen, 1); 171 | m_encRcvBuf = (BYTE*) calloc(plaintexts.size() * m_nBuflen, 1); 172 | 173 | encrypt(plaintexts, m_encSndBuf); 174 | 175 | clock_gettime(CLOCK_MONOTONIC, &end); 176 | 177 | // send & receive encrypted values 178 | int window = WINDOWSIZE; 179 | int tosend = m_nBuflen * plaintexts.size(); 180 | offset = 0; 181 | 182 | while (tosend > 0) { 183 | 184 | window = min(window, tosend); 185 | 186 | chan->send(m_encSndBuf + offset, window); 187 | chan->blocking_receive(m_encRcvBuf + offset, window); 188 | 189 | tosend -= window; 190 | offset += window; 191 | } 192 | 193 | #if CHECKCOMM 194 | for(int i = 0;i < m_nBuflen * plaintexts.size();i++) { 195 | if(m_encRcvBuf[i] != m_encSndBuf[i]){ 196 | std::cout << "Error: buff is not received correctly!" << std::endl; 197 | break; 198 | } else if(i+1 == m_nBuflen * plaintexts.size()) { 199 | std::cout << "checking successful." << std::endl; 200 | } 201 | } 202 | 203 | #endif 204 | 205 | //reconstructs the CTs from the received raw data buffer 206 | 207 | ciphertexts = (mpz_t*) calloc(plaintexts.size(), sizeof(mpz_t)); 208 | 209 | for(int i = 0; i < plaintexts.size();i++){ 210 | 211 | mpz_init(ciphertexts[i]); 212 | mpz_import(ciphertexts[i], m_nBuflen, -1, 1, 1, 0, m_encRcvBuf + i * m_nBuflen); 213 | //gmp_printf ("feature %d is %Zx\n", i, ciphertexts[i]); 214 | } 215 | 216 | //TODO: free unnecessary bufs 217 | } 218 | 219 | void DGK::mskSndRcvVec(e_role role, mpz_t* &CTs, mpz_t* &rndMsks, vector &mapping, mpz_t* &inputsVec, channel* &chan){ 220 | 221 | mpz_t tmp, rnd, res; 222 | mpz_inits(tmp, rnd, res, NULL); 223 | 224 | uint32_t statisParam = 40; 225 | 226 | BYTE *m_encSndBuf, *m_encRcvBuf; 227 | int bufSize = mapping.size() * m_nBuflen; 228 | m_encSndBuf = (BYTE*) calloc(bufSize, 1); 229 | m_encRcvBuf = (BYTE*) calloc(bufSize, 1); 230 | 231 | for(int i=0;i < mapping.size();i++){ 232 | 233 | //mpz_set_ui(rnd, rndMsks[i]); // mask > 100 bits 234 | mpz_set (rnd, rndMsks[i]); 235 | //mpz_urandomb(rnd, m_randstate, m_nShareLength - 1); 236 | 237 | dgk_encrypt_plain(res, m_remotepub, rnd); // server encrypts the mask 238 | 239 | mpz_mul(res, res, CTs[mapping[i]]); // masks the feature homomorphically 240 | mpz_mod(res,res, m_remotepub->n); //res % modulus n 241 | 242 | mpz_export(m_encSndBuf + i * m_nBuflen, NULL, -1, 1, 1, 0, res); // embeds the masked inputs in Snd buffer 243 | 244 | } 245 | 246 | // send & receive encrypted values 247 | int window = WINDOWSIZE; 248 | int tosend = m_nBuflen * mapping.size(); 249 | int offset = 0; 250 | 251 | while (tosend > 0) { 252 | 253 | window = min(window, tosend); 254 | 255 | chan->send(m_encSndBuf + offset, window); 256 | chan->blocking_receive(m_encRcvBuf + offset, window); 257 | 258 | tosend -= window; 259 | offset += window; 260 | } 261 | 262 | #if CHECKCOMM 263 | 264 | for(int i = 0;i < bufSize;i++) { 265 | if(m_encRcvBuf[i] != m_encSndBuf[i]){ 266 | std::cout << "Error: buff is not received correctly!" << std::endl; 267 | break; 268 | } else if(i+1 == bufSize) { 269 | std::cout << "checking successful." << std::endl; 270 | } 271 | } 272 | 273 | #endif 274 | 275 | //reconstructs the CTs from the received raw data buffer 276 | 277 | mpz_t* m_pCTVec = (mpz_t*) calloc(mapping.size(), sizeof(mpz_t)); //TODO: get rid of this 278 | inputsVec = (mpz_t*) calloc(mapping.size(), sizeof(mpz_t)); //inputs to the substraction circuit in plaintext 279 | 280 | for(int i = 0; i < mapping.size();i++){ 281 | 282 | mpz_inits(m_pCTVec[i], inputsVec[i], NULL); 283 | //mpz_import(m_pCTVec[i], m_nBuflen, -1, 1, 1, 0, m_encRcvBuf + i * m_nBuflen); 284 | //dgk_decrypt(inputsVec[i],m_localpub, m_prv, m_pCTVec[i]); // decryps the inputs here before returning the vec 285 | } 286 | 287 | //TODO: free unnecessary bufs; 288 | } 289 | 290 | /** 291 | * exchanges private keys with other party via sock, pre-calculates fixed-base representation of remote pub-key 292 | */ 293 | void DGK::keyExchange(channel* &chan) { 294 | 295 | //send public key 296 | sendmpz_t(m_localpub->n, chan); 297 | sendmpz_t(m_localpub->g, chan); 298 | sendmpz_t(m_localpub->h, chan); 299 | 300 | //receive and complete public key 301 | mpz_t n, g, h; 302 | mpz_inits(n, g, h, NULL); 303 | receivempz_t(n, chan); //n 304 | receivempz_t(g, chan); //g 305 | receivempz_t(h, chan); //h 306 | 307 | dgk_complete_pubkey(m_nDGKbits, m_nShareLength, &m_remotepub, n, g, h); 308 | 309 | // pre calculate table for fixed-base exponentiation for client 310 | fbpowmod_init_g(m_remotepub->g, m_remotepub->n, 2 * m_nShareLength + 2); 311 | fbpowmod_init_h(m_remotepub->h, m_remotepub->n, 400); // 2.5 * t = 2.5 * 160 = 400 bit 312 | 313 | //free a and b 314 | mpz_clears(n, g, h, NULL); 315 | 316 | #if DEBUG 317 | std::cout << "KX done. This pubkey: " << m_localpub->n << " remotekey: " << m_remotepub->n << std::endl; 318 | #endif 319 | } 320 | 321 | /** 322 | * send one mpz_t to sock 323 | */ 324 | void DGK::sendmpz_t(mpz_t t, channel* chan, BYTE * buf) { 325 | 326 | //clear upper bytes of the buffer, so tailing bytes are zero 327 | for (int i = mpz_sizeinbase(t, 256); i < m_nBuflen; i++) { 328 | *(buf + i) = 0; 329 | } 330 | 331 | #if NETDEBUG 332 | std::cout << mpz_sizeinbase(t, 256) << " vs. " << m_nBuflen << std::endl; 333 | #endif 334 | 335 | mpz_export(buf, NULL, -1, 1, 1, 0, t); 336 | 337 | //send bytes of t 338 | chan->send(buf, (uint64_t) m_nBuflen); 339 | 340 | #if NETDEBUG 341 | std::cout << std::endl << "SEND" << std::endl; 342 | for (int i = 0; i < m_nBuflen; i++) { 343 | printf("%02x.", *(buf + i)); 344 | } 345 | 346 | std::cout << std::endl << "sent: " << t << " with len: " << m_nBuflen << " should have been " << mpz_sizeinbase(t, 256) << std::endl; 347 | #endif 348 | } 349 | 350 | /** 351 | * receive one mpz_t from sock. t must be initialized. 352 | */ 353 | void DGK::receivempz_t(mpz_t t, channel* chan, BYTE * buf) { 354 | chan->blocking_receive(buf, (uint64_t) m_nBuflen); 355 | mpz_import(t, m_nBuflen, -1, 1, 1, 0, buf); 356 | 357 | #if NETDEBUG 358 | std::cout << std::endl << "RECEIVE" << std::endl; 359 | for (int i = 0; i < m_nBuflen; i++) { 360 | printf("%02x.", *(buf + i)); 361 | } 362 | 363 | std::cout << "received: " << t << " with len: " << m_nBuflen << std::endl; 364 | #endif 365 | } 366 | 367 | /** 368 | * send one mpz_t to sock, allocates buffer 369 | */ 370 | void DGK::sendmpz_t(mpz_t t, channel* chan) { 371 | unsigned int bytelen = mpz_sizeinbase(t, 256); 372 | BYTE* arr = (BYTE*) malloc(bytelen); 373 | mpz_export(arr, NULL, 1, 1, 1, 0, t); 374 | 375 | //send byte length 376 | chan->send((BYTE*) &bytelen, sizeof(bytelen)); 377 | 378 | //send bytes of t 379 | chan->send(arr, (uint64_t) bytelen); 380 | 381 | free(arr); 382 | #if NETDEBUG 383 | std::cout << "sent: " << t << " with len: " << bytelen << std::endl; 384 | #endif 385 | } 386 | 387 | /** 388 | * receive one mpz_t from sock. t must be initialized. 389 | */ 390 | void DGK::receivempz_t(mpz_t t, channel* chan) { 391 | unsigned int bytelen; 392 | 393 | //reiceive byte length 394 | chan->blocking_receive((BYTE*) &bytelen, sizeof(bytelen)); 395 | BYTE* arr = (BYTE*) malloc(bytelen); 396 | 397 | //receive bytes of t 398 | chan->blocking_receive(arr, (uint64_t) bytelen); 399 | mpz_import(t, bytelen, 1, 1, 1, 0, arr); 400 | 401 | free(arr); 402 | #if NETDEBUG 403 | std::cout << "received: " << t << " with len: " << bytelen << std::endl; 404 | #endif 405 | } 406 | 407 | void DGK::printBuf(BYTE* b, uint32_t len) { 408 | for (uint32_t i = 0; i < len; i++) { 409 | printf("%02x.", *(b + i)); 410 | } 411 | std::cout << std::endl; 412 | } 413 | 414 | -------------------------------------------------------------------------------- /XCMP_files/benchmark_gt/dectree.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | \file dectree.hpp 3 | \author kiss@encrypto.cs.tu-darmstadt.de 4 | \copyright Decision Tree 5 | Copyright (C) 2019 Cryptography and Privacy Engineering Group, TU Darmstadt 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Affero General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | You should have received a copy of the GNU Affero General Public License 15 | along with this program. If not, see . 16 | \brief DecTree class for reading in decision trees generated from scikit-learn. 17 | */ 18 | 19 | #ifndef DECTREE_H_INCLUDED 20 | #define DECTREE_H_INCLUDED 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include /* pow */ 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | typedef mcl::FpT<> Fp; 46 | typedef mcl::FpT Zn; // use ZnTag because Zn is different class with Fp 47 | typedef mcl::EcT Ec; 48 | typedef mcl::ElgamalT Elgamal; 49 | 50 | using namespace std; 51 | 52 | class DecTree { 53 | public: 54 | struct Node { 55 | // Pointer to the first child node 56 | Node* left; 57 | // Pointer to the second child node 58 | Node* right; 59 | // Pointer to the first parent node 60 | Node* parent; 61 | // True if the edges coming into the node are already colored 62 | uint32_t level; 63 | // True if the node is a leaf 64 | bool leaf; 65 | // Threshold in decision node to compare with 66 | uint64_t threshold; 67 | // Threshold in decision node to compare with 68 | uint64_t classification; 69 | // Attribute index to compare with, -1 if undefined 70 | uint32_t attribute_index; 71 | //pathcost until this node 72 | Elgamal::CipherText path_cost; 73 | 74 | Node(); 75 | Node(const Node&); 76 | }; 77 | // Vector of nodes that belong to the Gamma1 graph 78 | vector node_vec; 79 | // Vector of decision nodes that belong to the Gamma1 graph 80 | vector decnode_vec; 81 | //Node** node_array; 82 | // Vector of all attributes used for comparison with their occurrence 83 | vector attributes; 84 | // Vector of all thresholds used for comparison with their occurrence 85 | vector thresholds; 86 | 87 | //STATISTICS FOR DECISION TREES 88 | //number of attributes 89 | uint32_t num_attributes; 90 | //number of decision nodes 91 | uint32_t num_dec_nodes; 92 | //depth = largest level of leaves 93 | uint32_t depth; 94 | //number of leaves 95 | uint32_t num_of_leaves; 96 | //dummy in our case 97 | uint32_t dummy_non_full; 98 | 99 | DecTree(); 100 | DecTree(const DecTree&); 101 | 102 | void add_node(Node*); 103 | void add_decnode(Node*); 104 | void add_edge(Node*, Node*); 105 | void read_from_file(string); 106 | void evaluate(vector inputs); 107 | void depthPad(); 108 | void fullTree(uint32_t num_att, uint32_t depth); 109 | 110 | ~DecTree(); 111 | }; 112 | 113 | void tokenize(const std::string&, std::vector&); 114 | void eraseSubStr(std::string &, const std::string &); 115 | 116 | /** 117 | * Node constructor that takes its number num, by default it has no children 118 | * and parents, is not colored. 119 | * @param num the number that identifies the node 120 | */ 121 | DecTree::Node::Node() 122 | : left(0) 123 | , right(0) 124 | , parent(0) 125 | , level(0) 126 | , leaf(false) 127 | , threshold(0) 128 | , attribute_index(0) 129 | , classification(0) 130 | {} 131 | 132 | DecTree::Node::Node(const Node& other){ 133 | left = new Node(*(other.left)); 134 | right = new Node(*(other.right)); 135 | parent = new Node(*(other.parent)); 136 | level = other.level; 137 | leaf = other.leaf; 138 | threshold = other.threshold; 139 | attribute_index = other.attribute_index; 140 | classification = other.classification; 141 | } 142 | 143 | /** 144 | * Gamma2 constructor that creates a Gamma2 graph with specified number of Nodes 145 | * @param num the number specifying the number of Nodes 146 | */ 147 | DecTree::DecTree() 148 | { 149 | num_attributes = 0; 150 | num_dec_nodes = 0; 151 | depth = 0; 152 | num_of_leaves = 0; 153 | dummy_non_full = 0; 154 | } 155 | 156 | DecTree::DecTree(const DecTree& other){ 157 | node_vec = other.node_vec; 158 | decnode_vec = other.decnode_vec; 159 | attributes = other.attributes; 160 | thresholds = other.thresholds; 161 | num_attributes = other.num_attributes; 162 | num_dec_nodes = other.num_dec_nodes; 163 | depth = other.depth; 164 | num_of_leaves = other.num_of_leaves; 165 | dummy_non_full = other.dummy_non_full; 166 | } 167 | 168 | /** 169 | * Add a node 170 | * @param node the Node to be added to the tree 171 | */ 172 | void DecTree::add_node(DecTree::Node* node){ 173 | node_vec.push_back(node); 174 | } 175 | 176 | /** 177 | * Add a decision node 178 | * @param node the Node to be added to the tree 179 | */ 180 | void DecTree::add_decnode(DecTree::Node* node){ 181 | decnode_vec.push_back(node); 182 | } 183 | 184 | /** 185 | * Add an edge between two nodes 186 | * @param n1 the starting Node of the edge 187 | * @param n2 the ending Node of the edge 188 | */ 189 | void DecTree::add_edge(DecTree::Node* n1, DecTree::Node* n2){ 190 | n2->parent = n1; 191 | n2->level = n1->level + 1; 192 | if(n1->left == NULL){ 193 | n1->left = n2; 194 | } 195 | else{ 196 | n1->right = n2; 197 | } 198 | } 199 | 200 | /** 201 | * Takes a string in the Format "i i i ..." separated by ' ' 202 | * @param str the string to tokenize 203 | * @param tokens the result vector of wire id 204 | */ 205 | void tokenize(const std::string& str, std::vector& tokens) { 206 | tokens.clear(); 207 | std::size_t prev = 0, pos; 208 | while ((pos = str.find_first_of(" [] \\ ", prev)) != std::string::npos) 209 | { 210 | if (pos > prev) 211 | tokens.push_back(str.substr(prev, pos-prev)); 212 | prev = pos+1; 213 | } 214 | if (prev < str.length()) 215 | tokens.push_back(str.substr(prev, std::string::npos)); 216 | } 217 | 218 | /** 219 | * Erase First Occurrence of given substring from main string. 220 | */ 221 | void eraseSubStr(std::string & mainStr, const std::string & toErase) 222 | { 223 | // Search for the substring in string 224 | size_t pos = mainStr.find(toErase); 225 | 226 | if (pos != std::string::npos) 227 | { 228 | // If found then erase it from string 229 | mainStr.erase(pos, toErase.length()); 230 | } 231 | } 232 | 233 | class SearchFunction { 234 | public: 235 | SearchFunction(uint32_t item): item_(item) {} 236 | bool operator()(std::uint64_t const & ref) { 237 | return ref == item_; 238 | } 239 | private: 240 | uint32_t item_; 241 | }; 242 | 243 | //root node will be in decnode_vec[0] and node_vec[0] 244 | void DecTree::read_from_file(string string_file){ 245 | const char* filename = string_file.c_str(); 246 | ifstream file; 247 | file.open(filename); 248 | cout << filename << endl; 249 | 250 | //ofstream file2; 251 | //file2.open("dectree.txt", std::ios_base::app); 252 | 253 | uint32_t node1; 254 | uint32_t node2; 255 | 256 | DecTree::Node* node; 257 | uint32_t index; 258 | string line; 259 | vector tokens; 260 | vector::iterator it; 261 | float thres; 262 | while (getline(file, line)){ 263 | tokenize(line, tokens); 264 | if(tokens[1] == "label=\"gini"){ 265 | node1 = atoi(tokens[0].c_str()); 266 | this->add_node(new DecTree::Node()); 267 | this->node_vec[node1]->leaf = true; 268 | this->num_of_leaves++; 269 | this->node_vec[node1]->classification = atoi(tokens[6].c_str()); 270 | } 271 | else if(tokens[1] == "label=\"X"){ 272 | node1 = atoi(tokens[0].c_str()); 273 | //cout << node1 << endl; 274 | node = new DecTree::Node(); 275 | index = atoi(tokens[2].c_str()); 276 | node->attribute_index = index; 277 | //cout << index << endl; 278 | thres = atof(tokens[4].c_str()); 279 | node->threshold = thres*1000; 280 | //cout << node->threshold << endl; //Thresholds are converted so that we only compare integers 281 | this->num_dec_nodes++; 282 | this->add_node(node); 283 | this->add_decnode(node); 284 | 285 | it = find_if(this->attributes.begin(), this->attributes.end(), SearchFunction(index)); 286 | if(it == this->attributes.end()){ 287 | this->num_attributes++; 288 | } 289 | this->attributes.push_back(index); 290 | this->thresholds.push_back(node->threshold); 291 | } 292 | else if(tokens[1] == "->"){ 293 | node1 = atoi(tokens[0].c_str()); 294 | node2 = atoi(tokens[2].c_str()); 295 | this->add_edge(this->node_vec[node1], this->node_vec[node2]); 296 | } 297 | } 298 | for(uint32_t i = 0; i < this->node_vec.size(); ++i){ 299 | node = this->node_vec[i]; 300 | if(node->leaf){ //Right is also 0 in this case 301 | if(node->level > this->depth){ 302 | this->depth = node->level; 303 | } 304 | } 305 | } 306 | //cout << "Total number of attributes " << this->num_attributes << endl; 307 | //cout << "Depth of the tree " << this->depth << endl; 308 | //cout << "Total number of decision nodes " << this->num_dec_nodes << endl; 309 | //cout << "Total number of leaves " << this->num_of_leaves << endl; 310 | 311 | for(uint32_t i = 0; i < this->node_vec.size(); ++i){ 312 | node = this->node_vec[i]; 313 | if(node->leaf){ 314 | this->dummy_non_full += this->depth - node->level; 315 | } 316 | } 317 | //cout << "Total number of dummy nodes in non-full tree " << this->dummy_non_full << endl; 318 | 319 | uint32_t total_number_of_edges = 0; 320 | for(uint32_t i = 0; i < this->node_vec.size(); ++i){ 321 | node = this->node_vec[i]; 322 | if(node->leaf){ 323 | total_number_of_edges += node->level; 324 | } 325 | } 326 | //cout << "Total number of edges " << total_number_of_edges << endl; 327 | file.close(); 328 | //file2.close(); 329 | } 330 | 331 | 332 | void DecTree::fullTree(uint32_t num_att, uint32_t tree_depth){ 333 | this->num_attributes = num_att; 334 | this->num_dec_nodes = pow(2.0, num_att); 335 | this->depth = tree_depth; 336 | this->num_of_leaves = pow(2.0, num_att + 1); 337 | vector attr(num_att, 0); 338 | vector thres(this->num_dec_nodes, 0); 339 | this->attributes = attr; 340 | this->thresholds = thres; 341 | 342 | for(uint32_t i = 0; i < this->num_dec_nodes + this->num_of_leaves; ++i){ 343 | DecTree::Node* newNode = new DecTree::Node(); 344 | if(i == 0){ 345 | newNode->parent = NULL; 346 | newNode->level = 0; 347 | } 348 | else if(i%2 == 0){ 349 | this->node_vec[i/2 - 1]->right = newNode; 350 | newNode->parent = this->node_vec[i/2 - 1]; 351 | newNode->level = newNode->parent->level + 1; 352 | } 353 | else if(i%2 == 1){ //odd case 354 | this->node_vec[i/2]->left = newNode; 355 | newNode->parent = this->node_vec[i/2]; 356 | newNode->level = newNode->parent->level + 1; 357 | } 358 | 359 | if(i < this->num_dec_nodes){ 360 | this->decnode_vec.push_back(newNode); 361 | } 362 | else{ 363 | newNode->leaf = true; 364 | } 365 | this->node_vec.push_back(newNode); 366 | } 367 | } 368 | 369 | void DecTree::depthPad(){ 370 | DecTree::Node* tmp; 371 | for(uint32_t i = 0; i < this->node_vec.size(); ++i){ 372 | if(this->node_vec[i]->leaf){ 373 | if(this->node_vec[i]->level != this->depth){ 374 | tmp = this->node_vec[i]; 375 | this->node_vec[i] = new DecTree::Node(); 376 | this->node_vec[i]->parent = tmp->parent; 377 | this->node_vec[i]->level = tmp->level; //leaf is false, threshold is 0, attribute_index is 0 378 | this->decnode_vec.push_back(this->node_vec[i]); 379 | this->attributes.push_back(this->node_vec[i]->attribute_index); 380 | this->thresholds.push_back(this->node_vec[i]->threshold); 381 | this->num_dec_nodes++; 382 | 383 | tmp->level++; 384 | tmp->parent = this->node_vec[i]; 385 | this->node_vec[i]->left = tmp; 386 | this->node_vec[i]->right = tmp; 387 | this->node_vec.push_back(tmp); 388 | } 389 | } 390 | } 391 | //cout << "Number of decision nodes " << this->num_dec_nodes << endl; 392 | } 393 | 394 | void DecTree::evaluate(vector inputs){ 395 | DecTree::Node* this_node = this->node_vec[0]; 396 | while(!(this_node->leaf)){ 397 | //cout << inputs[this_node->attribute_index] << endl; 398 | //cout << this_node->threshold << endl; 399 | if(inputs[this_node->attribute_index] <= this_node->threshold){ 400 | this_node = this_node->left; 401 | } 402 | else{ 403 | this_node = this_node->right; 404 | } 405 | } 406 | } 407 | 408 | /** 409 | * Destructor DecTree 410 | */ 411 | DecTree::~DecTree(){ 412 | node_vec.clear(); 413 | } 414 | 415 | #endif // DECTREE_H_INCLUDED 416 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/decision-tree-circuit.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | \file decision-tree-circuit.cpp 3 | \author masoud.naderpour@helsinki.fi 4 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 5 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | ABY is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Lesser General Public License for more details. 14 | You should have received a copy of the GNU Lesser General Public License 15 | along with this program. If not, see . 16 | \brief Private decision tree evaluation 17 | */ 18 | 19 | #include "decision-tree-circuit.h" 20 | #include "garbledBP.h" 21 | #include "sndrcv.h" 22 | #include 23 | #include 24 | #include "auxiliary-functions.h" 25 | #include "../../../abycore/sharing/sharing.h" 26 | 27 | //#define AES_NOT_HASH 28 | 29 | int pri_eval_decision_tree(e_role role, char* address, uint16_t port, seclvl seclvl, uint32_t nthreads, e_mt_gen_alg mt_alg, e_sharing comparesharing, e_sel_alg sel_alg, uint64_t numNodes, uint64_t dimension, DecTree &tree) { 30 | 31 | //=============== Initialization ================ 32 | 33 | uint32_t bitlen = 8, i, j, maxbitlen=64, keybitlen = seclvl.symbits, keysize = keybitlen/8; 34 | uint16_t m_numNodes = numNodes; 35 | uint16_t dim = dimension; 36 | uint32_t nodeSize = keysize + sizeof(uint16_t) + sizeof(uint8_t); 37 | uint8_t *m_cGarbledTree; 38 | 39 | timeval tbegin, tend; 40 | srand(time(NULL)); 41 | 42 | // ----- generate a random permutation of [0 1...d-1] ---------- 43 | uint16_t *permutation; 44 | permutation = new uint16_t[m_numNodes]; 45 | for (uint16_t i = 0;i < m_numNodes;i++) permutation[i] = i; 46 | random_shuffle(permutation + 1, permutation + m_numNodes ); //permutation[0] = 0 */ 47 | 48 | //----------- generate a random feature vector ---------------- 49 | vector m_vFeatureVec; 50 | 51 | for(int i=0; i < dim; i++){ 52 | m_vFeatureVec.push_back(rand()); 53 | //cout << "Feature " << i << ":" << m_vFeatureVec[i] << endl; 54 | } 55 | 56 | // ---- ABY init -------- 57 | ABYParty* party = new ABYParty(role, address, port, seclvl, keybitlen, nthreads, mt_alg); 58 | 59 | vector& sharings = party->GetSharings(); 60 | BooleanCircuit *permuteCirc, *cmpCirc; 61 | //permuteCirc = (BooleanCircuit*) sharings[S_BOOL]->GetCircuitBuildRoutine(); // for B+Y testing 62 | cmpCirc = (BooleanCircuit*) sharings[S_YAO]->GetCircuitBuildRoutine(); 63 | permuteCirc = cmpCirc; 64 | 65 | share **m_shrCircOutput, **output; 66 | 67 | //----- Communication channel establishment ---------- 68 | NetConnection* netConnection = new NetConnection(address, port+1); 69 | if (!netConnection->EstConnection(role)) { 70 | std::exit(EXIT_FAILURE); 71 | } 72 | 73 | //===============Feature selection =================== 74 | switch(sel_alg) { 75 | case SEL_HE: 76 | { 77 | cout << "**Runing oblivious selection subprotocol (homomorphic encryption)..." << endl; 78 | selction_HE(role, netConnection->commChannel, m_vFeatureVec, seclvl, numNodes, permutation, cmpCirc, m_shrCircOutput); 79 | } 80 | break; 81 | case SEL_GC: 82 | { 83 | cout << "**Runing oblivious selection subprotocol (garbled circuit)..." << endl; 84 | selction_GC(m_vFeatureVec, m_numNodes, permutation, cmpCirc, m_shrCircOutput); 85 | } 86 | break; 87 | } 88 | cout << "\n**Running oblivious comparison subprotocol (Yao's garbled circuit protocol)..." << endl; 89 | party->ExecCircuit(); 90 | 91 | //------garbled key/colour bit per node-------- 92 | uint8_t **circuitOutputKeys = (uint8_t**) malloc(sizeof(uint8_t*) * m_numNodes); 93 | 94 | for (i = 0;i < m_numNodes;i++) { 95 | circuitOutputKeys[i] = (uint8_t*) malloc(sizeof(uint8_t) * keysize); 96 | memcpy(circuitOutputKeys[i], cmpCirc->GetEvaluatedKey(m_shrCircOutput[i]->get_wire_id(0)), keysize); 97 | //cout << "circuitOutputKeys" << i << ": "; print(circuitOutputKeys[i], keysize); 98 | } 99 | 100 | ofstream serverOutputFile ("server_colour_bits.txt"); 101 | ofstream clientOutputFile ("client_colour_bits.txt"); 102 | BYTE *pi, colorBit; 103 | CSocket socket; 104 | uint16_t port = 7750; 105 | 106 | if (role == SERVER) { 107 | if (serverOutputFile.is_open()) { 108 | cout << "Writing server colour bits to file..." << endl; 109 | for (i = 0; i < numNodes; i++) { 110 | pi = permuteCirc->GetPi(m_shrCircOutput[i]->get_wire_id(0)); 111 | serverOutputFile << int(*pi) << endl; 112 | } 113 | serverOutputFile.close(); 114 | } 115 | 116 | BYTE *tmp, *R, *pi, colorBit; 117 | tmp = new uint8_t[keysize]; 118 | R = new uint8_t[keysize]; 119 | uint8_t **pointerKey, *binPermute; 120 | pointerKey = new uint8_t*[2*m_numNodes]; 121 | binPermute = new uint8_t[m_numNodes]; 122 | 123 | memcpy(R, ((YaoServerSharing*)sharings[S_YAO])->get_R().GetArr(), keysize); //R: global difference of garbled pairs 124 | 125 | for (i = 0; i < m_numNodes; i++){ 126 | pointerKey[2*i] = new uint8_t[keysize]; 127 | pointerKey[2*i+1] = new uint8_t[keysize]; 128 | memcpy(tmp, permuteCirc->GetServerRandomKey(m_shrCircOutput[i]->get_wire_id(0)), keysize); 129 | pi = permuteCirc->GetPi(m_shrCircOutput[i]->get_wire_id(0)); 130 | memcpy(binPermute + i, pi, sizeof(uint8_t)); 131 | memcpy(pointerKey[2 * i], tmp, keysize); 132 | Xor(tmp, R, keysize); 133 | memcpy(pointerKey[2 * i + 1], tmp, keysize); 134 | } 135 | 136 | cout << "\n**Running oblivious path evaluation subprotocol (garbled decision tree)..." << endl; 137 | gettimeofday(&tbegin, NULL); 138 | m_cGarbledTree = create_garbled_tree(tree, seclvl, pointerKey, binPermute, permutation); 139 | gettimeofday(&tend, NULL); 140 | 141 | sendGarbledDT( netConnection->commChannel , m_numNodes, nodeSize, m_cGarbledTree ); 142 | cout << "SERVER: Created garbled decision tree in: " << time_diff_microsec(tbegin, tend) << "us" << endl; 143 | } else { // role = client 144 | if (clientOutputFile.is_open()) { 145 | cout << "Writing client colour bits to file..." << endl; 146 | for (i = 0; i < numNodes; i++) { 147 | colorBit = circuitOutputKeys[i][keysize-1] & 0x01; 148 | clientOutputFile << int(colorBit) << endl; 149 | } 150 | clientOutputFile.close(); 151 | } 152 | cout << "\n**Running oblivious path evaluation subprotocol (garbled decision tree)..." << endl; 153 | m_cGarbledTree = (uint8_t*) malloc(sizeof(uint8_t) *m_numNodes * nodeSize * 2); 154 | bool success = false; 155 | success = receiveGarbledDT(netConnection->commChannel, m_numNodes, nodeSize, m_cGarbledTree); 156 | if (success) { 157 | Eval_garbled_tree( m_cGarbledTree, circuitOutputKeys, m_numNodes, seclvl.symbits/8, nodeSize, seclvl); 158 | } 159 | } 160 | 161 | //TODO: free 162 | delete party; 163 | return 0; 164 | } 165 | 166 | uint8_t* create_garbled_tree(DecTree &dectree, seclvl seclvl, uint8_t** pointerKey, uint8_t* binPermute, uint16_t* permutation){ 167 | 168 | crypto *crypt = new crypto(seclvl.symbits, (uint8_t*) const_seed); 169 | //cout << "seclvl.symbits: " << seclvl.symbits << endl; 170 | const int type = sizeof(uint8_t), nodeIdxSize = sizeof(uint16_t), keySize = seclvl.symbits/8; // Size * Byte 171 | const int size = type + nodeIdxSize + keySize; //1+2+16 172 | //cout << "data size: " << size << endl; 173 | 174 | // n: number of nodes, d: number of decision nodes 175 | uint16_t n = dectree.node_vec.size(), d = dectree.num_dec_nodes; 176 | 177 | //generate random numbers as keys to hash fuction 178 | uint8_t **nodeKey; 179 | nodeKey = new uint8_t*[d]; 180 | 181 | for(int i = 0; i < d; i++){ 182 | nodeKey[i] = new uint8_t[keySize]; 183 | crypt->gen_rnd(nodeKey[i],keySize); 184 | //print(nodeKey[i],keySize); 185 | } 186 | //nodekey[0] = 0 187 | memset(nodeKey[0],0,keySize); 188 | //print(nodeKey[0],keySize); 189 | 190 | //create garbled decision tree 191 | garbldNode *garbledTree = new garbldNode[d]; 192 | uint8_t *gTree = (uint8_t*) malloc(sizeof(uint8_t) * d * size * 2); 193 | 194 | 195 | //copy node data from tree 196 | uint64_t global_index = 0; 197 | uint16_t i,j, rindex , lindex; 198 | uint32_t length = 0; 199 | DecTree::Node* current_node; 200 | 201 | for(i = 0; i < dectree.num_dec_nodes; i++){ 202 | 203 | current_node = dectree.decnode_vec[i]; 204 | j = permutation[i]; 205 | garbledTree[j].rnode = new uint8_t[size]; 206 | garbledTree[j].lnode = new uint8_t[size]; 207 | uint8_t *r = garbledTree[j].rnode, *l = garbledTree[j].lnode; 208 | 209 | if (current_node->right != current_node->left) { // non-dummy node 210 | 211 | //left node's data of node i in garbled Tree : [TYPE, PERMUTED INDEX, DELTA] 212 | lindex = ++global_index; 213 | if (!(current_node->left->leaf)){ 214 | *l = 0x00; // type : decision 215 | memcpy(l+type, &(permutation[lindex]), nodeIdxSize); //nodeId 216 | memcpy(l+type+nodeIdxSize, nodeKey[permutation[lindex]], keySize); //nodeKey 217 | } 218 | else{ 219 | *l = 0x01; // type : classification 220 | memcpy(l+type, &(current_node->left->classification), sizeof(uint64_t)); // Classification label 221 | memset(l+type+length, 0, size-(type+length));//Padding 222 | 223 | } 224 | //print(l,size); 225 | 226 | //right node: 227 | rindex = ++global_index; 228 | if (!(current_node->right->leaf)){ 229 | *r = 0x00; // type : decision 230 | memcpy(r+type, &(permutation[rindex]), nodeIdxSize); //nodeId 231 | memcpy(r+type+nodeIdxSize, nodeKey[permutation[rindex]], keySize); // nodeKey 232 | } 233 | else{ 234 | *r = 0x01; // type : classification 235 | memcpy(l+type, &(current_node->right->classification), sizeof(uint64_t)); // Classification label 236 | memset(l+type+length, 0, size-(type+length));//Padding 237 | } 238 | //print(r,size); 239 | } else { 240 | 241 | lindex = ++global_index; 242 | if (!(current_node->left->leaf)){ 243 | *l = 0x00; // type : decision 244 | memcpy(l+type, &(permutation[lindex]), nodeIdxSize); //nodeId 245 | memcpy(l+type+nodeIdxSize, nodeKey[permutation[lindex]], keySize); //nodeKey 246 | } 247 | else{ 248 | *l = 0x01; // type : classification 249 | memcpy(l+type, &(current_node->left->classification), sizeof(uint64_t)); // Classification label 250 | memset(l+type+length, 0, size-(type+length));//Padding 251 | 252 | } 253 | //print(l,size); 254 | 255 | //right node: 256 | rindex = lindex; //dummy node 257 | memcpy(r, l, size); 258 | //print(r,size); 259 | } 260 | } 261 | 262 | uint8_t *key, *ExpKey, colorBit; 263 | key = new uint8_t[keySize]; 264 | ExpKey = new uint8_t[size]; 265 | 266 | //cout << "Encrypted nodes:" << endl; 267 | 268 | for( i = 0;i < d;i++ ){ 269 | colorBit = (pointerKey[2 * i][keySize-1]) & 0x01; 270 | 271 | //Encrypt left node 272 | memcpy(key, nodeKey[i], keySize); 273 | timeval tbegin, tend; 274 | gettimeofday(&tbegin, NULL); 275 | 276 | #ifdef AES_NOT_HASH 277 | uint8_t* one = {}; 278 | crypt->encrypt(ExpKey, one, keySize); 279 | //crypt->encrypt(Xor(key, pointerKey[2 * i + (colorBit ^ binPermute[i])], keySize), ExpKey, one, keySize); 280 | //crypt->encrypt(Xor(key, pointerKey[2 * i + (colorBit ^ binPermute[i])], keySize), ExpKey, zero, keySize); 281 | #else 282 | crypt->hash(ExpKey, size, Xor(key, pointerKey[2 * i + (colorBit ^ binPermute[i])], keySize), keySize); 283 | #endif 284 | 285 | gettimeofday(&tend, NULL); 286 | //cout << "Hash/AES Time: " << ((tend.tv_sec-tbegin.tv_sec)*1000000 + tend.tv_usec - tbegin.tv_usec) << "us" << endl; 287 | //cout << "hash keys: ";print(ExpKey,size); 288 | Xor(garbledTree[i].lnode, ExpKey, size); 289 | //cout << "l node: ";print(garbledTree[i].lnode,size); 290 | 291 | //Encrypt right node 292 | memcpy(key, nodeKey[i], keySize); 293 | 294 | #ifdef AES_NOT_HASH 295 | crypt->encrypt(ExpKey, one, keySize); 296 | //crypt->encrypt(Xor(key, pointerKey[2 * i + !(colorBit ^ binPermute[i])], keySize), ExpKey, one, keySize); 297 | #else 298 | crypt->hash(ExpKey, size, Xor(key, pointerKey[2 * i + !(colorBit ^ binPermute[i])], keySize), keySize); 299 | #endif 300 | 301 | //cout << "hash keys: "; print(ExpKey,size); 302 | Xor(garbledTree[i].rnode, ExpKey, size); 303 | //cout << "r node: ";print(garbledTree[i].rnode,size); 304 | 305 | 306 | //swap nodes randomly 307 | if (binPermute[i]){ 308 | swap(garbledTree[i].rnode, garbledTree[i].lnode); 309 | } 310 | memcpy(gTree+(2*i) * size, garbledTree[i].lnode, size); 311 | memcpy(gTree+(2*i + 1) * size, garbledTree[i].rnode, size); 312 | } 313 | 314 | //delete[] permutation; 315 | //delete[] garbledTree; 316 | return gTree; 317 | 318 | } 319 | 320 | int Eval_garbled_tree(uint8_t *garbledTree, uint8_t **keys, uint16_t d, uint32_t keysize, uint32_t msgsize, seclvl seclvl){ 321 | 322 | crypto *crypt = new crypto(seclvl.symbits, (uint8_t*) const_seed); 323 | timeval tbegin, tend; 324 | uint8_t *nodekey, *data, colorBit; 325 | uint16_t i, nodeID = 0 ; 326 | string classlabel; 327 | nodekey = new uint8_t[keysize]; 328 | data = new uint8_t[msgsize]; 329 | 330 | gettimeofday(&tbegin, NULL); 331 | memset(nodekey, 0, keysize); //nodekey[0] = 0 332 | i = 0; 333 | while(1){ 334 | 335 | #ifdef AES_NOT_HASH 336 | crypt->encrypt(Xor(nodekey, keys[i], keysize), data, one, keysize); 337 | #else 338 | crypt->hash(data, msgsize, Xor(nodekey, keys[i], keysize), keysize); 339 | #endif 340 | 341 | colorBit = keys[i][keysize-1] & 0x01; 342 | //Decrypting the currentnode 343 | if (colorBit = 0x00){ 344 | Xor(data, garbledTree + (2*i)*msgsize, msgsize); 345 | } else { 346 | Xor(data, garbledTree + (2*i+1)*msgsize, msgsize); 347 | } 348 | //evaluating the decrypted node 349 | if(data[0]){ //classification node 350 | //cout << " retrieved classification label! "; //TODO: print the classification value 351 | break; 352 | } else { //Decision node 353 | memcpy( &i, data+1, sizeof(uint16_t)); 354 | memcpy( nodekey, data+3, keysize); 355 | } 356 | } 357 | 358 | gettimeofday(&tend, NULL); 359 | printf("CLIENT: Evaluated garbled decision tree in: %.0lf us\n" , time_diff_microsec(tbegin , tend)); 360 | 361 | delete[] nodekey; 362 | delete[] data; 363 | return 0; 364 | } 365 | -------------------------------------------------------------------------------- /ABY_example/dectree/common/crypto_party/paillier_party.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | \file paillier_party.h 3 | \author masoud.naderpour@helsinki.fi 4 | \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation 5 | Copyright (C) 2019 Engineering Cryptographic Protocols Group, TU Darmstadt 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Lesser General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | ABY is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Lesser General Public License for more details. 14 | You should have received a copy of the GNU Lesser General Public License 15 | along with this program. If not, see . 16 | \brief Paillier crypto 17 | */ 18 | 19 | #include "paillier_party.h" 20 | 21 | #define CHECKCOMM 0 22 | #define DEBUG 0 23 | #define NETDEBUG 0 24 | #define WINDOWSIZE 50000 //maximum size of a network packet in Byte 25 | 26 | PaillierParty::PaillierParty(uint32_t PaillierBits, uint32_t readkey) { 27 | 28 | m_nShareLength = 104; 29 | m_nPaillierBits = PaillierBits; 30 | m_nBuflen = 2 * (PaillierBits / 8 ); //size of one ciphertext to send via network. Paillier uses 2n bits == 2n/8 bytes 31 | 32 | #if DEBUG 33 | std::cout << "Created party with " << PaillierBits << " key bits " << std::endl; 34 | #endif 35 | 36 | gmp_randinit_default(m_randstate); 37 | gmp_randseed_ui(m_randstate, rand()); 38 | 39 | if (readkey) { 40 | if (!readKey()){ 41 | std::cout << "No key file. Generating a new Paillier key." << std::endl; 42 | generateKey(); 43 | storeKey(); 44 | } 45 | } else { 46 | generateKey(); 47 | } 48 | } 49 | 50 | bool PaillierParty::readKey() { 51 | 52 | char smod[5]; 53 | char slbit[4]; 54 | char name[40] = "paillier_key_"; 55 | const char* div = "_"; 56 | const char* ext = ".bin"; 57 | 58 | sprintf(smod, "%d", m_nPaillierBits); 59 | 60 | strcat(name, smod); 61 | // strcat(name, div); 62 | strcat(name, ext); 63 | 64 | //printf("reading Paillier key from %s\n", name); 65 | 66 | /* allocate the new key structures */ 67 | m_localpub = (paillier_pubkey_t*) malloc(sizeof(paillier_pubkey_t)); 68 | m_prv = (paillier_prvkey_t*) malloc(sizeof(paillier_prvkey_t)); 69 | 70 | FILE *fp; 71 | fp = fopen(name, "r"); 72 | 73 | if(!fp) { 74 | //printf("Cannot find Paillier key's file!\n"); 75 | return 0; 76 | } 77 | 78 | /* initialize our integers */ 79 | mpz_init(m_localpub->n); 80 | mpz_init(m_localpub->n_squared); 81 | mpz_init(m_localpub->n_plusone); 82 | mpz_init(m_prv->lambda); 83 | mpz_init(m_prv->x); 84 | 85 | mpz_inp_raw(m_prv->lambda, fp); 86 | mpz_inp_raw(m_prv->x, fp); 87 | mpz_inp_raw(m_localpub->n, fp); 88 | mpz_inp_raw(m_localpub->n_squared, fp); 89 | mpz_inp_raw(m_localpub->n_plusone, fp); 90 | 91 | fclose(fp); 92 | 93 | m_localpub->bits = m_nPaillierBits; 94 | 95 | return 1; 96 | } 97 | 98 | void PaillierParty::storeKey(){ 99 | 100 | FILE *fp; 101 | 102 | char smod[5]; 103 | char slbit[4]; 104 | char name[40] = "paillier_key_"; 105 | const char* div = "_"; 106 | const char* ext = ".bin"; 107 | 108 | sprintf(smod, "%d", m_nPaillierBits); 109 | 110 | strcat(name, smod); 111 | // strcat(name, div); 112 | strcat(name, ext); 113 | 114 | //printf("writing Paillier key to %s\n", name); 115 | 116 | fp = fopen(name, "w"); 117 | 118 | mpz_out_raw(fp, m_prv->lambda); 119 | mpz_out_raw(fp, m_prv->x); 120 | mpz_out_raw(fp, m_localpub->n); 121 | mpz_out_raw(fp, m_localpub->n_squared); 122 | mpz_out_raw(fp, m_localpub->n_plusone); 123 | 124 | fclose(fp); 125 | } 126 | 127 | void PaillierParty::generateKey() { 128 | 129 | paillier_keygen( m_nPaillierBits, &m_localpub, &m_prv, paillier_get_rand_devrandom ); 130 | 131 | } 132 | 133 | /** 134 | * deletes party and frees keys and randstate 135 | */ 136 | PaillierParty::~PaillierParty() { 137 | 138 | gmp_randclear(m_randstate); 139 | paillier_freeprvkey(m_prv); 140 | paillier_freepubkey(m_localpub); 141 | paillier_freepubkey(m_remotepub); 142 | 143 | } 144 | 145 | /** 146 | * exchanges private keys with other party via sock, pre-calculates fixed-base representation of remote pub-key 147 | */ 148 | void PaillierParty::keyExchange(channel* &chan) { 149 | 150 | //send public key 151 | sendmpz_t(m_localpub->n, chan); 152 | 153 | //receive and complete public key 154 | m_remotepub = (paillier_pubkey_t*) malloc(sizeof(paillier_pubkey_t)); 155 | mpz_inits(m_remotepub->n, m_remotepub->n_squared, m_remotepub->n_plusone, NULL); 156 | 157 | receivempz_t(m_remotepub->n, chan); //n 158 | complete_pubkey(m_remotepub); 159 | m_remotepub->bits = m_localpub->bits; 160 | 161 | #if NETDEBUG 162 | std::cout << "KX done. This pubkey: " << m_localpub->n << " remotekey: " << m_remotepub->n << std::endl; 163 | #endif 164 | } 165 | 166 | 167 | /** 168 | * encrypt values in the plaintext vector 169 | */ 170 | bool PaillierParty::encrypt(vector &plaintexts, BYTE* &ciphertexts){ 171 | 172 | paillier_plaintext_t tmp, tmp2; 173 | paillier_ciphertext_t res; 174 | mpz_inits(tmp.m, tmp2.m, res.c, NULL); 175 | 176 | for(int i = 0;i < plaintexts.size();i++){ 177 | 178 | mpz_set_ui(tmp.m, plaintexts[i]); 179 | 180 | paillier_enc(&res, m_localpub, &tmp, paillier_get_rand_devrandom); 181 | 182 | mpz_export(ciphertexts + i * m_nBuflen, NULL, 1, 1, 1, 0, res.c); 183 | 184 | // paillier_dec(&tmp2, m_localpub, m_prv, &res); 185 | 186 | //gmp_printf ("feature%d (%Zd) decryption is (%ZX)\n", i, tmp.m, tmp2.m); 187 | } 188 | 189 | paillier_freeplaintext( &tmp ); 190 | paillier_freeplaintext( &tmp2 ); 191 | paillier_freeciphertext( &res ); 192 | return 0; 193 | } 194 | 195 | /** 196 | * encrypts & sends a Vec of plaintexts 197 | */ 198 | void PaillierParty::encSndRcvVec(e_role role, vector &plaintexts, mpz_t* &ciphertexts, channel* &chan){ 199 | 200 | 201 | struct timespec start, end; 202 | //uint32_t shareBytes = 8; 203 | uint32_t offset = 0; 204 | 205 | 206 | BYTE *m_encSndBuf, *m_encRcvBuf; 207 | m_encSndBuf = (BYTE*) calloc(plaintexts.size() * m_nBuflen, 1); 208 | m_encRcvBuf = (BYTE*) calloc(plaintexts.size() * m_nBuflen, 1); 209 | 210 | // send & receive encrypted values 211 | int window = WINDOWSIZE; 212 | int tosend = m_nBuflen * plaintexts.size(); 213 | offset = 0; 214 | 215 | if (role == CLIENT) { 216 | 217 | clock_gettime(CLOCK_MONOTONIC, &start); 218 | encrypt(plaintexts, m_encSndBuf); 219 | clock_gettime(CLOCK_MONOTONIC, &end); 220 | //printf("CLIENT: Encrypted feature vector in %.0lf ms \n\n", getMillies(start, end)); 221 | 222 | while (tosend > 0) { 223 | 224 | window = min(window, tosend); 225 | 226 | chan->send(m_encSndBuf + offset, window); 227 | //chan->blocking_receive(m_encRcvBuf + offset, window); 228 | 229 | tosend -= window; 230 | offset += window; 231 | } 232 | 233 | } else { 234 | 235 | clock_gettime(CLOCK_MONOTONIC, &start); 236 | while (tosend > 0) { 237 | 238 | window = min(window, tosend); 239 | 240 | //chan->send(m_encSndBuf + offset, window); 241 | chan->blocking_receive(m_encRcvBuf + offset, window); 242 | 243 | tosend -= window; 244 | offset += window; 245 | } 246 | clock_gettime(CLOCK_MONOTONIC, &end); 247 | printf("SERVER: Received encrypted feature vector in %.0lf ms \n", getMillies(start, end)); 248 | 249 | ciphertexts = (mpz_t*) calloc(plaintexts.size(), sizeof(mpz_t)); 250 | 251 | for(int i = 0; i < plaintexts.size();i++){ 252 | 253 | mpz_init(ciphertexts[i]); 254 | mpz_import(ciphertexts[i], m_nBuflen, 1, 1, 1, 0, m_encRcvBuf + i * m_nBuflen); 255 | //gmp_printf ("ciphertext %d is %Zx\n", i, ciphertexts[i]); 256 | } 257 | } 258 | 259 | free(m_encSndBuf); 260 | free(m_encRcvBuf); 261 | } 262 | 263 | void PaillierParty::mskSndRcvVec(e_role role, mpz_t* &CTs, mpz_t* &rndMsks, vector &selectionVec, mpz_t* &blindedInputsVec, channel* &chan){ 264 | 265 | struct timespec start, end, startRndEnc, endRndEnc; 266 | double serverRndEncTime = 0; //time takes to blind the client's input 267 | 268 | mpz_t g_pow_m, rnd, tmp, packed_ct; 269 | mpz_inits(g_pow_m, rnd, tmp, packed_ct, NULL); 270 | 271 | uint32_t statisticalParam = 40; 272 | 273 | uint64_t n_batch, batch_size = m_localpub->bits / (sizeof(uint64_t)*8 + statisticalParam); // batch_size = bits / 104 274 | 275 | uint64_t numDecisionNodes = selectionVec.size(); 276 | 277 | if (batch_size > numDecisionNodes) 278 | n_batch = 1; 279 | else if (numDecisionNodes % batch_size == 0) 280 | n_batch = numDecisionNodes / batch_size; 281 | else 282 | n_batch= numDecisionNodes / batch_size + 1; 283 | 284 | //std::cout << "Paillier key size: " << m_localpub->bits << "\tPacking " << batch_size << " ciphertexts in one." << std::endl; 285 | 286 | BYTE *m_encSndBuf, *m_encRcvBuf; 287 | int bufSize = n_batch * m_nBuflen; 288 | m_encSndBuf = (BYTE*) calloc(bufSize, 1); 289 | m_encRcvBuf = (BYTE*) calloc(bufSize, 1); 290 | 291 | int window = WINDOWSIZE; 292 | int tosend = m_nBuflen * n_batch; 293 | int offset = 0; 294 | uint64_t counter = 0; 295 | 296 | if (role == SERVER) { 297 | 298 | clock_gettime(CLOCK_MONOTONIC, &start); 299 | mpz_t* sel_enc_attr = (mpz_t*) malloc(selectionVec.size() * sizeof(mpz_t)); 300 | 301 | //-------select and blind features------------ 302 | for (int i = 0; i < selectionVec.size(); i ++) 303 | { 304 | mpz_init(sel_enc_attr[i]); 305 | 306 | clock_gettime(CLOCK_MONOTONIC, &startRndEnc); 307 | mpz_powm(g_pow_m, m_remotepub->n_plusone, rndMsks[i], m_remotepub->n_squared); 308 | clock_gettime(CLOCK_MONOTONIC, &endRndEnc); 309 | serverRndEncTime += getMillies(startRndEnc, endRndEnc); 310 | 311 | mpz_mul(sel_enc_attr[i], CTs[selectionVec[i]], g_pow_m); // blind the feature homomorphically 312 | mpz_mod(sel_enc_attr[i], sel_enc_attr[i] , m_remotepub->n_squared); 313 | } 314 | 315 | //-------Pack the ciphertexts------------ 316 | counter = 0; 317 | for (int i = 0; i < n_batch; i++) 318 | { 319 | for (int j = 0; j < batch_size; j++) 320 | { 321 | if (j == 0) { 322 | mpz_set(packed_ct, sel_enc_attr[counter++]); 323 | continue; 324 | } 325 | mpz_ui_pow_ui(tmp, 2, 104*j); 326 | mpz_powm(tmp, sel_enc_attr[counter++], tmp, m_remotepub->n_squared); //shifting 327 | mpz_mul(packed_ct, packed_ct, tmp); // adding to the packed CT 328 | mpz_mod(packed_ct, packed_ct, m_remotepub->n_squared); 329 | if (counter == selectionVec.size()) 330 | break; 331 | } 332 | mpz_export(m_encSndBuf + i * m_nBuflen, NULL, 1, 1, 1, 0, packed_ct); // embeds the packed ct in Snd buffer 333 | } 334 | 335 | clock_gettime(CLOCK_MONOTONIC, &end); 336 | std::cout << "SERVER: Encrypted random numbers in " << serverRndEncTime << " ms" << std::endl; 337 | //printf("SERVER: selected features in %.0lf ms \n\n", getMillies(start, end) - serverRndEncTime); 338 | 339 | //----- send & receive encrypted values--------- 340 | 341 | while (tosend > 0) { 342 | 343 | window = min(window, tosend); 344 | 345 | chan->send(m_encSndBuf + offset, window); 346 | //chan->blocking_receive(m_encRcvBuf + offset, window); 347 | 348 | tosend -= window; 349 | offset += window; 350 | } 351 | 352 | } else { //CLIENT 353 | 354 | clock_gettime(CLOCK_MONOTONIC, &start); 355 | while (tosend > 0) { 356 | 357 | window = min(window, tosend); 358 | 359 | //chan->send(m_encSndBuf + offset, window); 360 | chan->blocking_receive(m_encRcvBuf + offset, window); 361 | 362 | tosend -= window; 363 | offset += window; 364 | } 365 | clock_gettime(CLOCK_MONOTONIC, &end); 366 | printf("CLIENT: Received blinded features in %.0lf ms \n", getMillies(start, end)); 367 | 368 | //reconstructs the encrypted blinded values from the received raw data buffer 369 | 370 | clock_gettime(CLOCK_MONOTONIC, &start); 371 | 372 | blindedInputsVec = (mpz_t*) calloc(selectionVec.size(), sizeof(mpz_t)); //inputs to the substraction circuit in plaintext 373 | 374 | mpz_t mod; 375 | mpz_init(mod); 376 | mpz_ui_pow_ui(mod, 2, 104); 377 | 378 | paillier_plaintext_t rcv_packed_ct; mpz_init(rcv_packed_ct.m); 379 | paillier_ciphertext_t tmpCT; mpz_init(tmpCT.c); 380 | 381 | counter = 0; 382 | for (int i = 0; i < n_batch; i++) 383 | { 384 | mpz_import(tmpCT.c, m_nBuflen, 1, 1, 1, 0, m_encRcvBuf + i * m_nBuflen); 385 | paillier_dec(&rcv_packed_ct, m_localpub, m_prv, &tmpCT); // decryps the inputs here before returning the vec 386 | 387 | for (int j = 0; j < batch_size; j++) 388 | { 389 | mpz_init(blindedInputsVec[counter]); 390 | 391 | mpz_mod(blindedInputsVec[counter], rcv_packed_ct.m, mod); 392 | 393 | mpz_fdiv_q(rcv_packed_ct.m, rcv_packed_ct.m, mod); 394 | 395 | counter++; 396 | 397 | if (counter == selectionVec.size()) 398 | break; 399 | } 400 | } 401 | 402 | clock_gettime(CLOCK_MONOTONIC, &end); 403 | printf("CLIENT: Depacked & decrypted blinded features in %.0lf ms \n", getMillies(start, end)); 404 | 405 | #if DEBUG 406 | for(int i = 0;i < mapping.size();i++) { 407 | std::cout << "random mask: " << rndMsks[i] << " \tfeature " << mapping[i] << "\tmasked value: "; gmp_printf("%Zd", blindedInputsVec[i]); std::cout << std::endl; 408 | } 409 | #endif 410 | 411 | } 412 | 413 | //paillier_freeplaintext(&tmp); 414 | //paillier_freeplaintext(&rnd); 415 | //TODO: free unnecessary bufs; 416 | } 417 | 418 | void PaillierParty::printBuf(BYTE* b, uint32_t len) { 419 | for (uint32_t i = 0; i < len; i++) { 420 | printf("%02x.", *(b + i)); 421 | } 422 | std::cout << std::endl; 423 | } 424 | 425 | /** 426 | * send one mpz_t to sock 427 | */ 428 | void PaillierParty::sendmpz_t(mpz_t t, channel* chan, BYTE * buf) { 429 | 430 | //clear upper bytes of the buffer, so tailing bytes are zero 431 | for (int i = mpz_sizeinbase(t, 256); i < m_nBuflen; i++) { 432 | *(buf + i) = 0; 433 | } 434 | 435 | #if NETDEBUG 436 | std::cout << mpz_sizeinbase(t, 256) << " vs. " << m_nBuflen << std::endl; 437 | #endif 438 | 439 | mpz_export(buf, NULL, -1, 1, 1, 0, t); 440 | 441 | //send bytes of t 442 | chan->send(buf, (uint64_t) m_nBuflen); 443 | 444 | #if NETDEBUG 445 | std::cout << std::endl << "SEND" << std::endl; 446 | for (int i = 0; i < m_nBuflen; i++) { 447 | printf("%02x.", *(buf + i)); 448 | } 449 | 450 | std::cout << std::endl << "sent: " << t << " with len: " << m_nBuflen << " should have been " << mpz_sizeinbase(t, 256) << std::endl; 451 | #endif 452 | } 453 | 454 | /** 455 | * receive one mpz_t from sock. t must be initialized. 456 | */ 457 | void PaillierParty::receivempz_t(mpz_t t, channel* chan, BYTE * buf) { 458 | chan->blocking_receive(buf, (uint64_t) m_nBuflen); 459 | mpz_import(t, m_nBuflen, -1, 1, 1, 0, buf); 460 | 461 | #if NETDEBUG 462 | std::cout << std::endl << "RECEIVE" << std::endl; 463 | for (int i = 0; i < m_nBuflen; i++) { 464 | printf("%02x.", *(buf + i)); 465 | } 466 | 467 | std::cout << "received: " << t << " with len: " << m_nBuflen << std::endl; 468 | #endif 469 | } 470 | 471 | /** 472 | * send one mpz_t to sock, allocates buffer 473 | */ 474 | void PaillierParty::sendmpz_t(mpz_t t, channel* chan) { 475 | unsigned int bytelen = mpz_sizeinbase(t, 256); 476 | BYTE* arr = (BYTE*) malloc(bytelen); 477 | mpz_export(arr, NULL, 1, 1, 1, 0, t); 478 | 479 | //send byte length 480 | chan->send((BYTE*) &bytelen, sizeof(bytelen)); 481 | 482 | //send bytes of t 483 | chan->send(arr, (uint64_t) bytelen); 484 | 485 | free(arr); 486 | #if NETDEBUG 487 | std::cout << "sent: " << t << " with len: " << bytelen << std::endl; 488 | #endif 489 | } 490 | 491 | /** 492 | * receive one mpz_t from sock. t must be initialized. 493 | */ 494 | void PaillierParty::receivempz_t(mpz_t t, channel* chan) { 495 | unsigned int bytelen; 496 | 497 | //reiceive byte length 498 | chan->blocking_receive((BYTE*) &bytelen, sizeof(bytelen)); 499 | BYTE* arr = (BYTE*) malloc(bytelen); 500 | 501 | //receive bytes of t 502 | chan->blocking_receive(arr, (uint64_t) bytelen); 503 | mpz_import(t, bytelen, 1, 1, 1, 0, arr); 504 | 505 | free(arr); 506 | #if NETDEBUG 507 | std::cout << "received: " << t << " with len: " << bytelen << std::endl; 508 | #endif 509 | } 510 | -------------------------------------------------------------------------------- /XCMP_files/benchmark_gt/hhh.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | \file hhh.cpp 3 | \author kiss@encrypto.cs.tu-darmstadt.de 4 | \copyright HHH protocol 5 | Copyright (C) 2019 Cryptography and Privacy Engineering Group, TU Darmstadt 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Affero General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | You should have received a copy of the GNU Affero General Public License 15 | along with this program. If not, see . 16 | \brief HHH protocol of Tai et al. implemented using the mcl library and the secure comparison implementation from https://github.com/fionser/XCMP 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include "network.hpp" 38 | #include "dectree.hpp" 39 | #define PROT 0 //0 for HHH, 1 for HH(G), 2 for (GG)/(HG)H where the parts in brackets are executed outside of this code before/after 40 | #define DT 0 //0 for wine", 1 for iris, 2 for breast cancer, 3 for digits, 4 for diabetes, 5 for linnerud, 6 for boston 41 | 42 | typedef mcl::FpT<> Fp; 43 | typedef mcl::FpT Zn; // use ZnTag because Zn is different class with Fp 44 | typedef mcl::EcT Ec; 45 | typedef mcl::ElgamalT Elgamal; 46 | 47 | cybozu::RandomGenerator rg; 48 | 49 | const uint32_t bitlen = 64; 50 | uint32_t ElGamalBits = 514; 51 | uint32_t Buflen = ElGamalBits / 8 + 1; //size of one ciphertext to send via network. Paillier uses n bits == n/8 bytes 52 | 53 | using namespace std; 54 | 55 | void SysInit() 56 | { 57 | const mcl::EcParam& para = mcl::ecparam::secp256k1; 58 | Zn::init(para.n); 59 | Fp::init(para.p); 60 | Ec::init(para.a, para.b); 61 | } 62 | 63 | //NETWORK BEGIN 64 | 65 | void send_ctxts(std::vector const& ctxts, 66 | tcp::iostream &conn) 67 | { 68 | for (const auto &ctx : ctxts) 69 | conn << ctx << '\n'; 70 | } 71 | 72 | void receive_ctxts(std::vector &ctxts, int32_t num, 73 | tcp::iostream &conn) 74 | { 75 | ctxts.resize(num); 76 | for (int32_t i = 0; i < num; i++) 77 | conn >> ctxts[i]; 78 | } 79 | 80 | //NETWORK END 81 | 82 | //COMPARISON PROTOCOL BEGIN 83 | 84 | vector encBitbyBitPrecomp(const Elgamal::PublicKey& pub){ 85 | vector xenc(bitlen); 86 | for(int32_t i = bitlen - 1; i >= 0; --i){ 87 | pub.enc_off(xenc[bitlen - i - 1], rg); 88 | } 89 | return xenc; 90 | } 91 | 92 | void encBitbyBitOnline(const Elgamal::PublicKey& pub, vector& xenc, uint64_t x){ 93 | int bit; 94 | for(int32_t i = bitlen - 1; i >= 0; --i){ 95 | bit = (x >> i) & 1; 96 | pub.enc_on(xenc[bitlen - i - 1], bit); 97 | } 98 | } 99 | 100 | vector encBitbyBit(const Elgamal::PublicKey& pub, uint64_t x){ 101 | vector xenc(bitlen); 102 | int bit; 103 | for(int32_t i = bitlen - 1; i >= 0; --i){ 104 | bit = (x >> i) & 1; 105 | pub.enc(xenc[bitlen - i - 1], bit, rg); 106 | } 107 | return xenc; 108 | } 109 | 110 | vector getBits(uint64_t number){ 111 | vector bits(bitlen); 112 | for(uint32_t i = 0; i < bitlen; ++i){ 113 | bits[i] = (number >> (bitlen-i-1)) & 1; 114 | } 115 | return bits; 116 | } 117 | 118 | Elgamal::CipherText xorWithConst(const Elgamal::PublicKey& pub, Elgamal::CipherText toXor, int thres){ 119 | Elgamal::CipherText result(toXor); 120 | if(thres == 1){ 121 | result.neg(); 122 | pub.add(result, 1); 123 | } 124 | else{ 125 | pub.rerandomize(result, rg); 126 | } 127 | return result; 128 | } 129 | 130 | vector PvtCmpS(const Elgamal::PublicKey& pub, Elgamal::CipherText& tmpsum, vector xenc, int64_t threshold, int server_bit){ 131 | vector result(bitlen); 132 | vector yBits = getBits(threshold); 133 | int32_t s = 1-2*server_bit; //BINDER 134 | Elgamal::CipherText currentRes, xorRes; 135 | 136 | for(uint32_t i = 0; i < bitlen; ++i){ 137 | currentRes = xenc[i]; 138 | pub.add(currentRes, s - yBits[i]); // x_i - y_i + s (latter two values known to server) 139 | xorRes = xorWithConst(pub, xenc[i], yBits[i]); //y_i + x_i 140 | xorRes.mul(3); //*3 141 | if(i > 0){ 142 | currentRes.add(tmpsum); 143 | } 144 | tmpsum.add(xorRes); 145 | result[i] = currentRes; 146 | } 147 | std::random_shuffle(result.begin(), result.end()); 148 | return result; 149 | } 150 | 151 | //decryption 152 | int32_t PvtCmpC(const Elgamal::PrivateKey& prv, vector c){ 153 | for(uint32_t i = 0; i < bitlen; ++i){ 154 | if(prv.isZeroMessage(c[i])){ 155 | return 1; 156 | } 157 | } 158 | return 0; 159 | } 160 | 161 | uint32_t testCompClient(const Elgamal::PublicKey& pub, const Elgamal::PrivateKey& prv, uint64_t client_input, tcp::iostream &conn){ 162 | vector enc_bits = encBitbyBitPrecomp(pub); 163 | encBitbyBitOnline(pub, enc_bits, client_input); 164 | send_ctxts(enc_bits, conn); 165 | 166 | std::vector gt_result; 167 | receive_ctxts(gt_result, bitlen, conn); 168 | 169 | uint32_t s = PvtCmpC(prv, gt_result); 170 | cout << client_input << " " << s << endl; 171 | return s; 172 | } 173 | 174 | uint32_t testCompServer(const Elgamal::PublicKey& pub, uint64_t server_input, tcp::iostream &conn){ 175 | uint32_t server_bit = std::rand() & 1; 176 | cout << server_input << " " << server_bit << endl; 177 | 178 | std::vector ctxts; 179 | receive_ctxts(ctxts, bitlen, conn); 180 | assert(ctxts.size() == bitlen); 181 | 182 | Elgamal::CipherText tmpsum; 183 | pub.enc(tmpsum, 0, rg); //ciphertext for m = 0 184 | 185 | vector gt_result = PvtCmpS(pub, tmpsum, ctxts, server_input, server_bit); 186 | 187 | send_ctxts(gt_result, conn); 188 | return server_bit; 189 | } 190 | 191 | //COMPARISON PROTOCOL END 192 | 193 | //EVALUATION PROTOCOL BEGIN 194 | 195 | void calculatePathCosts(const Elgamal::PublicKey& pub, DecTree& tree, vector& pathCost, 196 | vector& classif, vector& edgeCost0, 197 | vector& edgeCost1, vector& rand1, vector& rand2){ 198 | Elgamal::CipherText tmp; 199 | uint32_t i = 0, k = 0; 200 | for(uint32_t j = 0; j < tree.node_vec.size(); j++){ 201 | //start calculating path costs 202 | if(tree.node_vec[j]->parent == NULL){ //if root 203 | tree.node_vec[j]->right->path_cost = edgeCost1[i]; 204 | //right is 0, left is 1, could also be the other way around 205 | tree.node_vec[j]->left->path_cost = edgeCost0[i]; 206 | i++; 207 | } 208 | else if(!(tree.node_vec[j]->leaf)){ //decision nodes 209 | edgeCost1[i].add(tree.node_vec[j]->path_cost); 210 | edgeCost0[i].add(tree.node_vec[j]->path_cost); 211 | 212 | tree.node_vec[j]->right->path_cost = edgeCost1[i]; 213 | tree.node_vec[j]->left->path_cost = edgeCost0[i]; 214 | i++; 215 | } 216 | else if(tree.node_vec[j]->leaf){ 217 | tmp = tree.node_vec[j]->path_cost; 218 | tree.node_vec[j]->path_cost.mul(rand1[k]); 219 | pathCost[k] = tree.node_vec[j]->path_cost; 220 | 221 | tmp.mul(rand2[k]); 222 | pub.add(tmp, tree.node_vec[j]->classification); 223 | classif[k] = tmp; 224 | 225 | k++; 226 | } 227 | } 228 | } 229 | 230 | //EVALUATION PROTOCOL END 231 | 232 | 233 | //CLIENTSERVER BEGIN 234 | 235 | void play_server(tcp::iostream &conn) 236 | { 237 | const char* filename[7] = { 238 | "../../../UCI_dectrees/wine", 239 | "../../../UCI_dectrees/iris", 240 | "../../../UCI_dectrees/breast", 241 | "../../../UCI_dectrees/digits", 242 | "../../../UCI_dectrees/diabetes", 243 | "../../../UCI_dectrees/linnerud", 244 | "../../../UCI_dectrees/boston" 245 | }; 246 | uint32_t i = DT, k = 0; 247 | DecTree tree; 248 | tree.read_from_file(filename[i]); 249 | if(PROT == 2){ 250 | tree.depthPad(); //for benchmarking inefficient protocol HHG 251 | } 252 | 253 | conn << tree.num_attributes << '\n'; 254 | conn << tree.num_dec_nodes << '\n'; 255 | 256 | timeval tbegin, tend; 257 | 258 | Elgamal::PublicKey pub; 259 | conn >> pub; //reads public key 260 | 261 | //COMPARISON OFFLINE 262 | gettimeofday(&tbegin, NULL); 263 | vector server_bits(tree.num_dec_nodes); 264 | vector tmpsum(tree.num_dec_nodes); 265 | if(PROT == 0 || PROT == 1){ 266 | for (uint32_t i = 0; i < tree.num_dec_nodes; i++) { 267 | server_bits[i] = std::rand() & 1; 268 | } 269 | for(uint32_t i = 0; i < tree.num_dec_nodes; i++){ 270 | pub.enc(tmpsum[i], 0, rg); //ciphertext for m = 0 271 | } 272 | gettimeofday(&tend, NULL); 273 | cout << "Comp Offline: " << ((tend.tv_sec-tbegin.tv_sec)*1000000 + tend.tv_usec - tbegin.tv_usec)/1000 << "ms" << endl; 274 | } 275 | 276 | //EVAL OFFLINE 277 | gettimeofday(&tbegin, NULL); 278 | vector rand1(tree.num_dec_nodes + 1); 279 | vector rand2(tree.num_dec_nodes + 1); 280 | vector indeces(tree.num_dec_nodes + 1); 281 | if(PROT == 0 || PROT == 2){ 282 | for(uint32_t i = 0; i < tree.num_dec_nodes + 1; ++i){ 283 | rand1[i] = rg.get64(); 284 | rand2[i] = rg.get64(); 285 | } 286 | for(uint32_t i = 0; i < tree.num_dec_nodes + 1; ++i){ 287 | indeces.push_back(i); 288 | } 289 | std::random_shuffle(indeces.begin(), indeces.end()); 290 | 291 | gettimeofday(&tend, NULL); 292 | cout << "Eval Offline: " << ((tend.tv_sec-tbegin.tv_sec)*1000000 + tend.tv_usec - tbegin.tv_usec)/1000 << "ms" << endl; 293 | } 294 | 295 | //COMPARISON ONLINE 296 | gettimeofday(&tbegin, NULL); 297 | vector< vector > gt_results(tree.num_dec_nodes); 298 | if(PROT == 0 || PROT == 1){ 299 | std::vector< std::vector > ctxts(tree.num_attributes); 300 | for (uint32_t i = 0; i < tree.num_attributes; i++) { 301 | receive_ctxts(ctxts[i], bitlen, conn); 302 | } 303 | 304 | for(uint32_t i = 0; i < tree.num_dec_nodes; i++){ 305 | gt_results[i] = PvtCmpS(pub, tmpsum[i], ctxts[tree.decnode_vec[i]->attribute_index], 306 | tree.decnode_vec[i]->threshold, server_bits[i]); 307 | //cout << tree.decnode_vec[i]->threshold << " " << server_bits[i] << " " << tree.decnode_vec[i]->attribute_index << endl; CHECKED CORRECT 308 | send_ctxts(gt_results[i], conn); 309 | } 310 | gettimeofday(&tend, NULL); 311 | cout << "Comp Online: " << ((tend.tv_sec-tbegin.tv_sec)*1000000 + tend.tv_usec - tbegin.tv_usec)/1000 << "ms" << endl; 312 | } 313 | if(PROT == 1){ 314 | ofstream output_shares; 315 | output_shares.open("../../../output/compH_shares_server.txt"); 316 | for(uint32_t i = 0; i < tree.num_dec_nodes; i++){ 317 | output_shares << server_bits[i] << endl; 318 | } 319 | output_shares.close(); 320 | } 321 | if(PROT == 2){ 322 | ifstream output_shares; 323 | char c; 324 | output_shares.open("../../../output/compG_shares_server.txt"); 325 | uint32_t j = 0; 326 | while(output_shares >> server_bits[j]){ 327 | j++; 328 | } 329 | output_shares.close(); 330 | } 331 | 332 | //EVAL ONLINE 333 | gettimeofday(&tbegin, NULL); 334 | vector< vector > reenc(tree.num_dec_nodes); 335 | vector edgeCost1(tree.num_dec_nodes); 336 | vector edgeCost0(tree.num_dec_nodes); 337 | if(PROT == 0 || PROT == 2){ 338 | for(uint32_t i = 0; i < tree.num_dec_nodes; i++){ 339 | receive_ctxts(reenc[i], 1, conn); 340 | edgeCost1[i] = xorWithConst(pub, reenc[i][0], server_bits[i]); 341 | edgeCost0[i] = edgeCost1[i]; 342 | edgeCost1[i].mul(-1); 343 | pub.add(edgeCost1[i], 1); 344 | } 345 | 346 | vector pathCost(tree.num_dec_nodes + 1); //path costs on the leaves only! 347 | vector classif(tree.num_dec_nodes + 1); //classification on the leaves only! 348 | 349 | calculatePathCosts(pub, tree, pathCost, classif, edgeCost0, edgeCost1, rand1, rand2); 350 | 351 | vector pathCost_shuffled(tree.num_dec_nodes + 1); 352 | vector classif_shuffled(tree.num_dec_nodes + 1); 353 | for(uint32_t i = 0; i < tree.num_dec_nodes + 1; ++i){ 354 | pathCost_shuffled[i] = pathCost[indeces[i]]; 355 | classif_shuffled[i] = classif[indeces[i]]; 356 | } 357 | send_ctxts(pathCost, conn); 358 | send_ctxts(classif, conn); 359 | 360 | gettimeofday(&tend, NULL); 361 | cout << "Eval Online: " << ((tend.tv_sec-tbegin.tv_sec)*1000000 + tend.tv_usec - tbegin.tv_usec)/1000 << "ms" << endl; 362 | } 363 | } 364 | 365 | void play_client(tcp::iostream &conn) 366 | { 367 | 368 | uint32_t num_attributes; 369 | uint32_t num_dec_nodes; 370 | conn >> num_attributes; 371 | conn >> num_dec_nodes; 372 | 373 | vector client_inputs(num_attributes); //all values initialized, we need more than num_attributees because not all of them are used, which we do not consider 374 | for(uint32_t j = 0; j < num_attributes; ++j){ 375 | client_inputs[j] = rg.get64() % 10000; 376 | //cout << j << " " << client_inputs[j] << endl; 377 | } 378 | //tree.evaluate(client_inputs); 379 | 380 | timeval tbegin, tend; 381 | 382 | const mcl::EcParam& para = mcl::ecparam::secp256k1; 383 | const Fp x0(para.gx); 384 | const Fp y0(para.gy); 385 | const Ec P(x0, y0); 386 | 387 | Elgamal::PrivateKey prv; 388 | prv.init(P, para.bitSize, rg); 389 | const Elgamal::PublicKey& pub = prv.getPublicKey(); 390 | 391 | conn << pub << '\n'; //sends public key 392 | 393 | //COMPARISON OFFLINE 394 | gettimeofday(&tbegin, NULL); 395 | vector< vector > enc_bits(num_attributes); 396 | if(PROT == 0 || PROT == 1){ 397 | for(uint32_t j = 0; j < num_attributes; ++j){ 398 | enc_bits[j] = encBitbyBitPrecomp(pub); 399 | } 400 | 401 | gettimeofday(&tend, NULL); 402 | cout << "Comp Offline: " << ((tend.tv_sec-tbegin.tv_sec)*1000000 + tend.tv_usec - tbegin.tv_usec)/1000 << "ms" << endl; 403 | } 404 | 405 | //EVAL OFFLINE 406 | gettimeofday(&tbegin, NULL); 407 | vector< std::vector > gt_results_off(num_dec_nodes); 408 | if(PROT == 0 || PROT == 2){ 409 | for(uint32_t j = 0; j < num_dec_nodes; ++j){ 410 | gt_results_off[j].resize(1); 411 | pub.enc_off(gt_results_off[j][0], rg); 412 | } 413 | gettimeofday(&tend, NULL); 414 | cout << "Eval Offline: " << ((tend.tv_sec-tbegin.tv_sec)*1000000 + tend.tv_usec - tbegin.tv_usec)/1000 << "ms" << endl; 415 | } 416 | 417 | //COMPARISON ONLINE 418 | gettimeofday(&tbegin, NULL); 419 | vector< std::vector > gt_results(num_dec_nodes); 420 | vector client_out(num_dec_nodes); 421 | if(PROT == 0 || PROT == 1){ 422 | for(uint32_t j = 0; j < num_attributes; ++j){ 423 | encBitbyBitOnline(pub, enc_bits[j], client_inputs[j]); 424 | send_ctxts(enc_bits[j], conn); 425 | } 426 | 427 | for(uint32_t j = 0; j < num_dec_nodes; ++j){ 428 | receive_ctxts(gt_results[j], bitlen, conn); 429 | client_out[j] = PvtCmpC(prv, gt_results[j]); 430 | //cout << client_out[j] << endl; CHECKED CORRECT 431 | } 432 | 433 | gettimeofday(&tend, NULL); 434 | cout << "Comp Online: " << ((tend.tv_sec-tbegin.tv_sec)*1000000 + tend.tv_usec - tbegin.tv_usec)/1000 << "ms" << endl; 435 | } 436 | if(PROT == 1){ 437 | ofstream output_shares; 438 | output_shares.open("../../../output/compH_shares_client.txt"); 439 | for(uint32_t j = 0; j < num_dec_nodes; j++){ 440 | output_shares << client_out[j] << endl; 441 | } 442 | output_shares.close(); 443 | } 444 | if(PROT == 2){ 445 | ifstream output_shares; 446 | char c; 447 | output_shares.open("../../../output/compG_shares_client.txt"); 448 | uint32_t j = 0; 449 | while(output_shares >> client_out[j]){ 450 | j++; 451 | } 452 | output_shares.close(); 453 | } 454 | 455 | //EVAL ONLINE 456 | gettimeofday(&tbegin, NULL); 457 | vector pathCost(num_dec_nodes + 1); //path costs on the leaves only! 458 | vector classif(num_dec_nodes + 1); //classification on the leaves only! 459 | Zn result; 460 | if(PROT == 0 || PROT == 2){ 461 | for(uint32_t j = 0; j < num_dec_nodes; ++j){ 462 | pub.enc_on(gt_results_off[j][0], client_out[j]); 463 | //pub.enc(gt_results[j][0], client_out[j], rg); 464 | send_ctxts(gt_results_off[j], conn); 465 | } 466 | receive_ctxts(pathCost, num_dec_nodes + 1, conn); 467 | receive_ctxts(classif, num_dec_nodes + 1, conn); 468 | 469 | for(uint32_t j = 0; j < pathCost.size(); ++j){ 470 | if(prv.isZeroMessage(pathCost[j])){ 471 | prv.dec(result, classif[j], 1000); 472 | } 473 | } 474 | 475 | gettimeofday(&tend, NULL); 476 | cout << "Eval Online: " << ((tend.tv_sec-tbegin.tv_sec)*1000000 + tend.tv_usec - tbegin.tv_usec)/1000 << "ms" << endl << endl; 477 | cout << "Evaluation result: " << result << endl; 478 | } 479 | } 480 | 481 | //CLIENTSERVER END 482 | 483 | int main(int argc, char *argv[]) { 484 | long r = 0; //0 for server, 1 for client 485 | if (argc > 1) 486 | r = std::stol(argv[1]); 487 | SysInit(); 488 | std::srand(std::time(0)); 489 | 490 | switch(r) { 491 | case 0: 492 | std::cout << "waiting for client..." << std::endl; 493 | run_server(play_server); 494 | break; 495 | case 1: 496 | std::cout << "connect to server..." << std::endl; 497 | run_client(play_client); 498 | break; 499 | } 500 | return 0; 501 | } 502 | 503 | --------------------------------------------------------------------------------