From 2008a8782d91f52788d326577d3ad7d54f19b0a9 Mon Sep 17 00:00:00 2001 From: Marcel Keller Date: Fri, 2 Mar 2018 14:33:03 +0000 Subject: [PATCH] Overdrive. --- Auth/MAC_Check.cpp | 2 +- Auth/MAC_Check.h | 2 +- Auth/Subroutines.cpp | 2 +- Auth/Subroutines.h | 2 +- Auth/Summer.cpp | 2 +- Auth/Summer.h | 2 +- Auth/fake-stuff.cpp | 2 +- Auth/fake-stuff.h | 2 +- CHANGELOG.md | 6 + CONFIG | 2 +- Check-Offline.cpp | 2 +- Compiler/__init__.py | 2 +- Compiler/allocator.py | 2 +- Compiler/comparison.py | 2 +- Compiler/compilerLib.py | 2 +- Compiler/config.py | 2 +- Compiler/dijkstra.py | 2 +- Compiler/exceptions.py | 2 +- Compiler/floatingpoint.py | 2 +- Compiler/graph.py | 2 +- Compiler/gs.py | 2 +- Compiler/instructions.py | 2 +- Compiler/instructions_base.py | 2 +- Compiler/library.py | 2 +- Compiler/oram.py | 2 +- Compiler/path_oram.py | 2 +- Compiler/permutation.py | 2 +- Compiler/program.py | 2 +- Compiler/tools.py | 2 +- Compiler/types.py | 2 +- Compiler/util.py | 2 +- Exceptions/Exceptions.h | 2 +- ExternalIO/README.md | 2 +- ExternalIO/bankers-bonus-client.cpp | 2 +- ExternalIO/bankers-bonus-commsec-client.cpp | 6 +- FHE/AddableVector.h | 17 +- FHE/Ciphertext.cpp | 2 +- FHE/Ciphertext.h | 4 +- FHE/DiscreteGauss.cpp | 2 +- FHE/DiscreteGauss.h | 2 +- FHE/FFT.cpp | 2 +- FHE/FFT.h | 2 +- FHE/FFT_Data.cpp | 2 +- FHE/FFT_Data.h | 4 +- FHE/FHE_Keys.cpp | 30 +- FHE/FHE_Keys.h | 5 +- FHE/FHE_Params.cpp | 12 +- FHE/FHE_Params.h | 3 +- FHE/Generator.h | 2 +- FHE/Matrix.cpp | 33 +- FHE/Matrix.h | 12 +- FHE/NTL-Subs.cpp | 193 ++++++---- FHE/NTL-Subs.h | 18 +- FHE/NoiseBounds.cpp | 24 +- FHE/NoiseBounds.h | 3 +- FHE/P2Data.cpp | 53 ++- FHE/P2Data.h | 17 +- FHE/PPData.cpp | 2 +- FHE/PPData.h | 2 +- FHE/Plaintext.cpp | 28 +- FHE/Plaintext.h | 2 +- FHE/QGroup.cpp | 2 +- FHE/QGroup.h | 2 +- FHE/Random_Coins.cpp | 2 +- FHE/Random_Coins.h | 2 +- FHE/Ring.cpp | 2 +- FHE/Ring.h | 2 +- FHE/Ring_Element.cpp | 4 +- FHE/Ring_Element.h | 2 +- FHE/Rq_Element.cpp | 4 +- FHE/Rq_Element.h | 2 +- FHE/tools.h | 2 +- FHEOffline/CutAndChooseMachine.cpp | 49 +++ FHEOffline/CutAndChooseMachine.h | 24 ++ FHEOffline/DataSetup.cpp | 125 +++---- FHEOffline/DataSetup.h | 36 +- FHEOffline/DistDecrypt.cpp | 2 +- FHEOffline/DistDecrypt.h | 2 +- FHEOffline/DistKeyGen.cpp | 2 +- FHEOffline/DistKeyGen.h | 2 +- FHEOffline/EncCommit.cpp | 2 +- FHEOffline/EncCommit.h | 4 +- FHEOffline/FHE-Subroutines.cpp | 2 +- FHEOffline/FullSetup.cpp | 4 +- FHEOffline/FullSetup.h | 2 +- FHEOffline/Multiplier.cpp | 101 ++++++ FHEOffline/Multiplier.h | 54 +++ FHEOffline/PairwiseGenerator.cpp | 146 ++++++++ FHEOffline/PairwiseGenerator.h | 49 +++ FHEOffline/PairwiseMachine.cpp | 91 +++++ FHEOffline/PairwiseMachine.h | 36 ++ FHEOffline/PairwiseSetup.cpp | 50 +++ FHEOffline/PairwiseSetup.h | 30 ++ FHEOffline/Player-Offline.h | 2 +- FHEOffline/Producer.cpp | 10 +- FHEOffline/Producer.h | 2 +- FHEOffline/Proof.cpp | 159 +++++++++ FHEOffline/Proof.h | 124 +++++++ FHEOffline/Prover.cpp | 180 ++++++++++ FHEOffline/Prover.h | 52 +++ FHEOffline/Reshare.cpp | 2 +- FHEOffline/Reshare.h | 2 +- FHEOffline/Sacrificing.cpp | 2 +- FHEOffline/Sacrificing.h | 2 +- FHEOffline/SimpleDistDecrypt.cpp | 40 +++ FHEOffline/SimpleDistDecrypt.h | 27 ++ FHEOffline/SimpleEncCommit.cpp | 353 ++++++++++++++++++ FHEOffline/SimpleEncCommit.h | 195 ++++++++++ FHEOffline/SimpleGenerator.cpp | 97 +++++ FHEOffline/SimpleGenerator.h | 69 ++++ FHEOffline/SimpleMachine.cpp | 373 ++++++++++++++++++++ FHEOffline/SimpleMachine.h | 73 ++++ FHEOffline/Verifier.cpp | 121 +++++++ FHEOffline/Verifier.h | 34 ++ Fake-Offline.cpp | 2 +- License.txt | 2 +- Makefile | 26 +- Math/Integer.cpp | 2 +- Math/Integer.h | 2 +- Math/Setup.cpp | 5 +- Math/Setup.h | 2 +- Math/Share.cpp | 2 +- Math/Share.h | 2 +- Math/Subroutines.cpp | 2 +- Math/Subroutines.h | 2 +- Math/Zp_Data.cpp | 2 +- Math/Zp_Data.h | 22 +- Math/bigint.cpp | 4 +- Math/bigint.h | 4 +- Math/field_types.h | 2 +- Math/gf2n.cpp | 2 +- Math/gf2n.h | 2 +- Math/gf2nlong.cpp | 2 +- Math/gf2nlong.h | 4 +- Math/gfp.cpp | 2 +- Math/gfp.h | 2 +- Math/modp.cpp | 4 +- Math/modp.h | 6 +- Math/operators.h | 2 +- Networking/Player.cpp | 40 ++- Networking/Player.h | 18 +- Networking/Receiver.cpp | 2 +- Networking/Receiver.h | 2 +- Networking/STS.cpp | 2 +- Networking/STS.h | 2 +- Networking/Sender.cpp | 2 +- Networking/Sender.h | 2 +- Networking/Server.cpp | 14 +- Networking/Server.h | 3 +- Networking/ServerSocket.cpp | 4 +- Networking/ServerSocket.h | 2 +- Networking/data.h | 2 +- Networking/sockets.cpp | 4 +- Networking/sockets.h | 6 +- OT/BaseOT.cpp | 2 +- OT/BaseOT.h | 2 +- OT/BitMatrix.cpp | 28 +- OT/BitMatrix.h | 4 +- OT/BitVector.cpp | 2 +- OT/BitVector.h | 2 +- OT/NPartyTripleGenerator.cpp | 2 +- OT/NPartyTripleGenerator.h | 2 +- OT/OTExtension.cpp | 2 +- OT/OTExtension.h | 2 +- OT/OTExtensionWithMatrix.cpp | 2 +- OT/OTExtensionWithMatrix.h | 2 +- OT/OTMachine.cpp | 2 +- OT/OTMachine.h | 2 +- OT/OTMultiplier.cpp | 2 +- OT/OTMultiplier.h | 2 +- OT/OTTripleSetup.cpp | 2 +- OT/OTTripleSetup.h | 5 +- OT/OText_main.cpp | 2 +- OT/OutputCheck.h | 2 +- OT/Tools.cpp | 2 +- OT/Tools.h | 2 +- OT/TripleMachine.cpp | 2 +- OT/TripleMachine.h | 2 +- Player-Online.cpp | 21 +- Processor/Binary_File_IO.cpp | 2 +- Processor/Binary_File_IO.h | 2 +- Processor/Buffer.cpp | 2 +- Processor/Buffer.h | 2 +- Processor/Data_Files.cpp | 2 +- Processor/Data_Files.h | 2 +- Processor/ExternalClients.cpp | 2 +- Processor/ExternalClients.h | 2 +- Processor/Input.cpp | 2 +- Processor/Input.h | 2 +- Processor/InputTuple.h | 2 +- Processor/Instruction.cpp | 2 +- Processor/Instruction.h | 2 +- Processor/Machine.cpp | 2 +- Processor/Machine.h | 2 +- Processor/Memory.cpp | 2 +- Processor/Memory.h | 2 +- Processor/Online-Thread.cpp | 2 +- Processor/Online-Thread.h | 2 +- Processor/PrivateOutput.cpp | 2 +- Processor/PrivateOutput.h | 2 +- Processor/Processor.cpp | 2 +- Processor/Processor.h | 2 +- Processor/Program.cpp | 2 +- Processor/Program.h | 2 +- Programs/Source/aes.mpc | 2 +- Programs/Source/bankers_bonus.mpc | 2 +- Programs/Source/bankers_bonus_commsec.mpc | 2 +- Programs/Source/dijkstra_tutorial.mpc | 2 +- Programs/Source/fixed_point_tutorial.mpc | 2 +- Programs/Source/gale-shapley_tutorial.mpc | 2 +- Programs/Source/htmac.mpc | 2 +- Programs/Source/oram_tutorial.mpc | 2 +- Programs/Source/prf_leg.mpc | 2 +- Programs/Source/prf_mimc.mpc | 2 +- Programs/Source/tpmpc_tutorial.mpc | 2 +- Programs/Source/tutorial.mpc | 2 +- Programs/Source/vickrey.mpc | 2 +- README.md | 34 +- Scripts/gen_input_f2n.cpp | 2 +- Scripts/gen_input_fp.cpp | 2 +- Scripts/run-common.sh | 2 +- Scripts/run-online.sh | 2 +- Scripts/setup-online.sh | 2 +- Server.cpp | 2 +- Tools/Commit.cpp | 2 +- Tools/Commit.h | 2 +- Tools/Config.cpp | 2 +- Tools/Config.h | 2 +- Tools/Lock.cpp | 2 +- Tools/Lock.h | 2 +- Tools/MMO.cpp | 2 +- Tools/MMO.h | 2 +- Tools/MemoryUsage.h | 2 +- Tools/OfflineMachineBase.cpp | 2 +- Tools/OfflineMachineBase.h | 2 +- Tools/Signal.cpp | 2 +- Tools/Signal.h | 2 +- Tools/WaitQueue.h | 2 +- Tools/aes-ni.cpp | 2 +- Tools/aes.cpp | 2 +- Tools/aes.h | 6 +- Tools/avx_memcpy.h | 4 +- Tools/benchmarking.h | 2 +- Tools/ezOptionParser.h | 2 +- Tools/int.h | 2 +- Tools/mkpath.cpp | 2 +- Tools/mkpath.h | 2 +- Tools/names.cpp | 2 +- Tools/octetStream.cpp | 16 +- Tools/octetStream.h | 5 +- Tools/parse.h | 2 +- Tools/pprint.h | 2 +- Tools/random.cpp | 23 +- Tools/random.h | 4 +- Tools/sha1.cpp | 2 +- Tools/sha1.h | 2 +- Tools/time-func.cpp | 8 +- Tools/time-func.h | 14 +- check-passive.cpp | 2 +- client-setup.cpp | 2 +- cnc-offline.cpp | 14 + compile.py | 2 +- ot-offline.cpp | 2 +- pairwise-offline.cpp | 12 + simple-offline.cpp | 17 + spdz2-offline.cpp | 2 +- tutorial.md | 2 +- 267 files changed, 3440 insertions(+), 495 deletions(-) create mode 100644 FHEOffline/CutAndChooseMachine.cpp create mode 100644 FHEOffline/CutAndChooseMachine.h create mode 100644 FHEOffline/Multiplier.cpp create mode 100644 FHEOffline/Multiplier.h create mode 100644 FHEOffline/PairwiseGenerator.cpp create mode 100644 FHEOffline/PairwiseGenerator.h create mode 100644 FHEOffline/PairwiseMachine.cpp create mode 100644 FHEOffline/PairwiseMachine.h create mode 100644 FHEOffline/PairwiseSetup.cpp create mode 100644 FHEOffline/PairwiseSetup.h create mode 100644 FHEOffline/Proof.cpp create mode 100644 FHEOffline/Proof.h create mode 100644 FHEOffline/Prover.cpp create mode 100644 FHEOffline/Prover.h create mode 100644 FHEOffline/SimpleDistDecrypt.cpp create mode 100644 FHEOffline/SimpleDistDecrypt.h create mode 100644 FHEOffline/SimpleEncCommit.cpp create mode 100644 FHEOffline/SimpleEncCommit.h create mode 100644 FHEOffline/SimpleGenerator.cpp create mode 100644 FHEOffline/SimpleGenerator.h create mode 100644 FHEOffline/SimpleMachine.cpp create mode 100644 FHEOffline/SimpleMachine.h create mode 100644 FHEOffline/Verifier.cpp create mode 100644 FHEOffline/Verifier.h create mode 100644 cnc-offline.cpp create mode 100644 pairwise-offline.cpp create mode 100644 simple-offline.cpp diff --git a/Auth/MAC_Check.cpp b/Auth/MAC_Check.cpp index 225d038d8..64d15fdce 100644 --- a/Auth/MAC_Check.cpp +++ b/Auth/MAC_Check.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "Auth/MAC_Check.h" diff --git a/Auth/MAC_Check.h b/Auth/MAC_Check.h index 411350525..2bc3e5bc8 100644 --- a/Auth/MAC_Check.h +++ b/Auth/MAC_Check.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #ifndef _MAC_Check #define _MAC_Check diff --git a/Auth/Subroutines.cpp b/Auth/Subroutines.cpp index 7cfbc1e39..8c820a87b 100644 --- a/Auth/Subroutines.cpp +++ b/Auth/Subroutines.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "Auth/Subroutines.h" diff --git a/Auth/Subroutines.h b/Auth/Subroutines.h index 07b4cecdb..50daee6f3 100644 --- a/Auth/Subroutines.h +++ b/Auth/Subroutines.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #ifndef _Subroutines #define _Subroutines diff --git a/Auth/Summer.cpp b/Auth/Summer.cpp index 691f36b6e..5aa29b430 100644 --- a/Auth/Summer.cpp +++ b/Auth/Summer.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt /* * Summer.cpp diff --git a/Auth/Summer.h b/Auth/Summer.h index c3a9df138..78df33d8e 100644 --- a/Auth/Summer.h +++ b/Auth/Summer.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt /* * Summer.h diff --git a/Auth/fake-stuff.cpp b/Auth/fake-stuff.cpp index 2435bb45c..bec345a26 100644 --- a/Auth/fake-stuff.cpp +++ b/Auth/fake-stuff.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "Math/gf2n.h" diff --git a/Auth/fake-stuff.h b/Auth/fake-stuff.h index 3048df8fb..d4f4c1446 100644 --- a/Auth/fake-stuff.h +++ b/Auth/fake-stuff.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #ifndef _fake_stuff diff --git a/CHANGELOG.md b/CHANGELOG.md index f6336c16e..46fb0d85e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ The changelog explains changes pulled through from the private development repository. Bug fixes and small enchancements are committed between releases and not documented here. +## 0.0.3 (Mar 2, 2018) + +- Added offline phases based on homomorphic encryption, used in the [SPDZ-2 paper](https://eprint.iacr.org/2012/642) and the [Overdrive paper](https://eprint.iacr.org/2017/1230). +- On macOS, the minimum requirement is now Sierra. +- Compilation with LLVM/clang is now possible (tested with 3.8). + ## 0.0.2 (Sep 13, 2017) ### Support sockets based external client input and output to a SPDZ MPC program. diff --git a/CONFIG b/CONFIG index 2f644aa90..607c26a71 100644 --- a/CONFIG +++ b/CONFIG @@ -1,4 +1,4 @@ -# (C) 2017 University of Bristol. See License.txt +# (C) 2018 University of Bristol. See License.txt ROOT = . diff --git a/Check-Offline.cpp b/Check-Offline.cpp index b76156570..57b8dcde0 100644 --- a/Check-Offline.cpp +++ b/Check-Offline.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt /* * Check-Offline.cpp diff --git a/Compiler/__init__.py b/Compiler/__init__.py index 2879d6cbb..33338e9f0 100644 --- a/Compiler/__init__.py +++ b/Compiler/__init__.py @@ -1,4 +1,4 @@ -# (C) 2017 University of Bristol. See License.txt +# (C) 2018 University of Bristol. See License.txt import compilerLib, program, instructions, types, library, floatingpoint import inspect diff --git a/Compiler/allocator.py b/Compiler/allocator.py index 91095dd97..9e4471c57 100644 --- a/Compiler/allocator.py +++ b/Compiler/allocator.py @@ -1,4 +1,4 @@ -# (C) 2017 University of Bristol. See License.txt +# (C) 2018 University of Bristol. See License.txt import itertools, time from collections import defaultdict, deque diff --git a/Compiler/comparison.py b/Compiler/comparison.py index 8c6be3933..6be540274 100644 --- a/Compiler/comparison.py +++ b/Compiler/comparison.py @@ -1,4 +1,4 @@ -# (C) 2017 University of Bristol. See License.txt +# (C) 2018 University of Bristol. See License.txt """ Functions for secure comparison of GF(p) types. diff --git a/Compiler/compilerLib.py b/Compiler/compilerLib.py index 32d7573b1..ed66b4925 100644 --- a/Compiler/compilerLib.py +++ b/Compiler/compilerLib.py @@ -1,4 +1,4 @@ -# (C) 2017 University of Bristol. See License.txt +# (C) 2018 University of Bristol. See License.txt from Compiler.program import Program from Compiler.config import * diff --git a/Compiler/config.py b/Compiler/config.py index 3a237cc5c..58dff5b74 100644 --- a/Compiler/config.py +++ b/Compiler/config.py @@ -1,4 +1,4 @@ -# (C) 2017 University of Bristol. See License.txt +# (C) 2018 University of Bristol. See License.txt from collections import defaultdict diff --git a/Compiler/dijkstra.py b/Compiler/dijkstra.py index 2ca13df78..b9d6b3c17 100644 --- a/Compiler/dijkstra.py +++ b/Compiler/dijkstra.py @@ -1,4 +1,4 @@ -# (C) 2017 University of Bristol. See License.txt +# (C) 2018 University of Bristol. See License.txt from Compiler.oram import * diff --git a/Compiler/exceptions.py b/Compiler/exceptions.py index 8373b1d60..6400ce5b8 100644 --- a/Compiler/exceptions.py +++ b/Compiler/exceptions.py @@ -1,4 +1,4 @@ -# (C) 2017 University of Bristol. See License.txt +# (C) 2018 University of Bristol. See License.txt class CompilerError(Exception): """Base class for compiler exceptions.""" diff --git a/Compiler/floatingpoint.py b/Compiler/floatingpoint.py index 0e575925e..eb80e73b8 100644 --- a/Compiler/floatingpoint.py +++ b/Compiler/floatingpoint.py @@ -1,4 +1,4 @@ -# (C) 2017 University of Bristol. See License.txt +# (C) 2018 University of Bristol. See License.txt from math import log, floor, ceil from Compiler.instructions import * diff --git a/Compiler/graph.py b/Compiler/graph.py index 7f8e7f200..571e8b383 100644 --- a/Compiler/graph.py +++ b/Compiler/graph.py @@ -1,4 +1,4 @@ -# (C) 2017 University of Bristol. See License.txt +# (C) 2018 University of Bristol. See License.txt import heapq from Compiler.exceptions import * diff --git a/Compiler/gs.py b/Compiler/gs.py index 510f27c98..c6b3f52d1 100644 --- a/Compiler/gs.py +++ b/Compiler/gs.py @@ -1,4 +1,4 @@ -# (C) 2017 University of Bristol. See License.txt +# (C) 2018 University of Bristol. See License.txt import sys import math diff --git a/Compiler/instructions.py b/Compiler/instructions.py index 1453152e9..857ef345b 100644 --- a/Compiler/instructions.py +++ b/Compiler/instructions.py @@ -1,4 +1,4 @@ -# (C) 2017 University of Bristol. See License.txt +# (C) 2018 University of Bristol. See License.txt """ This module is for classes of actual assembly instructions. diff --git a/Compiler/instructions_base.py b/Compiler/instructions_base.py index 3a83501f9..d9b5e2f85 100644 --- a/Compiler/instructions_base.py +++ b/Compiler/instructions_base.py @@ -1,4 +1,4 @@ -# (C) 2017 University of Bristol. See License.txt +# (C) 2018 University of Bristol. See License.txt import itertools from random import randint diff --git a/Compiler/library.py b/Compiler/library.py index 27319e9f2..423bf6780 100644 --- a/Compiler/library.py +++ b/Compiler/library.py @@ -1,4 +1,4 @@ -# (C) 2017 University of Bristol. See License.txt +# (C) 2018 University of Bristol. See License.txt from Compiler.types import cint,sint,cfix,sfix,sfloat,MPCThread,Array,MemValue,cgf2n,sgf2n,_number,_mem,_register,regint,Matrix,_types, cfloat from Compiler.instructions import * diff --git a/Compiler/oram.py b/Compiler/oram.py index 99dccc818..c51c37d21 100644 --- a/Compiler/oram.py +++ b/Compiler/oram.py @@ -1,4 +1,4 @@ -# (C) 2017 University of Bristol. See License.txt +# (C) 2018 University of Bristol. See License.txt import random import math diff --git a/Compiler/path_oram.py b/Compiler/path_oram.py index a6cc52b7d..80a93f451 100644 --- a/Compiler/path_oram.py +++ b/Compiler/path_oram.py @@ -1,4 +1,4 @@ -# (C) 2017 University of Bristol. See License.txt +# (C) 2018 University of Bristol. See License.txt if '_Array' not in dir(): from oram import * diff --git a/Compiler/permutation.py b/Compiler/permutation.py index 394980f21..9284bff40 100644 --- a/Compiler/permutation.py +++ b/Compiler/permutation.py @@ -1,4 +1,4 @@ -# (C) 2017 University of Bristol. See License.txt +# (C) 2018 University of Bristol. See License.txt from random import randint import math diff --git a/Compiler/program.py b/Compiler/program.py index c46626df8..c65d5f39f 100644 --- a/Compiler/program.py +++ b/Compiler/program.py @@ -1,4 +1,4 @@ -# (C) 2017 University of Bristol. See License.txt +# (C) 2018 University of Bristol. See License.txt from Compiler.config import * from Compiler.exceptions import * diff --git a/Compiler/tools.py b/Compiler/tools.py index b36ede6b1..ac3c0abf9 100644 --- a/Compiler/tools.py +++ b/Compiler/tools.py @@ -1,4 +1,4 @@ -# (C) 2017 University of Bristol. See License.txt +# (C) 2018 University of Bristol. See License.txt import itertools diff --git a/Compiler/types.py b/Compiler/types.py index c54b05c11..19965ece3 100644 --- a/Compiler/types.py +++ b/Compiler/types.py @@ -1,4 +1,4 @@ -# (C) 2017 University of Bristol. See License.txt +# (C) 2018 University of Bristol. See License.txt from Compiler.program import Tape from Compiler.exceptions import * diff --git a/Compiler/util.py b/Compiler/util.py index f44c0d714..25bfb0b1f 100644 --- a/Compiler/util.py +++ b/Compiler/util.py @@ -1,4 +1,4 @@ -# (C) 2017 University of Bristol. See License.txt +# (C) 2018 University of Bristol. See License.txt import math import operator diff --git a/Exceptions/Exceptions.h b/Exceptions/Exceptions.h index cb96f3cec..7f4c97777 100644 --- a/Exceptions/Exceptions.h +++ b/Exceptions/Exceptions.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #ifndef _Exceptions #define _Exceptions diff --git a/ExternalIO/README.md b/ExternalIO/README.md index 07b5b7757..93ff4b432 100644 --- a/ExternalIO/README.md +++ b/ExternalIO/README.md @@ -1,4 +1,4 @@ -(C) 2017 University of Bristol. See License.txt. +(C) 2018 University of Bristol. See License.txt. The ExternalIO directory contains examples of managing I/O between external client processes and SPDZ parties running SPDZ engines. These instructions assume that SPDZ has been built as per the [project readme](../README.md). diff --git a/ExternalIO/bankers-bonus-client.cpp b/ExternalIO/bankers-bonus-client.cpp index 661d24f8e..7740c7f16 100644 --- a/ExternalIO/bankers-bonus-client.cpp +++ b/ExternalIO/bankers-bonus-client.cpp @@ -1,5 +1,5 @@ /* - * (C) 2017 University of Bristol. See License.txt + * (C) 2018 University of Bristol. See License.txt * * Demonstrate external client inputing and receiving outputs from a SPDZ process, * following the protocol described in https://eprint.iacr.org/2015/1006.pdf. diff --git a/ExternalIO/bankers-bonus-commsec-client.cpp b/ExternalIO/bankers-bonus-commsec-client.cpp index 9b99ad1e0..9ea927d8b 100644 --- a/ExternalIO/bankers-bonus-commsec-client.cpp +++ b/ExternalIO/bankers-bonus-commsec-client.cpp @@ -1,5 +1,5 @@ /* - * (C) 2017 University of Bristol. See License.txt + * (C) 2018 University of Bristol. See License.txt * * Demonstrate external client inputing and receiving outputs from a SPDZ process, * following the protocol described in https://eprint.iacr.org/2015/1006.pdf. @@ -274,10 +274,10 @@ void generate_symmetric_keys(vector& keys, vector& client_public_ke keys[i] = new octet[crypto_generichash_BYTES]; keyfile.read((char*)server_publickey, crypto_box_PUBLICKEYBYTES); if (keyfile.eof()) - throw end_of_file(client_filename.str(), "server public key for party " + i); + throw end_of_file(client_filename.str(), "server public key for party " + to_string(i)); keyfile.read((char*)(&sts_key->server_publickey[i][0]), crypto_sign_PUBLICKEYBYTES); if (keyfile.eof()) - throw end_of_file(client_filename.str(), "server public signing key for party " + i); + throw end_of_file(client_filename.str(), "server public signing key for party " + to_string(i)); // Derive a shared key from this server's secret key and the client's public key // shared key = h(q || client_secretkey || server_publickey) diff --git a/FHE/AddableVector.h b/FHE/AddableVector.h index c042db2fb..3d973ff03 100644 --- a/FHE/AddableVector.h +++ b/FHE/AddableVector.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt /* * AddableVector.h @@ -19,9 +19,15 @@ class AddableVector: public vector public: AddableVector() {} AddableVector(size_t n, const T& x = T()) : vector(n, x) {} - AddableVector(const FFT_Data& FTD) { (void)FTD; } template - AddableVector(const Plaintext& other) : vector(other.get_poly()) {} + AddableVector(const Plaintext& other) : + AddableVector(other.get_poly()) {} + + template + AddableVector(const vector& other) + { + this->assign(other.begin(), other.end()); + } template void allocate_slots(const U& init) @@ -138,6 +144,11 @@ class AddableVector: public vector return res; } + bool is_binary() const + { + throw not_implemented(); + } + size_t report_size(ReportType type) { size_t res = 4; diff --git a/FHE/Ciphertext.cpp b/FHE/Ciphertext.cpp index 4e786a412..c844709bc 100644 --- a/FHE/Ciphertext.cpp +++ b/FHE/Ciphertext.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "Ciphertext.h" #include "Exceptions/Exceptions.h" diff --git a/FHE/Ciphertext.h b/FHE/Ciphertext.h index ba64c15a4..9a5275c2f 100644 --- a/FHE/Ciphertext.h +++ b/FHE/Ciphertext.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #ifndef _Ciphertext #define _Ciphertext @@ -66,7 +66,7 @@ class Ciphertext friend void mul(Ciphertext& ans,const Ciphertext& c0,const Ciphertext& c1,const FHE_PK& pk); template friend void mul(Ciphertext& ans,const Plaintext& a,const Ciphertext& c); template friend void mul(Ciphertext& ans,const Ciphertext& c,const Plaintext& a) - { mul(ans,a,c); } + { ::mul(ans,a,c); } void mul(const Ciphertext& c, const Rq_Element& a); diff --git a/FHE/DiscreteGauss.cpp b/FHE/DiscreteGauss.cpp index e2accf65f..1b91843e7 100644 --- a/FHE/DiscreteGauss.cpp +++ b/FHE/DiscreteGauss.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "DiscreteGauss.h" diff --git a/FHE/DiscreteGauss.h b/FHE/DiscreteGauss.h index f0a132bce..1c11c7072 100644 --- a/FHE/DiscreteGauss.h +++ b/FHE/DiscreteGauss.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #ifndef _DiscreteGauss #define _DiscreteGauss diff --git a/FHE/FFT.cpp b/FHE/FFT.cpp index dbaf2b421..ff7421de7 100644 --- a/FHE/FFT.cpp +++ b/FHE/FFT.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "FHE/FFT.h" diff --git a/FHE/FFT.h b/FHE/FFT.h index 7d8e20deb..e94671809 100644 --- a/FHE/FFT.h +++ b/FHE/FFT.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #ifndef _FFT #define _FFT diff --git a/FHE/FFT_Data.cpp b/FHE/FFT_Data.cpp index 9f8064e4f..46c434695 100644 --- a/FHE/FFT_Data.cpp +++ b/FHE/FFT_Data.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "FHE/FFT_Data.h" #include "FHE/FFT.h" diff --git a/FHE/FFT_Data.h b/FHE/FFT_Data.h index fa83da066..1bc8ae7ae 100644 --- a/FHE/FFT_Data.h +++ b/FHE/FFT_Data.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #ifndef _FFT_Data #define _FFT_Data @@ -41,6 +41,8 @@ class FFT_Data void init(const Ring& Rg,const Zp_Data& PrD); + void init_field() const { gfp::init_field(prData.pr); } + void pack(octetStream& o) const; void unpack(octetStream& o); diff --git a/FHE/FHE_Keys.cpp b/FHE/FHE_Keys.cpp index 6a0c82d77..928b582c3 100644 --- a/FHE/FHE_Keys.cpp +++ b/FHE/FHE_Keys.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "FHE_Keys.h" @@ -54,7 +54,8 @@ void FHE_PK::KeyGen(Rq_Element& sk, PRNG& G, int noise_boost) mul(e0,e0,PK.pr); add(PK.b0,PK.b0,e0); - PK.check_noise(PK.b0 - PK.a0 * sk, true); + // strict check not working for GF(2^n) + PK.check_noise(PK.b0 - PK.a0 * sk, false); if (params->n_mults() > 0) { @@ -131,11 +132,8 @@ void FHE_PK::encrypt(Ciphertext& c, if (&rc.get_params()!=params) { throw params_mismatch(); } if (pr==2) { throw pr_mismatch(); } - Rq_Element mm((*params).FFTD(),polynomial,polynomial); mess.to_poly(); - mm.from_vec(mess.get_poly()); - - quasi_encrypt(c,mm,rc); + encrypt(c, mess.get_poly(), rc); } @@ -148,12 +146,19 @@ void FHE_PK::encrypt(Ciphertext& c, if (&rc.get_params()!=params) { throw params_mismatch(); } if (pr!=2) { throw pr_mismatch(); } - Rq_Element mm((*params).FFTD(),polynomial,polynomial); mess.to_poly(); - mm.from_vec(mess.get_poly()); + encrypt(c, mess.get_poly(), rc); +} - quasi_encrypt(c,mm,rc); +template +void FHE_PK::encrypt(Ciphertext& c, const vector& mess, + const Random_Coins& rc) const +{ + Rq_Element mm((*params).FFTD(),polynomial,polynomial); + mm.from_vec(mess); + quasi_encrypt(c, mm, rc); } + void FHE_PK::quasi_encrypt(Ciphertext& c, const Rq_Element& mess,const Random_Coins& rc) const { @@ -362,6 +367,11 @@ template Ciphertext FHE_PK::encrypt(const Plaintext_& mess, template Ciphertext FHE_PK::encrypt(const Plaintext_& mess) const; template Ciphertext FHE_PK::encrypt(const Plaintext_& mess) const; +template void FHE_PK::encrypt(Ciphertext& c, const vector& mess, + const Random_Coins& rc) const; +template void FHE_PK::encrypt(Ciphertext& c, const vector& mess, + const Random_Coins& rc) const; + template Plaintext_ FHE_SK::decrypt(const Ciphertext& c, const FFT_Data& FieldD); template Plaintext_ FHE_SK::decrypt(const Ciphertext& c, @@ -369,3 +379,5 @@ template Plaintext_ FHE_SK::decrypt(const Ciphertext& c, template void FHE_SK::decrypt_any(Plaintext_& res, const Ciphertext& c); +template void FHE_SK::decrypt_any(Plaintext_& res, + const Ciphertext& c); diff --git a/FHE/FHE_Keys.h b/FHE/FHE_Keys.h index 5ef01e1da..7983a1c31 100644 --- a/FHE/FHE_Keys.h +++ b/FHE/FHE_Keys.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #ifndef _FHE_Keys #define _FHE_Keys @@ -127,6 +127,9 @@ class FHE_PK void encrypt(Ciphertext& c, const Plaintext& mess, const Random_Coins& rc) const; void encrypt(Ciphertext& c, const Plaintext& mess, const Random_Coins& rc) const; + template + void encrypt(Ciphertext& c, const vector& mess, const Random_Coins& rc) const; + void quasi_encrypt(Ciphertext& c, const Rq_Element& mess, const Random_Coins& rc) const; template diff --git a/FHE/FHE_Params.cpp b/FHE/FHE_Params.cpp index ba290326d..0b3617110 100644 --- a/FHE/FHE_Params.cpp +++ b/FHE/FHE_Params.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "FHE_Params.h" @@ -10,8 +10,8 @@ void FHE_Params::set(const Ring& R, const vector& primes,double r,int hwt) { - if (primes.size() < FFTData.size()) - throw runtime_error("not enough primes"); + if (primes.size() != FFTData.size()) + throw runtime_error("wrong number of primes"); for (size_t i = 0; i < FFTData.size(); i++) FFTData[i].init(R,primes[i]); @@ -26,6 +26,8 @@ void FHE_Params::set_sec(int sec) sec_p=sec; Bval=1; Bval=Bval< > matrix; -typedef vector< vector > imatrix; typedef vector< vector > modp_matrix; +class imatrix : public vector< vector > +{ +public: + bool operator!=(const imatrix& other) const; + + void pack(octetStream& o) const; + void unpack(octetStream& o); +}; + /* Uses Algorithm 2.7 from Pohst-Zassenhaus to compute H and U st H = HNF(A) = A*U */ diff --git a/FHE/NTL-Subs.cpp b/FHE/NTL-Subs.cpp index 547d9aab8..f3e52e748 100644 --- a/FHE/NTL-Subs.cpp +++ b/FHE/NTL-Subs.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "FHE/NTL-Subs.h" @@ -13,6 +13,8 @@ #include "Tools/mkpath.h" +#include "FHEOffline/Proof.h" + #include using namespace std; @@ -41,11 +43,10 @@ template <> void generate_setup(int n_parties, int plaintext_length, int sec, FHE_Params& params, P2Data& P2D, int slack, bool round_up) { - if (sec != 40 or slack != 0 or round_up) - throw not_implemented(); Ring R; bigint pr0,pr1; - SPDZ_Data_Setup_Char_2(R, P2D, pr0, pr1, n_parties, plaintext_length); + SPDZ_Data_Setup_Char_2(R, P2D, pr0, pr1, n_parties, plaintext_length, sec, + slack, round_up); params.set(R, {pr0, pr1}); } @@ -69,17 +70,19 @@ bool same_word_length(int l1, int l2) return l1 / 64 == l2 / 64; } +template <> int generate_semi_setup(int plaintext_length, int sec, - bigint& p, FHE_Params& params, FFT_Data& FTD, bool round_up) + FHE_Params& params, FFT_Data& FTD, bool round_up) { int m = 1024; int lgp = plaintext_length; + bigint p; generate_prime(p, lgp, m); int lgp0, lgp1; while (true) { SemiHomomorphicNoiseBounds nb(p, phi_N(m), 1, sec, - 0, true); + numBits(NonInteractiveProof::slack(sec, phi_N(m))), true); bigint p1 = 2 * p * m, p0 = p; while (nb.min_p0(params.n_mults() > 0, p1) > p0) { @@ -97,6 +100,33 @@ int generate_semi_setup(int plaintext_length, int sec, break; } } + + int extra_slack = common_semi_setup(params, m, p, lgp0, lgp1, round_up); + + FTD.init(params.get_ring(), p); + gfp::init_field(p); + return extra_slack; +} + +template <> +int generate_semi_setup(int plaintext_length, int sec, + FHE_Params& params, P2Data& P2D, bool round_up) +{ + if (params.n_mults() > 0) + throw runtime_error("only implemented for 0-level BGV"); + gf2n::init_field(plaintext_length); + int m; + char_2_dimension(m, plaintext_length); + SemiHomomorphicNoiseBounds nb(2, phi_N(m), 1, sec, + numBits(NonInteractiveProof::slack(sec, phi_N(m))), true); + int lgp0 = numBits(nb.min_p0(false, 0)); + int extra_slack = common_semi_setup(params, m, 2, lgp0, -1, round_up); + load_or_generate(P2D, params.get_ring()); + return extra_slack; +} + +int common_semi_setup(FHE_Params& params, int m, bigint p, int lgp0, int lgp1, bool round_up) +{ cout << "Need ciphertext modulus of length " << lgp0; if (params.n_mults() > 0) cout << "+" << lgp1; @@ -123,12 +153,49 @@ int generate_semi_setup(int plaintext_length, int sec, ::init(R, m); bigint p0, p1 = 1; if (params.n_mults() > 0) + { generate_moduli(p0, p1, m, p, lgp0, lgp1); + params.set(R, {p0, p1}); + } else + { generate_modulus(p0, m, p, lgp0); - params.set(R, {p0, p1}); - FTD.init(R, p); - gfp::init_field(p); + params.set(R, {p0}); + } + return extra_slack; +} + +int finalize_lengths(int& lg2p0, int& lg2p1, int n, int m, int* lg2pi, bool round_up) +{ + if (n >= 2 and n <= 10) + cout << "Difference to suggestion for p0: " << lg2p0 - lg2pi[n - 2] + << ", for p1: " << lg2p1 - lg2pi[9 + n - 2] << endl; + cout << "p0 needs " << int(ceil(1. * lg2p0 / 64)) << " words" << endl; + cout << "p1 needs " << int(ceil(1. * lg2p1 / 64)) << " words" << endl; + + int extra_slack = 0; + if (round_up) + { + int i = 0; + for (i = 0; i < 10; i++) + { + if (phi_N(m) < NoiseBounds::min_phi_m(lg2p0 + lg2p1 + 2 * i)) + break; + if (not same_word_length(lg2p0 + i, lg2p0)) + break; + if (not same_word_length(lg2p1 + i, lg2p1)) + break; + } + i--; + extra_slack = 2 * i; + lg2p0 += i; + lg2p1 += i; + cout << "Rounding up to " << lg2p0 << "+" << lg2p1 + << ", giving extra slack of " << extra_slack << " bits" << endl; + } + + cout << "Total length: " << lg2p0 + lg2p1 << endl; + return extra_slack; } @@ -170,19 +237,9 @@ int SPDZ_Data_Setup_Char_p_Sub(Ring& R, bigint& pr0, bigint& pr1, int n, while (sec != -1) { - NoiseBounds nb(p, phi_N(m), n, sec, slack); - bigint min_p1 = nb.opt_p1(); - bigint min_p0 = nb.min_p0(min_p1); - while (nb.min_p0(min_p0, min_p1) > min_p0) - { - min_p0 *= 2; - min_p1 *= 2; - cout << "increasing lengths: " << numBits(min_p0) << "/" << numBits(min_p1) << endl; - } - lg2p1 = numBits(min_p1); - lg2p0 = numBits(min_p0); + double phi_m_bound = + NoiseBounds(p, phi_N(m), n, sec, slack).optimize(lg2p0, lg2p1); cout << "Trying primes of length " << lg2p0 << " and " << lg2p1 << endl; - double phi_m_bound = nb.min_phi_m(lg2p0 + lg2p1); if (phi_N(m) < phi_m_bound) { int old_m = m; @@ -194,36 +251,9 @@ int SPDZ_Data_Setup_Char_p_Sub(Ring& R, bigint& pr0, bigint& pr1, int n, break; } - if (n >= 2 and n <= 10) - cout << "Difference to suggestion for p0: " << lg2p0 - lg2pi[idx][0][n - 2] - << ", for p1: " << lg2p1 - lg2pi[idx][1][n - 2] << endl; - cout << "p0 needs " << int(ceil(1. * lg2p0 / 64)) << " words" << endl; - cout << "p1 needs " << int(ceil(1. * lg2p1 / 64)) << " words" << endl; - - int extra_slack = 0; - if (round_up) - { - int i = 0; - for (i = 0; i < 10; i++) - { - if (phi_N(m) < NoiseBounds::min_phi_m(lg2p0 + lg2p1 + 2 * i)) - break; - if (not same_word_length(lg2p0 + i, lg2p0)) - break; - if (not same_word_length(lg2p1 + i, lg2p1)) - break; - } - i--; - extra_slack = 2 * i; - lg2p0 += i; - lg2p1 += i; - cout << "Rounding up to " << lg2p0 << "+" << lg2p1 - << ", giving extra slack of " << extra_slack << " bits" << endl; - } - - cout << "Total length: " << lg2p0 + lg2p1 << endl; - init(R,m); + int extra_slack = finalize_lengths(lg2p0, lg2p1, n, m, lg2pi[idx][0], + round_up); generate_moduli(pr0, pr1, m, p, lg2p0, lg2p1); return extra_slack; } @@ -521,18 +551,8 @@ void init(P2Data& P2D,const Ring& Rg) /* * Create the FHE parameters */ -void SPDZ_Data_Setup_Char_2(Ring& R,P2Data& P2D,bigint& pr0,bigint& pr1,int n,int lg2) +void char_2_dimension(int& m, int& lg2) { - int lg2pi[2][9] - = { {70,70,70,70,70,70,70,70,70}, - {70,75,75,75,75,80,80,80,80} - }; - - cout << "Setting up parameters\n"; - if (n<2 || n>10) { throw invalid_params(); } - - int m,lg2p0,lg2p1,ex; - switch (lg2) { case -1: m=17; @@ -546,13 +566,40 @@ void SPDZ_Data_Setup_Char_2(Ring& R,P2Data& P2D,bigint& pr0,bigint& pr1,int n,in lg2=40; break; default: - throw invalid_params(); + throw runtime_error("field size not supported"); break; } +} + +void SPDZ_Data_Setup_Char_2(Ring& R, P2Data& P2D, bigint& pr0, bigint& pr1, + int n, int lg2, int sec, int slack, bool round_up) +{ + int lg2pi[2][9] + = { {70,70,70,70,70,70,70,70,70}, + {70,75,75,75,75,80,80,80,80} + }; + + cout << "Setting up parameters\n"; + if ((n<2 || n>10) and sec == -1) { throw invalid_params(); } + + int m,lg2p0,lg2p1,ex; + + char_2_dimension(m, lg2); + + if (sec == -1) + { + lg2p0=lg2pi[0][n-2]; + lg2p1=lg2pi[1][n-2]; + } + else + { + NoiseBounds(2, phi_N(m), n, sec, slack).optimize(lg2p0, lg2p1); + finalize_lengths(lg2p0, lg2p1, n, m, lg2pi[0], round_up); + } + + if (NoiseBounds::min_phi_m(lg2p0 + lg2p1) > phi_N(m)) + throw runtime_error("number of slots too small"); - lg2p0=lg2pi[0][n-2]; - lg2p1=lg2pi[1][n-2]; - cout << "m = " << m << endl; init(R,m); @@ -580,7 +627,21 @@ void SPDZ_Data_Setup_Char_2(Ring& R,P2Data& P2D,bigint& pr0,bigint& pr1,int n,in cout << "\t\tpr1 mod 2^lg2m = " << pr1%(1< int generate_semi_setup(int plaintext_length, int sec, - bigint& p, FHE_Params& params, FFT_Data& FTD, bool round_up); + FHE_Params& params, FD& FieldD, bool round_up); + +// field-independent semi-homomorphic setup +int common_semi_setup(FHE_Params& params, int m, bigint p, int lgp0, int lgp1, + bool round_up); // Everything else needs NTL void init(Ring& Rg,int m); @@ -47,7 +52,14 @@ void generate_moduli(bigint& pr0, bigint& pr1, const int m, void generate_modulus(bigint& pr, const int m, const bigint p, const int lg2pr, const string& i = "0", const bigint& pr0 = 0); -void SPDZ_Data_Setup_Char_2(Ring& R,P2Data& P2D,bigint& pr0,bigint& pr1,int n,int lg2); +// pre-generated dimensions for characteristic 2 +void char_2_dimension(int& m, int& lg2); + +void SPDZ_Data_Setup_Char_2(Ring& R, P2Data& P2D, bigint& pr0, bigint& pr1, + int n, int lg2, int sec = -1, int slacke = 0, bool round_up = false); + +// try to avoid expensive generation by loading from disk if possible +void load_or_generate(P2Data& P2D, const Ring& Rg); int phi_N(int N); diff --git a/FHE/NoiseBounds.cpp b/FHE/NoiseBounds.cpp index 4a9dce665..60ac75bab 100644 --- a/FHE/NoiseBounds.cpp +++ b/FHE/NoiseBounds.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt /* * NoiseBound.cpp @@ -6,13 +6,14 @@ */ #include +#include "FHEOffline/Proof.h" #include SemiHomomorphicNoiseBounds::SemiHomomorphicNoiseBounds(const bigint& p, int phi_m, int n, int sec, int slack_param, bool extra_h, double sigma, int h) : p(p), phi_m(phi_m), n(n), sec(sec), - slack(slack_param), sigma(sigma), h(h) + slack(numBits(Proof::slack(slack_param, sec, phi_m))), sigma(sigma), h(h) { h += extra_h * sec; B_clean = (phi_m * p / 2 @@ -108,8 +109,25 @@ bigint NoiseBounds::opt_p1() b = -2 * a * min_p1(); c = -n * B_clean * (2 * B_scale + 1) * min_p1() + n * n * B_scale * B_scale; // solve - bigint res = (-b + sqrt(b * b - 4 * a * c)) / (2 * a); + mpf_class s = (-b + sqrt(b * b - 4 * a * c)) / (2 * a); + bigint res = ceil(s); cout << "Optimal p1 vs minimal: " << numBits(res) << "/" << numBits(min_p1()) << endl; return res; } + +double NoiseBounds::optimize(int& lg2p0, int& lg2p1) +{ + bigint min_p1 = opt_p1(); + bigint min_p0 = this->min_p0(min_p1); + while (this->min_p0(min_p0, min_p1) > min_p0) + { + min_p0 *= 2; + min_p1 *= 2; + cout << "increasing lengths: " << numBits(min_p0) << "/" + << numBits(min_p1) << endl; + } + lg2p1 = numBits(min_p1); + lg2p0 = numBits(min_p0); + return min_phi_m(lg2p0 + lg2p1); +} diff --git a/FHE/NoiseBounds.h b/FHE/NoiseBounds.h index 65c7bd0a7..98c430e57 100644 --- a/FHE/NoiseBounds.h +++ b/FHE/NoiseBounds.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt /* * NoiseBound.h @@ -53,6 +53,7 @@ class NoiseBounds : public SemiHomomorphicNoiseBounds bigint min_p1(); bigint opt_p1(); bigint opt_p0() { return min_p0(opt_p1()); } + double optimize(int& lg2p0, int& lg2p1); }; #endif /* FHE_NOISEBOUNDS_H_ */ diff --git a/FHE/P2Data.cpp b/FHE/P2Data.cpp index bb9b319af..ec500d902 100644 --- a/FHE/P2Data.cpp +++ b/FHE/P2Data.cpp @@ -1,7 +1,9 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "FHE/P2Data.h" +#include "Math/Setup.h" +#include void P2Data::forward(vector& ans,const vector& a) const @@ -62,6 +64,27 @@ void P2Data::check_dimensions() const } +bool P2Data::operator!=(const P2Data& other) const +{ + return slots != other.slots or A != other.A or Ai != other.Ai; +} + +void P2Data::pack(octetStream& o) const +{ + check_dimensions(); + o.store(slots); + A.pack(o); + Ai.pack(o); +} + +void P2Data::unpack(octetStream& o) +{ + o.get(slots); + A.unpack(o); + Ai.unpack(o); + check_dimensions(); +} + ostream& operator<<(ostream& s,const P2Data& P2D) { P2D.check_dimensions(); @@ -79,3 +102,31 @@ istream& operator>>(istream& s,P2Data& P2D) P2D.check_dimensions(); return s; } + +string get_filename(const Ring& Rg) +{ + return (string) PREP_DIR + "P2D-" + to_string(gf2n::degree()) + "x" + + to_string(Rg.phi_m() / gf2n::degree()); +} + +void P2Data::load(const Ring& Rg) +{ + string filename = get_filename(Rg); + cout << "Loading from " << filename << endl; + ifstream s(filename); + octetStream os; + os.input(s); + if (s.eof() or s.fail()) + throw runtime_error("cannot load P2Data"); + unpack(os); +} + +void P2Data::store(const Ring& Rg) const +{ + string filename = get_filename(Rg); + cout << "Storing in " << filename << endl; + ofstream s(filename); + octetStream os; + pack(os); + os.output(s); +} diff --git a/FHE/P2Data.h b/FHE/P2Data.h index 4133c2547..1b2d6d60f 100644 --- a/FHE/P2Data.h +++ b/FHE/P2Data.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #ifndef _P2Data #define _P2Data @@ -24,7 +24,7 @@ class P2Data typedef int S; int num_slots() const { return slots; } - int degree() const { return A[0].size(); } + int degree() const { return A.size() ? A[0].size() : 0; } int phi_m() const { return A.size(); } void check_dimensions() const; @@ -36,6 +36,19 @@ class P2Data int get_prime() const { return 2; } + bool operator!=(const P2Data& other) const; + + // no op because we require field to be initalized first + void init_field() const {} + + void pack(octetStream& o) const; + void unpack(octetStream& o); + + void load(const Ring& Rg); + void store(const Ring& Rg) const; + + void load_or_generate(const Ring& Rg); + friend ostream& operator<<(ostream& s,const P2Data& P2D); friend istream& operator>>(istream& s,P2Data& P2D); diff --git a/FHE/PPData.cpp b/FHE/PPData.cpp index 6fdb0c9db..2d78eab2d 100644 --- a/FHE/PPData.cpp +++ b/FHE/PPData.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "Math/Subroutines.h" #include "FHE/PPData.h" diff --git a/FHE/PPData.h b/FHE/PPData.h index 906d63370..89dc7a673 100644 --- a/FHE/PPData.h +++ b/FHE/PPData.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #ifndef _PPData #define _PPData diff --git a/FHE/Plaintext.cpp b/FHE/Plaintext.cpp index c8b076f35..c977d3e35 100644 --- a/FHE/Plaintext.cpp +++ b/FHE/Plaintext.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "FHE/Plaintext.h" @@ -278,6 +278,8 @@ void Plaintext_::randomize(PRNG& G, bigint B, bool Diag, bool binary, { if (Diag or binary) throw not_implemented(); + if (B == 0) + throw runtime_error("cannot randomize modulo 0"); allocate(t); switch (t) @@ -296,8 +298,8 @@ void Plaintext_::randomize(PRNG& G, bigint B, bool Diag, bool binary, } -template<> -void Plaintext::randomize(PRNG& G, int n_bits, bool Diag, bool binary, PT_Type t) +template +void Plaintext::randomize(PRNG& G, int n_bits, bool Diag, bool binary, PT_Type t) { if (Diag or binary) throw not_implemented(); @@ -307,7 +309,7 @@ void Plaintext::randomize(PRNG& G, int n_bits, bool Diag, b { case Polynomial: for (int i = 0; i < n_slots; i++) - G.get_bigint(b[i], n_bits, false); + G.get(b[i], n_bits, false); break; default: throw not_implemented(); @@ -387,9 +389,9 @@ void Plaintext::assign_one(PT_Type t) } -template<> -Plaintext& Plaintext::operator+=( - const Plaintext& y) +template +Plaintext& Plaintext::operator+=( + const Plaintext& y) { if (Field_Data!=y.Field_Data) { throw field_mismatch(); } @@ -689,17 +691,17 @@ bool Plaintext::equals(const Plaintext& x) const -template <> -void Plaintext::pack(octetStream& o) const +template +void Plaintext::pack(octetStream& o) const { to_poly(); o.store((unsigned int)b.size()); for (unsigned int i = 0; i < b.size(); i++) - b[i].pack(o); + o.store(b[i]); } -template <> -void Plaintext::unpack(octetStream& o) +template +void Plaintext::unpack(octetStream& o) { type = Polynomial; unsigned int size; @@ -708,7 +710,7 @@ void Plaintext::unpack(octetStream& o) if (size != b.size()) throw length_error("unexpected length received"); for (unsigned int i = 0; i < b.size(); i++) - b[i].unpack(o); + o.get(b[i]); } diff --git a/FHE/Plaintext.h b/FHE/Plaintext.h index 2f4b4872e..9df5d727c 100644 --- a/FHE/Plaintext.h +++ b/FHE/Plaintext.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #ifndef _Plaintext #define _Plaintext diff --git a/FHE/QGroup.cpp b/FHE/QGroup.cpp index e0e31f495..3ddec9310 100644 --- a/FHE/QGroup.cpp +++ b/FHE/QGroup.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "Matrix.h" diff --git a/FHE/QGroup.h b/FHE/QGroup.h index 8e59ebe1d..862690e65 100644 --- a/FHE/QGroup.h +++ b/FHE/QGroup.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #ifndef _QGroup #define _QGroup diff --git a/FHE/Random_Coins.cpp b/FHE/Random_Coins.cpp index 56f33c86b..ff47e8160 100644 --- a/FHE/Random_Coins.cpp +++ b/FHE/Random_Coins.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "Random_Coins.h" diff --git a/FHE/Random_Coins.h b/FHE/Random_Coins.h index 1a99f6c9a..ff68f9e60 100644 --- a/FHE/Random_Coins.h +++ b/FHE/Random_Coins.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #ifndef _Random_Coins #define _Random_Coins diff --git a/FHE/Ring.cpp b/FHE/Ring.cpp index 2fc19bdaf..f2dc672fd 100644 --- a/FHE/Ring.cpp +++ b/FHE/Ring.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "Ring.h" diff --git a/FHE/Ring.h b/FHE/Ring.h index f5a345e38..d035aaec5 100644 --- a/FHE/Ring.h +++ b/FHE/Ring.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #ifndef _Ring #define _Ring diff --git a/FHE/Ring_Element.cpp b/FHE/Ring_Element.cpp index c3604fd89..b9ba49978 100644 --- a/FHE/Ring_Element.cpp +++ b/FHE/Ring_Element.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "FHE/Ring_Element.h" @@ -227,7 +227,7 @@ istream& operator>>(istream& s, Ring_Element& e) else if (ch == 'E') rep = evaluation; else - { throw IO_Error("Error reading Ring_Element : ch="+(char)(ch)); } + { throw IO_Error("Error reading Ring_Element : ch="+to_string((char)(ch))); } e.rep = rep; ch = s.peek(); while (isspace(ch)) diff --git a/FHE/Ring_Element.h b/FHE/Ring_Element.h index 8204a7d1a..4c88d89ad 100644 --- a/FHE/Ring_Element.h +++ b/FHE/Ring_Element.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #ifndef _Ring_Element #define _Ring_Element diff --git a/FHE/Rq_Element.cpp b/FHE/Rq_Element.cpp index 1dd1a954c..e28343203 100644 --- a/FHE/Rq_Element.cpp +++ b/FHE/Rq_Element.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "Rq_Element.h" #include "Exceptions/Exceptions.h" @@ -143,7 +143,7 @@ istream& operator>>(istream& s, Rq_Element& a) if (a.lev != 0) { if (ch != ',') - { throw IO_Error("bad Rq_Element input: no ',' ch = " +(char)ch); } + { throw IO_Error("bad Rq_Element input: no ',' ch = " +to_string((char)ch)); } if (!(s >> a.a[1])) { throw IO_Error("bad Rq_Element input for a1"); } diff --git a/FHE/Rq_Element.h b/FHE/Rq_Element.h index 97f18400e..55fc912b6 100644 --- a/FHE/Rq_Element.h +++ b/FHE/Rq_Element.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #ifndef _Rq_Element #define _Rq_Element diff --git a/FHE/tools.h b/FHE/tools.h index 32feafb07..cbbfe81e0 100644 --- a/FHE/tools.h +++ b/FHE/tools.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt /* * tools.h diff --git a/FHEOffline/CutAndChooseMachine.cpp b/FHEOffline/CutAndChooseMachine.cpp new file mode 100644 index 000000000..03a19d0bb --- /dev/null +++ b/FHEOffline/CutAndChooseMachine.cpp @@ -0,0 +1,49 @@ +// (C) 2018 University of Bristol. See License.txt + +/* + * CutAndChooseMachine.cpp + * + */ + +#include "FHEOffline/CutAndChooseMachine.h" +#include "FHEOffline/SimpleGenerator.h" + +CutAndChooseMachine::CutAndChooseMachine(int argc, const char** argv) +{ + opt.add( + "", // Default. + 0, // Required? + 0, // Number of args expected. + 0, // Delimiter if expecting multiple args. + "Use covert security (default: active; use -s for parameter)", // Help description. + "-c", // Flag token. + "--covert" // Flag token. + ); + parse_options(argc, argv); + covert = opt.isSet("--covert"); + if (not covert and sec != 40) + throw runtime_error("active cut-and-choose only implemented for 40-bit security"); + if (covert) + generate_setup(COVERT_SPDZ2_SLACK); + else + generate_setup(ACTIVE_SPDZ2_SLACK); + for (int i = 0; i < nthreads; i++) + { + if (use_gf2n) + generators.push_back(new_generator(i)); + else + generators.push_back(new_generator(i)); + } +} + +template +GeneratorBase* CutAndChooseMachine::new_generator(int i) +{ + SimpleGenerator* generator = + new SimpleGenerator(N, setup.part(), *this, i, data_type); + if (covert) + generator->EC.init(generator->P, setup.part().pk, sec, Full); + else + generator->EC.init(generator->P, setup.part().pk, Full, setup.part().FieldD, i); + return generator; +} diff --git a/FHEOffline/CutAndChooseMachine.h b/FHEOffline/CutAndChooseMachine.h new file mode 100644 index 000000000..a88011f19 --- /dev/null +++ b/FHEOffline/CutAndChooseMachine.h @@ -0,0 +1,24 @@ +// (C) 2018 University of Bristol. See License.txt + +/* + * CutAndChooseMachine.h + * + */ + +#ifndef FHEOFFLINE_CUTANDCHOOSEMACHINE_H_ +#define FHEOFFLINE_CUTANDCHOOSEMACHINE_H_ + +#include "FHEOffline/SimpleMachine.h" + +class CutAndChooseMachine : public MultiplicativeMachine +{ + bool covert; + + template + GeneratorBase* new_generator(int i); + +public: + CutAndChooseMachine(int argc, const char** argv); +}; + +#endif /* FHEOFFLINE_CUTANDCHOOSEMACHINE_H_ */ diff --git a/FHEOffline/DataSetup.cpp b/FHEOffline/DataSetup.cpp index 1acdb406b..a41c3c965 100644 --- a/FHEOffline/DataSetup.cpp +++ b/FHEOffline/DataSetup.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt /* * DataSetup.cpp @@ -59,6 +59,7 @@ template void PartSetup::generate_setup(int n_parties, int plaintext_length, int sec, int slack, bool round_up) { + sec = max(sec, 40); ::generate_setup(n_parties, plaintext_length, sec, params, FieldD, slack, round_up); params.set_sec(sec); @@ -67,15 +68,6 @@ void PartSetup::generate_setup(int n_parties, int plaintext_length, int sec, calpha = Ciphertext(params); } -template <> -void DataSetup::generate_setup(int n_parties, int plaintext_length, int sec, - int slack, bool write_output) -{ - setup_p.generate_setup(n_parties, plaintext_length, sec, slack, true); - if (write_output) - write_setup(true); -} - void DataSetup::write_setup(string dir, bool skip_2) { ofstream outf; @@ -155,8 +147,8 @@ void DataSetup::read(Names& N, bool skip_2, string dir) cout << "Loaded the public keys etc" << endl; } -template <> -void DataSetup::fake(vector& sks, vector& alphais, +template +void PartSetup::fake(vector& sks, vector& alphais, int nplayers, bool distributed) { insecure("global key generation"); @@ -166,70 +158,71 @@ void DataSetup::fake(vector& sks, vector& alphais, cout << "Faking key generation with extra noise" << endl; PRNG G; G.ReSeed(); - pk_p = FHE_PK(params_p, FTD.get_prime()); - FHE_SK sk(params_p, FTD.get_prime()); - calphap = Ciphertext(params_p); - sks.resize(nplayers, pk_p); + pk = FHE_PK(params, FieldD.get_prime()); + FHE_SK sk(params, FieldD.get_prime()); + calpha = Ciphertext(params); + sks.resize(nplayers, pk); alphais.resize(nplayers); if (distributed) - DistKeyGen::fake(pk_p, sks, FTD.get_prime(), nplayers); + DistKeyGen::fake(pk, sks, FieldD.get_prime(), nplayers); else { - Rq_Element sk = FHE_SK(pk_p).s(); + Rq_Element sk = FHE_SK(pk).s(); for (int i = 0; i < nplayers; i++) { - Rq_Element ski = pk_p.sample_secret_key(G); + Rq_Element ski = pk.sample_secret_key(G); sks[i].assign(ski); sk += ski; } - pk_p.KeyGen(sk, G, nplayers); + pk.KeyGen(sk, G, nplayers); } for (int i = 0; i < nplayers; i++) { - Plaintext m(FTD); + Plaintext_ m(FieldD); m.randomize(G,Diagonal); - Ciphertext calphai = pk_p.encrypt(m); - calphap += calphai; + Ciphertext calphai = pk.encrypt(m); + calpha += calphai; alphais[i] = m.element(0); } } -template <> -void DataSetup::fake(vector& setups, int nplayers, +template +void PartSetup::fake(vector >& setups, int nplayers, bool distributed) { vector sks; - vector alphais; - fake(sks, alphais, nplayers, distributed); + vector alphais; + fake(sks, alphais, nplayers, distributed); setups.clear(); setups.resize(nplayers, *this); for (int i = 0; i < nplayers; i++) { - setups[i].sk_p = sks[i]; - setups[i].alphapi = alphais[i]; + setups[i].sk = sks[i]; + setups[i].alphai = alphais[i]; } } -void DataSetup::insecure_debug_keys(vector& setups, int nplayers, bool simple_pk) +template +void PartSetup::insecure_debug_keys(vector >& setups, int nplayers, bool simple_pk) { cout << "generating INSECURE keys for debugging" << endl; setups.clear(); - Rq_Element zero(params_p, evaluation, evaluation), - one(params_p, evaluation, evaluation); + Rq_Element zero(params, evaluation, evaluation), + one(params, evaluation, evaluation); zero.assign_zero(); one.assign_one(); PRNG G; G.ReSeed(); if (simple_pk) - pk_p.assign(zero, zero, zero, zero - one); + pk.assign(zero, zero, zero, zero - one); else - pk_p.KeyGen(one, G, nplayers); + pk.KeyGen(one, G, nplayers); setups.resize(nplayers, *this); - setups[0].sk_p.assign(one); + setups[0].sk.assign(one); for (int i = 1; i < nplayers; i++) - setups[i].sk_p.assign(zero); + setups[i].sk.assign(zero); } void DataSetup::output(int my_number, int nn, bool specific_dir) @@ -260,41 +253,55 @@ void DataSetup::output(int my_number, int nn, bool specific_dir) write_mac_keys(dir, my_number, nn, alphapi, alpha2i); } +template +void PartSetup::pack(octetStream& os) +{ + params.pack(os); + FieldD.pack(os); + pk.pack(os); + sk.pack(os); + calpha.pack(os); + alphai.pack(os); +} + +template +void PartSetup::unpack(octetStream& os) +{ + params.unpack(os); + FieldD.unpack(os); + pk.unpack(os); + sk.unpack(os); + calpha.unpack(os); + alphai.unpack(os); + init_field(); +} + template <> -void DataSetup::pack(octetStream& os) +void PartSetup::init_field() { - params_p.pack(os); - FTD.pack(os); - pk_p.pack(os); - sk_p.pack(os); - calphap.pack(os); - alphapi.pack(os); + gfp::init_field(FieldD.get_prime()); } template <> -void DataSetup::unpack(octetStream& os) +void PartSetup::init_field() { - params_p.unpack(os); - FTD.unpack(os); - pk_p.unpack(os); - sk_p.unpack(os); - calphap.unpack(os); - alphapi.unpack(os); - gfp::init_field(FTD.get_prime()); } -void DataSetup::check(int sec) const +template +void PartSetup::check(int sec) const { - if (sec < params_p.secp()) - throw runtime_error("security parameter for distributed decryption too big"); - sk_p.check(params_p, pk_p, FTD.get_prime()); + sec = max(sec, 40); + if (abs(sec - params.secp()) > 2) + throw runtime_error("security parameters vary too much between protocol and distributed decryption"); + sk.check(params, pk, FieldD.get_prime()); } -bool DataSetup::operator!=(const DataSetup& other) +template +bool PartSetup::operator!=(const PartSetup& other) { - if (params_p != other.params_p or FTD != other.FTD or pk_p != other.pk_p - or sk_p != other.sk_p or calphap != other.calphap - or alphapi != other.alphapi) + if (params != other.params or FieldD != other.FieldD or pk != other.pk + or sk != other.sk or calpha != other.calpha + or alphai != other.alphai) return true; else return false; diff --git a/FHEOffline/DataSetup.h b/FHEOffline/DataSetup.h index 68a34e2be..1b623454a 100644 --- a/FHEOffline/DataSetup.h +++ b/FHEOffline/DataSetup.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt /* * DataSetup.h @@ -13,10 +13,14 @@ #include "FHEOffline/FullSetup.h" #include "Math/Setup.h" +class DataSetup; + template class PartSetup { public: + typedef typename FD::T T; + FHE_Params params; FD FieldD; FHE_PK pk; @@ -28,6 +32,18 @@ class PartSetup void generate_setup(int n_parties, int plaintext_length, int sec, int slack, bool round_up); void output_setup(ostream& s) const; + + void fake(vector& sks, vector& alphais, int nplayers, bool distributed = true); + void fake(vector >& setups, int nplayers, bool distributed = true); + void insecure_debug_keys(vector >& setups, int nplayers, bool simple_pk); + + void pack(octetStream& os); + void unpack(octetStream& os); + + void init_field(); + + void check(int sec) const; + bool operator!=(const PartSetup& other); }; class DataSetup @@ -57,26 +73,18 @@ class DataSetup DataSetup(const DataSetup& other) : DataSetup() { *this = other; } DataSetup& operator=(const DataSetup& other); - template - void generate_setup(int n_parties, int plaintext_length, int sec, int slack, bool write_output); void write_setup(string dir, bool skip_2); void write_setup(bool skip_2); void write_setup(const Names& N, bool skip_2); string get_prep_dir(int n_parties) const; void read_setup(bool skip_2, string dir = PREP_DIR); void read(Names& N, bool skip_2 = false, string dir = PREP_DIR); - template - void fake(vector& sks, vector& alphais, int nplayers, bool distributed = true); - template - void fake(vector& setups, int nplayers, bool distributed = true); - void insecure_debug_keys(vector& setups, int nplayers, bool simple_pk); void output(int my_number, int nn, bool specific_dir = false); - template - void pack(octetStream& os); - template - void unpack(octetStream& os); - void check(int sec) const; - bool operator!=(const DataSetup& other); + template + PartSetup& part(); }; +template<> inline PartSetup& DataSetup::part() { return setup_p; } +template<> inline PartSetup& DataSetup::part() { return setup_2; } + #endif /* FHEOFFLINE_DATASETUP_H_ */ diff --git a/FHEOffline/DistDecrypt.cpp b/FHEOffline/DistDecrypt.cpp index 8447907fd..284535597 100644 --- a/FHEOffline/DistDecrypt.cpp +++ b/FHEOffline/DistDecrypt.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "DistDecrypt.h" diff --git a/FHEOffline/DistDecrypt.h b/FHEOffline/DistDecrypt.h index cf8903be4..d5a18fe08 100644 --- a/FHEOffline/DistDecrypt.h +++ b/FHEOffline/DistDecrypt.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #ifndef _DistDecrypt #define _DistDecrypt diff --git a/FHEOffline/DistKeyGen.cpp b/FHEOffline/DistKeyGen.cpp index 6864a7edf..dcd572b62 100644 --- a/FHEOffline/DistKeyGen.cpp +++ b/FHEOffline/DistKeyGen.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt /* * DistKeyGen.cpp diff --git a/FHEOffline/DistKeyGen.h b/FHEOffline/DistKeyGen.h index 398d6a25e..27220d870 100644 --- a/FHEOffline/DistKeyGen.h +++ b/FHEOffline/DistKeyGen.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt /* * DistKeyGen.h diff --git a/FHEOffline/EncCommit.cpp b/FHEOffline/EncCommit.cpp index 78ed91974..0c987431e 100644 --- a/FHEOffline/EncCommit.cpp +++ b/FHEOffline/EncCommit.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "Auth/Subroutines.h" diff --git a/FHEOffline/EncCommit.h b/FHEOffline/EncCommit.h index f73dfacc9..f11ae464d 100644 --- a/FHEOffline/EncCommit.h +++ b/FHEOffline/EncCommit.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #ifndef _EncCommit #define _EncCommit @@ -88,7 +88,7 @@ class EncCommit : public EncCommitBase ~EncCommit(); // for compatibility - EncCommit(const PlayerBase& P, const FHE_PK& pk, const FFT_Data& FTD, + EncCommit(const PlayerBase& P, const FHE_PK& pk, const FD& FTD, map& timers, const MachineBase& machine, int thread_num) : EncCommit() diff --git a/FHEOffline/FHE-Subroutines.cpp b/FHEOffline/FHE-Subroutines.cpp index cbc63b40b..96832896e 100644 --- a/FHEOffline/FHE-Subroutines.cpp +++ b/FHEOffline/FHE-Subroutines.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "Auth/Subroutines.h" diff --git a/FHEOffline/FullSetup.cpp b/FHEOffline/FullSetup.cpp index e1f16f5f0..bfcf6250e 100644 --- a/FHEOffline/FullSetup.cpp +++ b/FHEOffline/FullSetup.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "FHEOffline/FullSetup.h" @@ -63,5 +63,7 @@ void get_setup(FHE_Params& params_p,FFT_Data& FTD, if (!skip_2) { params_2.set(R2,{p02,p12}); + cout << "GF(2^" << lg2 << "): log(p0) = " << numBits(p02) + << ", log(p1) = " << numBits(p12) << endl; } } diff --git a/FHEOffline/FullSetup.h b/FHEOffline/FullSetup.h index fc2891e06..e741a8341 100644 --- a/FHEOffline/FullSetup.h +++ b/FHEOffline/FullSetup.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #ifndef _FullSetup #define _FullSetup diff --git a/FHEOffline/Multiplier.cpp b/FHEOffline/Multiplier.cpp new file mode 100644 index 000000000..5f80fcefa --- /dev/null +++ b/FHEOffline/Multiplier.cpp @@ -0,0 +1,101 @@ +// (C) 2018 University of Bristol. See License.txt + +/* + * Multiplier.cpp + * + */ + +#include +#include "FHEOffline/PairwiseGenerator.h" +#include "FHEOffline/PairwiseMachine.h" + +template +Multiplier::Multiplier(int offset, PairwiseGenerator& generator) : + generator(generator), machine(generator.machine), + P(generator.global_player, offset), + num_players(generator.global_player.num_players()), + my_num(generator.global_player.my_num()), + other_pk(machine.other_pks[(my_num + num_players - offset) % num_players]), + other_enc_alpha(machine.enc_alphas[(my_num + num_players - offset) % num_players]), + timers(generator.timers), + C(machine.pk), mask(machine.pk), + product_share(machine.setup().FieldD), rc(machine.pk), + volatile_capacity(0) +{ + product_share.allocate_slots(machine.setup().params.p0() << 64); +} + +template +void Multiplier::multiply_and_add(Plaintext_& res, + const Ciphertext& enc_a, const Plaintext_& b) +{ + Rq_Element bb(enc_a.get_params(), evaluation, evaluation); + bb.from_vec(b.get_poly()); + multiply_and_add(res, enc_a, bb); +} + +template +void Multiplier::multiply_and_add(Plaintext_& res, + const Ciphertext& enc_a, const Rq_Element& b) +{ + PRNG G; + G.ReSeed(); + timers["Ciphertext multiplication"].start(); + C.mul(enc_a, b); + timers["Ciphertext multiplication"].stop(); + timers["Mask randomization"].start(); + product_share.randomize(G); + bigint B = 6 * machine.setup().params.get_R(); + B *= machine.setup().FieldD.get_prime(); + B <<= machine.sec; + // slack + B *= NonInteractiveProof::slack(machine.sec, + machine.setup().params.phi_m()); + B <<= machine.extra_slack; + rc.generateUniform(G, 0, B, B); + timers["Mask randomization"].stop(); + timers["Encryption"].start(); + other_pk.encrypt(mask, product_share, rc); + timers["Encryption"].stop(); + timers["Multiplied ciphertext sending"].start(); + octetStream o; + mask += C; + mask.pack(o); + P.reverse_exchange(o); + C.unpack(o); + timers["Multiplied ciphertext sending"].stop(); + timers["Decryption"].start(); + res -= product_share; + machine.sk.decrypt_any(product_share, C); + res += product_share; + timers["Decryption"].stop(); + memory_usage.update("multiplied ciphertext", C.report_size(CAPACITY)); + memory_usage.update("mask ciphertext", mask.report_size(CAPACITY)); + memory_usage.update("product shares", product_share.report_size(CAPACITY)); + memory_usage.update("masking random coins", rc.report_size(CAPACITY)); +} + +template +void Multiplier::multiply_alpha_and_add(Plaintext_& res, + const Rq_Element& b) +{ + multiply_and_add(res, other_enc_alpha, b); +} + +template +size_t Multiplier::report_size(ReportType type) +{ + return C.report_size(type) + mask.report_size(type) + + product_share.report_size(type) + rc.report_size(type); +} + +template +void Multiplier::report_size(ReportType type, MemoryUsage& res) +{ + (void)type; + res += memory_usage; +} + + +template class Multiplier; +template class Multiplier; diff --git a/FHEOffline/Multiplier.h b/FHEOffline/Multiplier.h new file mode 100644 index 000000000..f6048cdb0 --- /dev/null +++ b/FHEOffline/Multiplier.h @@ -0,0 +1,54 @@ +// (C) 2018 University of Bristol. See License.txt + +/* + * Multiplier.h + * + */ + +#ifndef FHEOFFLINE_MULTIPLIER_H_ +#define FHEOFFLINE_MULTIPLIER_H_ + +#include "FHEOffline/SimpleEncCommit.h" +#include "FHE/AddableVector.h" +#include "Tools/MemoryUsage.h" + +template +using PlaintextVector = AddableVector< Plaintext_ >; + +template +class PairwiseGenerator; +class PairwiseMachine; + +template +class Multiplier +{ + PairwiseGenerator& generator; + PairwiseMachine& machine; + OffsetPlayer P; + int num_players, my_num; + const FHE_PK& other_pk; + const Ciphertext& other_enc_alpha; + map& timers; + + // temporary + Ciphertext C, mask; + Plaintext_ product_share; + Random_Coins rc; + + size_t volatile_capacity; + MemoryUsage memory_usage; + +public: + Multiplier(int offset, PairwiseGenerator& generator); + void multiply_and_add(Plaintext_& res, const Ciphertext& C, + const Plaintext_& b); + void multiply_and_add(Plaintext_& res, const Ciphertext& C, + const Rq_Element& b); + void multiply_alpha_and_add(Plaintext_& res, const Rq_Element& b); + int get_offset() { return P.get_offset(); } + size_t report_size(ReportType type); + void report_size(ReportType type, MemoryUsage& res); + size_t report_volatile() { return volatile_capacity; } +}; + +#endif /* FHEOFFLINE_MULTIPLIER_H_ */ diff --git a/FHEOffline/PairwiseGenerator.cpp b/FHEOffline/PairwiseGenerator.cpp new file mode 100644 index 000000000..591ab5701 --- /dev/null +++ b/FHEOffline/PairwiseGenerator.cpp @@ -0,0 +1,146 @@ +// (C) 2018 University of Bristol. See License.txt + +/* + * PairwiseGenerator.cpp + * + */ + +#include "FHEOffline/PairwiseGenerator.h" +#include "FHEOffline/PairwiseMachine.h" +#include "FHEOffline/Producer.h" + +template +PairwiseGenerator::PairwiseGenerator(int thread_num, + PairwiseMachine& machine) : + GeneratorBase(thread_num, machine.N), + producer(machine.setup().FieldD, machine.N.my_num(), + thread_num, machine.output), + EC(P, machine.other_pks, machine.setup().FieldD, timers, machine, *this), + C(machine.sec, machine.setup().params), volatile_memory(0), + machine(machine), global_player(machine.N, (1LL << 28) + (thread_num << 16)) +{ + for (int i = 1; i < machine.N.num_players(); i++) + multipliers.push_back(new Multiplier(i, *this)); + const FD& FieldD = machine.setup().FieldD; + a.resize(machine.sec, FieldD); + b.resize(machine.sec, FieldD); + c.resize(machine.sec, FieldD); + a.allocate_slots(FieldD.get_prime()); + b.allocate_slots(FieldD.get_prime()); + // extra limb for addition + c.allocate_slots((bigint)FieldD.get_prime() << 64); + b_mod_q.resize(machine.sec, + { machine.setup().params, evaluation, evaluation }); +} + +template +PairwiseGenerator::~PairwiseGenerator() +{ + for (auto m : multipliers) + delete m; +} + +template +void PairwiseGenerator::run() +{ + PRNG G; + G.ReSeed(); + MAC_Check MC(machine.setup().alphai); + + while (total < machine.nTriplesPerThread) + { + timers["Randomization"].start(); + a.randomize(G); + b.randomize(G); + timers["Randomization"].stop(); + size_t prover_memory = EC.generate_proof(C, a, ciphertexts, cleartexts); + timers["Plaintext multiplication"].start(); + c.mul(a, b); + timers["Plaintext multiplication"].stop(); + timers["FFT of b"].start(); + for (int i = 0; i < machine.sec; i++) + b_mod_q.at(i).from_vec(b.at(i).get_poly()); + timers["FFT of b"].stop(); + timers["Proof exchange"].start(); + size_t verifier_memory = EC.create_more(ciphertexts, cleartexts); + timers["Proof exchange"].stop(); + volatile_memory = max(prover_memory, verifier_memory); + + Rq_Element values({machine.setup().params, evaluation, evaluation}); + for (int k = 0; k < machine.sec; k++) + { + producer.ai = a[k]; + producer.bi = b[k]; + producer.ci = c[k]; + + for (int j = 0; j < 3; j++) + { + timers["Plaintext multiplication"].start(); + producer.macs[j].mul(machine.setup().alpha, producer.values[j]); + timers["Plaintext multiplication"].stop(); + + if (j == 1) + values = b_mod_q[k]; + else + { + timers["Plaintext conversion"].start(); + values.from_vec(producer.values[j].get_poly()); + timers["Plaintext conversion"].stop(); + } + + for (auto m : multipliers) + m->multiply_alpha_and_add(producer.macs[j], values); + } + producer.reset(); + total += producer.sacrifice(P, MC); + } + + timers["Checking"].start(); + MC.Check(P); + timers["Checking"].stop(); + } + + cout << "Could save " << 1e-9 * a.report_size(CAPACITY) << " GB" << endl; + timers.insert(EC.timers.begin(), EC.timers.end()); + timers.insert(producer.timers.begin(), producer.timers.end()); + timers["Networking"] = P.timer; +} + +template +size_t PairwiseGenerator::report_size(ReportType type) +{ + size_t res = a.report_size(type) + b.report_size(type) + c.report_size(type); + for (auto m : multipliers) + res += m->report_size(type); + res += producer.report_size(type); + res += multipliers[0]->report_volatile(); + res += volatile_memory + C.report_size(type); + res += ciphertexts.get_max_length() + cleartexts.get_max_length(); + res += EC.report_size(type) + EC.volatile_memory; + res += b_mod_q.report_size(type); + return res; +} + +template +size_t PairwiseGenerator::report_sent() +{ + return P.sent + global_player.sent; +} + +template +void PairwiseGenerator::report_size(ReportType type, MemoryUsage& res) +{ + multipliers[0]->report_size(type, res); + res.add("shares", + a.report_size(type) + b.report_size(type) + c.report_size(type)); + res.add("producer", producer.report_size(type)); + res.add("my ciphertexts", C.report_size(CAPACITY)); + res.add("serialized ciphertexts", ciphertexts.get_max_length()); + res.add("serialized cleartexts", cleartexts.get_max_length()); + res.add("generator volatile", volatile_memory); + res.add("b mod p", b_mod_q.report_size(type)); + res += EC.memory_usage; +} + +template class PairwiseGenerator; +template class PairwiseGenerator; diff --git a/FHEOffline/PairwiseGenerator.h b/FHEOffline/PairwiseGenerator.h new file mode 100644 index 000000000..f87485b41 --- /dev/null +++ b/FHEOffline/PairwiseGenerator.h @@ -0,0 +1,49 @@ +// (C) 2018 University of Bristol. See License.txt + +/* + * PairwiseGenerator.h + * + */ + +#ifndef FHEOFFLINE_PAIRWISEGENERATOR_H_ +#define FHEOFFLINE_PAIRWISEGENERATOR_H_ + +#include +using namespace std; + +#include "FHEOffline/Multiplier.h" +#include "FHEOffline/SimpleGenerator.h" + +class PairwiseMachine; + +template +class PairwiseGenerator : public GeneratorBase +{ + friend MultiEncCommit; + + PlaintextVector a, b, c; + AddableVector b_mod_q; + vector*> multipliers; + TripleProducer_ producer; + MultiEncCommit EC; + + // temporary data + AddableVector C; + octetStream ciphertexts, cleartexts; + + size_t volatile_memory; + +public: + PairwiseMachine& machine; + Player global_player; + + PairwiseGenerator(int thread_num, PairwiseMachine& machine); + ~PairwiseGenerator(); + + void run(); + size_t report_size(ReportType type); + void report_size(ReportType type, MemoryUsage& res); + size_t report_sent(); +}; + +#endif /* FHEOFFLINE_PAIRWISEGENERATOR_H_ */ diff --git a/FHEOffline/PairwiseMachine.cpp b/FHEOffline/PairwiseMachine.cpp new file mode 100644 index 000000000..0abb3a712 --- /dev/null +++ b/FHEOffline/PairwiseMachine.cpp @@ -0,0 +1,91 @@ +// (C) 2018 University of Bristol. See License.txt + +/* + * PairwiseMachine.cpp + * + */ + +#include "FHEOffline/PairwiseMachine.h" +#include "Tools/benchmarking.h" +#include "Auth/fake-stuff.h" + +PairwiseMachine::PairwiseMachine(int argc, const char** argv) : + MachineBase(argc, argv), P(N, 0xffff << 16), + other_pks(N.num_players(), {setup_p.params, 0}), + pk(other_pks[N.my_num()]), sk(pk) +{ + if (use_gf2n) + { + field_size = 40; + gf2n::init_field(field_size); + setup_keys(); + } + else + { + setup_keys(); + bigint p = setup_p.FieldD.get_prime(); + gfp::init_field(p); + ofstream outf; + if (output) + write_online_setup(outf, PREP_DIR, p, 40); + } + + for (int i = 0; i < nthreads; i++) + if (use_gf2n) + generators.push_back(new PairwiseGenerator(i, *this)); + else + generators.push_back(new PairwiseGenerator(i, *this)); +} + +template <> +PairwiseSetup& PairwiseMachine::setup() +{ + return setup_p; +} + +template <> +PairwiseSetup& PairwiseMachine::setup() +{ + return setup_2; +} + +template +void PairwiseMachine::setup_keys() +{ + PairwiseSetup& s = setup(); + s.init(P, sec, field_size, extra_slack); + if (output) + write_mac_keys(PREP_DIR, P.my_num(), P.num_players(), setup_p.alphai, + setup_2.alphai); + for (auto& x : other_pks) + x = FHE_PK(s.params, s.FieldD.get_prime()); + sk = FHE_SK(pk); + PRNG G; + G.ReSeed(); + insecure("local key generation"); + KeyGen(pk, sk, G); + vector os(N.num_players()); + pk.pack(os[N.my_num()]); + P.Broadcast_Receive(os); + for (int i = 0; i < N.num_players(); i++) + if (i != N.my_num()) + other_pks[i].unpack(os[i]); + + insecure("MAC key generation"); + Ciphertext enc_alpha = pk.encrypt(s.alpha); + os.clear(); + os.resize(N.num_players()); + enc_alphas.resize(N.num_players(), pk); + enc_alpha.pack(os[N.my_num()]); + P.Broadcast_Receive(os); + for (int i = 0; i < N.num_players(); i++) + if (i != N.my_num()) + enc_alphas[i].unpack(os[i]); + for (int i = 0; i < N.num_players(); i++) + cout << "Player " << i << " has pk " + << other_pks[i].a().get(0).get_constant().get_limb(0) << " ..." + << endl; +} + +template void PairwiseMachine::setup_keys(); +template void PairwiseMachine::setup_keys(); diff --git a/FHEOffline/PairwiseMachine.h b/FHEOffline/PairwiseMachine.h new file mode 100644 index 000000000..8743a908b --- /dev/null +++ b/FHEOffline/PairwiseMachine.h @@ -0,0 +1,36 @@ +// (C) 2018 University of Bristol. See License.txt + +/* + * PairwiseMachine.h + * + */ + +#ifndef FHEOFFLINE_PAIRWISEMACHINE_H_ +#define FHEOFFLINE_PAIRWISEMACHINE_H_ + +#include "FHEOffline/PairwiseGenerator.h" +#include "FHEOffline/SimpleMachine.h" +#include "FHEOffline/PairwiseSetup.h" + +class PairwiseMachine : public MachineBase +{ +public: + PairwiseSetup setup_p; + PairwiseSetup setup_2; + Player P; + + vector other_pks; + FHE_PK& pk; + FHE_SK sk; + vector enc_alphas; + + PairwiseMachine(int argc, const char** argv); + + template + void setup_keys(); + + template + PairwiseSetup& setup(); +}; + +#endif /* FHEOFFLINE_PAIRWISEMACHINE_H_ */ diff --git a/FHEOffline/PairwiseSetup.cpp b/FHEOffline/PairwiseSetup.cpp new file mode 100644 index 000000000..fb89fa99f --- /dev/null +++ b/FHEOffline/PairwiseSetup.cpp @@ -0,0 +1,50 @@ +// (C) 2018 University of Bristol. See License.txt + +/* + * PairwiseSetup.cpp + * + */ + +#include +#include "FHE/NoiseBounds.h" +#include "FHE/NTL-Subs.h" +#include "Math/Setup.h" +#include "FHEOffline/Proof.h" + +template +void PairwiseSetup::init(const Player& P, int sec, int plaintext_length, + int& extra_slack) +{ + sec = max(sec, 40); + cout << "Finding parameters for security " << sec << " and field size ~2^" + << plaintext_length << endl; + PRNG G; + G.ReSeed(); + dirname = PREP_DIR; + + octetStream o; + if (P.my_num() == 0) + { + extra_slack = + generate_semi_setup(plaintext_length, sec, params, FieldD, true); + params.pack(o); + FieldD.pack(o); + o.store(extra_slack); + P.send_all(o); + } + else + { + P.receive_player(0, o); + params.unpack(o); + FieldD.unpack(o); + FieldD.init_field(); + o.get(extra_slack); + } + + alpha = FieldD; + alpha.randomize(G, Diagonal); + alphai = alpha.element(0); +} + +template class PairwiseSetup; +template class PairwiseSetup; diff --git a/FHEOffline/PairwiseSetup.h b/FHEOffline/PairwiseSetup.h new file mode 100644 index 000000000..1b4e5f842 --- /dev/null +++ b/FHEOffline/PairwiseSetup.h @@ -0,0 +1,30 @@ +// (C) 2018 University of Bristol. See License.txt + +/* + * PairwiseSetup.h + * + */ + +#ifndef FHEOFFLINE_PAIRWISESETUP_H_ +#define FHEOFFLINE_PAIRWISESETUP_H_ + +#include "FHE/FHE_Params.h" +#include "FHE/Plaintext.h" +#include "Networking/Player.h" + +template +class PairwiseSetup +{ +public: + FHE_Params params; + FD FieldD; + typename FD::T alphai; + Plaintext_ alpha; + string dirname; + + PairwiseSetup() : params(0), alpha(FieldD) {} + + void init(const Player& P, int sec, int plaintext_length, int& extra_slack); +}; + +#endif /* FHEOFFLINE_PAIRWISESETUP_H_ */ diff --git a/FHEOffline/Player-Offline.h b/FHEOffline/Player-Offline.h index 38b3be366..bc506f794 100644 --- a/FHEOffline/Player-Offline.h +++ b/FHEOffline/Player-Offline.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt /* * Player-Offline.h diff --git a/FHEOffline/Producer.cpp b/FHEOffline/Producer.cpp index ae87b760c..7b09e9fdc 100644 --- a/FHEOffline/Producer.cpp +++ b/FHEOffline/Producer.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt /* * Producer.cpp @@ -22,8 +22,8 @@ template TripleProducer::TripleProducer(const FD& FieldD, int my_num, int output_thread, bool write_output, string dir) : Producer(output_thread, write_output), - i(FieldD.num_slots()), values({ FieldD, FieldD, FieldD }), - macs({ FieldD, FieldD, FieldD }), ai(values[0]), bi(values[1]), + i(FieldD.num_slots()), values{ FieldD, FieldD, FieldD }, + macs{ FieldD, FieldD, FieldD }, ai(values[0]), bi(values[1]), ci(values[2]), gam_ai(macs[0]), gam_bi(macs[1]), gam_ci(macs[2]) { this->dir = dir; @@ -41,8 +41,8 @@ template TupleProducer::TupleProducer(const FD& FieldD, int output_thread, bool write_output) : Producer(output_thread, write_output), - i(FieldD.num_slots()), values({ FieldD, FieldD }), - macs({ FieldD, FieldD }) + i(FieldD.num_slots()), values{ FieldD, FieldD }, + macs{ FieldD, FieldD } { } diff --git a/FHEOffline/Producer.h b/FHEOffline/Producer.h index 8766957fa..f11705cc5 100644 --- a/FHEOffline/Producer.h +++ b/FHEOffline/Producer.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt /* * Producer.h diff --git a/FHEOffline/Proof.cpp b/FHEOffline/Proof.cpp new file mode 100644 index 000000000..e459176c5 --- /dev/null +++ b/FHEOffline/Proof.cpp @@ -0,0 +1,159 @@ +// (C) 2018 University of Bristol. See License.txt + +/* + * Proof.cpp + * + */ + +#include "Proof.h" +#include "FHEOffline/EncCommit.h" + + +double Proof::dist = 0; + +bigint Proof::slack(int slack, int sec, int phim) +{ + switch (slack) + { + case NONINTERACTIVE_SPDZ1_SLACK: + cout << "Computing slack for non-interactive SPDZ1 proof" << endl; + return NonInteractiveProof::slack(sec, phim); + case INTERACTIVE_SPDZ1_SLACK: + cout << "Computing slack for interactive SPDZ1 proof" << endl; + return InteractiveProof::slack(sec, phim); + case COVERT_SPDZ2_SLACK: + cout << "No slack for covert SPDZ2 proof" << endl; + return 0; + case ACTIVE_SPDZ2_SLACK: + cout << "Computing slack for active SPDZ2 proof" << endl; + return EncCommit_::active_slack(phim); + default: + if (slack < 0) + throw runtime_error("slack type unknown"); + return bigint(1) << slack; + } +} + +void Proof::get_challenge(vector& e, const octetStream& ciphertexts) const +{ + unsigned int i; + bigint hashout = ciphertexts.check_sum(); + + for (i=0; i>(i))&1; } +} + +class AbsoluteBoundChecker +{ + bigint bound, neg_bound; + +public: + AbsoluteBoundChecker(bigint bound) : bound(bound), neg_bound(-bound) {} + bool outside(const bigint& value, double& dist) + { + (void)dist; +#ifdef PRINT_MIN_DIST + dist = max(dist, abs(value.get_d()) / bound.get_d()); +#endif + return value > bound || value < neg_bound; + } +}; + +template +bool Proof::check_bounds(T& z, AddableMatrix& t, int i) const +{ + unsigned int j,k; + + // Check Bound 1 and Bound 2 + AbsoluteBoundChecker plain_checker(plain_check * n_proofs); + AbsoluteBoundChecker rand_checker(rand_check * n_proofs); + for (j=0; j& coeffs = t[k]; + for (j=0; j& z, AddableMatrix& t, int i) const; +template bool Proof::check_bounds(AddableVector& z, AddableMatrix& t, int i) const; + +template bool Proof::check_bounds(Plaintext_& z, AddableMatrix& t, int i) const; diff --git a/FHEOffline/Proof.h b/FHEOffline/Proof.h new file mode 100644 index 000000000..f35173951 --- /dev/null +++ b/FHEOffline/Proof.h @@ -0,0 +1,124 @@ +// (C) 2018 University of Bristol. See License.txt + +#ifndef _Proof +#define _Proof + +#include +#include +using namespace std; + +#include "Math/bigint.h" +#include "FHE/Ciphertext.h" +#include "FHE/AddableVector.h" + +enum SlackType +{ + NONINTERACTIVE_SPDZ1_SLACK = -1, + INTERACTIVE_SPDZ1_SLACK = -2, + COVERT_SPDZ2_SLACK = -3, + ACTIVE_SPDZ2_SLACK = -4, +}; + +class Proof +{ + Proof(); // Private to avoid default + + public: + + typedef AddableVector< Int_Random_Coins > Randomness; + + class Preimages + { + bigint m_tmp; + AddableVector r_tmp; + + public: + Preimages(int size, const FHE_PK& pk, const bigint& p, int n_players); + AddableMatrix m; + Randomness r; + void add(octetStream& os); + void pack(octetStream& os); + void unpack(octetStream& os); + void check_sizes(); + size_t report_size(ReportType type) { return m.report_size(type) + r.report_size(type); } + }; + + unsigned int sec; + bigint tau,rho; + + unsigned int phim; + int B_plain_length, B_rand_length; + bigint plain_check, rand_check; + unsigned int V; + + const FHE_PK* pk; + + int n_proofs; + + static double dist; + + protected: + Proof(int sc, const bigint& Tau, const bigint& Rho, const FHE_PK& pk, + int n_proofs = 1) : + B_plain_length(0), B_rand_length(0), pk(&pk), n_proofs(n_proofs) + { sec=sc; + tau=Tau; rho=Rho; + + phim=(pk.get_params()).phi_m(); + V=2*sec-1; + } + + Proof(int sec, const FHE_PK& pk, int n_proofs = 1) : + Proof(sec, pk.p() / 2, 2 * 3.2 * sqrt(pk.get_params().phi_m()), pk, + n_proofs) {} + + public: + static bigint slack(int slack, int sec, int phim); + + void get_challenge(vector& e, const octetStream& ciphertexts) const; + template + bool check_bounds(T& z, AddableMatrix& t, int i) const; +}; + +class NonInteractiveProof : public Proof +{ +public: + bigint static slack(int sec, int phim) + { return bigint(phim * sec * sec) << (sec / 2 + 8); } + + NonInteractiveProof(int sec, const FHE_PK& pk, + int extra_slack) : + Proof(sec, pk, 1) + { + bigint B; + B=128*sec*sec; + B <<= extra_slack; + B_plain_length = numBits(B*phim*tau); + B_rand_length = numBits(B*3*phim*rho); + plain_check = (bigint(1) << B_plain_length) - sec * tau; + rand_check = (bigint(1) << B_rand_length) - sec * rho; + } +}; + +class InteractiveProof : public Proof +{ +public: + bigint static slack(int sec, int phim) + { (void)phim; return pow(2, 1.5 * sec + 1); } + + InteractiveProof(int sec, const FHE_PK& pk, + int n_proofs = 1) : + Proof(sec, pk, n_proofs) + { + bigint B; + // using mu = 1 + B = bigint(1) << (sec - 1); + B_plain_length = numBits(B * tau); + B_rand_length = numBits(B * rho); + // leeway for completeness + plain_check = (bigint(2) << B_plain_length); + rand_check = (bigint(2) << B_rand_length); + } +}; + +#endif diff --git a/FHEOffline/Prover.cpp b/FHEOffline/Prover.cpp new file mode 100644 index 000000000..18deed5b0 --- /dev/null +++ b/FHEOffline/Prover.cpp @@ -0,0 +1,180 @@ +// (C) 2018 University of Bristol. See License.txt + + +#include "Prover.h" + +#include "Tools/random.h" + + +template +Prover::Prover(Proof& proof, const FD& FieldD) : + volatile_memory(0) +{ + s.resize(proof.V, proof.pk->get_params()); + y.resize(proof.V, FieldD); +#ifdef LESS_ALLOC_MORE_MEM + s.allocate_slots(bigint(1) << proof.B_rand_length); + y.allocate_slots(bigint(1) << proof.B_plain_length); + t = s[0]; + z = y[0]; + // extra limb to prevent reallocation + t.allocate_slots(bigint(1) << (proof.B_rand_length + 64)); + z.allocate_slots(bigint(1) << (proof.B_plain_length + 64)); +#endif +} + +template +void Prover::Stage_1(const Proof& P, octetStream& ciphertexts, + const AddableVector& c, + const FHE_PK& pk, bool Diag, bool binary) +{ + size_t allocate = 3 * c.size() * c[0].report_size(USED); + ciphertexts.resize_precise(allocate); + ciphertexts.reset_write_head(); + c.pack(ciphertexts); + + int V=P.V; + +// AElement AE; +// ZZX rd; +// ZZ pr=(*AE.A).prime(); +// ZZ bd=B_plain/(pr+1); + PRNG G; + G.ReSeed(); + Random_Coins rc(pk.get_params()); + Ciphertext ciphertext(pk.get_params()); + ciphertexts.store(V); + for (int i=0; i +bool Prover::Stage_2(Proof& P, octetStream& cleartexts, + const vector& x, + const Proof::Randomness& r, + const vector& e) +{ + size_t allocate = P.V * P.phim + * (5 + numBytes(P.plain_check) + 3 * (5 + numBytes(P.rand_check))); + cleartexts.resize_precise(allocate); + cleartexts.reset_write_head(); + + unsigned int i,k; + int j,ee; +#ifndef LESS_ALLOC_MORE_MEM + AddableVector z; + AddableMatrix t; +#endif + cleartexts.reset_write_head(); + cleartexts.store(P.V); + for (i=0; i=(int) P.sec) { ee=0; } + else { ee=e[j]; } + + if (ee!=0) + { + z += x[j]; + t += r[j]; + } + } + if (not P.check_bounds(z, t, i)) + return false; + z.pack(cleartexts); + t.pack(cleartexts); + } +#ifndef LESS_ALLOC_MORE_MEM + volatile_memory = t.report_size(CAPACITY) + z.report_size(CAPACITY); +#endif +#ifdef PRINT_MIN_DIST + cout << "Minimal distance (log) " << log2(P.dist) << ", compare to " << + log2(P.plain_check.get_d() / pow(2, P.B_plain_length)) << endl; +#endif + return true; +} + + + +/* This is the non-interactive version using the ROM +*/ +template +size_t Prover::NIZKPoK(Proof& P, octetStream& ciphertexts, octetStream& cleartexts, + const FHE_PK& pk, + const AddableVector& c, + const vector& x, + const Proof::Randomness& r, + bool Diag,bool binary) +{ + vector e(P.sec); + +// AElement AE; +// for (i=0; i 1) + cout << "\t\tNumber iterations of prover = " << cnt << endl; + return report_size(CAPACITY) + volatile_memory; +} + + +template +size_t Prover::report_size(ReportType type) +{ + size_t res = 0; + for (unsigned int i = 0; i < s.size(); i++) + res += s[i].report_size(type); + for (unsigned int i = 0; i < y.size(); i++) + res += y[i].report_size(type); +#ifdef LESS_ALLOC_MORE_MEM + res += z.report_size(type) + t.report_size(type); +#endif + return res; +} + + +template +void Prover::report_size(ReportType type, MemoryUsage& res) +{ + res.update("prover s", s.report_size(type)); + res.update("prover y", y.report_size(type)); +#ifdef LESS_ALLOC_MORE_MEM + res.update("prover z", z.report_size(type)); + res.update("prover t", t.report_size(type)); +#endif + res.update("prover volatile", volatile_memory); +} + + +template class Prover >; +template class Prover >; + +template class Prover >; +template class Prover >; diff --git a/FHEOffline/Prover.h b/FHEOffline/Prover.h new file mode 100644 index 000000000..4cbecbdf4 --- /dev/null +++ b/FHEOffline/Prover.h @@ -0,0 +1,52 @@ +// (C) 2018 University of Bristol. See License.txt + +#ifndef _Prover +#define _Prover + +#include "Proof.h" +#include "Tools/MemoryUsage.h" + +/* Class for the prover */ + +template +class Prover +{ + /* Provers state */ + Proof::Randomness s; + AddableVector< Plaintext_ > y; + +#ifdef LESS_ALLOC_MORE_MEM + AddableVector z; + AddableMatrix t; +#endif + +public: + size_t volatile_memory; + + Prover(Proof& proof, const FD& FieldD); + + void Stage_1(const Proof& P, octetStream& ciphertexts, const AddableVector& c, + const FHE_PK& pk, bool Diag, + bool binary = false); + + bool Stage_2(Proof& P, octetStream& cleartexts, + const vector& x, + const Proof::Randomness& r, + const vector& e); + + /* Only has a non-interactive version using the ROM + - If Diag is true then the plaintexts x are assumed to be + diagonal elements, i.e. x=(x_1,x_1,...,x_1) + */ + size_t NIZKPoK(Proof& P, octetStream& ciphertexts, octetStream& cleartexts, + const FHE_PK& pk, + const AddableVector& c, + const vector& x, + const Proof::Randomness& r, + bool Diag,bool binary=false); + + size_t report_size(ReportType type); + void report_size(ReportType type, MemoryUsage& res); +}; + +#endif diff --git a/FHEOffline/Reshare.cpp b/FHEOffline/Reshare.cpp index 0c40d538e..4059003cf 100644 --- a/FHEOffline/Reshare.cpp +++ b/FHEOffline/Reshare.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #include "FHEOffline/Reshare.h" diff --git a/FHEOffline/Reshare.h b/FHEOffline/Reshare.h index 410518bea..073c0d359 100644 --- a/FHEOffline/Reshare.h +++ b/FHEOffline/Reshare.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt #ifndef _Reshare #define _Reshare diff --git a/FHEOffline/Sacrificing.cpp b/FHEOffline/Sacrificing.cpp index 9a909612d..a22562fb0 100644 --- a/FHEOffline/Sacrificing.cpp +++ b/FHEOffline/Sacrificing.cpp @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt /* * Checking.cpp diff --git a/FHEOffline/Sacrificing.h b/FHEOffline/Sacrificing.h index 040964985..6f0e45086 100644 --- a/FHEOffline/Sacrificing.h +++ b/FHEOffline/Sacrificing.h @@ -1,4 +1,4 @@ -// (C) 2017 University of Bristol. See License.txt +// (C) 2018 University of Bristol. See License.txt /* * Checking.h diff --git a/FHEOffline/SimpleDistDecrypt.cpp b/FHEOffline/SimpleDistDecrypt.cpp new file mode 100644 index 000000000..20008b074 --- /dev/null +++ b/FHEOffline/SimpleDistDecrypt.cpp @@ -0,0 +1,40 @@ +// (C) 2018 University of Bristol. See License.txt + +/* + * SimpleDistDecrypt.cpp + * + */ + +#include + +template +void SimpleDistDecrypt::intermediate_step() +{ + for (unsigned int i = 0; i < this->vv.size(); i++) + this->vv[i] += this->f.coeff(i); +} + +template +void SimpleDistDecrypt::reshare(Plaintext& m, + const Ciphertext& cm, + EncCommitBase& EC) +{ + (void)EC; + + PRNG G; + G.ReSeed(); + this->f.randomize(G, Full); + + // Step 3 + this->run(cm); + + // Step 4 + if (this->P.my_num()==0) + { sub(m,this->mf,this->f); } + else + { m=this->f; m.negate(); } +} + + +template class SimpleDistDecrypt; +template class SimpleDistDecrypt; diff --git a/FHEOffline/SimpleDistDecrypt.h b/FHEOffline/SimpleDistDecrypt.h new file mode 100644 index 000000000..d25c170b8 --- /dev/null +++ b/FHEOffline/SimpleDistDecrypt.h @@ -0,0 +1,27 @@ +// (C) 2018 University of Bristol. See License.txt + +/* + * SimpleDistDecrypt.h + * + */ + +#ifndef FHEOFFLINE_SIMPLEDISTDECRYPT_H_ +#define FHEOFFLINE_SIMPLEDISTDECRYPT_H_ + +#include "FHEOffline/DistDecrypt.h" +#include "FHEOffline/DataSetup.h" + +template +class SimpleDistDecrypt : public DistDecrypt +{ +public: + SimpleDistDecrypt(const Player& P, const PartSetup& setup) : + DistDecrypt(P, setup.sk, setup.pk, setup.FieldD) {} + + void intermediate_step(); + void reshare(Plaintext& m, + const Ciphertext& cm, + EncCommitBase& EC); +}; + +#endif /* FHEOFFLINE_SIMPLEDISTDECRYPT_H_ */ diff --git a/FHEOffline/SimpleEncCommit.cpp b/FHEOffline/SimpleEncCommit.cpp new file mode 100644 index 000000000..cc389c5b5 --- /dev/null +++ b/FHEOffline/SimpleEncCommit.cpp @@ -0,0 +1,353 @@ +// (C) 2018 University of Bristol. See License.txt + +/* + * SimpleEncCommit.cpp + * + */ + +#include +#include "FHEOffline/SimpleMachine.h" +#include "FHEOffline/Multiplier.h" +#include "FHEOffline/PairwiseGenerator.h" +#include "Auth/Subroutines.h" +#include "Auth/MAC_Check.h" + +template +SimpleEncCommitBase::SimpleEncCommitBase(const MachineBase& machine) : + sec(machine.sec), extra_slack(machine.extra_slack), n_rounds(0) +{ +} + +template +SimpleEncCommit::SimpleEncCommit(const PlayerBase& P, const FHE_PK& pk, + const FD& FTD, map& timers, const MachineBase& machine, + int thread_num) : + NonInteractiveProofSimpleEncCommit(P, pk, FTD, timers, machine), + SimpleEncCommitFactory(pk, FTD, machine) +{ + (void)thread_num; +} + +template +NonInteractiveProofSimpleEncCommit::NonInteractiveProofSimpleEncCommit( + const PlayerBase& P, const FHE_PK& pk, const FD& FTD, + map& timers, const MachineBase& machine) : + SimpleEncCommitBase_(machine), + P(P), pk(pk), FTD(FTD), + proof(machine.sec, pk, machine.extra_slack), +#ifdef LESS_ALLOC_MORE_MEM + r(this->sec, this->pk.get_params()), prover(proof, FTD), + verifier(proof), +#endif + timers(timers) +{ +} + +template +SimpleEncCommitFactory::SimpleEncCommitFactory(const FHE_PK& pk, + const FD& FTD, const MachineBase& machine) : + cnt(-1), n_calls(0) +{ + int sec = machine.sec; + c.resize(sec, pk.get_params()); + m.resize(sec, FTD); + for (int i = 0; i < sec; i++) + { + m[i].assign_zero(Polynomial); + } +} + +template +SimpleEncCommitFactory::~SimpleEncCommitFactory() +{ + cout << "EncCommit called " << n_calls << " times" << endl; +} + +template +void SimpleEncCommitFactory::next(Plaintext_& mess, Ciphertext& C) +{ + if (cnt < 0) + create_more(); + mess = m[cnt]; + C = c[cnt]; + cnt--; + n_calls++; +} + +template +void SimpleEncCommitFactory::prepare_plaintext(PRNG& G) +{ + for (auto& mess : m) + mess.randomize(G); +} + +template +void SimpleEncCommitBase::generate_ciphertexts( + AddableVector& c, const vector >& m, + Proof::Randomness& r, const FHE_PK& pk, TimerMap& timers) +{ + timers["Generating"].start(); + PRNG G; + G.ReSeed(); + prepare_plaintext(G); + Random_Coins rc(pk.get_params()); + for (int i = 0; i < sec; i++) + { + r[i].sample(G); + rc.assign(r[i]); + pk.encrypt(c[i], m[i], rc); + } + timers["Generating"].stop(); + memory_usage.update("random coins", rc.report_size(CAPACITY)); +} + +template +size_t NonInteractiveProofSimpleEncCommit::generate_proof(AddableVector& c, + const vector >& m, octetStream& ciphertexts, + octetStream& cleartexts) +{ + timers["Proving"].start(); +#ifndef LESS_ALLOC_MORE_MEM + Proof::Randomness r(this->sec, pk.get_params()); +#endif + this->generate_ciphertexts(c, m, r, pk, timers); +#ifndef LESS_ALLOC_MORE_MEM + Prover > prover(proof, FTD); +#endif + size_t prover_memory = prover.NIZKPoK(proof, ciphertexts, cleartexts, + pk, c, m, r, false, false); + timers["Proving"].stop(); + + // cout << "Checking my own proof" << endl; + // if (!Verifier().NIZKPoK(c[P.my_num()], proofs[P.my_num()], pk, false, false)) + // throw runtime_error("proof check failed"); + this->memory_usage.update("randomness", r.report_size(CAPACITY)); + prover.report_size(CAPACITY, this->memory_usage); + return r.report_size(CAPACITY) + prover_memory; +} + +template +void SimpleEncCommit::create_more() +{ + cout << "Generating more ciphertexts in round " << this->n_rounds << endl; + octetStream ciphertexts, cleartexts; + size_t prover_memory = this->generate_proof(this->c, this->m, ciphertexts, cleartexts); + size_t verifier_memory = + NonInteractiveProofSimpleEncCommit::create_more(ciphertexts, + cleartexts); + cout << "Done checking proofs in round " << this->n_rounds << endl; + this->n_rounds++; + this->cnt = this->sec - 1; + this->memory_usage.update("serialized ciphertexts", + ciphertexts.get_max_length()); + this->memory_usage.update("serialized cleartexts", cleartexts.get_max_length()); + this->volatile_memory = max(prover_memory, verifier_memory) + + ciphertexts.get_max_length() + cleartexts.get_max_length(); +} + +template +size_t NonInteractiveProofSimpleEncCommit::create_more(octetStream& ciphertexts, + octetStream& cleartexts) +{ + AddableVector others_ciphertexts; + others_ciphertexts.resize(this->sec, pk.get_params()); + for (int i = 1; i < P.num_players(); i++) + { + cout << "Sending proof with " << 1e-9 * ciphertexts.get_length() << "+" + << 1e-9 * cleartexts.get_length() << " GB" << endl; + timers["Sending"].start(); + P.pass_around(ciphertexts); + P.pass_around(cleartexts); + timers["Sending"].stop(); +#ifndef LESS_ALLOC_MORE_MEM + Verifier verifier(proof); +#endif + cout << "Checking proof of player " << i << endl; + timers["Verifying"].start(); + verifier.NIZKPoK(others_ciphertexts, ciphertexts, + cleartexts, get_pk_for_verification(i), false, false); + timers["Verifying"].stop(); + add_ciphertexts(others_ciphertexts, i); + this->memory_usage.update("verifier", verifier.report_size(CAPACITY)); + } + this->memory_usage.update("cleartexts", cleartexts.get_max_length()); + this->memory_usage.update("others' ciphertexts", others_ciphertexts.report_size(CAPACITY)); +#ifdef LESS_ALLOC_MORE_MEM + return others_ciphertexts.report_size(CAPACITY); +#else + return others_ciphertexts.report_size(CAPACITY) + + this->memory_usage.get("verifier"); +#endif +} + +template +void SimpleEncCommit::add_ciphertexts( + vector& ciphertexts, int offset) +{ + (void)offset; + for (int j = 0; j < this->sec; j++) + add(this->c[j], this->c[j], ciphertexts[j]); +} + +template +void SummingEncCommit::create_more() +{ + octetStream cleartexts; + const Player& P = this->P; + InteractiveProof proof(this->sec, this->pk, P.num_players()); + AddableVector commitments; + vector e(this->sec); + size_t prover_size; + MemoryUsage& memory_usage = this->memory_usage; + TreeSum tree_sum(2, 2, thread_num % P.num_players()); + octetStream& ciphertexts = tree_sum.get_buffer(); + + { +#ifdef LESS_ALLOC_MORE_MEM + Proof::Randomness& r = preimages.r; +#else + Proof::Randomness r(this->sec, this->pk.get_params()); + Prover > prover(proof, this->FTD); +#endif + this->generate_ciphertexts(this->c, this->m, r, pk, timers); + this->timers["Stage 1 of proof"].start(); + prover.Stage_1(proof, ciphertexts, this->c, this->pk, false, false); + this->timers["Stage 1 of proof"].stop(); + + this->c.unpack(ciphertexts, this->pk); + commitments.unpack(ciphertexts, this->pk); + + cout << "Tree-wise sum of ciphertexts with " + << 1e-9 * ciphertexts.get_length() << " GB" << endl; + this->timers["Exchanging ciphertexts"].start(); + tree_sum.run(this->c, P); + tree_sum.run(commitments, P); + this->timers["Exchanging ciphertexts"].stop(); + + generate_challenge(e, P); + + this->timers["Stage 2 of proof"].start(); + prover.Stage_2(proof, cleartexts, this->m, r, e); + this->timers["Stage 2 of proof"].stop(); + + prover_size = prover.report_size(CAPACITY) + r.report_size(CAPACITY) + + prover.volatile_memory; + memory_usage.update("prover", prover.report_size(CAPACITY)); + memory_usage.update("randomness", r.report_size(CAPACITY)); + } + +#ifndef LESS_ALLOC_MORE_MEM + Proof::Preimages preimages(proof.V, this->pk, this->FTD.get_prime(), + P.num_players()); +#endif + preimages.unpack(cleartexts); + + this->timers["Committing"].start(); + AllCommitments cleartext_commitments(P); + cleartext_commitments.commit_and_open(cleartexts); + this->timers["Committing"].stop(); + + for (int i = 1; i < P.num_players(); i++) + { + cout << "Sending cleartexts with " << 1e-9 * cleartexts.get_length() + << " GB in round " << i << endl; + TimeScope(this->timers["Exchanging cleartexts"]); + P.pass_around(cleartexts); + preimages.add(cleartexts); + cleartext_commitments.check_relative(i, cleartexts); + } + + ciphertexts.reset_write_head(); + this->c.pack(ciphertexts); + commitments.pack(ciphertexts); + cleartexts.clear(); + cleartexts.resize_precise(preimages.report_size(USED)); + preimages.pack(cleartexts); + this->timers["Verifying"].start(); +#ifdef LESS_ALLOC_MORE_MEM + Verifier& verifier = this->verifier; +#else + Verifier verifier(proof); +#endif + verifier.Stage_2(e, this->c, ciphertexts, cleartexts, + this->pk, false, false); + this->timers["Verifying"].stop(); + this->cnt = this->sec - 1; + + this->volatile_memory = + + commitments.report_size(CAPACITY) + ciphertexts.get_max_length() + + cleartexts.get_max_length() + + max(prover_size, preimages.report_size(CAPACITY)) + + tree_sum.report_size(CAPACITY); + memory_usage.update("verifier", verifier.report_size(CAPACITY)); + memory_usage.update("preimages", preimages.report_size(CAPACITY)); + memory_usage.update("commitments", commitments.report_size(CAPACITY)); + memory_usage.update("received cleartexts", cleartexts.get_max_length()); + memory_usage.update("tree sum", tree_sum.report_size(CAPACITY)); +} + +template +size_t NonInteractiveProofSimpleEncCommit::report_size(ReportType type) +{ +#ifdef LESS_ALLOC_MORE_MEM + return r.report_size(type) + + prover.report_size(type) + verifier.report_size(type); +#else + (void)type; + return 0; +#endif +} + +template +size_t SimpleEncCommitFactory::report_size(ReportType type) +{ + return m.report_size(type) + c.report_size(type); +} + +template +void SimpleEncCommitFactory::report_size(ReportType type, MemoryUsage& res) +{ + res.add("my plaintexts", m.report_size(type)); + res.add("my ciphertexts", c.report_size(type)); +} + +template +size_t SummingEncCommit::report_size(ReportType type) +{ +#ifdef LESS_ALLOC_MORE_MEM + return prover.report_size(type) + preimages.report_size(type); +#else + (void)type; + return 0; +#endif +} + +template +MultiEncCommit::MultiEncCommit(const Player& P, const vector& pks, + const FD& FTD, map& timers, MachineBase& machine, + PairwiseGenerator& generator) : + NonInteractiveProofSimpleEncCommit(P, pks[P.my_real_num()], FTD, + timers, machine), pks(pks), P(P), generator(generator) +{ +} + +template +void MultiEncCommit::add_ciphertexts(vector& ciphertexts, + int offset) +{ + for (int i = 0; i < this->sec; i++) + generator.multipliers[offset - 1]->multiply_and_add(generator.c.at(i), + ciphertexts.at(i), generator.b_mod_q.at(i)); +} + +template class SimpleEncCommitBase; +template class SimpleEncCommit; +template class SummingEncCommit; +template class NonInteractiveProofSimpleEncCommit; +template class MultiEncCommit; + +template class SimpleEncCommitBase; +template class SimpleEncCommit; +template class SummingEncCommit; +template class NonInteractiveProofSimpleEncCommit; +template class MultiEncCommit; diff --git a/FHEOffline/SimpleEncCommit.h b/FHEOffline/SimpleEncCommit.h new file mode 100644 index 000000000..3c466f132 --- /dev/null +++ b/FHEOffline/SimpleEncCommit.h @@ -0,0 +1,195 @@ +// (C) 2018 University of Bristol. See License.txt + +/* + * SimpleEncCommit.h + * + */ + +#ifndef FHEOFFLINE_SIMPLEENCCOMMIT_H_ +#define FHEOFFLINE_SIMPLEENCCOMMIT_H_ + +#include "FHEOffline/EncCommit.h" +#include "FHEOffline/Proof.h" +#include "FHEOffline/Prover.h" +#include "FHEOffline/Verifier.h" +#include "Tools/MemoryUsage.h" + +class MachineBase; + +typedef map TimerMap; + +template +class SimpleEncCommitBase : public EncCommitBase +{ +protected: + int sec; + int extra_slack; + + int n_rounds; + + void generate_ciphertexts(AddableVector& c, + const vector >& m, Proof::Randomness& r, + const FHE_PK& pk, map& timers); + + virtual void prepare_plaintext(PRNG& G) = 0; + +public: + MemoryUsage memory_usage; + + SimpleEncCommitBase(const MachineBase& machine); + virtual ~SimpleEncCommitBase() {} + void report_size(ReportType type, MemoryUsage& res) { (void)type; res += memory_usage; } +}; + +template +using SimpleEncCommitBase_ = SimpleEncCommitBase; + +template +class NonInteractiveProofSimpleEncCommit : public SimpleEncCommitBase_ +{ +protected: + typedef bigint S; + + const PlayerBase& P; + const FHE_PK& pk; + const FD& FTD; + + NonInteractiveProof proof; + +#ifdef LESS_ALLOC_MORE_MEM + Proof::Randomness r; + Prover > prover; + Verifier verifier; +#endif + + virtual const FHE_PK& get_pk_for_verification(int offset) = 0; + virtual void add_ciphertexts(vector& ciphertexts, int offset) = 0; + +public: + map& timers; + + NonInteractiveProofSimpleEncCommit(const PlayerBase& P, const FHE_PK& pk, + const FD& FTD, map& timers, + const MachineBase& machine); + virtual ~NonInteractiveProofSimpleEncCommit() {} + size_t generate_proof(AddableVector& c, const vector >& m, + octetStream& ciphertexts, octetStream& cleartexts); + size_t create_more(octetStream& my_ciphertext, octetStream& my_cleartext); + virtual size_t report_size(ReportType type); + using SimpleEncCommitBase_::report_size; +}; + +template +class SimpleEncCommitFactory +{ +protected: + int cnt; + AddableVector c; + AddableVector< Plaintext_ > m; + + int n_calls; + + void prepare_plaintext(PRNG& G); + virtual void create_more() = 0; + +public: + SimpleEncCommitFactory(const FHE_PK& pk, const FD& FTD, const MachineBase& machine); + virtual ~SimpleEncCommitFactory(); + void next(Plaintext_& mess, Ciphertext& C); + virtual size_t report_size(ReportType type); + void report_size(ReportType type, MemoryUsage& res); +}; + +template +class SimpleEncCommit: public NonInteractiveProofSimpleEncCommit, + public SimpleEncCommitFactory +{ +protected: + const FHE_PK& get_pk_for_verification(int offset) { (void)offset; return this->pk; } + void prepare_plaintext(PRNG& G) + { SimpleEncCommitFactory::prepare_plaintext(G); } + void add_ciphertexts(vector& ciphertexts, int offset); + +public: + SimpleEncCommit(const PlayerBase& P, const FHE_PK& pk, const FD& FTD, + map& timers, const MachineBase& machine, int thread_num); + void next(Plaintext_& mess, Ciphertext& C) { SimpleEncCommitFactory::next(mess, C); } + void create_more(); + size_t report_size(ReportType type) + { return SimpleEncCommitFactory::report_size(type) + EncCommitBase_::report_size(type); } + void report_size(ReportType type, MemoryUsage& res) + { SimpleEncCommitFactory::report_size(type, res); SimpleEncCommitBase_::report_size(type, res); } +}; + +template +using SimpleEncCommit_ = SimpleEncCommit; + +template +class SummingEncCommit: public SimpleEncCommitFactory, + public SimpleEncCommitBase_ +{ + typedef bigint S; + + InteractiveProof proof; + const FHE_PK& pk; + const FD& FTD; + const Player& P; + int thread_num; + +#ifdef LESS_ALLOC_MORE_MEM + Prover > prover; + Verifier verifier; + Proof::Preimages preimages; +#endif + + void prepare_plaintext(PRNG& G) + { SimpleEncCommitFactory::prepare_plaintext(G); } + +public: + map& timers; + + SummingEncCommit(const Player& P, const FHE_PK& pk, const FD& FTD, + map& timers, const MachineBase& machine, int thread_num) : + SimpleEncCommitFactory(pk, FTD, machine), SimpleEncCommitBase_(machine), + proof(this->sec, pk, P.num_players()), pk(pk), FTD(FTD), P(P), + thread_num(thread_num), +#ifdef LESS_ALLOC_MORE_MEM + prover(proof, FTD), verifier(proof), preimages(proof.V, this->pk, + FTD.get_prime(), P.num_players()), +#endif + timers(timers) {} + void next(Plaintext_& mess, Ciphertext& C) { SimpleEncCommitFactory::next(mess, C); } + void create_more(); + size_t report_size(ReportType type); + void report_size(ReportType type, MemoryUsage& res) + { SimpleEncCommitFactory::report_size(type, res); SimpleEncCommitBase_::report_size(type, res); } +}; + +template +class Multiplier; +template +class PairwiseGenerator; + +template +class MultiEncCommit : public NonInteractiveProofSimpleEncCommit +{ + friend PairwiseGenerator; + +protected: + const vector& pks; + const Player& P; + PairwiseGenerator& generator; + + void prepare_plaintext(PRNG& G) { (void)G; } + const FHE_PK& get_pk_for_verification(int offset) + { return pks[(P.my_num() - offset + P.num_players()) % P.num_players()]; } + void add_ciphertexts(vector& ciphertexts, int offset); + +public: + MultiEncCommit(const Player& P, const vector& pks, + const FD& FTD, + map& timers, MachineBase& machine, + PairwiseGenerator& generator); +}; + +#endif /* FHEOFFLINE_SIMPLEENCCOMMIT_H_ */ diff --git a/FHEOffline/SimpleGenerator.cpp b/FHEOffline/SimpleGenerator.cpp new file mode 100644 index 000000000..d074b2869 --- /dev/null +++ b/FHEOffline/SimpleGenerator.cpp @@ -0,0 +1,97 @@ +// (C) 2018 University of Bristol. See License.txt + +/* + * SimpleThread.cpp + * + */ + +#include +#include "FHEOffline/SimpleMachine.h" +#include "FHEOffline/Sacrificing.h" +#include "Auth/MAC_Check.h" + +template