├── .github
└── workflows
│ ├── arm.yml
│ └── x86.yml
├── .gitignore
├── CMakeLists.txt
├── LICENSE
├── README.md
├── cmake
└── emp-agmpc-config.cmake
├── debug
├── emp-agmpc
├── abitmp.h
├── cmpc_config.h
├── emp-agmpc.h
├── flexible_input_output.h
├── fpremp.h
├── helper.h
├── mpc.h
└── netmp.h
├── lgtm.yml
├── run
└── test
├── CMakeLists.txt
├── aes.cpp
├── ands.txt
├── not.txt
├── pr10_circuit.txt
├── pr10_test.cpp
├── scratch.cpp
├── sha1.cpp
├── sha256.cpp
├── test.h
├── test_in_out.cpp
├── test_mpc.cpp
├── test_mpc_individual.cpp
├── triple.cpp
└── xor.txt
/.github/workflows/arm.yml:
--------------------------------------------------------------------------------
1 | name: arm
2 | on: [push]
3 |
4 | jobs:
5 | build_arm:
6 | strategy:
7 | matrix:
8 | os: [ubuntu-latest]
9 | build_type: [Debug, Release]
10 | runs-on: [self-hosted]
11 | env:
12 | BUILD_TYPE: ${{matrix.build_type}}
13 | steps:
14 | - uses: actions/checkout@v2
15 | - name: install dependency
16 | run: |
17 | wget https://raw.githubusercontent.com/emp-toolkit/emp-readme/master/scripts/install.py
18 | python3 install.py --deps --tool --ot
19 | - name: Create Build Environment
20 | run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DUSE_RANDOM_DEVICE=On && make
21 | - name: Test
22 | shell: bash
23 | run: make test
24 |
--------------------------------------------------------------------------------
/.github/workflows/x86.yml:
--------------------------------------------------------------------------------
1 | name: x86
2 | on: [push]
3 |
4 | jobs:
5 | build_x86:
6 | strategy:
7 | matrix:
8 | os: [ubuntu-latest, macos-latest]
9 | build_type: [Debug, Release]
10 | runs-on: ${{ matrix.os }}
11 | env:
12 | BUILD_TYPE: ${{matrix.build_type}}
13 | steps:
14 | - uses: actions/checkout@v2
15 | - name: install dependency
16 | run: |
17 | wget https://raw.githubusercontent.com/emp-toolkit/emp-readme/master/scripts/install.py
18 | python install.py --deps --tool --ot
19 | - name: Create Build Environment
20 | run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DUSE_RANDOM_DEVICE=On && make
21 | - name: Test
22 | shell: bash
23 | run: make test
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | Testing/
2 | *CTestTestfile.cmake
3 | CMakeCache.txt
4 | CMakeFiles/
5 | Makefile
6 | bin/
7 | cmake_install.cmake
8 | *.DS_Store
9 | # Compiled Object files
10 | *.slo
11 | *.lo
12 | *.o
13 | *.obj
14 |
15 | # Precompiled Headers
16 | *.gch
17 | *.pch
18 |
19 | # Compiled Dynamic libraries
20 | *.so
21 | *.dylib
22 | *.dll
23 |
24 | # Fortran module files
25 | *.mod
26 |
27 | # Compiled Static libraries
28 | *.lai
29 | *.la
30 | *.a
31 | *.lib
32 |
33 | # Executables
34 | *.exe
35 | *.out
36 | *.app
37 |
38 | perf.data*
39 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required (VERSION 2.8.11)
2 | project (emp-agmpc)
3 | set(NAME "emp-agmpc")
4 |
5 | find_path(CMAKE_FOLDER NAMES cmake/emp-tool-config.cmake)
6 | include(${CMAKE_FOLDER}/cmake/emp-base.cmake)
7 |
8 | FIND_PACKAGE(emp-ot REQUIRED)
9 | INCLUDE_DIRECTORIES(${EMP-OT_INCLUDE_DIRS})
10 |
11 | install(FILES cmake/emp-agmpc-config.cmake DESTINATION cmake/)
12 | install(DIRECTORY emp-agmpc DESTINATION include/)
13 |
14 | ENABLE_TESTING()
15 | ADD_SUBDIRECTORY(test)
16 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Xiao Wang (wangxiao@gmail.com)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 | Enquiries about further applications and development opportunities are welcome.
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # EMP-agmpc
2 | 
3 | 
4 | [](https://lgtm.com/projects/g/emp-toolkit/emp-agmpc/alerts/)
5 | [](https://lgtm.com/projects/g/emp-toolkit/emp-agmpc/context:cpp)
6 |
7 |
8 |
9 | ## Global-Scale Secure Multiparty Computation
10 |
11 | More details of the protocol can be found in the [paper](https://eprint.iacr.org/2017/189).
12 |
13 |
14 |
15 |
16 | # Installation
17 | 1. `wget https://raw.githubusercontent.com/emp-toolkit/emp-readme/master/scripts/install.py`
18 | 2. `python[3] install.py --deps --tool --ot --agmpc`
19 | 1. By default it will build for Release. `-DCMAKE_BUILD_TYPE=[Release|Debug]` option is also available.
20 | 2. No sudo? Change [`CMAKE_INSTALL_PREFIX`](https://cmake.org/cmake/help/v2.8.8/cmake.html#variable%3aCMAKE_INSTALL_PREFIX).
21 |
22 |
23 | ### Question
24 | Please send email to wangxiao1254@gmail.com
25 |
26 |
--------------------------------------------------------------------------------
/cmake/emp-agmpc-config.cmake:
--------------------------------------------------------------------------------
1 | find_package(emp-tool)
2 | find_package(emp-ot)
3 | find_path(EMP-AGMPC_INCLUDE_DIR emp-agmpc/emp-agmpc.h)
4 |
5 | include(FindPackageHandleStandardArgs)
6 |
7 | find_package_handle_standard_args(EMP-AGMPC DEFAULT_MSG EMP-AGMPC_INCLUDE_DIR)
8 |
9 | if(EMP-AGMPC_FOUND)
10 | set(EMP-AGMPC_INCLUDE_DIRS ${EMP-AGMPC_INCLUDE_DIR} ${EMP-OT_INCLUDE_DIRS})
11 | set(EMP-AGMPC_LIBRARIES ${EMP-OT_LIBRARIES})
12 | endif()
--------------------------------------------------------------------------------
/debug:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | $1 1 12345 & $1 2 12345 & valgrind --leak-check=full $1 3 12345
3 | #valgrind --leak-check=full $1 1 12345 & $1 2 12345 & $1 3 12345
4 | #$1 1 12345 & $1 2 12345 & perf record $1 3 12345
5 | #perf record -g $1 1 12345 & $1 2 12345 & $1 3 12345
6 | #valgrind --leak-check=full $1 1 12345 & $1 2 12345 & $1 3 12345
--------------------------------------------------------------------------------
/emp-agmpc/abitmp.h:
--------------------------------------------------------------------------------
1 | #ifndef ABIT_MP_H__
2 | #define ABIT_MP_H__
3 | #include
4 | #include
5 | #include "netmp.h"
6 | #include "helper.h"
7 |
8 | template
9 | class ABitMP { public:
10 | IKNP *abit1[nP+1];
11 | IKNP *abit2[nP+1];
12 | NetIOMP *io;
13 | ThreadPool * pool;
14 | int party;
15 | PRG prg;
16 | block Delta;
17 | Hash hash;
18 | int ssp;
19 | block * pretable;
20 | ABitMP(NetIOMP* io, ThreadPool * pool, int party, bool * _tmp = nullptr, int ssp = 40) {
21 | this->ssp = ssp;
22 | this->io = io;
23 | this->pool = pool;
24 | this->party = party;
25 | bool tmp[128];
26 | if(_tmp == nullptr) {
27 | prg.random_bool(tmp, 128);
28 | } else {
29 | memcpy(tmp, _tmp, 128);
30 | }
31 |
32 | for(int i = 1; i <= nP; ++i) for(int j = 1; j <= nP; ++j) if(i < j) {
33 | if(i == party) {
34 | abit1[j] = new IKNP(io->get(j, false));
35 | abit2[j] = new IKNP(io->get(j, true));
36 | } else if (j == party) {
37 | abit2[i] = new IKNP(io->get(i, false));
38 | abit1[i] = new IKNP(io->get(i, true));
39 | }
40 | }
41 |
42 | vector> res;//relic multi-thread problems...
43 | for(int i = 1; i <= nP; ++i) for(int j = 1; j <= nP; ++j) if(i < j) {
44 | if(i == party) {
45 | res.push_back(pool->enqueue([this, io, tmp, j]() {
46 | abit1[j]->setup_send(tmp);
47 | io->flush(j);
48 | }));
49 | res.push_back(pool->enqueue([this, io, j]() {
50 | abit2[j]->setup_recv();
51 | io->flush(j);
52 | }));
53 | } else if (j == party) {
54 | res.push_back(pool->enqueue([this, io, i]() {
55 | abit2[i]->setup_recv();
56 | io->flush(i);
57 | }));
58 | res.push_back(pool->enqueue([this, io, tmp, i]() {
59 | abit1[i]->setup_send(tmp);
60 | io->flush(i);
61 | }));
62 | }
63 | }
64 | joinNclean(res);
65 |
66 | if(party == 1)
67 | Delta = abit1[2]->Delta;
68 | else
69 | Delta = abit1[1]->Delta;
70 | }
71 | ~ABitMP() {
72 | for(int i = 1; i <= nP; ++i) if( i!= party ) {
73 | delete abit1[i];
74 | delete abit2[i];
75 | }
76 | }
77 | void compute(block * MAC[nP+1], block * KEY[nP+1], bool* data, int length) {
78 | vector> res;
79 | for(int i = 1; i <= nP; ++i) for(int j = 1; j<= nP; ++j) if( (i < j) and (i == party or j == party) ) {
80 | int party2 = i + j - party;
81 | res.push_back(pool->enqueue([this, KEY, length, party2]() {
82 | abit1[party2]->send_cot(KEY[party2], length);
83 | io->flush(party2);
84 | }));
85 | res.push_back(pool->enqueue([this, MAC, data, length, party2]() {
86 | abit2[party2]->recv_cot(MAC[party2], data, length);
87 | io->flush(party2);
88 | }));
89 | }
90 | joinNclean(res);
91 | #ifdef __debug
92 | check_MAC(io, MAC, KEY, data, Delta, length, party);
93 | #endif
94 | }
95 |
96 | future check(block * MAC[nP+1], block * KEY[nP+1], bool* data, int length) {
97 | future ret = pool->enqueue([this, MAC, KEY, data, length](){
98 | check1(MAC, KEY, data, length);
99 | check2(MAC, KEY, data, length);
100 | });
101 | return ret;
102 | }
103 |
104 | void check1(block * MAC[nP+1], block * KEY[nP+1], bool* data, int length) {
105 | block seed = sampleRandom(io, &prg, pool, party);
106 | PRG prg2(&seed);
107 | uint8_t * tmp;
108 | block * Ms[nP+1];
109 | bool * bs[nP+1];
110 | block * Ks[nP+1];
111 | block * tMs[nP+1];
112 | bool * tbs[nP+1];
113 |
114 | tmp = new uint8_t[ssp*length];
115 | prg2.random_data(tmp, ssp*length);
116 | for(int i = 0; i < ssp*length; ++i)
117 | tmp[i] = tmp[i] % 4;
118 | // for(int j = 0; j < ssp; ++j) {
119 | // tmp[j] = new bool[length];
120 | // for(int k = 0; k < ssp; ++k)
121 | // tmp[j][length - ssp + k] = (k == j);
122 | // }
123 | for(int i = 1; i <= nP; ++i) {
124 | Ms[i] = new block[ssp];
125 | Ks[i] = new block[ssp];
126 | bs[i] = new bool[ssp];
127 | memset(Ms[i], 0, ssp*sizeof(block));
128 | memset(Ks[i], 0, ssp*sizeof(block));
129 | memset(bs[i], false, ssp);
130 | tMs[i] = new block[ssp];
131 | tbs[i] = new bool[ssp];
132 | }
133 |
134 | const int chk = 1;
135 | const int SIZE = 1024*2;
136 | block (* tMAC)[4] = new block[SIZE/chk][4];
137 | block (* tKEY)[4] = new block[SIZE/chk][4];
138 | bool (* tb)[4] = new bool[length/chk][4];
139 | memset(tMAC, 0, sizeof(block)*4*SIZE/chk);
140 | memset(tKEY, 0, sizeof(block)*4*SIZE/chk);
141 | memset(tb, false, 4*length/chk);
142 | for(int i = 0; i < length; i+=chk) {
143 | tb[i/chk][1] = data[i];
144 | tb[i/chk][2] = data[i+1];
145 | tb[i/chk][3] = data[i] != data[i+1];
146 | }
147 |
148 | for(int k = 1; k <= nP; ++k) if(k != party) {
149 | uint8_t * tmpptr = tmp;
150 | for(int tt = 0; tt < length/SIZE; tt++) {
151 | int start = SIZE*tt;
152 | for(int i = SIZE*tt; i < SIZE*(tt+1) and i < length; i+=chk) {
153 | tMAC[(i-start)/chk][1] = MAC[k][i];
154 | tMAC[(i-start)/chk][2] = MAC[k][i+1];
155 | tMAC[(i-start)/chk][3] = MAC[k][i] ^ MAC[k][i+1];
156 |
157 | tKEY[(i-start)/chk][1] = KEY[k][i];
158 | tKEY[(i-start)/chk][2] = KEY[k][i+1];
159 | tKEY[(i-start)/chk][3] = KEY[k][i] ^ KEY[k][i+1];
160 | for(int j = 0; j < ssp; ++j) {
161 | Ms[k][j] = Ms[k][j] ^ tMAC[(i-start)/chk][*tmpptr];
162 | Ks[k][j] = Ks[k][j] ^ tKEY[(i-start)/chk][*tmpptr];
163 | bs[k][j] = bs[k][j] != tb[i/chk][*tmpptr];
164 | ++tmpptr;
165 | }
166 | }
167 | }
168 | }
169 | delete[] tmp;
170 | vector> res;
171 | //TODO: they should not need to send MACs.
172 | for(int i = 1; i <= nP; ++i) for(int j = 1; j<= nP; ++j) if( (i < j) and (i == party or j == party) ) {
173 | int party2 = i + j - party;
174 | res.push_back(pool->enqueue([this, Ms, bs, party2]()->bool {
175 | io->send_data(party2, Ms[party2], sizeof(block)*ssp);
176 | io->send_data(party2, bs[party2], ssp);
177 | io->flush(party2);
178 | return false;
179 | }));
180 | res.push_back(pool->enqueue([this, tMs, tbs, Ks, party2]()->bool {
181 | io->recv_data(party2, tMs[party2], sizeof(block)*ssp);
182 | io->recv_data(party2, tbs[party2], ssp);
183 | for(int k = 0; k < ssp; ++k) {
184 | if(tbs[party2][k])
185 | Ks[party2][k] = Ks[party2][k] ^ Delta;
186 | }
187 | return !cmpBlock(Ks[party2], tMs[party2], ssp);
188 | }));
189 | }
190 | if(joinNcleanCheat(res)) error("cheat check1\n");
191 |
192 | for(int i = 1; i <= nP; ++i) {
193 | delete[] Ms[i];
194 | delete[] Ks[i];
195 | delete[] bs[i];
196 | delete[] tMs[i];
197 | delete[] tbs[i];
198 | }
199 | }
200 |
201 | void check2(block * MAC[nP+1], block * KEY[nP+1], bool* data, int length) {
202 | //last 2*ssp are garbage already.
203 | block * Ks[2], *Ms[nP+1][nP+1];
204 | block * KK[nP+1];
205 | bool * bs[nP+1];
206 | Ks[0] = new block[ssp];
207 | Ks[1] = new block[ssp];
208 | for(int i = 1; i <= nP; ++i) {
209 | bs[i] = new bool[ssp];
210 | KK[i] = new block[ssp];
211 | for(int j = 1; j <= nP; ++j)
212 | Ms[i][j] = new block[ssp];
213 | }
214 | char (*dgst)[Hash::DIGEST_SIZE] = new char[nP+1][Hash::DIGEST_SIZE];
215 | char (*dgst0)[Hash::DIGEST_SIZE] = new char[ssp*(nP+1)][Hash::DIGEST_SIZE];
216 | char (*dgst1)[Hash::DIGEST_SIZE] = new char[ssp*(nP+1)][Hash::DIGEST_SIZE];
217 |
218 |
219 | for(int i = 0; i < ssp; ++i) {
220 | Ks[0][i] = zero_block;
221 | for(int j = 1; j <= nP; ++j) if(j != party)
222 | Ks[0][i] = Ks[0][i] ^ KEY[j][length-3*ssp+i];
223 |
224 | Ks[1][i] = Ks[0][i] ^ Delta;
225 | Hash::hash_once(dgst0[party*ssp+i], &Ks[0][i], sizeof(block));
226 | Hash::hash_once(dgst1[party*ssp+i], &Ks[1][i], sizeof(block));
227 | }
228 | Hash h;
229 | h.put(data+length-3*ssp, ssp);
230 | for(int j = 1; j <= nP; ++j) if(j != party) {
231 | h.put(&MAC[j][length-3*ssp], ssp*sizeof(block));
232 | }
233 | h.digest(dgst[party]);
234 |
235 | vector> res;
236 | for(int i = 1; i <= nP; ++i) for(int j = 1; j<= nP; ++j) if( (i < j) and (i == party or j == party) ) {
237 | int party2 = i + j - party;
238 | res.push_back(pool->enqueue([this, dgst, dgst0, dgst1, party2](){
239 | io->send_data(party2, dgst[party], Hash::DIGEST_SIZE);
240 | io->send_data(party2, dgst0[party*ssp], Hash::DIGEST_SIZE*ssp);
241 | io->send_data(party2, dgst1[party*ssp], Hash::DIGEST_SIZE*ssp);
242 | io->recv_data(party2, dgst[party2], Hash::DIGEST_SIZE);
243 | io->recv_data(party2, dgst0[party2*ssp], Hash::DIGEST_SIZE*ssp);
244 | io->recv_data(party2, dgst1[party2*ssp], Hash::DIGEST_SIZE*ssp);
245 | }));
246 | }
247 | joinNclean(res);
248 |
249 | vector> res2;
250 | for(int k = 1; k <= nP; ++k) if(k!= party)
251 | memcpy(Ms[party][k], MAC[k]+length-3*ssp, sizeof(block)*ssp);
252 |
253 | for(int i = 1; i <= nP; ++i) for(int j = 1; j<= nP; ++j) if( (i < j) and (i == party or j == party) ) {
254 | int party2 = i + j - party;
255 | res2.push_back(pool->enqueue([this, data, MAC, length, party2]() -> bool {
256 | io->send_data(party2, data + length - 3*ssp, ssp);
257 | for(int k = 1; k <= nP; ++k) if(k != party)
258 | io->send_data(party2, MAC[k] + length - 3*ssp, sizeof(block)*ssp);
259 | return false;
260 | }));
261 | res2.push_back(pool->enqueue([this, dgst, bs, Ms, party2]() -> bool {
262 | Hash h;
263 | io->recv_data(party2, bs[party2], ssp);
264 | h.put(bs[party2], ssp);
265 | for(int k = 1; k <= nP; ++k) if(k != party2) {
266 | io->recv_data(party2, Ms[party2][k], sizeof(block)*ssp);
267 | h.put(Ms[party2][k], sizeof(block)*ssp);
268 | }
269 | char tmp[Hash::DIGEST_SIZE];h.digest(tmp);
270 | return strncmp(tmp, dgst[party2], Hash::DIGEST_SIZE) != 0;
271 | }));
272 | }
273 | if(joinNcleanCheat(res2)) error("commitment 1\n");
274 |
275 | memset(bs[party], false, ssp);
276 | for(int i = 1; i <= nP; ++i) if(i != party) {
277 | for(int j = 0; j < ssp; ++j)
278 | bs[party][j] = bs[party][j] != bs[i][j];
279 | }
280 | for(int i = 1; i <= nP; ++i) for(int j = 1; j<= nP; ++j) if( (i < j) and (i == party or j == party) ) {
281 | int party2 = i + j - party;
282 | res2.push_back(pool->enqueue([this, bs, Ks, party2]() -> bool {
283 | io->send_data(party2, bs[party], ssp);
284 | for(int i = 0; i < ssp; ++i) {
285 | if(bs[party][i])
286 | io->send_data(party2, &Ks[1][i], sizeof(block));
287 | else
288 | io->send_data(party2, &Ks[0][i], sizeof(block));
289 | }
290 | io->flush(party2);
291 | return false;
292 | }));
293 | res2.push_back(pool->enqueue([this, KK, dgst0, dgst1, party2]() -> bool {
294 | bool cheat = false;
295 | bool *tmp_bool = new bool[ssp];
296 | io->recv_data(party2, tmp_bool, ssp);
297 | io->recv_data(party2, KK[party2], ssp*sizeof(block));
298 | for(int i = 0; i < ssp; ++i) {
299 | char tmp[Hash::DIGEST_SIZE];
300 | Hash::hash_once(tmp, &KK[party2][i], sizeof(block));
301 | if(tmp_bool[i])
302 | cheat = cheat or (strncmp(tmp, dgst1[party2*ssp+i], Hash::DIGEST_SIZE)!=0);
303 | else
304 | cheat = cheat or (strncmp(tmp, dgst0[party2*ssp+i], Hash::DIGEST_SIZE)!=0);
305 | }
306 | delete[] tmp_bool;
307 | return cheat;
308 | }));
309 | }
310 | if(joinNcleanCheat(res2)) error("commitments 2\n");
311 |
312 | bool cheat = false;
313 | block *tmp_block = new block[ssp];
314 | for(int i = 1; i <= nP; ++i) if (i != party) {
315 | memset(tmp_block, 0, sizeof(block)*ssp);
316 | for(int j = 1; j <= nP; ++j) if(j != i) {
317 | for(int k = 0; k < ssp; ++k)
318 | tmp_block[k] = tmp_block[k] ^ Ms[j][i][k];
319 | }
320 | cheat = cheat or !cmpBlock(tmp_block, KK[i], ssp);
321 | }
322 | if(cheat) error("cheat aShare\n");
323 |
324 | delete[] Ks[0];
325 | delete[] Ks[1];
326 | delete[] dgst;
327 | delete[] dgst0;
328 | delete[] dgst1;
329 | delete[] tmp_block;
330 | for(int i = 1; i <= nP; ++i) {
331 | delete[] bs[i];
332 | delete[] KK[i];
333 | for(int j = 1; j <= nP; ++j)
334 | delete[] Ms[i][j];
335 | }
336 | }
337 | };
338 | #endif //ABIT_MP_H__
339 |
--------------------------------------------------------------------------------
/emp-agmpc/cmpc_config.h:
--------------------------------------------------------------------------------
1 | #ifndef __CMPC_CONFIG
2 | #define __CMPC_CONFIG
3 | const static int abit_block_size = 1024;
4 | const static int fpre_threads = 1;
5 | #define LOCALHOST
6 |
7 | #ifdef __clang__
8 | #define __MORE_FLUSH
9 | #endif
10 |
11 | //#define __debug
12 | const static char *IP[] = {""
13 | , "127.0.0.1"
14 | , "127.0.0.1"
15 | , "127.0.0.1"};
16 |
17 | const static bool lan_network = false;
18 | #endif// __C2PC_CONFIG
19 |
--------------------------------------------------------------------------------
/emp-agmpc/emp-agmpc.h:
--------------------------------------------------------------------------------
1 | #ifndef EMP_AGMPC_H__
2 | #define EMP_AGMPC_H__
3 | #include "emp-agmpc/abitmp.h"
4 | #include "emp-agmpc/cmpc_config.h"
5 | #include "emp-agmpc/fpremp.h"
6 | #include "emp-agmpc/helper.h"
7 | #include "emp-agmpc/mpc.h"
8 | #include "emp-agmpc/netmp.h"
9 | #endif// EMP_AGMPC_H__
10 |
--------------------------------------------------------------------------------
/emp-agmpc/flexible_input_output.h:
--------------------------------------------------------------------------------
1 | #ifndef EMP_AGMPC_FLEXIBLE_INPUT_OUTPUT_H
2 | #define EMP_AGMPC_FLEXIBLE_INPUT_OUTPUT_H
3 |
4 | using namespace std;
5 |
6 | template
7 | struct AuthBitShare
8 | {
9 | bool bit_share;
10 | block key[nP + 1];
11 | block mac[nP + 1];
12 | };
13 |
14 | struct BitWithMac
15 | {
16 | bool bit_share;
17 | block mac;
18 | };
19 |
20 | template
21 | class FlexIn
22 | {
23 | public:
24 |
25 | int len{};
26 | int party{};
27 |
28 | bool cmpc_associated = false;
29 | ThreadPool* pool;
30 | bool *value;
31 | block *key[nP + 1];
32 | block *mac[nP + 1];
33 | NetIOMP * io;
34 | block Delta;
35 |
36 | vector party_assignment;
37 | // -2 represents an un-authenticated share (e.g., for random tape),
38 | // -1 represents an authenticated share,
39 | // 0 represents public input/output,
40 |
41 | vector plaintext_assignment; // if `party` provides the value for this bit, the plaintext value is here
42 | vector> authenticated_share_assignment; // if this bit is from authenticated shares, the authenticated share is stored here
43 |
44 | FlexIn(int len, int party) {
45 | this->len = len;
46 | this->party = party;
47 | this->pool = pool;
48 |
49 | AuthBitShare empty_abit;
50 | memset(&empty_abit, 0, sizeof(AuthBitShare));
51 |
52 | party_assignment.resize(len, 0);
53 | plaintext_assignment.resize(len, false);
54 | authenticated_share_assignment.resize(len, empty_abit);
55 | }
56 |
57 | ~FlexIn() {
58 | party_assignment.clear();
59 | plaintext_assignment.clear();
60 | authenticated_share_assignment.clear();
61 | }
62 |
63 | void associate_cmpc(ThreadPool *associated_pool, bool *associated_value, block *associated_mac[nP + 1], block *associated_key[nP + 1], NetIOMP *associated_io, block associated_Delta) {
64 | this->cmpc_associated = true;
65 | this->pool = associated_pool;
66 | this->value = associated_value;
67 | for(int j = 1; j <= nP; j++) {
68 | this->mac[j] = associated_mac[j];
69 | this->key[j] = associated_key[j];
70 | }
71 | this->io = associated_io;
72 | this->Delta = associated_Delta;
73 | }
74 |
75 | void assign_party(int pos, int which_party) {
76 | party_assignment[pos] = which_party;
77 | }
78 |
79 | void assign_plaintext_bit(int pos, bool cur_bit) {
80 | assert(party_assignment[pos] == party || party_assignment[pos] == -2 || party_assignment[pos] == 0);
81 | plaintext_assignment[pos] = cur_bit;
82 | }
83 |
84 | void assign_authenticated_bitshare(int pos, AuthBitShare *abit) {
85 | assert(party_assignment[pos] == -1);
86 | memcpy(&authenticated_share_assignment[pos], abit, sizeof(AuthBitShare));
87 | }
88 |
89 | void input(bool *masked_input_ret) {
90 | assert(cmpc_associated);
91 |
92 | /* assemble an array of the input masks, their macs, and their keys */
93 | /*
94 | * Then,
95 | * for a plaintext bit, the input mask, as well as its MAC, is sent to the input party, who uses the KEY for verification;
96 | * for an un-authenticated bit, the input mask XOR with the input share is broadcast;
97 | * for an authenticated bit share, they are used to masked the previously data (and then checking its opening)
98 | */
99 | vector> input_mask;
100 | for(int i = 0; i < len; i++) {
101 | AuthBitShare abit;
102 | abit.bit_share = value[i];
103 | for(int j = 1; j <= nP; j++) {
104 | if(j != party) {
105 | abit.key[j] = key[j][i];
106 | abit.mac[j] = mac[j][i];
107 | }
108 | }
109 | input_mask.emplace_back(abit);
110 | }
111 |
112 | /*
113 | * first of all, handle the case party_assignment[] > 0
114 | */
115 |
116 | /* prepare the bit shares to open for the corresponding party */
117 | vector> open_bit_shares_for_plaintext_input_send;
118 | open_bit_shares_for_plaintext_input_send.resize(nP + 1);
119 |
120 | for(int j = 1; j <= nP; j++) {
121 | if(j != party) {
122 | for(int i = 0; i < len; i++) {
123 | BitWithMac mbit{};
124 | if(party_assignment[i] == j) {
125 | mbit.bit_share = input_mask[i].bit_share;
126 | mbit.mac = input_mask[i].mac[j];
127 | }
128 | open_bit_shares_for_plaintext_input_send[j].push_back(mbit);
129 | }
130 | }
131 | }
132 |
133 | vector> open_bit_shares_for_plaintext_input_recv;
134 | open_bit_shares_for_plaintext_input_recv.resize(nP + 1);
135 | for(int j = 1; j <= nP; j++) {
136 | open_bit_shares_for_plaintext_input_recv[j].resize(len);
137 | }
138 |
139 | /*
140 | * exchange the opening of the input mask
141 | */
142 | vector> res;
143 | for (int i = 1; i <= nP; ++i) {
144 | for (int j = 1; j <= nP; ++j) {
145 | if ((i < j) and (i == party or j == party)) {
146 | int party2 = i + j - party;
147 |
148 | res.push_back(pool->enqueue([this, &open_bit_shares_for_plaintext_input_recv, party2]() {
149 | io->recv_data(party2, open_bit_shares_for_plaintext_input_recv[party2].data(), sizeof(BitWithMac) * len);
150 | io->flush(party2);
151 | }));
152 | res.push_back(pool->enqueue([this, &open_bit_shares_for_plaintext_input_send, party2]() {
153 | io->send_data(party2, open_bit_shares_for_plaintext_input_send[party2].data(), sizeof(BitWithMac) * len);
154 | io->flush(party2);
155 | }));
156 | }
157 | }
158 | }
159 | joinNclean(res);
160 |
161 | /*
162 | * verify the input mask
163 | */
164 | vector> res_check;
165 | for (int j = 1; j <= nP; ++j) {
166 | if(j != party) {
167 | res_check.push_back(pool->enqueue([this, &input_mask, &open_bit_shares_for_plaintext_input_recv, j]() {
168 | for (int i = 0; i < len; i++) {
169 | if (party_assignment[i] == party) {
170 | block supposed_mac = Delta & select_mask[open_bit_shares_for_plaintext_input_recv[j][i].bit_share? 1 : 0];
171 | supposed_mac ^= input_mask[i].key[j];
172 |
173 | block provided_mac = open_bit_shares_for_plaintext_input_recv[j][i].mac;
174 |
175 | if(!cmpBlock(&supposed_mac, &provided_mac, 1)) {
176 | return true;
177 | }
178 | }
179 | }
180 | return false;
181 | }));
182 | }
183 | }
184 | if(joinNcleanCheat(res_check)) error("cheat in FlexIn's plaintext input mask!");
185 |
186 | /*
187 | * broadcast the masked input
188 | */
189 | vector masked_input_sent; // use char instead of bool because bools seem to fail for "data()"
190 | vector> masked_input_recv;
191 | masked_input_sent.resize(len);
192 | masked_input_recv.resize(nP + 1);
193 | for(int j = 1; j <= nP; j++) {
194 | masked_input_recv[j].resize(len);
195 | }
196 |
197 | for(int i = 0; i < len; i++) {
198 | if(party_assignment[i] == party) {
199 | masked_input_sent[i] = plaintext_assignment[i] ^ input_mask[i].bit_share;
200 | for(int j = 1; j <= nP; j++) {
201 | if(j != party) {
202 | masked_input_sent[i] = masked_input_sent[i] ^ open_bit_shares_for_plaintext_input_recv[j][i].bit_share;
203 | }
204 | }
205 | }
206 | }
207 |
208 | for (int i = 1; i <= nP; ++i) {
209 | for (int j = 1; j <= nP; ++j) {
210 | if ((i < j) and (i == party or j == party)) {
211 | int party2 = i + j - party;
212 |
213 | res.push_back(pool->enqueue([this, &masked_input_recv, party2]() {
214 | io->recv_data(party2, masked_input_recv[party2].data(), sizeof(char) * len);
215 | io->flush(party2);
216 | }));
217 | res.push_back(pool->enqueue([this, &masked_input_sent, party2]() {
218 | io->send_data(party2, masked_input_sent.data(), sizeof(char) * len);
219 | io->flush(party2);
220 | }));
221 | }
222 | }
223 | }
224 | joinNclean(res);
225 |
226 | vector masked_input;
227 | masked_input.resize(len);
228 | for(int i = 0; i < len; i++) {
229 | if(party_assignment[i] > 0) {
230 | int this_party = party_assignment[i];
231 | if(this_party == party) {
232 | masked_input[i] = masked_input_sent[i];
233 | } else {
234 | masked_input[i] = masked_input_recv[this_party][i];
235 | }
236 | }
237 | }
238 |
239 | /*
240 | * secondly, handle the case party_assignment[] == -1
241 | */
242 |
243 | /*
244 | * Compute the authenticated bit share to the new circuit
245 | * by XOR-ing with the input mask
246 | */
247 | vector> authenticated_bitshares_new_circuit;
248 | for(int i = 0; i < len; i++) {
249 | AuthBitShare new_entry;
250 | memset(&new_entry, 0, sizeof(AuthBitShare));
251 | if(party_assignment[i] == -1) {
252 | new_entry.bit_share = authenticated_share_assignment[i].bit_share ^ input_mask[i].bit_share;
253 | for (int j = 1; j <= nP; j++) {
254 | new_entry.key[j] = authenticated_share_assignment[i].key[j] ^ input_mask[i].key[j];
255 | new_entry.mac[j] = authenticated_share_assignment[i].mac[j] ^ input_mask[i].mac[j];
256 | }
257 | }
258 | authenticated_bitshares_new_circuit.emplace_back(new_entry);
259 | }
260 |
261 | //print_block(Delta);
262 |
263 | /*
264 | cout << "Debug the authenticated input" << endl;
265 | for(int i = 0; i < 10; i++){
266 | if(party_assignment[i] == -1) {
267 | cout << "index: " << i << ", value: " << authenticated_share_assignment[i].bit_share << endl;
268 | cout << "mac: " << endl;
269 | for(int j = 1; j <= nP; j++) {
270 | if(j != party) {
271 | //cout << j << ": ";
272 | print_block(authenticated_share_assignment[i].mac[j]);
273 | }
274 | }
275 | cout << "key: " << endl;
276 | for(int j = 1; j <= nP; j++) {
277 | if(j != party) {
278 | //cout << j << ": ";
279 | print_block(authenticated_share_assignment[i].key[j]);
280 | print_block(authenticated_share_assignment[i].key[j] ^ Delta);
281 | }
282 | }
283 | cout << "=============" << endl;
284 | }
285 | }
286 | */
287 |
288 | /*
289 | * Opening the authenticated shares
290 | */
291 | vector> open_bit_shares_for_authenticated_bits_send;
292 | open_bit_shares_for_authenticated_bits_send.resize(nP + 1);
293 |
294 | for(int j = 1; j <= nP; j++) {
295 | if(j != party) {
296 | for(int i = 0; i < len; i++) {
297 | BitWithMac mbit{};
298 | if(party_assignment[i] == -1) {
299 | mbit.bit_share = authenticated_bitshares_new_circuit[i].bit_share;
300 | mbit.mac = authenticated_bitshares_new_circuit[i].mac[j];
301 | }
302 | open_bit_shares_for_authenticated_bits_send[j].push_back(mbit);
303 | }
304 | }
305 | }
306 |
307 | vector> open_bit_shares_for_authenticated_bits_recv;
308 | open_bit_shares_for_authenticated_bits_recv.resize(nP + 1);
309 | for(int j = 1; j <= nP; j++) {
310 | open_bit_shares_for_authenticated_bits_recv[j].resize(len);
311 | }
312 |
313 | for (int i = 1; i <= nP; ++i) {
314 | for (int j = 1; j <= nP; ++j) {
315 | if ((i < j) and (i == party or j == party)) {
316 | int party2 = i + j - party;
317 |
318 | res.push_back(pool->enqueue([this, &open_bit_shares_for_authenticated_bits_recv, party2]() {
319 | io->recv_data(party2, open_bit_shares_for_authenticated_bits_recv[party2].data(), sizeof(BitWithMac) * len);
320 | io->flush(party2);
321 | }));
322 | res.push_back(pool->enqueue([this, &open_bit_shares_for_authenticated_bits_send, party2]() {
323 | io->send_data(party2, open_bit_shares_for_authenticated_bits_send[party2].data(), sizeof(BitWithMac) * len);
324 | io->flush(party2);
325 | }));
326 | }
327 | }
328 | }
329 | joinNclean(res);
330 |
331 | /*
332 | * verify the input mask shares
333 | */
334 | for (int j = 1; j <= nP; ++j) {
335 | if(j != party) {
336 | res_check.push_back(pool->enqueue([this, &authenticated_bitshares_new_circuit, &open_bit_shares_for_authenticated_bits_recv, j]() {
337 | for (int i = 0; i < len; i++) {
338 | if (party_assignment[i] == -1) {
339 | block supposed_mac = Delta & select_mask[open_bit_shares_for_authenticated_bits_recv[j][i].bit_share? 1 : 0];
340 | supposed_mac ^= authenticated_bitshares_new_circuit[i].key[j];
341 |
342 | block provided_mac = open_bit_shares_for_authenticated_bits_recv[j][i].mac;
343 |
344 | if(!cmpBlock(&supposed_mac, &provided_mac, 1)) {
345 | return true;
346 | }
347 | }
348 | }
349 | return false;
350 | }));
351 | }
352 | }
353 | if(joinNcleanCheat(res_check)) error("cheat in FlexIn's authenticated share input mask!");
354 |
355 | /*
356 | * Reconstruct the authenticated shares
357 | */
358 | for(int i = 0; i < len; i++) {
359 | if(party_assignment[i] == -1) {
360 | masked_input[i] = authenticated_bitshares_new_circuit[i].bit_share;
361 | for(int j = 1; j <= nP; j++) {
362 | if(j != party) {
363 | masked_input[i] = masked_input[i] ^ open_bit_shares_for_authenticated_bits_recv[j][i].bit_share;
364 | }
365 | }
366 | }
367 | }
368 |
369 | /*
370 | * thirdly, handle the case party_assignment[] = -2
371 | */
372 |
373 | /*
374 | * Collect the masked input shares for un-authenticated bits
375 | */
376 | vector open_bit_shares_for_unauthenticated_bits_send;
377 | open_bit_shares_for_unauthenticated_bits_send.resize(len);
378 |
379 | for(int i = 0; i < len; i++) {
380 | if(party_assignment[i] == -2) {
381 | open_bit_shares_for_unauthenticated_bits_send[i] = (plaintext_assignment[i] ^ input_mask[i].bit_share)? 1 : 0;
382 | }
383 | }
384 |
385 | vector> open_bit_shares_for_unauthenticated_bits_recv;
386 | open_bit_shares_for_unauthenticated_bits_recv.resize(nP + 1);
387 | for(int j = 1; j <= nP; j++) {
388 | open_bit_shares_for_unauthenticated_bits_recv[j].resize(len);
389 | }
390 |
391 | for (int i = 1; i <= nP; ++i) {
392 | for (int j = 1; j <= nP; ++j) {
393 | if ((i < j) and (i == party or j == party)) {
394 | int party2 = i + j - party;
395 |
396 | res.push_back(pool->enqueue([this, &open_bit_shares_for_unauthenticated_bits_recv, party2]() {
397 | io->recv_data(party2, open_bit_shares_for_unauthenticated_bits_recv[party2].data(), sizeof(char) * len);
398 | io->flush(party2);
399 | }));
400 | res.push_back(pool->enqueue([this, &open_bit_shares_for_unauthenticated_bits_send, party2]() {
401 | io->send_data(party2, open_bit_shares_for_unauthenticated_bits_send.data(), sizeof(char) * len);
402 | io->flush(party2);
403 | }));
404 | }
405 | }
406 | }
407 | joinNclean(res);
408 |
409 | /*
410 | * update the array of masked_input accordingly
411 | */
412 | for(int i = 0; i < len; i++) {
413 | if(party_assignment[i] == -2) {
414 | masked_input[i] = open_bit_shares_for_unauthenticated_bits_send[i];
415 | for(int j = 1; j <= nP; j++) {
416 | if(j != party) {
417 | masked_input[i] = masked_input[i] ^ (open_bit_shares_for_unauthenticated_bits_recv[j][i] == 1);
418 | }
419 | }
420 | }
421 | }
422 |
423 | /*
424 | * lastly, handle the case party_assignment[] = 0
425 | */
426 |
427 | /*
428 | * broadcast the input mask and its MAC
429 | */
430 | vector> open_bit_shares_for_public_input_send;
431 | open_bit_shares_for_public_input_send.resize(nP + 1);
432 |
433 | for(int j = 1; j <= nP; j++) {
434 | if(j != party) {
435 | for(int i = 0; i < len; i++) {
436 | BitWithMac mbit{};
437 | if(party_assignment[i] == 0) {
438 | mbit.bit_share = input_mask[i].bit_share;
439 | mbit.mac = input_mask[i].mac[j];
440 | }
441 | open_bit_shares_for_public_input_send[j].push_back(mbit);
442 | }
443 | }
444 | }
445 |
446 | vector> open_bit_shares_for_public_input_recv;
447 | open_bit_shares_for_public_input_recv.resize(nP + 1);
448 | for(int j = 1; j <= nP; j++) {
449 | open_bit_shares_for_public_input_recv[j].resize(len);
450 | }
451 |
452 | /*
453 | * exchange the opening of the input mask
454 | */
455 | for (int i = 1; i <= nP; ++i) {
456 | for (int j = 1; j <= nP; ++j) {
457 | if ((i < j) and (i == party or j == party)) {
458 | int party2 = i + j - party;
459 |
460 | res.push_back(pool->enqueue([this, &open_bit_shares_for_public_input_recv, party2]() {
461 | io->recv_data(party2, open_bit_shares_for_public_input_recv[party2].data(), sizeof(BitWithMac) * len);
462 | io->flush(party2);
463 | }));
464 | res.push_back(pool->enqueue([this, &open_bit_shares_for_public_input_send, party2]() {
465 | io->send_data(party2, open_bit_shares_for_public_input_send[party2].data(), sizeof(BitWithMac) * len);
466 | io->flush(party2);
467 | }));
468 | }
469 | }
470 | }
471 | joinNclean(res);
472 |
473 | /*
474 | * verify the input mask
475 | */
476 | for (int j = 1; j <= nP; ++j) {
477 | if(j != party) {
478 | res_check.push_back(pool->enqueue([this, &input_mask, &open_bit_shares_for_public_input_recv, j]() {
479 | for (int i = 0; i < len; i++) {
480 | if (party_assignment[i] == 0) {
481 | block supposed_mac = Delta & select_mask[open_bit_shares_for_public_input_recv[j][i].bit_share? 1 : 0];
482 | supposed_mac ^= input_mask[i].key[j];
483 |
484 | block provided_mac = open_bit_shares_for_public_input_recv[j][i].mac;
485 |
486 | if(!cmpBlock(&supposed_mac, &provided_mac, 1)) {
487 | return true;
488 | }
489 | }
490 | }
491 | return false;
492 | }));
493 | }
494 | }
495 | if(joinNcleanCheat(res_check)) error("cheat in FlexIn's public input mask!");
496 |
497 | /*
498 | * update the masked input
499 | */
500 | for(int i = 0; i < len; i++) {
501 | if(party_assignment[i] == 0) {
502 | masked_input[i] = plaintext_assignment[i] ^ input_mask[i].bit_share;
503 | for(int j = 1; j <= nP; j++) {
504 | if(j != party) {
505 | masked_input[i] = masked_input[i] ^ open_bit_shares_for_public_input_recv[j][i].bit_share;
506 | }
507 | }
508 | }
509 | }
510 |
511 | /*
512 | cout << "masked_input" << endl;
513 | for(int i = 0; i < len; i++) {
514 | cout << masked_input[i] << " ";
515 | }
516 | cout << endl;
517 | */
518 |
519 | for(int i = 0; i < len; i++) {
520 | masked_input_ret[i] = masked_input[i];
521 | }
522 | }
523 |
524 | int get_length() {
525 | return len;
526 | }
527 | };
528 |
529 | template
530 | class FlexOut
531 | {
532 | public:
533 |
534 | int len{};
535 | int party{};
536 |
537 | bool cmpc_associated = false;
538 | ThreadPool* pool;
539 | bool *value;
540 | block *key[nP + 1];
541 | block *mac[nP + 1];
542 | block *eval_labels[nP + 1];
543 | NetIOMP * io;
544 | block Delta;
545 | block *labels;
546 |
547 | vector party_assignment;
548 | // -1 represents an authenticated share,
549 | // 0 represents public output
550 |
551 | vector plaintext_results; // if `party` provides the value for this bit, the plaintext value is here
552 | vector> authenticated_share_results; // if this bit is from authenticated shares, the authenticated share is stored here
553 |
554 | FlexOut(int len, int party) {
555 | this->len = len;
556 | this->party = party;
557 | this->pool = pool;
558 |
559 | AuthBitShare empty_abit;
560 | memset(&empty_abit, 0, sizeof(AuthBitShare));
561 |
562 | party_assignment.resize(len, 0);
563 | plaintext_results.resize(len, false);
564 | authenticated_share_results.resize(len, empty_abit);
565 | }
566 |
567 | ~FlexOut() {
568 | party_assignment.clear();
569 | plaintext_results.clear();
570 | authenticated_share_results.clear();
571 | }
572 |
573 | void associate_cmpc(ThreadPool *associated_pool, bool *associated_value, block *associated_mac[nP + 1], block *associated_key[nP + 1], block *associated_eval_labels[nP + 1], block *associated_labels, NetIOMP *associated_io, block associated_Delta) {
574 | this->cmpc_associated = true;
575 | this->pool = associated_pool;
576 | this->value = associated_value;
577 | this->labels = associated_labels;
578 | for (int j = 1; j <= nP; j++) {
579 | this->mac[j] = associated_mac[j];
580 | this->key[j] = associated_key[j];
581 | }
582 | if (party == ALICE){
583 | for (int j = 2; j <= nP; j++) {
584 | this->eval_labels[j] = associated_eval_labels[j];
585 | }
586 | }
587 | this->io = associated_io;
588 | this->Delta = associated_Delta;
589 | }
590 |
591 | void assign_party(int pos, int which_party) {
592 | party_assignment[pos] = which_party;
593 | }
594 |
595 | bool get_plaintext_bit(int pos) {
596 | assert(party_assignment[pos] == party || party_assignment[pos] == 0);
597 | return plaintext_results[pos];
598 | }
599 |
600 | AuthBitShare get_authenticated_bitshare(int pos) {
601 | assert(party_assignment[pos] == -1);
602 | return authenticated_share_results[pos];
603 | }
604 |
605 | int get_length() {
606 | return len;
607 | }
608 |
609 | void output(bool *masked_input_ret, int output_shift) {
610 | assert(cmpc_associated);
611 |
612 | /*
613 | * Party 1 sends the labels of all the output wires out.
614 | */
615 | vector output_wire_label_recv;
616 | output_wire_label_recv.resize(len);
617 |
618 | vector> res;
619 |
620 | if(party == ALICE) {
621 | vector> output_wire_label_send;
622 | output_wire_label_send.resize(nP + 1);
623 |
624 | for (int j = 2; j <= nP; j++) {
625 | output_wire_label_send[j].resize(len);
626 | for(int i = 0; i < len; i++) {
627 | output_wire_label_send[j][i] = eval_labels[j][output_shift + i];
628 | }
629 | }
630 |
631 | for(int j = 2; j <= nP; j++) {
632 | res.push_back(pool->enqueue([this, &output_wire_label_send, j]() {
633 | io->send_data(j, output_wire_label_send[j].data(), sizeof(block) * len);
634 | io->flush(j);
635 | }));
636 | }
637 | joinNclean(res);
638 | }else {
639 | io->recv_data(ALICE, output_wire_label_recv.data(), sizeof(block) * len);
640 | io->flush(ALICE);
641 | }
642 |
643 | /*
644 | * Each party extracts x ^ r of each output wire
645 | */
646 | vector masked_output;
647 | masked_output.resize(len);
648 |
649 | if(party == ALICE) {
650 | for(int i = 0; i < len; i++) {
651 | masked_output[i] = masked_input_ret[output_shift + i];
652 | }
653 | } else {
654 | for(int i = 0; i < len; i++) {
655 | block cur_label = output_wire_label_recv[i];
656 | block zero_label = labels[i + output_shift];
657 | block one_label = zero_label ^ Delta;
658 |
659 | if(cmpBlock(&cur_label, &zero_label, 1)) {
660 | masked_output[i] = false;
661 | } else if(cmpBlock(&cur_label, &one_label, 1)) {
662 | masked_output[i] = true;
663 | } else {
664 | error("Output label mismatched.\n");
665 | }
666 | }
667 | }
668 |
669 | /*
670 | * Decide the broadcasting of the shares of r, as well as their MAC
671 | */
672 | vector> output_mask_send;
673 | output_mask_send.resize(nP + 1);
674 | for(int j = 1; j <= nP; j++) {
675 | BitWithMac empty_mbit{};
676 | output_mask_send[j].resize(len, empty_mbit);
677 | }
678 |
679 | for(int i = 0; i < len; i++) {
680 | if(party_assignment[i] == -1) {
681 | // do nothing, just update the share (for the first party) later
682 | } else if(party_assignment[i] == 0) {
683 | // public output, all parties receive the mbit
684 | for(int j = 1; j <= nP; j++){
685 | output_mask_send[j][i].bit_share = value[output_shift + i];
686 | output_mask_send[j][i].mac = mac[j][output_shift + i];
687 | }
688 | } else {
689 | // only one party is supposed to receive the mbit
690 | int cur_party = party_assignment[i];
691 | output_mask_send[cur_party][i].bit_share = value[output_shift + i];
692 | output_mask_send[cur_party][i].mac = mac[cur_party][output_shift + i];
693 | }
694 | }
695 |
696 | /*
697 | * Exchange the output mask
698 | */
699 | vector> output_mask_recv;
700 | output_mask_recv.resize(nP + 1);
701 | for(int j = 1; j <= nP; j++) {
702 | output_mask_recv[j].resize(len);
703 | }
704 |
705 | for (int i = 1; i <= nP; ++i) {
706 | for (int j = 1; j <= nP; ++j) {
707 | if ((i < j) and (i == party or j == party)) {
708 | int party2 = i + j - party;
709 |
710 | res.push_back(pool->enqueue([this, &output_mask_recv, party2]() {
711 | io->recv_data(party2, output_mask_recv[party2].data(), sizeof(BitWithMac) * len);
712 | io->flush(party2);
713 | }));
714 | res.push_back(pool->enqueue([this, &output_mask_send, party2]() {
715 | io->send_data(party2, output_mask_send[party2].data(), sizeof(BitWithMac) * len);
716 | io->flush(party2);
717 | }));
718 | }
719 | }
720 | }
721 | joinNclean(res);
722 |
723 | /*
724 | * Verify the output mask
725 | */
726 | vector> res_check;
727 | for (int j = 1; j <= nP; ++j) {
728 | if(j != party) {
729 | res_check.push_back(pool->enqueue([this, &output_mask_recv, j, output_shift]() {
730 | for (int i = 0; i < len; i++) {
731 | if (party_assignment[i] == party || party_assignment[i] == 0) {
732 | block supposed_mac = Delta & select_mask[output_mask_recv[j][i].bit_share? 1 : 0];
733 | supposed_mac ^= key[j][output_shift + i];
734 |
735 | block provided_mac = output_mask_recv[j][i].mac;
736 |
737 | if(!cmpBlock(&supposed_mac, &provided_mac, 1)) {
738 | return true;
739 | }
740 | }
741 | }
742 | return false;
743 | }));
744 | }
745 | }
746 | if(joinNcleanCheat(res_check)) error("cheat in FlexOut's output mask!");
747 |
748 | /*
749 | * Handle the case party_assignment[] = -1
750 | */
751 | if(party == ALICE) {
752 | for(int i = 0; i < len; i++) {
753 | if(party_assignment[i] == -1) {
754 | authenticated_share_results[i].bit_share = value[output_shift + i] ^ masked_output[i];
755 | for(int j = 1; j <= nP; j++) {
756 | if(j != party) {
757 | authenticated_share_results[i].mac[j] = mac[j][output_shift + i];
758 | authenticated_share_results[i].key[j] = key[j][output_shift + i];
759 | }
760 | }
761 | }
762 | }
763 | } else {
764 | for(int i = 0; i < len; i++) {
765 | if(party_assignment[i] == -1) {
766 | authenticated_share_results[i].bit_share = value[output_shift + i];
767 | for(int j = 1; j <= nP; j++) {
768 | if(j != party) {
769 | authenticated_share_results[i].mac[j] = mac[j][output_shift + i];
770 | if(j == ALICE) {
771 | authenticated_share_results[i].key[j] =
772 | key[j][output_shift + i] ^ (Delta & select_mask[masked_output[i] ? 1 : 0]);
773 | // change the MAC key for the first party
774 | } else {
775 | authenticated_share_results[i].key[j] = key[j][output_shift + i];
776 | }
777 | }
778 | }
779 | }
780 | }
781 | }
782 |
783 | //print_block(Delta);
784 |
785 | /*
786 | cout << "Debug the authenticated output" << endl;
787 | for(int i = 0; i < 10; i++){
788 | if(party_assignment[i] == -1) {
789 | cout << "index: " << i << ", value: " << authenticated_share_results[i].bit_share << endl;
790 | cout << "mac: " << endl;
791 | for(int j = 1; j <= nP; j++) {
792 | if(j != party) {
793 | //cout << j << ": ";
794 | print_block(authenticated_share_results[i].mac[j]);
795 | }
796 | }
797 | cout << "key: " << endl;
798 | for(int j = 1; j <= nP; j++) {
799 | if(j != party) {
800 | //cout << j << ": ";
801 | print_block(authenticated_share_results[i].key[j]);
802 | print_block(authenticated_share_results[i].key[j] ^ Delta);
803 | }
804 | }
805 | cout << "=============" << endl;
806 | }
807 | }
808 | */
809 |
810 | /*
811 | * Handle the case party_assignment[] = 0 or == party
812 | */
813 | for(int i = 0; i < len; i++) {
814 | if(party_assignment[i] == 0 || party_assignment[i] == party) {
815 | plaintext_results[i] = value[output_shift + i] ^ masked_output[i];
816 | for(int j = 1; j <= nP; j++) {
817 | if(j != party) {
818 | plaintext_results[i] = plaintext_results[i] ^ output_mask_recv[j][i].bit_share;
819 | }
820 | }
821 | }
822 | }
823 | }
824 | };
825 |
826 | #endif //EMP_AGMPC_FLEXIBLE_INPUT_OUTPUT_H
827 |
--------------------------------------------------------------------------------
/emp-agmpc/fpremp.h:
--------------------------------------------------------------------------------
1 | //TODO: check MACs
2 | #ifndef FPRE_MP_H__
3 | #define FPRE_MP_H__
4 | #include
5 | #include
6 | #include "abitmp.h"
7 | #include "netmp.h"
8 | #include "cmpc_config.h"
9 |
10 | using namespace emp;
11 | template
12 | class FpreMP { public:
13 | ThreadPool *pool;
14 | int party;
15 | NetIOMP * io;
16 | ABitMP* abit;
17 | block Delta;
18 | CRH * prps;
19 | CRH * prps2;
20 | PRG * prgs;
21 | PRG prg;
22 | int ssp;
23 | FpreMP(NetIOMP * io[2], ThreadPool * pool, int party, bool * _delta = nullptr, int ssp = 40) {
24 | this->party = party;
25 | this->pool = pool;
26 | this->io = io[0];
27 | this ->ssp = ssp;
28 | abit = new ABitMP(io[1], pool, party, _delta, ssp);
29 | Delta = abit->Delta;
30 | prps = new CRH[nP+1];
31 | prps2 = new CRH[nP+1];
32 | prgs = new PRG[nP+1];
33 | }
34 | ~FpreMP(){
35 | delete[] prps;
36 | delete[] prps2;
37 | delete[] prgs;
38 | delete abit;
39 | }
40 | int get_bucket_size(int size) {
41 | size = max(size, 320);
42 | int batch_size = ((size+2-1)/2)*2;
43 | if(batch_size >= 280*1000)
44 | return 3;
45 | else if(batch_size >= 3100)
46 | return 4;
47 | else return 5;
48 | }
49 | void compute(block * MAC[nP+1], block * KEY[nP+1], bool * r, int length) {
50 | int64_t bucket_size = get_bucket_size(length);
51 | block * tMAC[nP+1];
52 | block * tKEY[nP+1];
53 | block * tKEYphi[nP+1];
54 | block * tMACphi[nP+1];
55 | block * phi;
56 | block *X [nP+1];
57 | bool *tr = new bool[length*bucket_size*3+3*ssp];
58 | phi = new block[length*bucket_size];
59 | bool *s[nP+1], *e = new bool[length*bucket_size];
60 | for(int i = 1; i <= nP; ++i) {
61 | tMAC[i] = new block[length*bucket_size*3+3*ssp];
62 | tKEY[i] = new block[length*bucket_size*3+3*ssp];
63 | tKEYphi[i] = new block[length*bucket_size+3*ssp];
64 | tMACphi[i] = new block[length*bucket_size+3*ssp];
65 | X[i] = new block[ssp];
66 | }
67 | for(int i = 0; i <= nP; ++i) {
68 | s[i] = new bool[length*bucket_size];
69 | memset(s[i], 0, length*bucket_size);
70 | }
71 | prg.random_bool(tr, length*bucket_size*3+3*ssp);
72 | // memset(tr, false, length*bucket_size*3+3*ssp);
73 | abit->compute(tMAC, tKEY, tr, length*bucket_size*3 + 3*ssp);
74 | vector> res;
75 |
76 | for(int i = 1; i <= nP; ++i) for(int j = 1; j <= nP; ++j) if (i < j ) {
77 | if(i == party) {
78 | res.push_back(pool->enqueue([this, tKEY, tr, s, length, bucket_size, j]() {
79 | prgs[j].random_bool(s[j], length*bucket_size);
80 | for(int k = 0; k < length*bucket_size; ++k) {
81 | uint8_t data = garble(tKEY[j], tr, s[j], k, j);
82 | io->send_data(j, &data, 1);
83 | s[j][k] = (s[j][k] != (tr[3*k] and tr[3*k+1]));
84 | }
85 | io->flush(j);
86 | }));
87 | } else if (j == party) {
88 | res.push_back(pool->enqueue([this, tMAC, tr, s, length, bucket_size, i]() {
89 | for(int k = 0; k < length*bucket_size; ++k) {
90 | uint8_t data = 0;
91 | io->recv_data(i, &data, 1);
92 | bool tmp = evaluate(data, tMAC[i], tr, k, i);
93 | s[i][k] = (tmp != (tr[3*k] and tr[3*k+1]));
94 | }
95 | }));
96 | }
97 | }
98 | joinNclean(res);
99 | for(int k = 0; k < length*bucket_size; ++k) {
100 | s[0][k] = (tr[3*k] and tr[3*k+1]);
101 | for(int i = 1; i <= nP; ++i)
102 | if (i != party) {
103 | s[0][k] = (s[0][k] != s[i][k]);
104 | }
105 | e[k] = (s[0][k] != tr[3*k+2]);
106 | tr[3*k+2] = s[0][k];
107 | }
108 |
109 | #ifdef __debug
110 | check_correctness(io, tr, length*bucket_size, party);
111 | #endif
112 | for(int i = 1; i <= nP; ++i) for(int j = 1; j<= nP; ++j) if( (i < j) and (i == party or j == party) ) {
113 | int party2 = i + j - party;
114 | res.push_back(pool->enqueue([this, e, length, bucket_size, party2]() {
115 | io->send_data(party2, e, length*bucket_size);
116 | io->flush(party2);
117 | }));
118 | res.push_back(pool->enqueue([this, tKEY, length, bucket_size, party2]() {
119 | bool * tmp = new bool[length*bucket_size];
120 | io->recv_data(party2, tmp, length*bucket_size);
121 | for(int k = 0; k < length*bucket_size; ++k) {
122 | if(tmp[k])
123 | tKEY[party2][3*k+2] = tKEY[party2][3*k+2] ^ Delta;
124 | }
125 | delete[] tmp;
126 | }));
127 | }
128 | joinNclean(res);
129 | #ifdef __debug
130 | check_MAC(io, tMAC, tKEY, tr, Delta, length*bucket_size*3, party);
131 | #endif
132 | auto ret = abit->check(tMAC, tKEY, tr, length*bucket_size*3 + 3*ssp);
133 | ret.get();
134 | //check compute phi
135 | for(int k = 0; k < length*bucket_size; ++k) {
136 | phi[k] = zero_block;
137 | for(int i = 1; i <= nP; ++i) if (i != party) {
138 | phi[k] = phi[k] ^ tKEY[i][3*k+1];
139 | phi[k] = phi[k] ^ tMAC[i][3*k+1];
140 | }
141 | if(tr[3*k+1])phi[k] = phi[k] ^ Delta;
142 | }
143 |
144 | for(int i = 1; i <= nP; ++i) for(int j = 1; j<= nP; ++j) if( (i < j) and (i == party or j == party) ) {
145 | int party2 = i + j - party;
146 | res.push_back(pool->enqueue([this, tKEY, tKEYphi, phi, length, bucket_size, party2]() {
147 | block bH[2], tmpH[2];
148 | for(int k = 0; k < length*bucket_size; ++k) {
149 | bH[0] = tKEY[party2][3*k];
150 | bH[1] = bH[0] ^ Delta;
151 | HnID(prps+party2, bH, bH, 2*k, 2, tmpH);
152 | tKEYphi[party2][k] = bH[0];
153 | bH[1] = bH[0] ^ bH[1];
154 | bH[1] = phi[k] ^ bH[1];
155 | io->send_data(party2, &bH[1], sizeof(block));
156 | }
157 | io->flush(party2);
158 | }));
159 | res.push_back(pool->enqueue([this, tMAC, tMACphi, tr, length, bucket_size, party2]() {
160 | block bH;
161 | for(int k = 0; k < length*bucket_size; ++k) {
162 | io->recv_data(party2, &bH, sizeof(block));
163 | block hin = sigma(tMAC[party2][3*k]) ^ makeBlock(0, 2*k+tr[3*k]);
164 | tMACphi[party2][k] = prps2[party2].H(hin);
165 | if(tr[3*k])tMACphi[party2][k] = tMACphi[party2][k] ^ bH;
166 | }
167 | }));
168 | }
169 | joinNclean(res);
170 |
171 | bool * xs = new bool[length*bucket_size];
172 | for(int i = 0; i < length*bucket_size; ++i) xs[i] = tr[3*i];
173 |
174 | #ifdef __debug
175 | check_MAC_phi(tMACphi, tKEYphi, phi, xs, length*bucket_size);
176 | #endif
177 | //tKEYphti use as H
178 | for(int k = 0; k < length*bucket_size; ++k) {
179 | tKEYphi[party][k] = zero_block;
180 | for(int i = 1; i <= nP; ++i) if (i != party) {
181 | tKEYphi[party][k] = tKEYphi[party][k] ^ tKEYphi[i][k];
182 | tKEYphi[party][k] = tKEYphi[party][k] ^ tMACphi[i][k];
183 | tKEYphi[party][k] = tKEYphi[party][k] ^ tKEY[i][3*k+2];
184 | tKEYphi[party][k] = tKEYphi[party][k] ^ tMAC[i][3*k+2];
185 | }
186 | if(tr[3*k]) tKEYphi[party][k] = tKEYphi[party][k] ^ phi[k];
187 | if(tr[3*k+2])tKEYphi[party][k] = tKEYphi[party][k] ^ Delta;
188 | }
189 |
190 | #ifdef __debug
191 | check_zero(tKEYphi[party], length*bucket_size);
192 | #endif
193 |
194 | block prg_key = sampleRandom(io, &prg, pool, party);
195 | PRG prgf(&prg_key);
196 | char (*dgst)[Hash::DIGEST_SIZE] = new char[nP+1][Hash::DIGEST_SIZE];
197 | bool * tmp = new bool[length*bucket_size];
198 | for(int i = 0; i < ssp; ++i) {
199 | prgf.random_bool(tmp, length*bucket_size);
200 | X[party][i] = inProd(tmp, tKEYphi[party], length*bucket_size);
201 | }
202 | Hash::hash_once(dgst[party], X[party], sizeof(block)*ssp);
203 |
204 | for(int i = 1; i <= nP; ++i) for(int j = 1; j<= nP; ++j) if( (i < j) and (i == party or j == party) ) {
205 | int party2 = i + j - party;
206 | res.push_back(pool->enqueue([this, dgst, party2]() {
207 | io->send_data(party2, dgst[party], Hash::DIGEST_SIZE);
208 | io->recv_data(party2, dgst[party2], Hash::DIGEST_SIZE);
209 | }));
210 | }
211 | joinNclean(res);
212 | vector> res2;
213 |
214 | for(int i = 1; i <= nP; ++i) for(int j = 1; j<= nP; ++j) if( (i < j) and (i == party or j == party) ) {
215 | int party2 = i + j - party;
216 | res2.push_back(pool->enqueue([this, X, dgst, party2]() -> bool {
217 | io->send_data(party2, X[party], sizeof(block)*ssp);
218 | io->recv_data(party2, X[party2], sizeof(block)*ssp);
219 | char tmp[Hash::DIGEST_SIZE];
220 | Hash::hash_once(tmp, X[party2], sizeof(block)*ssp);
221 | return strncmp(tmp, dgst[party2], Hash::DIGEST_SIZE)!=0;
222 | }));
223 | }
224 | if(joinNcleanCheat(res2)) error("commitment");
225 |
226 | for(int i = 2; i <= nP; ++i)
227 | xorBlocks_arr(X[1], X[1], X[i], ssp);
228 | for(int i = 0; i < ssp; ++i)X[2][i] = zero_block;
229 | if(!cmpBlock(X[1], X[2], ssp)) error("AND check");
230 |
231 | //land -> and
232 | block S = sampleRandom(io, &prg, pool, party);
233 |
234 | int * ind = new int[length*bucket_size];
235 | int *location = new int[length*bucket_size];
236 | bool * d[nP+1];
237 | for(int i = 1; i <= nP; ++i)
238 | d[i] = new bool[length*(bucket_size-1)];
239 | for(int i = 0; i < length*bucket_size; ++i)
240 | location[i] = i;
241 | PRG prg2(&S);
242 | prg2.random_data(ind, length*bucket_size*4);
243 | for(int i = length*bucket_size-1; i>=0; --i) {
244 | int index = ind[i]%(i+1);
245 | index = index>0? index:(-1*index);
246 | int tmp = location[i];
247 | location[i] = location[index];
248 | location[index] = tmp;
249 | }
250 | delete[] ind;
251 |
252 | for(int i = 0; i < length; ++i) {
253 | for(int j = 0; j < bucket_size-1; ++j)
254 | d[party][(bucket_size-1)*i+j] = tr[3*location[i*bucket_size]+1] != tr[3*location[i*bucket_size+1+j]+1];
255 | for(int j = 1; j <= nP; ++j) if (j!= party) {
256 | memcpy(MAC[j]+3*i, tMAC[j]+3*location[i*bucket_size], 3*sizeof(block));
257 | memcpy(KEY[j]+3*i, tKEY[j]+3*location[i*bucket_size], 3*sizeof(block));
258 | for(int k = 1; k < bucket_size; ++k) {
259 | MAC[j][3*i] = MAC[j][3*i] ^ tMAC[j][3*location[i*bucket_size+k]];
260 | KEY[j][3*i] = KEY[j][3*i] ^ tKEY[j][3*location[i*bucket_size+k]];
261 |
262 | MAC[j][3*i+2] = MAC[j][3*i+2] ^ tMAC[j][3*location[i*bucket_size+k]+2];
263 | KEY[j][3*i+2] = KEY[j][3*i+2] ^ tKEY[j][3*location[i*bucket_size+k]+2];
264 | }
265 | }
266 | memcpy(r+3*i, tr+3*location[i*bucket_size], 3);
267 | for(int k = 1; k < bucket_size; ++k) {
268 | r[3*i] = r[3*i] != tr[3*location[i*bucket_size+k]];
269 | r[3*i+2] = r[3*i+2] != tr[3*location[i*bucket_size+k]+2];
270 | }
271 | }
272 |
273 | for(int i = 1; i <= nP; ++i) for(int j = 1; j<= nP; ++j) if( (i < j) and (i == party or j == party) ) {
274 | int party2 = i + j - party;
275 | res.push_back(pool->enqueue([this, d, length, bucket_size, party2]() {
276 | io->send_data(party2, d[party], (bucket_size-1)*length);
277 | io->flush(party2);
278 | }));
279 | res.push_back(pool->enqueue([this, d, length, bucket_size, party2]() {
280 | io->recv_data(party2, d[party2], (bucket_size-1)*length);
281 | }));
282 | }
283 | joinNclean(res);
284 | for(int i = 2; i <= nP; ++i)
285 | for(int j = 0; j < (bucket_size-1)*length; ++j)
286 | d[1][j] = d[1][j]!=d[i][j];
287 |
288 | for(int i = 0; i < length; ++i) {
289 | for(int j = 1; j <= nP; ++j)if (j!= party) {
290 | for(int k = 1; k < bucket_size; ++k)
291 | if(d[1][(bucket_size-1)*i+k-1]) {
292 | MAC[j][3*i+2] = MAC[j][3*i+2] ^ tMAC[j][3*location[i*bucket_size+k]];
293 | KEY[j][3*i+2] = KEY[j][3*i+2] ^ tKEY[j][3*location[i*bucket_size+k]];
294 | }
295 | }
296 | for(int k = 1; k < bucket_size; ++k)
297 | if(d[1][(bucket_size-1)*i+k-1]) {
298 | r[3*i+2] = r[3*i+2] != tr[3*location[i*bucket_size+k]];
299 | }
300 | }
301 |
302 | #ifdef __debug
303 | check_MAC(io, MAC, KEY, r, Delta, length*3, party);
304 | check_correctness(io, r, length, party);
305 | #endif
306 |
307 | // ret.get();
308 | delete[] tr;
309 | delete[] phi;
310 | delete[] e;
311 | delete[] dgst;
312 | delete[] tmp;
313 | delete[] location;
314 | delete[] xs;
315 | for(int i = 1; i <= nP; ++i) {
316 | delete[] tMAC[i];
317 | delete[] tKEY[i];
318 | delete[] tMACphi[i];
319 | delete[] tKEYphi[i];
320 | delete[] X[i];
321 | delete[] s[i];
322 | delete[] d[i];
323 | }
324 | delete[] s[0];
325 | }
326 |
327 | //TODO: change to justGarble
328 | uint8_t garble(block * KEY, bool * r, bool * r2, int i, int I) {
329 | uint8_t data = 0;
330 | block tmp[4], tmp2[4], tmpH[4];
331 | tmp[0] = KEY[3*i];
332 | tmp[1] = tmp[0] ^ Delta;
333 | tmp[2] = KEY[3*i+1];
334 | tmp[3] = tmp[2] ^ Delta;
335 | HnID(prps+I, tmp, tmp, 4*i, 4, tmpH);
336 |
337 | tmp2[0] = tmp[0] ^ tmp[2];
338 | tmp2[1] = tmp[1] ^ tmp[2];
339 | tmp2[2] = tmp[0] ^ tmp[3];
340 | tmp2[3] = tmp[1] ^ tmp[3];
341 |
342 | data = LSB(tmp2[0]);
343 | data |= (LSB(tmp2[1])<<1);
344 | data |= (LSB(tmp2[2])<<2);
345 | data |= (LSB(tmp2[3])<<3);
346 | if ( ((false != r[3*i] ) && (false != r[3*i+1])) != r2[i] )
347 | data= data ^ 0x1;
348 | if ( ((true != r[3*i] ) && (false != r[3*i+1])) != r2[i] )
349 | data = data ^ 0x2;
350 | if ( ((false != r[3*i] ) && (true != r[3*i+1])) != r2[i] )
351 | data = data ^ 0x4;
352 | if ( ((true != r[3*i] ) && (true != r[3*i+1])) != r2[i] )
353 | data = data ^ 0x8;
354 | return data;
355 | }
356 | bool evaluate(uint8_t tmp, block * MAC, bool * r, int i, int I) {
357 | block hin = sigma(MAC[3*i]) ^ makeBlock(0, 4*i + r[3*i]);
358 | block hin2 = sigma(MAC[3*i+1]) ^ makeBlock(0, 4*i + 2 + r[3*i+1]);
359 | block bH = prps[I].H(hin) ^ prps[I].H(hin2);
360 | uint8_t res = LSB(bH);
361 | tmp >>= (r[3*i+1]*2+r[3*i]);
362 | return (tmp&0x1) != (res&0x1);
363 | }
364 |
365 | void check_MAC_phi(block * MAC[nP+1], block * KEY[nP+1], block * phi, bool * r, int length) {
366 | block * tmp = new block[length];
367 | block *tD = new block[length];
368 | for(int i = 1; i <= nP; ++i) for(int j = 1; j <= nP; ++j) if (i < j) {
369 | if(party == i) {
370 | io->send_data(j, phi, length*sizeof(block));
371 | io->send_data(j, KEY[j], sizeof(block)*length);
372 | io->flush(j);
373 | } else if(party == j) {
374 | io->recv_data(i, tD, length*sizeof(block));
375 | io->recv_data(i, tmp, sizeof(block)*length);
376 | for(int k = 0; k < length; ++k) {
377 | if(r[k])tmp[k] = tmp[k] ^ tD[k];
378 | }
379 | if(!cmpBlock(MAC[i], tmp, length))
380 | error("check_MAC_phi failed!");
381 | }
382 | }
383 | delete[] tmp;
384 | delete[] tD;
385 | if(party == 1)
386 | cerr<<"check_MAC_phi pass!\n"<recv_data(i, tmp2, l*sizeof(block));
397 | xorBlocks_arr(tmp1, tmp1, tmp2, l);
398 | }
399 | block z = zero_block;
400 | for(int i = 0; i < l; ++i)
401 | if(!cmpBlock(&z, &tmp1[i], 1))
402 | error("check sum zero failed!");
403 | cerr<<"check zero sum pass!\n"<send_data(1, b, l*sizeof(block));
408 | io->flush(1);
409 | }
410 | }
411 | void HnID(CRH* crh, block*out, block* in, uint64_t id, int length, block * scratch = nullptr) {
412 | bool del = false;
413 | if(scratch == nullptr) {
414 | del = true;
415 | scratch = new block[length];
416 | }
417 | for(int i = 0; i < length; ++i){
418 | out[i] = scratch[i] = sigma(in[i]) ^ makeBlock(0, id);
419 | ++id;
420 | }
421 | crh->permute_block(scratch, length);
422 | xorBlocks_arr(out, scratch, out, length);
423 | if(del) {
424 | delete[] scratch;
425 | scratch = nullptr;
426 | }
427 | }
428 | };
429 | #endif// FPRE_H__
430 |
--------------------------------------------------------------------------------
/emp-agmpc/helper.h:
--------------------------------------------------------------------------------
1 | #ifndef __HELPER
2 | #define __HELPER
3 | #include
4 | #include "cmpc_config.h"
5 | #include "netmp.h"
6 | #include
7 | using namespace emp;
8 | using std::future;
9 | using std::cout;
10 | using std::max;
11 | using std::cerr;
12 | using std::endl;
13 | using std::flush;
14 |
15 | const static block inProdTableBlock[] = {zero_block, all_one_block};
16 |
17 | block inProd(bool * b, block * blk, int length) {
18 | block res = zero_block;
19 | for(int i = 0; i < length; ++i)
20 | // if(b[i])
21 | // res = res ^ blk[i];
22 | res = res ^ (inProdTableBlock[b[i]] & blk[i]);
23 | return res;
24 | }
25 | #ifdef __GNUC__
26 | #ifndef __clang__
27 | #pragma GCC push_options
28 | #pragma GCC optimize ("unroll-loops")
29 | #endif
30 | #endif
31 |
32 | template
33 | void inProdhelp(block *Ms, bool * tmp[ssp], block * MAC, int i) {
34 | for(int j = 0; j < ssp; ++j)
35 | Ms[j] = Ms[j] ^ (inProdTableBlock[tmp[j][i]] & MAC[i]);
36 | }
37 | #ifdef __GNUC__
38 | #ifndef __clang__
39 | #pragma GCC pop_options
40 | #endif
41 | #endif
42 |
43 |
44 | template
45 | void inProds(block *Ms, bool * tmp[ssp], block * MAC, int length) {
46 | memset(Ms, 0, sizeof(block)*ssp);
47 | for(int i = 0; i < length; ++i) {
48 | inProdhelp(Ms, tmp, MAC, i);
49 | }
50 | }
51 | bool inProd(bool * b, bool* b2, int length) {
52 | bool res = false;
53 | for(int i = 0; i < length; ++i)
54 | res = (res != (b[i] and b2[i]));
55 | return res;
56 | }
57 |
58 | template
59 | void joinNclean(vector>& res) {
60 | for(auto &v: res) v.get();
61 | res.clear();
62 | }
63 |
64 | bool joinNcleanCheat(vector>& res) {
65 | bool cheat = false;
66 | for(auto &v: res) cheat = cheat or v.get();
67 | res.clear();
68 | return cheat;
69 | }
70 |
71 | void send_bool(NetIO * io, const bool * data, int length) {
72 | if(lan_network) {
73 | io->send_data(data, length);
74 | return;
75 | }
76 | for(int i = 0; i < length;) {
77 | uint64_t tmp = 0;
78 | for(int j = 0; j < 64 and i < length; ++i,++j) {
79 | if(data[i])
80 | tmp|=(0x1ULL<send_data(&tmp, 8);
83 | }
84 | }
85 |
86 | void recv_bool(NetIO * io, bool * data, int length) {
87 | if(lan_network) {
88 | io->recv_data(data, length);
89 | return;
90 | }
91 | for(int i = 0; i < length;) {
92 | uint64_t tmp = 0;
93 | io->recv_data(&tmp, 8);
94 | for(int j = 63; j >= 0 and i < length; ++i,--j) {
95 | data[i] = (tmp&0x1) == 0x1;
96 | tmp>>=1;
97 | }
98 | }
99 | }
100 |
101 | template
102 | void send_partial_block(NetIO * io, const block * data, int length) {
103 | for(int i = 0; i < length; ++i) {
104 | io->send_data(&(data[i]), B);
105 | }
106 | }
107 |
108 | template
109 | void recv_partial_block(NetIO * io, block * data, int length) {
110 | for(int i = 0; i < length; ++i) {
111 | io->recv_data(&(data[i]), B);
112 | }
113 | }
114 |
115 | inline uint8_t LSB(block & b) {
116 | return _mm_extract_epi8(b, 0) & 0x1;
117 | }
118 |
119 | template
120 | block sampleRandom(NetIOMP * io, PRG * prg, ThreadPool * pool, int party) {
121 | vector> res;
122 | vector> res2;
123 | char (*dgst)[Hash::DIGEST_SIZE] = new char[nP+1][Hash::DIGEST_SIZE];
124 | block *S = new block[nP+1];
125 | prg->random_block(&S[party], 1);
126 | Hash::hash_once(dgst[party], &S[party], sizeof(block));
127 |
128 | for(int i = 1; i <= nP; ++i) for(int j = 1; j<= nP; ++j) if( (i < j) and (i == party or j == party) ) {
129 | int party2 = i + j - party;
130 | res.push_back(pool->enqueue([dgst, io, party, party2]() {
131 | io->send_data(party2, dgst[party], Hash::DIGEST_SIZE);
132 | io->recv_data(party2, dgst[party2], Hash::DIGEST_SIZE);
133 | }));
134 | }
135 | joinNclean(res);
136 | for(int i = 1; i <= nP; ++i) for(int j = 1; j<= nP; ++j) if( (i < j) and (i == party or j == party) ) {
137 | int party2 = i + j - party;
138 | res2.push_back(pool->enqueue([io, S, dgst, party, party2]() -> bool {
139 | io->send_data(party2, &S[party], sizeof(block));
140 | io->recv_data(party2, &S[party2], sizeof(block));
141 | char tmp[Hash::DIGEST_SIZE];
142 | Hash::hash_once(tmp, &S[party2], sizeof(block));
143 | return strncmp(tmp, dgst[party2], Hash::DIGEST_SIZE)!=0;
144 | }));
145 | }
146 | bool cheat = joinNcleanCheat(res2);
147 | if(cheat) {
148 | cout <<"cheat in sampleRandom\n"<
160 | void check_MAC(NetIOMP * io, block * MAC[nP+1], block * KEY[nP+1], bool * r, block Delta, int length, int party) {
161 | block * tmp = new block[length];
162 | block tD;
163 | for(int i = 1; i <= nP; ++i) for(int j = 1; j <= nP; ++j) if (i < j) {
164 | if(party == i) {
165 | io->send_data(j, &Delta, sizeof(block));
166 | io->send_data(j, KEY[j], sizeof(block)*length);
167 | io->flush(j);
168 | } else if(party == j) {
169 | io->recv_data(i, &tD, sizeof(block));
170 | io->recv_data(i, tmp, sizeof(block)*length);
171 | for(int k = 0; k < length; ++k) {
172 | if(r[k])tmp[k] = tmp[k] ^ tD;
173 | }
174 | if(!cmpBlock(MAC[i], tmp, length))
175 | error("check_MAC failed!");
176 | }
177 | }
178 | delete[] tmp;
179 | if(party == 1)
180 | cerr<<"check_MAC pass!\n"<
184 | void check_correctness(NetIOMP* io, bool * r, int length, int party) {
185 | if (party == 1) {
186 | bool * tmp1 = new bool[length*3];
187 | bool * tmp2 = new bool[length*3];
188 | memcpy(tmp1, r, length*3);
189 | for(int i = 2; i <= nP; ++i) {
190 | io->recv_data(i, tmp2, length*3);
191 | for(int k = 0; k < length*3; ++k)
192 | tmp1[k] = (tmp1[k] != tmp2[k]);
193 | }
194 | for(int k = 0; k < length; ++k) {
195 | if((tmp1[3*k] and tmp1[3*k+1]) != tmp1[3*k+2])
196 | error("check_correctness failed!");
197 | }
198 | delete[] tmp1;
199 | delete[] tmp2;
200 | cerr<<"check_correctness pass!\n"<send_data(1, r, length*3);
203 | io->flush(1);
204 | }
205 | }
206 |
207 | inline const char* hex_char_to_bin(char c) {
208 | switch(toupper(c)) {
209 | case '0': return "0000";
210 | case '1': return "0001";
211 | case '2': return "0010";
212 | case '3': return "0011";
213 | case '4': return "0100";
214 | case '5': return "0101";
215 | case '6': return "0110";
216 | case '7': return "0111";
217 | case '8': return "1000";
218 | case '9': return "1001";
219 | case 'A': return "1010";
220 | case 'B': return "1011";
221 | case 'C': return "1100";
222 | case 'D': return "1101";
223 | case 'E': return "1110";
224 | case 'F': return "1111";
225 | default: return "0";
226 | }
227 | }
228 |
229 |
230 | inline std::string hex_to_binary(std::string hex) {
231 | std::string bin;
232 | for(unsigned i = 0; i != hex.length(); ++i)
233 | bin += hex_char_to_bin(hex[i]);
234 | return bin;
235 | }
236 |
237 | #endif// __HELPER
238 |
239 |
--------------------------------------------------------------------------------
/emp-agmpc/mpc.h:
--------------------------------------------------------------------------------
1 | #ifndef CMPC_H__
2 | #define CMPC_H__
3 | #include "fpremp.h"
4 | #include "abitmp.h"
5 | #include "netmp.h"
6 | #include "flexible_input_output.h"
7 | #include
8 | using namespace emp;
9 |
10 | template
11 | class CMPC { public:
12 | const static int SSP = 5;//5*8 in fact...
13 | const block MASK = makeBlock(0x0ULL, 0xFFFFFULL);
14 | FpreMP* fpre = nullptr;
15 | block* mac[nP+1];
16 | block* key[nP+1];
17 | bool* value;
18 |
19 | block * preprocess_mac[nP+1];
20 | block * preprocess_key[nP+1];
21 | bool* preprocess_value;
22 |
23 | block * sigma_mac[nP+1];
24 | block * sigma_key[nP+1];
25 | bool * sigma_value;
26 |
27 | block * ANDS_mac[nP+1];
28 | block * ANDS_key[nP+1];
29 | bool * ANDS_value;
30 |
31 | block * labels;
32 | BristolFormat * cf;
33 | NetIOMP * io;
34 | int num_ands = 0, num_in;
35 | int party, total_pre, ssp;
36 | ThreadPool * pool;
37 | block Delta;
38 |
39 | block (*GTM)[4][nP+1];
40 | block (*GTK)[4][nP+1];
41 | bool (*GTv)[4];
42 | block (*GT)[nP+1][4][nP+1];
43 | block * eval_labels[nP+1];
44 | PRP prp;
45 | CMPC(NetIOMP * io[2], ThreadPool * pool, int party, BristolFormat * cf, bool * _delta = nullptr, int ssp = 40) {
46 | this->party = party;
47 | this->io = io[0];
48 | this->cf = cf;
49 | this->ssp = ssp;
50 | this->pool = pool;
51 |
52 | for(int i = 0; i < cf->num_gate; ++i) {
53 | if (cf->gates[4*i+3] == AND_GATE)
54 | ++num_ands;
55 | }
56 | num_in = cf->n1+cf->n2;
57 | total_pre = num_in + num_ands + 3*ssp;
58 | fpre = new FpreMP(io, pool, party, _delta, ssp);
59 | Delta = fpre->Delta;
60 |
61 | if(party == 1) {
62 | GTM = new block[num_ands][4][nP+1];
63 | GTK = new block[num_ands][4][nP+1];
64 | GTv = new bool[num_ands][4];
65 | GT = new block[num_ands][nP+1][4][nP+1];
66 | }
67 |
68 | labels = new block[cf->num_wire];
69 | for(int i = 1; i <= nP; ++i) {
70 | key[i] = new block[cf->num_wire];
71 | mac[i] = new block[cf->num_wire];
72 | ANDS_key[i] = new block[num_ands*3];
73 | ANDS_mac[i] = new block[num_ands*3];
74 | preprocess_mac[i] = new block[total_pre];
75 | preprocess_key[i] = new block[total_pre];
76 | sigma_mac[i] = new block[num_ands];
77 | sigma_key[i] = new block[num_ands];
78 | eval_labels[i] = new block[cf->num_wire];
79 | }
80 | value = new bool[cf->num_wire];
81 | ANDS_value = new bool[num_ands*3];
82 | preprocess_value = new bool[total_pre];
83 | sigma_value = new bool[num_ands];
84 | }
85 | ~CMPC() {
86 | delete fpre;
87 | if(party == 1) {
88 | delete[] GTM;
89 | delete[] GTK;
90 | delete[] GTv;
91 | delete[] GT;
92 | }
93 | delete[] labels;
94 | for(int i = 1; i <= nP; ++i) {
95 | delete[] key[i];
96 | delete[] mac[i];
97 | delete[] ANDS_key[i];
98 | delete[] ANDS_mac[i];
99 | delete[] preprocess_mac[i];
100 | delete[] preprocess_key[i];
101 | delete[] sigma_mac[i];
102 | delete[] sigma_key[i];
103 | delete[] eval_labels[i];
104 | }
105 | delete[] value;
106 | delete[] ANDS_value;
107 | delete[] preprocess_value;
108 | delete[] sigma_value;
109 | }
110 | PRG prg;
111 |
112 | void function_independent() {
113 | if(party != 1)
114 | prg.random_block(labels, cf->num_wire);
115 |
116 | fpre->compute(ANDS_mac, ANDS_key, ANDS_value, num_ands);
117 |
118 | prg.random_bool(preprocess_value, total_pre);
119 | fpre->abit->compute(preprocess_mac, preprocess_key, preprocess_value, total_pre);
120 | auto ret = fpre->abit->check(preprocess_mac, preprocess_key, preprocess_value, total_pre);
121 | ret.get();
122 |
123 | for(int i = 1; i <= nP; ++i) {
124 | memcpy(key[i], preprocess_key[i], num_in * sizeof(block));
125 | memcpy(mac[i], preprocess_mac[i], num_in * sizeof(block));
126 | }
127 | memcpy(value, preprocess_value, num_in * sizeof(bool));
128 | #ifdef __debug
129 | check_MAC(io, ANDS_mac, ANDS_key, ANDS_value, Delta, num_ands*3, party);
130 | check_correctness(io, ANDS_value, num_ands, party);
131 | #endif
132 | // ret.get();
133 | }
134 |
135 | void function_dependent() {
136 | int ands = num_in;
137 | bool * x[nP+1];
138 | bool * y[nP+1];
139 | for(int i = 1; i <= nP; ++i) {
140 | x[i] = new bool[num_ands];
141 | y[i] = new bool[num_ands];
142 | }
143 |
144 | for(int i = 0; i < cf->num_gate; ++i) {
145 | if (cf->gates[4*i+3] == AND_GATE) {
146 | for(int j = 1; j <= nP; ++j) {
147 | key[j][cf->gates[4*i+2]] = preprocess_key[j][ands];
148 | mac[j][cf->gates[4*i+2]] = preprocess_mac[j][ands];
149 | }
150 | value[cf->gates[4*i+2]] = preprocess_value[ands];
151 | ++ands;
152 | }
153 | }
154 |
155 | for(int i = 0; i < cf->num_gate; ++i) {
156 | if (cf->gates[4*i+3] == XOR_GATE) {
157 | for(int j = 1; j <= nP; ++j) {
158 | key[j][cf->gates[4*i+2]] = key[j][cf->gates[4*i]] ^ key[j][cf->gates[4*i+1]];
159 | mac[j][cf->gates[4*i+2]] = mac[j][cf->gates[4*i]] ^ mac[j][cf->gates[4*i+1]];
160 | }
161 | value[cf->gates[4*i+2]] = value[cf->gates[4*i]] != value[cf->gates[4*i+1]];
162 | if(party != 1)
163 | labels[cf->gates[4*i+2]] = labels[cf->gates[4*i]] ^ labels[cf->gates[4*i+1]];
164 | } else if (cf->gates[4*i+3] == NOT_GATE) {
165 | for(int j = 1; j <= nP; ++j) {
166 | key[j][cf->gates[4*i+2]] = key[j][cf->gates[4*i]];
167 | mac[j][cf->gates[4*i+2]] = mac[j][cf->gates[4*i]];
168 | }
169 | value[cf->gates[4*i+2]] = value[cf->gates[4*i]];
170 | if(party != 1)
171 | labels[cf->gates[4*i+2]] = labels[cf->gates[4*i]] ^ Delta;
172 | }
173 | }
174 |
175 | #ifdef __debug
176 | check_MAC(io, mac, key, value, Delta, cf->num_wire, party);
177 | #endif
178 |
179 | ands = 0;
180 | for(int i = 0; i < cf->num_gate; ++i) {
181 | if (cf->gates[4*i+3] == AND_GATE) {
182 | x[party][ands] = value[cf->gates[4*i]] != ANDS_value[3*ands];
183 | y[party][ands] = value[cf->gates[4*i+1]] != ANDS_value[3*ands+1];
184 | ands++;
185 | }
186 | }
187 |
188 | vector> res;
189 | for(int i = 1; i <= nP; ++i) for(int j = 1; j <= nP; ++j) if( (i < j) and (i == party or j == party) ) {
190 | int party2 = i + j - party;
191 | res.push_back(pool->enqueue([this, x, y, party2]() {
192 | io->send_data(party2, x[party], num_ands);
193 | io->send_data(party2, y[party], num_ands);
194 | io->flush(party2);
195 | }));
196 | res.push_back(pool->enqueue([this, x, y, party2]() {
197 | io->recv_data(party2, x[party2], num_ands);
198 | io->recv_data(party2, y[party2], num_ands);
199 | }));
200 | }
201 | joinNclean(res);
202 | for(int i = 2; i <= nP; ++i) for(int j = 0; j < num_ands; ++j) {
203 | x[1][j] = x[1][j] != x[i][j];
204 | y[1][j] = y[1][j] != y[i][j];
205 | }
206 |
207 | ands = 0;
208 | for(int i = 0; i < cf->num_gate; ++i) {
209 | if (cf->gates[4*i+3] == AND_GATE) {
210 | for(int j = 1; j <= nP; ++j) {
211 | sigma_mac[j][ands] = ANDS_mac[j][3*ands+2];
212 | sigma_key[j][ands] = ANDS_key[j][3*ands+2];
213 | }
214 | sigma_value[ands] = ANDS_value[3*ands+2];
215 |
216 | if(x[1][ands]) {
217 | for(int j = 1; j <= nP; ++j) {
218 | sigma_mac[j][ands] = sigma_mac[j][ands] ^ ANDS_mac[j][3*ands+1];
219 | sigma_key[j][ands] = sigma_key[j][ands] ^ ANDS_key[j][3*ands+1];
220 | }
221 | sigma_value[ands] = sigma_value[ands] != ANDS_value[3*ands+1];
222 | }
223 | if(y[1][ands]) {
224 | for(int j = 1; j <= nP; ++j) {
225 | sigma_mac[j][ands] = sigma_mac[j][ands] ^ ANDS_mac[j][3*ands];
226 | sigma_key[j][ands] = sigma_key[j][ands] ^ ANDS_key[j][3*ands];
227 | }
228 | sigma_value[ands] = sigma_value[ands] != ANDS_value[3*ands];
229 | }
230 | if(x[1][ands] and y[1][ands]) {
231 | if(party != 1)
232 | sigma_key[1][ands] = sigma_key[1][ands] ^ Delta;
233 | else
234 | sigma_value[ands] = not sigma_value[ands];
235 | }
236 | ands++;
237 | }
238 | }//sigma_[] stores the and of input wires to each AND gates
239 | #ifdef __debug_
240 | check_MAC(io, sigma_mac, sigma_key, sigma_value, Delta, num_ands, party);
241 | ands = 0;
242 | for(int i = 0; i < cf->num_gate; ++i) {
243 | if (cf->gates[4*i+3] == AND_GATE) {
244 | bool tmp[] = { value[cf->gates[4*i]], value[cf->gates[4*i+1]], sigma_value[ands]};
245 | check_correctness(io, tmp, 1, party);
246 | ands++;
247 | }
248 | }
249 | #endif
250 |
251 | ands = 0;
252 | block H[4][nP+1];
253 | block K[4][nP+1], M[4][nP+1];
254 | bool r[4];
255 | if(party != 1) {
256 | for(int i = 0; i < cf->num_gate; ++i) if(cf->gates[4*i+3] == AND_GATE) {
257 | r[0] = sigma_value[ands] != value[cf->gates[4*i+2]];
258 | r[1] = r[0] != value[cf->gates[4*i]];
259 | r[2] = r[0] != value[cf->gates[4*i+1]];
260 | r[3] = r[1] != value[cf->gates[4*i+1]];
261 |
262 | for(int j = 1; j <= nP; ++j) {
263 | M[0][j] = sigma_mac[j][ands] ^ mac[j][cf->gates[4*i+2]];
264 | M[1][j] = M[0][j] ^ mac[j][cf->gates[4*i]];
265 | M[2][j] = M[0][j] ^ mac[j][cf->gates[4*i+1]];
266 | M[3][j] = M[1][j] ^ mac[j][cf->gates[4*i+1]];
267 |
268 | K[0][j] = sigma_key[j][ands] ^ key[j][cf->gates[4*i+2]];
269 | K[1][j] = K[0][j] ^ key[j][cf->gates[4*i]];
270 | K[2][j] = K[0][j] ^ key[j][cf->gates[4*i+1]];
271 | K[3][j] = K[1][j] ^ key[j][cf->gates[4*i+1]];
272 | }
273 | K[3][1] = K[3][1] ^ Delta;
274 |
275 | Hash(H, labels[cf->gates[4*i]], labels[cf->gates[4*i+1]], ands);
276 | for(int j = 0; j < 4; ++j) {
277 | for(int k = 1; k <= nP; ++k) if(k != party) {
278 | H[j][k] = H[j][k] ^ M[j][k];
279 | H[j][party] = H[j][party] ^ K[j][k];
280 | }
281 | H[j][party] = H[j][party] ^ labels[cf->gates[4*i+2]];
282 | if(r[j])
283 | H[j][party] = H[j][party] ^ Delta;
284 | }
285 | for(int j = 0; j < 4; ++j)
286 | io->send_data(1, H[j]+1, sizeof(block)*(nP));
287 | ++ands;
288 | }
289 | io->flush(1);
290 | } else {
291 | for(int i = 2; i <= nP; ++i) {
292 | int party2 = i;
293 | res.push_back(pool->enqueue([this, party2]() {
294 | for(int i = 0; i < num_ands; ++i)
295 | for(int j = 0; j < 4; ++j)
296 | io->recv_data(party2, GT[i][party2][j]+1, sizeof(block)*(nP));
297 | }));
298 | }
299 | for(int i = 0; i < cf->num_gate; ++i) if(cf->gates[4*i+3] == AND_GATE) {
300 | r[0] = sigma_value[ands] != value[cf->gates[4*i+2]];
301 | r[1] = r[0] != value[cf->gates[4*i]];
302 | r[2] = r[0] != value[cf->gates[4*i+1]];
303 | r[3] = r[1] != value[cf->gates[4*i+1]];
304 | r[3] = r[3] != true;
305 |
306 | for(int j = 1; j <= nP; ++j) {
307 | M[0][j] = sigma_mac[j][ands] ^ mac[j][cf->gates[4*i+2]];
308 | M[1][j] = M[0][j] ^ mac[j][cf->gates[4*i]];
309 | M[2][j] = M[0][j] ^ mac[j][cf->gates[4*i+1]];
310 | M[3][j] = M[1][j] ^ mac[j][cf->gates[4*i+1]];
311 |
312 | K[0][j] = sigma_key[j][ands] ^ key[j][cf->gates[4*i+2]];
313 | K[1][j] = K[0][j] ^ key[j][cf->gates[4*i]];
314 | K[2][j] = K[0][j] ^ key[j][cf->gates[4*i+1]];
315 | K[3][j] = K[1][j] ^ key[j][cf->gates[4*i+1]];
316 | }
317 | memcpy(GTK[ands], K, sizeof(block)*4*(nP+1));
318 | memcpy(GTM[ands], M, sizeof(block)*4*(nP+1));
319 | memcpy(GTv[ands], r, sizeof(bool)*4);
320 | ++ands;
321 | }
322 | joinNclean(res);
323 | }
324 | for(int i = 1; i <= nP; ++i) {
325 | delete[] x[i];
326 | delete[] y[i];
327 | }
328 | }
329 |
330 | void online (bool * input, bool * output) {
331 | bool * mask_input = new bool[cf->num_wire];
332 | for(int i = 0; i < num_in; ++i)
333 | mask_input[i] = input[i] != value[i];
334 | if(party != 1) {
335 | io->send_data(1, mask_input, num_in);
336 | io->flush(1);
337 | io->recv_data(1, mask_input, num_in);
338 | } else {
339 | bool * tmp[nP+1];
340 | for(int i = 2; i <= nP; ++i) tmp[i] = new bool[num_in];
341 | vector> res;
342 | for(int i = 2; i <= nP; ++i) {
343 | int party2 = i;
344 | res.push_back(pool->enqueue([this, tmp, party2]() {
345 | io->recv_data(party2, tmp[party2], num_in);
346 | }));
347 | }
348 | joinNclean(res);
349 | for(int i = 0; i < num_in; ++i)
350 | for(int j = 2; j <= nP; ++j)
351 | mask_input[i] = tmp[j][i] != mask_input[i];
352 | for(int i = 2; i <= nP; ++i) {
353 | int party2 = i;
354 | res.push_back(pool->enqueue([this, mask_input, party2]() {
355 | io->send_data(party2, mask_input, num_in);
356 | io->flush(party2);
357 | }));
358 | }
359 | joinNclean(res);
360 | for(int i = 2; i <= nP; ++i) delete[] tmp[i];
361 | }
362 |
363 | if(party!= 1) {
364 | for(int i = 0; i < num_in; ++i) {
365 | block tmp = labels[i];
366 | if(mask_input[i]) tmp = tmp ^ Delta;
367 | io->send_data(1, &tmp, sizeof(block));
368 | }
369 | io->flush(1);
370 | } else {
371 | vector> res;
372 | for(int i = 2; i <= nP; ++i) {
373 | int party2 = i;
374 | res.push_back(pool->enqueue([this, party2]() {
375 | io->recv_data(party2, eval_labels[party2], num_in*sizeof(block));
376 | }));
377 | }
378 | joinNclean(res);
379 |
380 | int ands = 0;
381 | for(int i = 0; i < cf->num_gate; ++i) {
382 | if (cf->gates[4*i+3] == XOR_GATE) {
383 | for(int j = 2; j<= nP; ++j)
384 | eval_labels[j][cf->gates[4*i+2]] = eval_labels[j][cf->gates[4*i]] ^ eval_labels[j][cf->gates[4*i+1]];
385 | mask_input[cf->gates[4*i+2]] = mask_input[cf->gates[4*i]] != mask_input[cf->gates[4*i+1]];
386 | } else if (cf->gates[4*i+3] == AND_GATE) {
387 | int index = 2*mask_input[cf->gates[4*i]] + mask_input[cf->gates[4*i+1]];
388 | block H[nP+1];
389 | for(int j = 2; j <= nP; ++j)
390 | eval_labels[j][cf->gates[4*i+2]] = GTM[ands][index][j];
391 | mask_input[cf->gates[4*i+2]] = GTv[ands][index];
392 | for(int j = 2; j <= nP; ++j) {
393 | Hash(H, eval_labels[j][cf->gates[4*i]], eval_labels[j][cf->gates[4*i+1]], ands, index);
394 | xorBlocks_arr(H, H, GT[ands][j][index], nP+1);
395 | for(int k = 2; k <= nP; ++k)
396 | eval_labels[k][cf->gates[4*i+2]] = H[k] ^ eval_labels[k][cf->gates[4*i+2]];
397 |
398 | block t0 = GTK[ands][index][j] ^ Delta;
399 |
400 | if(cmpBlock(&H[1], >K[ands][index][j], 1))
401 | mask_input[cf->gates[4*i+2]] = mask_input[cf->gates[4*i+2]] != false;
402 | else if(cmpBlock(&H[1], &t0, 1))
403 | mask_input[cf->gates[4*i+2]] = mask_input[cf->gates[4*i+2]] != true;
404 | else {cout <gates[4*i+2]] = not mask_input[cf->gates[4*i]];
410 | for(int j = 2; j <= nP; ++j)
411 | eval_labels[j][cf->gates[4*i+2]] = eval_labels[j][cf->gates[4*i]];
412 | }
413 | }
414 | }
415 | if(party != 1) {
416 | io->send_data(1, value+cf->num_wire - cf->n3, cf->n3);
417 | io->flush(1);
418 | } else {
419 | vector> res;
420 | bool * tmp[nP+1];
421 | for(int i = 2; i <= nP; ++i)
422 | tmp[i] = new bool[cf->n3];
423 | for(int i = 2; i <= nP; ++i) {
424 | int party2 = i;
425 | res.push_back(pool->enqueue([this, tmp, party2]() {
426 | io->recv_data(party2, tmp[party2], cf->n3);
427 | }));
428 | }
429 | joinNclean(res);
430 | for(int i = 0; i < cf->n3; ++i)
431 | for(int j = 2; j <= nP; ++j)
432 | mask_input[cf->num_wire - cf->n3 + i] = tmp[j][i] != mask_input[cf->num_wire - cf->n3 + i];
433 | for(int i = 0; i < cf->n3; ++i)
434 | mask_input[cf->num_wire - cf->n3 + i] = value[cf->num_wire - cf->n3 + i] != mask_input[cf->num_wire - cf->n3 + i];
435 |
436 | for(int i = 2; i <= nP; ++i) delete[] tmp[i];
437 | memcpy(output, mask_input + cf->num_wire - cf->n3, cf->n3);
438 | }
439 | delete[] mask_input;
440 | }
441 | void Hash(block H[4][nP+1], const block & a, const block & b, uint64_t idx) {
442 | block T[4];
443 | T[0] = sigma(a);
444 | T[1] = sigma(a ^ Delta);
445 | T[2] = sigma(sigma(b));
446 | T[3] = sigma(sigma(b ^ Delta));
447 |
448 | H[0][0] = T[0] ^ T[2];
449 | H[1][0] = T[0] ^ T[3];
450 | H[2][0] = T[1] ^ T[2];
451 | H[3][0] = T[1] ^ T[3];
452 | for(int j = 0; j < 4; ++j) for(int i = 1; i <= nP; ++i) {
453 | H[j][i] = H[j][0] ^ makeBlock(4*idx+j, i);
454 | }
455 | for(int j = 0; j < 4; ++j) {
456 | prp.permute_block(H[j]+1, nP);
457 | }
458 | }
459 |
460 | void Hash(block H[nP+1], const block &a, const block& b, uint64_t idx, uint64_t row) {
461 | H[0] = sigma(a) ^ sigma(sigma(b));
462 | for(int i = 1; i <= nP; ++i) {
463 | H[i] = H[0] ^ makeBlock(4*idx+row, i);
464 | }
465 | prp.permute_block(H+1, nP);
466 | }
467 |
468 | string tostring(bool a) {
469 | if(a) return "T";
470 | else return "F";
471 | }
472 |
473 | void online (bool * input, bool * output, int* start, int* end) {
474 | bool * mask_input = new bool[cf->num_wire];
475 | bool * input_mask[nP+1];
476 | for(int i = 0; i <= nP; ++i) input_mask[i] = new bool[end[party] - start[party]];
477 | memcpy(input_mask[party], value+start[party], end[party] - start[party]);
478 | memcpy(input_mask[0], input+start[party], end[party] - start[party]);
479 |
480 | vector> res;
481 | for(int i = 1; i <= nP; ++i) for(int j = 1; j<= nP; ++j) if( (i < j) and (i == party or j == party) ) {
482 | int party2 = i + j - party;
483 | res.push_back(pool->enqueue([this, start, end, party2]() {
484 | char dig[Hash::DIGEST_SIZE];
485 | io->send_data(party2, value+start[party2], end[party2]-start[party2]);
486 | emp::Hash::hash_once(dig, mac[party2]+start[party2], (end[party2]-start[party2])*sizeof(block));
487 | io->send_data(party2, dig, Hash::DIGEST_SIZE);
488 | io->flush(party2);
489 | return false;
490 | }));
491 | res.push_back(pool->enqueue([this, start, end, input_mask, party2]() {
492 | char dig[Hash::DIGEST_SIZE];
493 | char dig2[Hash::DIGEST_SIZE];
494 | io->recv_data(party2, input_mask[party2], end[party]-start[party]);
495 | block * tmp = new block[end[party]-start[party]];
496 | for(int i = 0; i < end[party] - start[party]; ++i) {
497 | tmp[i] = key[party2][i+start[party]];
498 | if(input_mask[party2][i])tmp[i] = tmp[i] ^ Delta;
499 | }
500 | emp::Hash::hash_once(dig2, tmp, (end[party]-start[party])*sizeof(block));
501 | io->recv_data(party2, dig, Hash::DIGEST_SIZE);
502 | delete[] tmp;
503 | return strncmp(dig, dig2, Hash::DIGEST_SIZE) != 0;
504 | }));
505 | }
506 | if(joinNcleanCheat(res)) error("cheat!");
507 | for(int i = 1; i <= nP; ++i)
508 | for(int j = 0; j < end[party] - start[party]; ++j)
509 | input_mask[0][j] = input_mask[0][j] != input_mask[i][j];
510 |
511 |
512 | if(party != 1) {
513 | io->send_data(1, input_mask[0], end[party] - start[party]);
514 | io->flush(1);
515 | io->recv_data(1, mask_input, num_in);
516 | } else {
517 | vector> res;
518 | for(int i = 2; i <= nP; ++i) {
519 | int party2 = i;
520 | res.push_back(pool->enqueue([this, mask_input, start, end , party2]() {
521 | io->recv_data(party2, mask_input+start[party2], end[party2] - start[party2]);
522 | }));
523 | }
524 | joinNclean(res);
525 | memcpy(mask_input, input_mask[0], end[1]-start[1]);
526 | for(int i = 2; i <= nP; ++i) {
527 | int party2 = i;
528 | res.push_back(pool->enqueue([this, mask_input, party2]() {
529 | io->send_data(party2, mask_input, num_in);
530 | io->flush(party2);
531 | }));
532 | }
533 | joinNclean(res);
534 | }
535 |
536 | if(party!= 1) {
537 | for(int i = 0; i < num_in; ++i) {
538 | block tmp = labels[i];
539 | if(mask_input[i]) tmp = tmp ^ Delta;
540 | io->send_data(1, &tmp, sizeof(block));
541 | }
542 | io->flush(1);
543 | } else {
544 | vector> res;
545 | for(int i = 2; i <= nP; ++i) {
546 | int party2 = i;
547 | res.push_back(pool->enqueue([this, party2]() {
548 | io->recv_data(party2, eval_labels[party2], num_in*sizeof(block));
549 | }));
550 | }
551 | joinNclean(res);
552 |
553 | int ands = 0;
554 | for(int i = 0; i < cf->num_gate; ++i) {
555 | if (cf->gates[4*i+3] == XOR_GATE) {
556 | for(int j = 2; j<= nP; ++j)
557 | eval_labels[j][cf->gates[4*i+2]] = eval_labels[j][cf->gates[4*i]] ^ eval_labels[j][cf->gates[4*i+1]];
558 | mask_input[cf->gates[4*i+2]] = mask_input[cf->gates[4*i]] != mask_input[cf->gates[4*i+1]];
559 | } else if (cf->gates[4*i+3] == AND_GATE) {
560 | int index = 2*mask_input[cf->gates[4*i]] + mask_input[cf->gates[4*i+1]];
561 | block H[nP+1];
562 | for(int j = 2; j <= nP; ++j)
563 | eval_labels[j][cf->gates[4*i+2]] = GTM[ands][index][j];
564 | mask_input[cf->gates[4*i+2]] = GTv[ands][index];
565 | for(int j = 2; j <= nP; ++j) {
566 | Hash(H, eval_labels[j][cf->gates[4*i]], eval_labels[j][cf->gates[4*i+1]], ands, index);
567 | xorBlocks_arr(H, H, GT[ands][j][index], nP+1);
568 | for(int k = 2; k <= nP; ++k)
569 | eval_labels[k][cf->gates[4*i+2]] = H[k] ^ eval_labels[k][cf->gates[4*i+2]];
570 |
571 | block t0 = GTK[ands][index][j] ^ Delta;
572 |
573 | if(cmpBlock(&H[1], >K[ands][index][j], 1))
574 | mask_input[cf->gates[4*i+2]] = mask_input[cf->gates[4*i+2]] != false;
575 | else if(cmpBlock(&H[1], &t0, 1))
576 | mask_input[cf->gates[4*i+2]] = mask_input[cf->gates[4*i+2]] != true;
577 | else {cout <gates[4*i+2]] = not mask_input[cf->gates[4*i]];
583 | for(int j = 2; j <= nP; ++j)
584 | eval_labels[j][cf->gates[4*i+2]] = eval_labels[j][cf->gates[4*i]];
585 | }
586 | }
587 | }
588 | if(party != 1) {
589 | io->send_data(1, value+cf->num_wire - cf->n3, cf->n3);
590 | io->flush(1);
591 | } else {
592 | vector> res;
593 | bool * tmp[nP+1];
594 | for(int i = 2; i <= nP; ++i)
595 | tmp[i] = new bool[cf->n3];
596 | for(int i = 2; i <= nP; ++i) {
597 | int party2 = i;
598 | res.push_back(pool->enqueue([this, tmp, party2]() {
599 | io->recv_data(party2, tmp[party2], cf->n3);
600 | }));
601 | }
602 | joinNclean(res);
603 | for(int i = 0; i < cf->n3; ++i)
604 | for(int j = 2; j <= nP; ++j)
605 | mask_input[cf->num_wire - cf->n3 + i] = tmp[j][i] != mask_input[cf->num_wire - cf->n3 + i];
606 | for(int i = 0; i < cf->n3; ++i)
607 | mask_input[cf->num_wire - cf->n3 + i] = value[cf->num_wire - cf->n3 + i] != mask_input[cf->num_wire - cf->n3 + i];
608 |
609 | for(int i = 2; i <= nP; ++i) delete[] tmp[i];
610 | memcpy(output, mask_input + cf->num_wire - cf->n3, cf->n3);
611 | }
612 | delete[] mask_input;
613 | }
614 |
615 | void online (FlexIn * input, FlexOut *output) {
616 | bool * mask_input = new bool[cf->num_wire];
617 | input->associate_cmpc(pool, value, mac, key, io, Delta);
618 | input->input(mask_input);
619 |
620 | if(party!= 1) {
621 | for(int i = 0; i < num_in; ++i) {
622 | block tmp = labels[i];
623 | if(mask_input[i]) tmp = tmp ^ Delta;
624 | io->send_data(1, &tmp, sizeof(block));
625 | }
626 | io->flush(1);
627 | } else {
628 | vector> res;
629 | for(int i = 2; i <= nP; ++i) {
630 | int party2 = i;
631 | res.push_back(pool->enqueue([this, party2]() {
632 | io->recv_data(party2, eval_labels[party2], num_in*sizeof(block));
633 | }));
634 | }
635 | joinNclean(res);
636 |
637 | int ands = 0;
638 | for(int i = 0; i < cf->num_gate; ++i) {
639 | if (cf->gates[4*i+3] == XOR_GATE) {
640 | for(int j = 2; j<= nP; ++j)
641 | eval_labels[j][cf->gates[4*i+2]] = eval_labels[j][cf->gates[4*i]] ^ eval_labels[j][cf->gates[4*i+1]];
642 | mask_input[cf->gates[4*i+2]] = mask_input[cf->gates[4*i]] != mask_input[cf->gates[4*i+1]];
643 | } else if (cf->gates[4*i+3] == AND_GATE) {
644 | int index = 2*mask_input[cf->gates[4*i]] + mask_input[cf->gates[4*i+1]];
645 | block H[nP+1];
646 | for(int j = 2; j <= nP; ++j)
647 | eval_labels[j][cf->gates[4*i+2]] = GTM[ands][index][j];
648 | mask_input[cf->gates[4*i+2]] = GTv[ands][index];
649 | for(int j = 2; j <= nP; ++j) {
650 | Hash(H, eval_labels[j][cf->gates[4*i]], eval_labels[j][cf->gates[4*i+1]], ands, index);
651 | xorBlocks_arr(H, H, GT[ands][j][index], nP+1);
652 | for(int k = 2; k <= nP; ++k)
653 | eval_labels[k][cf->gates[4*i+2]] = H[k] ^ eval_labels[k][cf->gates[4*i+2]];
654 |
655 | block t0 = GTK[ands][index][j] ^ Delta;
656 |
657 | if(cmpBlock(&H[1], >K[ands][index][j], 1))
658 | mask_input[cf->gates[4*i+2]] = mask_input[cf->gates[4*i+2]] != false;
659 | else if(cmpBlock(&H[1], &t0, 1))
660 | mask_input[cf->gates[4*i+2]] = mask_input[cf->gates[4*i+2]] != true;
661 | else {cout <gates[4*i+2]] = not mask_input[cf->gates[4*i]];
667 | for(int j = 2; j <= nP; ++j)
668 | eval_labels[j][cf->gates[4*i+2]] = eval_labels[j][cf->gates[4*i]];
669 | }
670 | }
671 | }
672 |
673 | output->associate_cmpc(pool, value, mac, key, eval_labels, labels, io, Delta);
674 | output->output(mask_input, cf->num_wire - cf->n3);
675 |
676 | delete[] mask_input;
677 | }
678 | };
679 | #endif// CMPC_H__
680 |
--------------------------------------------------------------------------------
/emp-agmpc/netmp.h:
--------------------------------------------------------------------------------
1 | #ifndef NETIOMP_H__
2 | #define NETIOMP_H__
3 | #include
4 | #include "cmpc_config.h"
5 | using namespace emp;
6 |
7 | template
8 | class NetIOMP { public:
9 | NetIO*ios[nP+1];
10 | NetIO*ios2[nP+1];
11 | int party;
12 | bool sent[nP+1];
13 | NetIOMP(int party, int port) {
14 | this->party = party;
15 | memset(sent, false, nP+1);
16 | for(int i = 1; i <= nP; ++i)for(int j = 1; j <= nP; ++j)if(i < j){
17 | if(i == party) {
18 | #ifdef LOCALHOST
19 | usleep(1000);
20 | ios[j] = new NetIO(IP[j], port+2*(i*nP+j), true);
21 | #else
22 | usleep(1000);
23 | ios[j] = new NetIO(IP[j], port+2*(i), true);
24 | #endif
25 | ios[j]->set_nodelay();
26 |
27 | #ifdef LOCALHOST
28 | usleep(1000);
29 | ios2[j] = new NetIO(nullptr, port+2*(i*nP+j)+1, true);
30 | #else
31 | usleep(1000);
32 | ios2[j] = new NetIO(nullptr, port+2*(j)+1, true);
33 | #endif
34 | ios2[j]->set_nodelay();
35 | } else if(j == party) {
36 | #ifdef LOCALHOST
37 | usleep(1000);
38 | ios[i] = new NetIO(nullptr, port+2*(i*nP+j), true);
39 | #else
40 | usleep(1000);
41 | ios[i] = new NetIO(nullptr, port+2*(i), true);
42 | #endif
43 | ios[i]->set_nodelay();
44 |
45 | #ifdef LOCALHOST
46 | usleep(1000);
47 | ios2[i] = new NetIO(IP[i], port+2*(i*nP+j)+1, true);
48 | #else
49 | usleep(1000);
50 | ios2[i] = new NetIO(IP[i], port+2*(j)+1, true);
51 | #endif
52 | ios2[i]->set_nodelay();
53 | }
54 | }
55 | }
56 | int64_t count() {
57 | int64_t res = 0;
58 | for(int i = 1; i <= nP; ++i) if(i != party){
59 | res += ios[i]->counter;
60 | res += ios2[i]->counter;
61 | }
62 | return res;
63 | }
64 |
65 | ~NetIOMP() {
66 | for(int i = 1; i <= nP; ++i)
67 | if(i != party) {
68 | delete ios[i];
69 | delete ios2[i];
70 | }
71 | }
72 | void send_data(int dst, const void * data, size_t len) {
73 | if(dst != 0 and dst!= party) {
74 | if(party < dst)
75 | ios[dst]->send_data(data, len);
76 | else
77 | ios2[dst]->send_data(data, len);
78 | sent[dst] = true;
79 | }
80 | #ifdef __MORE_FLUSH
81 | flush(dst);
82 | #endif
83 | }
84 | void recv_data(int src, void * data, size_t len) {
85 | if(src != 0 and src!= party) {
86 | if(sent[src])flush(src);
87 | if(src < party)
88 | ios[src]->recv_data(data, len);
89 | else
90 | ios2[src]->recv_data(data, len);
91 | }
92 | }
93 | NetIO*& get(size_t idx, bool b = false){
94 | if (b)
95 | return ios[idx];
96 | else return ios2[idx];
97 | }
98 | void flush(int idx = 0) {
99 | if(idx == 0) {
100 | for(int i = 1; i <= nP; ++i)
101 | if(i != party) {
102 | ios[i]->flush();
103 | ios2[i]->flush();
104 | }
105 | } else {
106 | if(party < idx)
107 | ios[idx]->flush();
108 | else
109 | ios2[idx]->flush();
110 | }
111 | }
112 | void sync() {
113 | for(int i = 1; i <= nP; ++i) for(int j = 1; j <= nP; ++j) if(i < j) {
114 | if(i == party) {
115 | ios[j]->sync();
116 | ios2[j]->sync();
117 | } else if(j == party) {
118 | ios[i]->sync();
119 | ios2[i]->sync();
120 | }
121 | }
122 | }
123 | };
124 | #endif //NETIOMP_H__
125 |
--------------------------------------------------------------------------------
/lgtm.yml:
--------------------------------------------------------------------------------
1 | extraction:
2 | cpp:
3 | configure: # Customizable step used only by C/C++ extraction.
4 | command:
5 | - export DEPS_BUILD_DIR=$LGTM_WORKSPACE/deps
6 | - mkdir -p $DEPS_BUILD_DIR
7 | - git clone https://github.com/emp-toolkit/emp-tool.git
8 | - cd emp-tool
9 | - cmake -DENABLE_FLOAT=True -DCMAKE_INSTALL_PREFIX=$DEPS_BUILD_DIR .
10 | - make -j4
11 | - make install
12 | - git clone https://github.com/emp-toolkit/emp-ot.git
13 | - cd emp-ot
14 | - cmake -DCMAKE_INSTALL_PREFIX=$DEPS_BUILD_DIR .
15 | - make -j4
16 | - make install
17 | index: # Customizable step used by all languages.
18 | build_command:
19 | - export DEPS_BUILD_DIR=$LGTM_WORKSPACE/deps
20 | - cmake -DCMAKE_INSTALL_PREFIX=$DEPS_BUILD_DIR . && make
21 |
--------------------------------------------------------------------------------
/run:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | $1 1 12345 & $1 2 12345 & $1 3 12345
3 |
--------------------------------------------------------------------------------
/test/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | #Testing macro
2 | macro (add_test_executable_with_lib _name libs)
3 | add_executable(test_${_name} "${_name}.cpp")
4 | target_link_libraries(test_${_name} ${EMP-OT_LIBRARIES})
5 | endmacro()
6 |
7 | macro (add_test_case _name)
8 | add_test_executable_with_lib(${_name} "")
9 | add_test(NAME ${_name} COMMAND "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_${_name}" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/")
10 | endmacro()
11 |
12 | macro (add_test_case_with_run _name)
13 | add_test_executable_with_lib(${_name} "")
14 | add_test(NAME ${_name} COMMAND "./run" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_${_name}" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/")
15 |
16 | endmacro()
17 |
18 | # Test cases
19 | add_test_case_with_run(test_mpc)
20 | add_test_case_with_run(test_mpc_individual)
21 | add_test_case_with_run(aes)
22 | add_test_case_with_run(sha1)
23 | add_test_case_with_run(sha256)
24 | add_test_case_with_run(triple)
25 | add_test_case_with_run(pr10_test)
26 | add_test_case_with_run(test_in_out)
27 |
--------------------------------------------------------------------------------
/test/aes.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "emp-agmpc/emp-agmpc.h"
3 | #include "test/test.h"
4 | using namespace std;
5 | using namespace emp;
6 |
7 | const static int nP = 3;
8 | int party, port;
9 | int main(int argc, char** argv) {
10 | parse_party_and_port(argv, &party, &port);
11 | if(party > nP)return 0;
12 | NetIOMP io(party, port);
13 | #ifdef LOCALHOST
14 | NetIOMP io2(party, port+2*(nP+1)*(nP+1)+1);
15 | #else
16 | NetIOMP io2(party, port+2*(nP+1));
17 | #endif
18 | NetIOMP *ios[2] = {&io, &io2};
19 | ThreadPool pool(2*(nP-1)+2);
20 |
21 | bench_once(party, ios, &pool, circuit_file_location+"AES-non-expanded.txt");
22 | return 0;
23 | }
24 |
--------------------------------------------------------------------------------
/test/ands.txt:
--------------------------------------------------------------------------------
1 | 6 14
2 | 4 4 6
3 |
4 | 2 1 0 4 8 AND
5 | 2 1 1 5 9 AND
6 | 2 1 2 6 10 AND
7 | 2 1 3 7 11 AND
8 | 1 1 8 12 INV
9 | 2 1 9 12 13 AND
10 |
--------------------------------------------------------------------------------
/test/not.txt:
--------------------------------------------------------------------------------
1 | 8 16
2 | 4 4 8
3 |
4 | 1 1 0 8 INV
5 | 1 1 1 9 INV
6 | 1 1 2 10 INV
7 | 1 1 3 11 INV
8 | 1 1 4 12 INV
9 | 1 1 5 13 INV
10 | 1 1 6 14 INV
11 | 1 1 7 15 INV
12 |
--------------------------------------------------------------------------------
/test/pr10_circuit.txt:
--------------------------------------------------------------------------------
1 | 158 222
2 | 32 32 1
3 |
4 | 2 1 32 0 64 XOR
5 | 2 1 64 0 65 AND
6 | 2 1 33 1 66 XOR
7 | 2 1 65 1 67 XOR
8 | 2 1 66 65 68 XOR
9 | 2 1 66 67 69 AND
10 | 2 1 65 69 70 XOR
11 | 2 1 34 2 71 XOR
12 | 2 1 70 2 72 XOR
13 | 2 1 71 70 73 XOR
14 | 2 1 71 72 74 AND
15 | 2 1 70 74 75 XOR
16 | 2 1 35 3 76 XOR
17 | 2 1 75 3 77 XOR
18 | 2 1 76 75 78 XOR
19 | 2 1 76 77 79 AND
20 | 2 1 75 79 80 XOR
21 | 2 1 36 4 81 XOR
22 | 2 1 80 4 82 XOR
23 | 2 1 81 80 83 XOR
24 | 2 1 81 82 84 AND
25 | 2 1 80 84 85 XOR
26 | 2 1 37 5 86 XOR
27 | 2 1 85 5 87 XOR
28 | 2 1 86 85 88 XOR
29 | 2 1 86 87 89 AND
30 | 2 1 85 89 90 XOR
31 | 2 1 38 6 91 XOR
32 | 2 1 90 6 92 XOR
33 | 2 1 91 90 93 XOR
34 | 2 1 91 92 94 AND
35 | 2 1 90 94 95 XOR
36 | 2 1 39 7 96 XOR
37 | 2 1 95 7 97 XOR
38 | 2 1 96 95 98 XOR
39 | 2 1 96 97 99 AND
40 | 2 1 95 99 100 XOR
41 | 2 1 40 8 101 XOR
42 | 2 1 100 8 102 XOR
43 | 2 1 101 100 103 XOR
44 | 2 1 101 102 104 AND
45 | 2 1 100 104 105 XOR
46 | 2 1 41 9 106 XOR
47 | 2 1 105 9 107 XOR
48 | 2 1 106 105 108 XOR
49 | 2 1 106 107 109 AND
50 | 2 1 105 109 110 XOR
51 | 2 1 42 10 111 XOR
52 | 2 1 110 10 112 XOR
53 | 2 1 111 110 113 XOR
54 | 2 1 111 112 114 AND
55 | 2 1 110 114 115 XOR
56 | 2 1 43 11 116 XOR
57 | 2 1 115 11 117 XOR
58 | 2 1 116 115 118 XOR
59 | 2 1 116 117 119 AND
60 | 2 1 115 119 120 XOR
61 | 2 1 44 12 121 XOR
62 | 2 1 120 12 122 XOR
63 | 2 1 121 120 123 XOR
64 | 2 1 121 122 124 AND
65 | 2 1 120 124 125 XOR
66 | 2 1 45 13 126 XOR
67 | 2 1 125 13 127 XOR
68 | 2 1 126 125 128 XOR
69 | 2 1 126 127 129 AND
70 | 2 1 125 129 130 XOR
71 | 2 1 46 14 131 XOR
72 | 2 1 130 14 132 XOR
73 | 2 1 131 130 133 XOR
74 | 2 1 131 132 134 AND
75 | 2 1 130 134 135 XOR
76 | 2 1 47 15 136 XOR
77 | 2 1 135 15 137 XOR
78 | 2 1 136 135 138 XOR
79 | 2 1 136 137 139 AND
80 | 2 1 135 139 140 XOR
81 | 2 1 48 16 141 XOR
82 | 2 1 140 16 142 XOR
83 | 2 1 141 140 143 XOR
84 | 2 1 141 142 144 AND
85 | 2 1 140 144 145 XOR
86 | 2 1 49 17 146 XOR
87 | 2 1 145 17 147 XOR
88 | 2 1 146 145 148 XOR
89 | 2 1 146 147 149 AND
90 | 2 1 145 149 150 XOR
91 | 2 1 50 18 151 XOR
92 | 2 1 150 18 152 XOR
93 | 2 1 151 150 153 XOR
94 | 2 1 151 152 154 AND
95 | 2 1 150 154 155 XOR
96 | 2 1 51 19 156 XOR
97 | 2 1 155 19 157 XOR
98 | 2 1 156 155 158 XOR
99 | 2 1 156 157 159 AND
100 | 2 1 155 159 160 XOR
101 | 2 1 52 20 161 XOR
102 | 2 1 160 20 162 XOR
103 | 2 1 161 160 163 XOR
104 | 2 1 161 162 164 AND
105 | 2 1 160 164 165 XOR
106 | 2 1 53 21 166 XOR
107 | 2 1 165 21 167 XOR
108 | 2 1 166 165 168 XOR
109 | 2 1 166 167 169 AND
110 | 2 1 165 169 170 XOR
111 | 2 1 54 22 171 XOR
112 | 2 1 170 22 172 XOR
113 | 2 1 171 170 173 XOR
114 | 2 1 171 172 174 AND
115 | 2 1 170 174 175 XOR
116 | 2 1 55 23 176 XOR
117 | 2 1 175 23 177 XOR
118 | 2 1 176 175 178 XOR
119 | 2 1 176 177 179 AND
120 | 2 1 175 179 180 XOR
121 | 2 1 56 24 181 XOR
122 | 2 1 180 24 182 XOR
123 | 2 1 181 180 183 XOR
124 | 2 1 181 182 184 AND
125 | 2 1 180 184 185 XOR
126 | 2 1 57 25 186 XOR
127 | 2 1 185 25 187 XOR
128 | 2 1 186 185 188 XOR
129 | 2 1 186 187 189 AND
130 | 2 1 185 189 190 XOR
131 | 2 1 58 26 191 XOR
132 | 2 1 190 26 192 XOR
133 | 2 1 191 190 193 XOR
134 | 2 1 191 192 194 AND
135 | 2 1 190 194 195 XOR
136 | 2 1 59 27 196 XOR
137 | 2 1 195 27 197 XOR
138 | 2 1 196 195 198 XOR
139 | 2 1 196 197 199 AND
140 | 2 1 195 199 200 XOR
141 | 2 1 60 28 201 XOR
142 | 2 1 200 28 202 XOR
143 | 2 1 201 200 203 XOR
144 | 2 1 201 202 204 AND
145 | 2 1 200 204 205 XOR
146 | 2 1 61 29 206 XOR
147 | 2 1 205 29 207 XOR
148 | 2 1 206 205 208 XOR
149 | 2 1 206 207 209 AND
150 | 2 1 205 209 210 XOR
151 | 2 1 62 30 211 XOR
152 | 2 1 210 30 212 XOR
153 | 2 1 211 210 213 XOR
154 | 2 1 211 212 214 AND
155 | 2 1 210 214 215 XOR
156 | 2 1 63 31 216 XOR
157 | 2 1 216 215 217 XOR
158 | 1 1 217 218 INV
159 | 1 1 218 219 INV
160 | 2 1 0 0 220 XOR
161 | 2 1 220 219 221 XOR
162 |
--------------------------------------------------------------------------------
/test/pr10_test.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "emp-agmpc/emp-agmpc.h"
3 | using namespace std;
4 | using namespace emp;
5 |
6 | //const string circuit_file_location = macro_xstr(EMP_CIRCUIT_PATH);
7 |
8 | // test from root directory of repo using
9 | // ./run ./bin/pr10_test ...
10 |
11 | const static int nP = 3;
12 | int party, port;
13 | void bench_once(NetIOMP * ios[2], ThreadPool * pool, string filename) {
14 | if(party == 1)cout <<"CIRCUIT:\t"<* mpc = new CMPC(ios, pool, party, &cf);
20 | ios[0]->flush();
21 | ios[1]->flush();
22 | double t2 = time_from(start);
23 | // ios[0]->sync();
24 | // ios[1]->sync();
25 | if(party == 1)cout <<"Setup:\t"<function_independent();
29 | ios[0]->flush();
30 | ios[1]->flush();
31 | t2 = time_from(start);
32 | if(party == 1)cout <<"FUNC_IND:\t"<function_dependent();
36 | ios[0]->flush();
37 | ios[1]->flush();
38 | t2 = time_from(start);
39 | if(party == 1)cout <<"FUNC_DEP:\t"<online(in, out);
45 | ios[0]->flush();
46 | ios[1]->flush();
47 | t2 = time_from(start);
48 | // uint64_t band2 = io.count();
49 | // if(party == 1)cout <<"bandwidth\t"< nP)return 0;
56 | NetIOMP io(party, port);
57 | #ifdef LOCALHOST
58 | NetIOMP io2(party, port+2*(nP+1)*(nP+1)+1);
59 | #else
60 | NetIOMP io2(party, port+2*(nP+1));
61 | #endif
62 | NetIOMP *ios[2] = {&io, &io2};
63 | ThreadPool pool(2*(nP-1)+2);
64 |
65 | char d[100];
66 | char* t = getcwd(d, 100);
67 | (void) t;
68 | string circuit_file_location = string(d) + "/test/";
69 | bench_once(ios, &pool, circuit_file_location+"pr10_circuit.txt");
70 | return 0;
71 | }
--------------------------------------------------------------------------------
/test/scratch.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "netmp.h"
3 | #include "abitmp.h"
4 | #include "fpremp.h"
5 | using namespace std;
6 |
7 | int main(int argc, char** argv) {
8 | int port, party;
9 | parse_party_and_port(argv, &party, &port);
10 |
11 | NetIOMP<3> io(party, port);
12 | for(int i = 1; i <= 3; ++i)for(int j = 1; j <= 3; ++j)if(i < j) {
13 | if(i == party) {
14 | int data = i*100+j;
15 | io.send_data(j, &data, 4);
16 | } else if (j == party) {
17 | int data = 0;
18 | io.recv_data(i, &data, 4);
19 | if(data!= i*100+j) {
20 | cout <<"WRONG\n"< abitmp(&io, &pool, party);
39 | double t1 = timeStamp();
40 | abitmp.compute(MAC, KEY, data, LEN);
41 | if(party == 1)
42 | cout < fpre(&io, &pool, party);
53 | // fpre.compute(MAC, KEY, data, LEN);
54 |
55 | // cout <<"DONE3 !"<
2 | #include "emp-agmpc/emp-agmpc.h"
3 | #include "test/test.h"
4 | using namespace std;
5 | using namespace emp;
6 |
7 | const static int nP = 3;
8 | int party, port;
9 | int main(int argc, char** argv) {
10 | parse_party_and_port(argv, &party, &port);
11 | if(party > nP)return 0;
12 | NetIOMP io(party, port);
13 | #ifdef LOCALHOST
14 | NetIOMP io2(party, port+2*(nP+1)*(nP+1)+1);
15 | #else
16 | NetIOMP io2(party, port+2*(nP+1));
17 | #endif
18 | NetIOMP *ios[2] = {&io, &io2};
19 | ThreadPool pool(2*(nP-1)+2);
20 |
21 | bench_once(party, ios, &pool, circuit_file_location+"sha-1.txt");
22 | return 0;
23 | }
24 |
--------------------------------------------------------------------------------
/test/sha256.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "emp-agmpc/emp-agmpc.h"
3 | #include "test/test.h"
4 | using namespace std;
5 | using namespace emp;
6 |
7 | const static int nP = 3;
8 | int party, port;
9 | int main(int argc, char** argv) {
10 | parse_party_and_port(argv, &party, &port);
11 | if(party > nP)return 0;
12 | NetIOMP io(party, port);
13 | #ifdef LOCALHOST
14 | NetIOMP io2(party, port+2*(nP+1)*(nP+1)+1);
15 | #else
16 | NetIOMP io2(party, port+2*(nP+1));
17 | #endif
18 | NetIOMP *ios[2] = {&io, &io2};
19 | ThreadPool pool(2*(nP-1)+2);
20 |
21 | bench_once(party, ios, &pool, circuit_file_location+"sha-256.txt");
22 | return 0;
23 | }
24 |
--------------------------------------------------------------------------------
/test/test.h:
--------------------------------------------------------------------------------
1 | #ifndef EMP_AGMPC_TEST_H__
2 | #define EMP_AGMPC_TEST_H__
3 | const string circuit_file_location = macro_xstr(EMP_CIRCUIT_PATH) + string("bristol_format/");
4 |
5 |
6 | template
7 | int communication(NetIOMP * ios[2]) {
8 | return ios[0]->count() + ios[1]->count();
9 | }
10 |
11 | template
12 | void bench_once(int party, NetIOMP * ios[2], ThreadPool * pool, string filename) {
13 | if(party == 1)cout <<"CIRCUIT:\t"<* mpc = new CMPC(ios, pool, party, &cf);
19 | ios[0]->flush();
20 | ios[1]->flush();
21 | double t2 = time_from(start);
22 | // ios[0]->sync();
23 | // ios[1]->sync();
24 | if(party == 1)cout <<"Setup:\t"<function_independent();
28 | ios[0]->flush();
29 | ios[1]->flush();
30 | t2 = time_from(start);
31 | if(party == 1) cout <<"FUNC_IND:\t"<function_dependent();
35 | ios[0]->flush();
36 | ios[1]->flush();
37 | t2 = time_from(start);
38 | if(party == 1) cout <<"FUNC_DEP:\t"<(ios)/1000.0/1000.0<<" MB"<online(in, out);
45 | ios[0]->flush();
46 | ios[1]->flush();
47 | t2 = time_from(start);
48 | // uint64_t band2 = io.count();
49 | // if(party == 1)cout <<"bandwidth\t"<(ios)/1000.0/1000.0<<" MB"<
2 | #include "emp-agmpc/emp-agmpc.h"
3 |
4 | #include "emp-agmpc/flexible_input_output.h"
5 |
6 | using namespace std;
7 | using namespace emp;
8 |
9 | const string filename = macro_xstr(EMP_CIRCUIT_PATH) + string("bristol_format/AES-non-expanded.txt");
10 |
11 | const static int nP = 2;
12 | int party, port;
13 |
14 | void test_non_in_out(int party, int port) {
15 | cout << "Standard in/out without using FlexIn/FlexOut" << endl;
16 | cout << "compute: K = E_{010101...}(101010...); E_{010101...}(K)" << endl;
17 | PRG prg;
18 | bool delta[128];
19 | prg.random_bool(delta, 128);
20 | NetIOMP io(party, port);
21 | NetIOMP io2(party, port+2*(nP+1)*(nP+1)+1);
22 |
23 | NetIOMP *ios[2] = {&io, &io2};
24 | ThreadPool pool(2*(nP-1)+2);
25 |
26 | BristolFormat cf(filename.c_str());
27 |
28 | CMPC* mpc = new CMPC(ios, &pool, party, &cf, delta);
29 | ios[0]->flush();
30 | ios[1]->flush();
31 |
32 | mpc->function_independent();
33 | ios[0]->flush();
34 | ios[1]->flush();
35 |
36 | mpc->function_dependent();
37 | ios[0]->flush();
38 | ios[1]->flush();
39 |
40 | bool *in = new bool[cf.n1+cf.n2];
41 | memset(in, false, cf.n1+cf.n2);
42 | bool *out = new bool[cf.n3];
43 |
44 | if(party == ALICE) {
45 | for (int i = 0; i < cf.n1; i++) {
46 | in[i] = i % 2 == 0;
47 | }
48 | } else if (party == BOB){
49 | for (int i = 0; i < cf.n2; i++) {
50 | in[cf.n1 + i] = i % 2 == 1;
51 | }
52 | }
53 |
54 | mpc->online(in, out);
55 | ios[0]->flush();
56 | ios[1]->flush();
57 |
58 | delete mpc;
59 |
60 | CMPC* mpc2 = new CMPC(ios, &pool, party, &cf, delta);
61 | ios[0]->flush();
62 | ios[1]->flush();
63 |
64 | mpc2->function_independent();
65 | ios[0]->flush();
66 | ios[1]->flush();
67 |
68 | mpc2->function_dependent();
69 | ios[0]->flush();
70 | ios[1]->flush();
71 |
72 | bool *in2 = new bool[cf.n1+cf.n2];
73 | memset(in2, false, cf.n1+cf.n2);
74 | bool *out2 = new bool[cf.n3];
75 |
76 | if(party == ALICE) {
77 | for (int i = 0; i < cf.n1; i++) {
78 | in2[i] = out[i];
79 | }
80 | } else if (party == BOB){
81 | for (int i = 0; i < cf.n2; i++) {
82 | in2[cf.n1 + i] = i % 2 == 1;
83 | }
84 | }
85 |
86 | mpc2->online(in2, out2);
87 | ios[0]->flush();
88 | ios[1]->flush();
89 |
90 | if(party == ALICE) {
91 | cout << "output:" << endl;
92 | for (int i = 0; i < cf.n3; i++) {
93 | cout << out2[i] << " ";
94 | }
95 | cout << endl;
96 | }
97 |
98 | delete mpc2;
99 | }
100 |
101 | void test_in_out(int party, int port) {
102 | cout << "FlexIn/FlexOut" << endl;
103 | cout << "compute: K = E_{010101...}(101010...); E_{010101...}(K)" << endl;
104 | PRG prg;
105 | bool delta[128];
106 | prg.random_bool(delta, 128);
107 |
108 | NetIOMP io(party, port);
109 | NetIOMP io2(party, port+2*(nP+1)*(nP+1)+1);
110 |
111 | NetIOMP *ios[2] = {&io, &io2};
112 | ThreadPool pool(2*(nP-1)+2);
113 |
114 | BristolFormat cf(filename.c_str());
115 |
116 | CMPC* mpc = new CMPC(ios, &pool, party, &cf, delta);
117 | ios[0]->flush();
118 | ios[1]->flush();
119 |
120 | mpc->function_independent();
121 | ios[0]->flush();
122 | ios[1]->flush();
123 |
124 | mpc->function_dependent();
125 | ios[0]->flush();
126 | ios[1]->flush();
127 |
128 | FlexIn in(cf.n1 + cf.n2, party);
129 | for(int i = 0; i < 64; i++) {
130 | in.assign_party(i, ALICE);
131 | }
132 | for(int i = 64; i < cf.n1; i++) {
133 | in.assign_party(i, -2);
134 | }
135 | for(int i = 0; i < 64; i++) {
136 | in.assign_party(cf.n1 + i, 0);
137 | }
138 | for(int i = 64; i < cf.n2; i++) {
139 | in.assign_party(cf.n1 + i, BOB);
140 | }
141 |
142 | FlexOut out(cf.n3, party);
143 | for(int i = 0; i < cf.n3; i++) {
144 | out.assign_party(i, -1);
145 | }
146 |
147 | if(party == ALICE) {
148 | for(int i = 0; i < 64; i++){
149 | in.assign_plaintext_bit(i, i % 2 == 0);
150 | }
151 | for(int i = 64; i < cf.n1; i++){
152 | in.assign_plaintext_bit(i, i % 2 == 0);
153 | }
154 | for(int i = 0; i < 64; i++) {
155 | in.assign_plaintext_bit(cf.n1 + i, i % 2 == 1);
156 | }
157 | } else {
158 | for(int i = 64; i < cf.n1; i++){
159 | in.assign_plaintext_bit(i, false);
160 | }
161 | for(int i = 0; i < 64; i++) {
162 | in.assign_plaintext_bit(cf.n1 + i, i % 2 == 1);
163 | }
164 | for(int i = 64; i < cf.n2; i++) {
165 | in.assign_plaintext_bit(cf.n1 + i, i % 2 == 1);
166 | }
167 | }
168 |
169 | mpc->online(&in, &out);
170 | ios[0]->flush();
171 | ios[1]->flush();
172 |
173 | CMPC* mpc2 = new CMPC(ios, &pool, party, &cf, delta);
174 | ios[0]->flush();
175 | ios[1]->flush();
176 |
177 | mpc2->function_independent();
178 | ios[0]->flush();
179 | ios[1]->flush();
180 |
181 | mpc2->function_dependent();
182 | ios[0]->flush();
183 | ios[1]->flush();
184 |
185 | FlexIn in2(cf.n1 + cf.n2, party);
186 | for(int i = 0; i < cf.n1; i++) {
187 | in2.assign_party(i, -1);
188 | }
189 | for(int i = cf.n1; i < cf.n1 + cf.n2; i++) {
190 | in2.assign_party(i, BOB);
191 | }
192 |
193 | FlexOut out2(cf.n3, party);
194 | for(int i = 0; i < 32; i++) {
195 | out2.assign_party(i, ALICE);
196 | }
197 | for(int i = 32; i < 64; i++) {
198 | out2.assign_party(i, BOB);
199 | }
200 | for(int i = 64; i < cf.n3; i++) {
201 | out2.assign_party(i, 0);
202 | }
203 |
204 | for(int i = 0; i < cf.n1; i++) {
205 | AuthBitShare mabit = out.get_authenticated_bitshare(i);
206 | in2.assign_authenticated_bitshare(i, &mabit);
207 | }
208 |
209 | if(party == BOB) {
210 | for(int i = 0; i < cf.n2; i++) {
211 | in2.assign_plaintext_bit(cf.n1 + i, i % 2 == 1);
212 | }
213 | }
214 |
215 | mpc2->online(&in2, &out2);
216 | ios[0]->flush();
217 | ios[1]->flush();
218 |
219 | cout << "output:" << endl;
220 | if(party == ALICE) {
221 | for (int i = 0; i < 32; i++) {
222 | cout << out2.get_plaintext_bit(i) << " ";
223 | }
224 | for (int i = 32; i < 64; i++) {
225 | cout << "x" << " ";
226 | }
227 | for (int i = 64; i < cf.n3; i++) {
228 | cout << out2.get_plaintext_bit(i) << " ";
229 | }
230 | } else {
231 | for (int i = 0; i < 32; i++) {
232 | cout << "x" << " ";
233 | }
234 | for (int i = 32; i < 64; i++) {
235 | cout << out2.get_plaintext_bit(i) << " ";
236 | }
237 | for (int i = 64; i < cf.n3; i++) {
238 | cout << out2.get_plaintext_bit(i) << " ";
239 | }
240 | }
241 | cout << endl;
242 |
243 | delete mpc;
244 | delete mpc2;
245 | }
246 |
247 | int main(int argc, char** argv) {
248 | parse_party_and_port(argv, &party, &port);
249 | if(party > nP)return 0;
250 |
251 | test_non_in_out(party, port);
252 |
253 | cout << "============================" << endl;
254 |
255 | test_in_out(party, port);
256 |
257 | return 0;
258 | }
--------------------------------------------------------------------------------
/test/test_mpc.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "emp-agmpc/emp-agmpc.h"
3 | using namespace std;
4 | using namespace emp;
5 |
6 | const string circuit_file_location = macro_xstr(EMP_CIRCUIT_PATH) + string("bristol_format/");
7 | static char out3[] = "92b404e556588ced6c1acd4ebf053f6809f73a93";//bafbc2c87c33322603f38e06c3e0f79c1f1b1475";
8 |
9 | int main(int argc, char** argv) {
10 | int port, party;
11 | parse_party_and_port(argv, &party, &port);
12 |
13 | const static int nP = 3;
14 | NetIOMP io(party, port);
15 | NetIOMP io2(party, port+2*(nP+1)*(nP+1)+1);
16 | NetIOMP *ios[2] = {&io, &io2};
17 | ThreadPool pool(4);
18 | string file = circuit_file_location+"/AES-non-expanded.txt";
19 | file = circuit_file_location+"/sha-1.txt";
20 | BristolFormat cf(file.c_str());
21 |
22 | CMPC* mpc = new CMPC(ios, &pool, party, &cf);
23 | cout <<"Setup:\t"<function_independent();
26 | cout <<"FUNC_IND:\t"<function_dependent();
29 | cout <<"FUNC_DEP:\t"<online(in, out);
34 | uint64_t band2 = io.count();
35 | cout <<"bandwidth\t"<
2 | #include "emp-agmpc/emp-agmpc.h"
3 | using namespace std;
4 | using namespace emp;
5 |
6 | const string circuit_file_location = macro_xstr(EMP_CIRCUIT_PATH) + string("bristol_format/");
7 | static char out3[] = "92b404e556588ced6c1acd4ebf053f6809f73a93";//bafbc2c87c33322603f38e06c3e0f79c1f1b1475";
8 |
9 | int main(int argc, char** argv) {
10 | int port, party;
11 | parse_party_and_port(argv, &party, &port);
12 |
13 | const static int nP = 3;
14 | int start[] = {0, 0, 32, 64};
15 | int end[] = {0, 32, 64, 512};
16 | int start2[] = {0, 0, 64, 64};
17 | int end2[] = {0, 64, 65, 512};
18 |
19 | NetIOMP io(party, port);
20 | NetIOMP io2(party, port+2*(nP+1)*(nP+1)+1);
21 | NetIOMP *ios[2] = {&io, &io2};
22 | ThreadPool pool(4);
23 | string file = circuit_file_location+"/AES-non-expanded.txt";
24 | file = circuit_file_location+"/sha-1.txt";
25 | BristolFormat cf(file.c_str());
26 |
27 | CMPC* mpc = new CMPC(ios, &pool, party, &cf);
28 | cout <<"Setup:\t"<function_independent();
31 | cout <<"FUNC_IND:\t"<function_dependent();
34 | cout <<"FUNC_DEP:\t"<online(in, out, start, end);
43 | // else
44 | // mpc->online(in, out, start2, end2);
45 | uint64_t band2 = io.count();
46 | cout <<"bandwidth\t"<
2 | #include "emp-agmpc/emp-agmpc.h"
3 | using namespace std;
4 | using namespace emp;
5 |
6 | const static int nP = 3;
7 | int party, port;
8 | int main(int argc, char** argv) {
9 | parse_party_and_port(argv, &party, &port);
10 | if(party > nP)return 0;
11 | NetIOMP io(party, port);
12 | #ifdef LOCALHOST
13 | NetIOMP io2(party, port+2*(nP+1)*(nP+1)+1);
14 | #else
15 | NetIOMP io2(party, port+2*(nP+1));
16 | #endif
17 | NetIOMP *ios[2] = {&io, &io2};
18 |
19 | ThreadPool pool(2*(nP-1)+2);
20 | FpreMP mp(ios, &pool, party);
21 |
22 | int num_ands = 1<<15;
23 | block * mac[nP+1];
24 | block * key[nP+1];
25 | bool * value;
26 |
27 | for(int i = 1; i <= nP; ++i) {
28 | key[i] = new block[num_ands*3];
29 | mac[i] = new block[num_ands*3];
30 | }
31 | value = new bool[num_ands*3];
32 | auto t1 = clock_start();
33 | mp.compute(mac, key, value, num_ands);
34 | cout <<"Gates: "<