From 216fbdf1e19df012e0ccae63127b0ef8af4ce550 Mon Sep 17 00:00:00 2001 From: Marcel Keller Date: Sat, 5 Jan 2019 15:10:01 +0100 Subject: [PATCH] Shamir secret sharing. --- Auth/MAC_Check.cpp | 6 + Auth/MaliciousShamirMC.h | 35 ++++ Auth/MaliciousShamirMC.hpp | 52 ++++++ Auth/ShamirMC.h | 40 +++++ Auth/ShamirMC.hpp | 47 +++++ CHANGELOG.md | 6 + Compiler/GC/types.py | 8 +- Compiler/types.py | 32 ++-- Compiler/util.py | 3 + GC/Machine.cpp | 1 + License.txt | 2 +- Makefile | 10 +- Math/MaliciousRep3Share.h | 1 + Math/MaliciousShamirShare.h | 40 +++++ Math/ShamirShare.h | 100 +++++++++++ Math/gf2n.h | 2 + Math/gf2nlong.h | 2 + Math/modp.cpp | 6 - Math/modp.h | 5 + Networking/CryptoPlayer.cpp | 46 ++++- Networking/Player.cpp | 2 + Processor/Data_Files.cpp | 134 +++++++++++---- Processor/Data_Files.h | 8 +- Processor/DummyProtocol.h | 41 +++++ Processor/Input.h | 2 +- Processor/Input.hpp | 7 +- Processor/Instruction.cpp | 9 + Processor/Machine.cpp | 14 ++ Processor/MaliciousRepPrep.h | 15 +- Processor/MaliciousRepPrep.hpp | 28 +-- Processor/Online-Thread.hpp | 9 +- Processor/Processor.h | 6 +- Processor/Processor.hpp | 4 +- Processor/Replicated.h | 30 +++- Processor/{Replicated.cpp => Replicated.hpp} | 35 ++-- Processor/ReplicatedInput.h | 45 ++++- Processor/ReplicatedInput.hpp | 51 ++++-- Processor/ReplicatedMachine.h | 3 +- Processor/ReplicatedMachine.hpp | 5 +- Processor/ReplicatedPrep.h | 20 ++- ...{ReplicatedPrep.cpp => ReplicatedPrep.hpp} | 161 +++++++++++------- Processor/Shamir.h | 60 +++++++ Processor/Shamir.hpp | 121 +++++++++++++ Processor/ShamirInput.h | 47 +++++ Processor/ShamirInput.hpp | 75 ++++++++ Processor/ShamirMachine.cpp | 68 ++++++++ Processor/ShamirMachine.h | 34 ++++ README.md | 39 +++++ Scripts/mal-shamir.sh | 14 ++ Scripts/run-common.sh | 5 +- Scripts/shamir.sh | 14 ++ Tools/random.h | 4 + malicious-rep-field-party.cpp | 4 +- malicious-shamir-party.cpp | 12 ++ replicated-field-party.cpp | 4 +- replicated-ring-party.cpp | 4 +- shamir-party.cpp | 12 ++ 57 files changed, 1375 insertions(+), 215 deletions(-) create mode 100644 Auth/MaliciousShamirMC.h create mode 100644 Auth/MaliciousShamirMC.hpp create mode 100644 Auth/ShamirMC.h create mode 100644 Auth/ShamirMC.hpp create mode 100644 Math/MaliciousShamirShare.h create mode 100644 Math/ShamirShare.h rename Processor/{Replicated.cpp => Replicated.hpp} (78%) rename Processor/{ReplicatedPrep.cpp => ReplicatedPrep.hpp} (56%) create mode 100644 Processor/Shamir.h create mode 100644 Processor/Shamir.hpp create mode 100644 Processor/ShamirInput.h create mode 100644 Processor/ShamirInput.hpp create mode 100644 Processor/ShamirMachine.cpp create mode 100644 Processor/ShamirMachine.h create mode 100755 Scripts/mal-shamir.sh create mode 100755 Scripts/shamir.sh create mode 100644 malicious-shamir-party.cpp create mode 100644 shamir-party.cpp diff --git a/Auth/MAC_Check.cpp b/Auth/MAC_Check.cpp index 0bbeb79cf..c2eeee852 100644 --- a/Auth/MAC_Check.cpp +++ b/Auth/MAC_Check.cpp @@ -12,6 +12,8 @@ #include "Math/BitVec.h" #include "Math/Rep3Share.h" #include "Math/MaliciousRep3Share.h" +#include "Math/ShamirShare.h" +#include "Math/MaliciousShamirShare.h" #include @@ -460,3 +462,7 @@ template class MAC_Check_Base>; template class MAC_Check_Base>; template class MAC_Check_Base>; template class MAC_Check_Base>; +template class MAC_Check_Base>; +template class MAC_Check_Base>; +template class MAC_Check_Base>; +template class MAC_Check_Base>; diff --git a/Auth/MaliciousShamirMC.h b/Auth/MaliciousShamirMC.h new file mode 100644 index 000000000..4fa6cec06 --- /dev/null +++ b/Auth/MaliciousShamirMC.h @@ -0,0 +1,35 @@ +/* + * MaliciousShamirMC.h + * + */ + +#ifndef AUTH_MALICIOUSSHAMIRMC_H_ +#define AUTH_MALICIOUSSHAMIRMC_H_ + +#include "ShamirMC.h" + +template +class MaliciousShamirMC : public ShamirMC +{ + vector> reconstructions; + +public: + MaliciousShamirMC(); + + // emulate MAC_Check + MaliciousShamirMC(const typename T::value_type& _, int __ = 0, int ___ = 0) : + MaliciousShamirMC() + { (void)_; (void)__; (void)___; } + + // emulate Direct_MAC_Check + MaliciousShamirMC(const typename T::value_type& _, Names& ____, int __ = 0, + int ___ = 0) : + MaliciousShamirMC() + { (void)_; (void)__; (void)___; (void)____; } + + + void POpen_End(vector& values, const vector& S, + const Player& P); +}; + +#endif /* AUTH_MALICIOUSSHAMIRMC_H_ */ diff --git a/Auth/MaliciousShamirMC.hpp b/Auth/MaliciousShamirMC.hpp new file mode 100644 index 000000000..457a67bc5 --- /dev/null +++ b/Auth/MaliciousShamirMC.hpp @@ -0,0 +1,52 @@ +/* + * MaliciousShamirMC.cpp + * + */ + +#include "MaliciousShamirMC.h" +#include "Processor/ShamirMachine.h" + +template +MaliciousShamirMC::MaliciousShamirMC() +{ + this->threshold = 2 * ShamirMachine::s().threshold; +} + +template +void MaliciousShamirMC::POpen_End(vector& values, + const vector& S, const Player& P) +{ + (void) P; + int threshold = ShamirMachine::s().threshold; + if (reconstructions.empty()) + { + reconstructions.resize(2 * threshold + 2); + for (int i = threshold + 1; i <= 2 * threshold + 1; i++) + { + reconstructions[i].resize(i); + for (int j = 0; j < i; j++) + reconstructions[i][j] = Shamir::get_rec_factor(j, i); + } + } + + values.clear(); + values.resize(S.size()); + vector shares(2 * threshold + 1); + for (size_t i = 0; i < values.size(); i++) + { + for (size_t j = 0; j < shares.size(); j++) + shares[j].unpack(this->os[j]); + T value = 0; + for (int j = 0; j < threshold + 1; j++) + value += shares[j] * reconstructions[threshold + 1][j]; + for (int j = threshold + 2; j <= 2 * threshold + 1; j++) + { + T check = 0; + for (int k = 0; k < j; k++) + check += shares[k] * reconstructions[j][k]; + if (check != value) + throw mac_fail(); + } + values[i] = value; + } +} diff --git a/Auth/ShamirMC.h b/Auth/ShamirMC.h new file mode 100644 index 000000000..a0f1bc21b --- /dev/null +++ b/Auth/ShamirMC.h @@ -0,0 +1,40 @@ +/* + * ShamirMC.h + * + */ + +#ifndef AUTH_SHAMIRMC_H_ +#define AUTH_SHAMIRMC_H_ + +#include "MAC_Check.h" +#include "Math/ShamirShare.h" +#include "Processor/ShamirMachine.h" + +template +class ShamirMC : public MAC_Check_Base +{ + vector reconstruction; + +protected: + vector os; + int threshold; + +public: + ShamirMC() : threshold(ShamirMachine::s().threshold) {} + + // emulate MAC_Check + ShamirMC(const typename T::value_type& _, int __ = 0, int ___ = 0) : ShamirMC() + { (void)_; (void)__; (void)___; } + + // emulate Direct_MAC_Check + ShamirMC(const typename T::value_type& _, Names& ____, int __ = 0, int ___ = 0) : + ShamirMC() + { (void)_; (void)__; (void)___; (void)____; } + + void POpen_Begin(vector& values,const vector& S,const Player& P); + void POpen_End(vector& values,const vector& S,const Player& P); + + void Check(const Player& P) { (void)P; } +}; + +#endif /* AUTH_SHAMIRMC_H_ */ diff --git a/Auth/ShamirMC.hpp b/Auth/ShamirMC.hpp new file mode 100644 index 000000000..41840ebfb --- /dev/null +++ b/Auth/ShamirMC.hpp @@ -0,0 +1,47 @@ +/* + * ShamirMC.cpp + * + */ + +#include "ShamirMC.h" + +template +void ShamirMC::POpen_Begin(vector& values, + const vector& S, const Player& P) +{ + (void) values; + os.clear(); + os.resize(P.num_players()); + if (P.my_num() <= threshold) + { + for (auto& share : S) + share.pack(os[P.my_num()]); + for (int i = 0; i < P.num_players(); i++) + if (i != P.my_num()) + P.send_to(i, os[P.my_num()], true); + } + for (int i = 0; i <= threshold; i++) + if (i != P.my_num()) + P.receive_player(i, os[i], true); +} + +template +void ShamirMC::POpen_End(vector& values, + const vector& S, const Player& P) +{ + (void) P; + int n_relevant_players = ShamirMachine::s().threshold + 1; + if (reconstruction.empty()) + { + reconstruction.resize(n_relevant_players, 1); + for (int i = 0; i < n_relevant_players; i++) + reconstruction[i] = Shamir::get_rec_factor(i, + n_relevant_players); + } + + values.clear(); + values.resize(S.size()); + for (size_t i = 0; i < values.size(); i++) + for (int j = 0; j < n_relevant_players; j++) + values[i] += os[j].template get() * reconstruction[j]; +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fc607eae..01390079a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ 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.6 (Jan 5, 2019) + +- Shamir secret sharing + ## 0.0.5 (Nov 5, 2018) + +- More three-party replicated secret sharing - Encrypted communication for replicated secret sharing ## 0.0.4 (Oct 11, 2018) diff --git a/Compiler/GC/types.py b/Compiler/GC/types.py index 8a5ad329e..9258c38d8 100644 --- a/Compiler/GC/types.py +++ b/Compiler/GC/types.py @@ -1,5 +1,5 @@ from Compiler.types import MemValue, read_mem_value, regint, Array -from Compiler.types import _bitint, _number, _fix +from Compiler.types import _bitint, _number, _fix, _structure from Compiler.program import Tape, Program from Compiler.exceptions import * from Compiler import util, oram, floatingpoint @@ -66,6 +66,12 @@ def bit_decompose(self, bit_length=None): else: return self.decomposed[:n] + suffix @classmethod + def malloc(cls, size): + return Program.prog.malloc(size, cls) + @staticmethod + def n_elements(): + return 1 + @classmethod def load_mem(cls, address, mem_type=None): res = cls() if mem_type == 'sd': diff --git a/Compiler/types.py b/Compiler/types.py index 4d55f814a..6f12e2284 100644 --- a/Compiler/types.py +++ b/Compiler/types.py @@ -1773,7 +1773,7 @@ class cfix(_number, _structure): """ Clear fixed point type. """ __slots__ = ['value', 'f', 'k', 'size'] reg_type = 'c' - scalars = (int, long, float) + scalars = (int, long, float, regint) @classmethod def set_precision(cls, f, k = None): # k is the whole bitlength of fixed point @@ -1829,7 +1829,12 @@ def __init__(self, v=None, size=None): if isinstance(v, cint): self.v = cint(v,size=self.size) elif isinstance(v, cfix.scalars): - self.v = cint(int(round(v * (2 ** f))),size=self.size) + v = v * (2 ** f) + try: + v = int(round(v)) + except TypeError: + pass + self.v = cint(v, size=self.size) elif isinstance(v, cfix): self.v = v.v elif isinstance(v, MemValue): @@ -2072,9 +2077,11 @@ def __init__(self, _v=None, size=None): self.v = _v.v elif isinstance(_v, (MemValue, MemFix)): #this is a memvalue object - self.v = self.conv(_v.read()) + self.v = sfix(_v.read()).v else: raise CompilerError('cannot convert %s to sfix' % _v) + if not isinstance(self.v, self.int_type): + raise CompilerError('sfix conversion failure: %s/%s' % (_v, self.v)) @vectorize def load_int(self, v): @@ -2304,16 +2311,17 @@ def __init__(self, v, p=None, z=None, s=None, size=None): z = v.z s = v.s v = v.v - elif isinstance(v, sint): - v, p, z, s = floatingpoint.Int2FL(v, program.bit_length, - self.vlen, self.kappa) elif isinstance(v, sfix): f = v.f v, p, z, s = floatingpoint.Int2FL(v.v, v.k, self.vlen, self.kappa) p = p - f - else: + elif util.is_constant_float(v): v, p, z, s = self.convert_float(v, self.vlen, self.plen) + else: + v, p, z, s = floatingpoint.Int2FL(sint.conv(v), + program.bit_length, + self.vlen, self.kappa) if isinstance(v, int): if not ((v >= 2**(self.vlen-1) and v < 2**(self.vlen)) or v == 0): raise CompilerError('Floating point number malformed: significand') @@ -2554,6 +2562,11 @@ def print_float_plain(self): 'ci': regint, } +def _get_type(t): + if t in _types: + return _types[t] + else: + return t class Array(object): @classmethod @@ -2566,8 +2579,7 @@ def create_from(cls, l): return res def __init__(self, length, value_type, address=None, debug=None): - if value_type in _types: - value_type = _types[value_type] + value_type = _get_type(value_type) self.address = address self.length = length self.value_type = value_type @@ -2695,7 +2707,7 @@ def reveal(self): class SubMultiArray(object): def __init__(self, sizes, value_type, address, index, debug=None): self.sizes = sizes - self.value_type = value_type + self.value_type = _get_type(value_type) self.address = address + index * reduce(operator.mul, self.sizes) * \ self.value_type.n_elements() self.sub_cache = {} diff --git a/Compiler/util.py b/Compiler/util.py index 6c2bad08f..b2bcd3543 100644 --- a/Compiler/util.py +++ b/Compiler/util.py @@ -137,6 +137,9 @@ def reveal(x): def is_constant(x): return isinstance(x, (int, long, bool)) +def is_constant_float(x): + return isinstance(x, float) or is_constant(x) + def is_zero(x): try: return int(x) is 0 diff --git a/GC/Machine.cpp b/GC/Machine.cpp index 2c5e9f50b..43ec27a6e 100644 --- a/GC/Machine.cpp +++ b/GC/Machine.cpp @@ -14,6 +14,7 @@ #include "Thread.hpp" #include "ThreadMaster.hpp" #include "Auth/MaliciousRepMC.hpp" +#include "Processor/Replicated.hpp" namespace GC { diff --git a/License.txt b/License.txt index 8b482f469..5c7c4b13d 100644 --- a/License.txt +++ b/License.txt @@ -1,5 +1,5 @@ CSIRO Open Source Software Licence Agreement (variation of the BSD / MIT License) -Copyright (c) 2018, Commonwealth Scientific and Industrial Research Organisation (CSIRO) ABN 41 687 119 230. +Copyright (c) 2019, Commonwealth Scientific and Industrial Research Organisation (CSIRO) ABN 41 687 119 230. All rights reserved. CSIRO is willing to grant you a licence to this MP-SPDZ sofware on the following terms, except where otherwise indicated for third party material. Redistribution and use of this software in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. diff --git a/Makefile b/Makefile index 6f0e6c468..44e555ffd 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ OBJS = $(BMR) $(FHEOFFLINE) $(TINYOTOFFLINE) $(YAO) $(COMPLETE) DEPS := $(OBJS:.o=.d) -all: gen_input online offline externalIO yao replicated +all: gen_input online offline externalIO yao replicated shamir ifeq ($(USE_GF2N_LONG),1) all: bmr @@ -80,6 +80,8 @@ replicated: rep-field rep-ring rep-bin tldr: malicious-rep-field-party.x Setup.x +shamir: shamir-party.x malicious-shamir-party.x galois-degree.x + Fake-Offline.x: Fake-Offline.cpp $(COMMON) $(PROCESSOR) $(CXX) $(CFLAGS) -o $@ Fake-Offline.cpp $(COMMON) $(PROCESSOR) $(LDLIBS) @@ -179,6 +181,12 @@ replicated-field-party.x: replicated-field-party.cpp $(PROCESSOR) $(COMMON) malicious-rep-field-party.x: malicious-rep-field-party.cpp $(PROCESSOR) $(COMMON) $(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS) +shamir-party.x: shamir-party.cpp $(PROCESSOR) $(COMMON) + $(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS) + +malicious-shamir-party.x: malicious-shamir-party.cpp $(PROCESSOR) $(COMMON) + $(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS) + $(LIBSIMPLEOT): SimpleOT/Makefile $(MAKE) -C SimpleOT diff --git a/Math/MaliciousRep3Share.h b/Math/MaliciousRep3Share.h index 815ef2c83..4ade5c6f7 100644 --- a/Math/MaliciousRep3Share.h +++ b/Math/MaliciousRep3Share.h @@ -23,6 +23,7 @@ class MaliciousRep3Share : public Rep3Share typedef MAC_Check Direct_MC; typedef ReplicatedInput> Input; typedef ReplicatedPrivateOutput> PrivateOutput; + typedef Rep3Share Honest; static string type_short() { diff --git a/Math/MaliciousShamirShare.h b/Math/MaliciousShamirShare.h new file mode 100644 index 000000000..85995ba02 --- /dev/null +++ b/Math/MaliciousShamirShare.h @@ -0,0 +1,40 @@ +/* + * MaliciousShamirShare.h + * + */ + +#ifndef MATH_MALICIOUSSHAMIRSHARE_H_ +#define MATH_MALICIOUSSHAMIRSHARE_H_ + +#include "ShamirShare.h" +#include "Processor/Beaver.h" +#include "Auth/MaliciousShamirMC.h" + +template +class MaliciousShamirShare : public ShamirShare +{ + typedef ShamirShare super; + +public: + typedef Beaver> Protocol; + typedef MaliciousShamirMC MAC_Check; + typedef MAC_Check Direct_MC; + typedef ShamirInput Input; + typedef ReplicatedPrivateOutput PrivateOutput; + typedef ShamirShare Honest; + + static string type_short() + { + return "M" + super::type_short(); + } + + MaliciousShamirShare() + { + } + template + MaliciousShamirShare(const U& other) : super(other) + { + } +}; + +#endif /* MATH_MALICIOUSSHAMIRSHARE_H_ */ diff --git a/Math/ShamirShare.h b/Math/ShamirShare.h new file mode 100644 index 000000000..ec7217cb1 --- /dev/null +++ b/Math/ShamirShare.h @@ -0,0 +1,100 @@ +/* + * ShamirShare.h + * + */ + +#ifndef MATH_SHAMIRSHARE_H_ +#define MATH_SHAMIRSHARE_H_ + +#include "gfp.h" +#include "gf2n.h" +#include "Processor/Shamir.h" +#include "Processor/ShamirInput.h" + +template +class ShamirShare : public T +{ +public: + typedef T clear; + + typedef Shamir Protocol; + typedef ShamirMC MAC_Check; + typedef MAC_Check Direct_MC; + typedef ShamirInput Input; + typedef ReplicatedPrivateOutput PrivateOutput; + + static string type_short() + { + return "S" + string(1, clear::type_char()); + } + static string type_string() + { + return "Shamir " + T::type_string(); + } + + ShamirShare() + { + } + template + ShamirShare(const U& other) + { + T::operator=(other); + } + template + ShamirShare(const U& other, int my_num) : ShamirShare(other) + { + (void) my_num; + } + + // Share compatibility + void assign(clear other, int my_num, const T& alphai) + { + (void)alphai, (void)my_num; + *this = other; + } + void assign(const char* buffer) + { + T::assign(buffer); + } + + void add(const ShamirShare& x, const ShamirShare& y) + { + *this = x + y; + } + void sub(const ShamirShare& x, const ShamirShare& y) + { + *this = x - y; + } + + void add(const ShamirShare& S, const clear aa, int my_num, + const T& alphai) + { + (void) my_num, (void) alphai; + *this = S + aa; + } + void sub(const ShamirShare& S, const clear& aa, int my_num, + const T& alphai) + { + (void) my_num, (void) alphai; + *this = S - aa; + } + void sub(const clear& aa, const ShamirShare& S, int my_num, + const T& alphai) + { + (void) my_num, (void) alphai; + *this = aa - S; + } + + void pack(octetStream& os, bool full = true) const + { + (void)full; + T::pack(os); + } + void unpack(octetStream& os, bool full = true) + { + (void)full; + T::unpack(os); + } +}; + +#endif /* MATH_SHAMIRSHARE_H_ */ diff --git a/Math/gf2n.h b/Math/gf2n.h index dd689a9d4..39786de44 100644 --- a/Math/gf2n.h +++ b/Math/gf2n.h @@ -174,6 +174,8 @@ class gf2n_short gf2n_short operator<<(int i) const { gf2n_short res; res.SHL(*this, i); return res; } gf2n_short operator>>(int i) const { gf2n_short res; res.SHR(*this, i); return res; } + gf2n_short& operator>>=(int i) { SHR(*this, i); return *this; } + /* Crap RNG */ void randomize(PRNG& G); // compatibility with gfp diff --git a/Math/gf2nlong.h b/Math/gf2nlong.h index f4ff6bd48..108e7e1eb 100644 --- a/Math/gf2nlong.h +++ b/Math/gf2nlong.h @@ -218,6 +218,8 @@ class gf2n_long gf2n_long operator<<(int i) const { gf2n_long res; res.SHL(*this, i); return res; } gf2n_long operator>>(int i) const { gf2n_long res; res.SHR(*this, i); return res; } + gf2n_long& operator>>=(int i) { SHR(*this, i); return *this; } + /* Crap RNG */ void randomize(PRNG& G); // compatibility with gfp diff --git a/Math/modp.cpp b/Math/modp.cpp index 7f6a46e51..84f38f3ce 100644 --- a/Math/modp.cpp +++ b/Math/modp.cpp @@ -14,12 +14,6 @@ void modp::randomize(PRNG& G, const Zp_Data& ZpD) G.randomBnd(x, ZpD.get_prA(), ZpD.pr_byte_length); } -void modp::pack(octetStream& o,const Zp_Data& ZpD) const -{ - o.append((octet*) x,ZpD.t*sizeof(mp_limb_t)); -} - - void modp::unpack(octetStream& o,const Zp_Data& ZpD) { o.consume((octet*) x,ZpD.t*sizeof(mp_limb_t)); diff --git a/Math/modp.h b/Math/modp.h index 1b9d4be27..7d556fa21 100644 --- a/Math/modp.h +++ b/Math/modp.h @@ -101,6 +101,11 @@ class modp }; +inline void modp::pack(octetStream& o,const Zp_Data& ZpD) const +{ + o.append((octet*) x,ZpD.t*sizeof(mp_limb_t)); +} + inline void assignZero(modp& x,const Zp_Data& ZpD) { if (sizeof(x.x) <= 3 * 16) diff --git a/Networking/CryptoPlayer.cpp b/Networking/CryptoPlayer.cpp index 9c0e71ac5..d7051fffe 100644 --- a/Networking/CryptoPlayer.cpp +++ b/Networking/CryptoPlayer.cpp @@ -6,13 +6,35 @@ #include "CryptoPlayer.h" #include "Math/Setup.h" +void check_ssl_file(string filename) +{ + if (not ifstream(filename)) + throw runtime_error("Cannot access " + filename + + ". Have you set up SSL?\n" + "You can use `Scripts/setup-ssl.sh `."); +} + +void ssl_error(string side, string pronoun, int other, int server) +{ + cerr << side << "-side handshake with party " << other + << " failed. Make sure " << pronoun + << " have the necessary certificate (" << PREP_DIR "P" << server + << ".pem in the default configuration)," + << " and run `c_rehash ` on its location." << endl; +} + CryptoPlayer::CryptoPlayer(const Names& Nms, int id_base) : MultiPlayer(Nms, id_base), plaintext_player(Nms, id_base), ctx(boost::asio::ssl::context::tlsv12) { string prefix = PREP_DIR "P" + to_string(my_num()); - ctx.use_certificate_file(prefix + ".pem", ctx.pem); - ctx.use_private_key_file(prefix + ".key", ctx.pem); + string cert_file = prefix + ".pem"; + string key_file = prefix + ".key"; + check_ssl_file(cert_file); + check_ssl_file(key_file); + + ctx.use_certificate_file(cert_file, ctx.pem); + ctx.use_private_key_file(key_file, ctx.pem); ctx.add_verify_path("Player-Data"); sockets.resize(num_players()); @@ -30,9 +52,25 @@ CryptoPlayer::CryptoPlayer(const Names& Nms, int id_base) : sockets[i]->set_verify_mode(boost::asio::ssl::verify_peer); sockets[i]->set_verify_callback(boost::asio::ssl::rfc2818_verification("P" + to_string(i))); if (i < my_num()) - sockets[i]->handshake(ssl_socket::client); + try + { + sockets[i]->handshake(ssl_socket::client); + } + catch (...) + { + ssl_error("Client", "we", i, i); + throw; + } if (i > my_num()) - sockets[i]->handshake(ssl_socket::server); + try + { + sockets[i]->handshake(ssl_socket::server); + } + catch (...) + { + ssl_error("Server", "they", i, my_num()); + throw; + } } } diff --git a/Networking/Player.cpp b/Networking/Player.cpp index 8c7cbb3f4..d398d824c 100644 --- a/Networking/Player.cpp +++ b/Networking/Player.cpp @@ -371,6 +371,8 @@ void MultiPlayer::Broadcast_Receive(vector& o,bool donthash) con void Player::Check_Broadcast() const { + if (ctx.size == 0) + return; octet hashVal[HASH_SIZE]; vector h(nplayers); blk_SHA1_Final(hashVal,&ctx); diff --git a/Processor/Data_Files.cpp b/Processor/Data_Files.cpp index 25f265bf9..dff1c2a0b 100644 --- a/Processor/Data_Files.cpp +++ b/Processor/Data_Files.cpp @@ -5,8 +5,16 @@ #include "Processor/MaliciousRepPrep.h" #include "GC/MaliciousRepSecret.h" #include "Math/MaliciousRep3Share.h" +#include "Math/ShamirShare.h" +#include "Math/MaliciousShamirShare.h" #include "Processor/MaliciousRepPrep.hpp" +#include "Processor/Replicated.hpp" +#include "Processor/ReplicatedPrep.hpp" +#include "Processor/Input.hpp" +#include "Processor/ReplicatedInput.hpp" +#include "Processor/Shamir.hpp" +#include "Auth/MaliciousShamirMC.hpp" #include #include @@ -53,6 +61,26 @@ const bool Sub_Data_Files::implemented[N_DTYPE] = { true, false, true, false, false, false } ; +template<> +const bool Sub_Data_Files>::implemented[N_DTYPE] = + { false, false, false, false, false, false } +; + +template<> +const bool Sub_Data_Files>::implemented[N_DTYPE] = + { false, false, false, false, false, false } +; + +template<> +const bool Sub_Data_Files>::implemented[N_DTYPE] = + { false, false, false, false, false, false } +; + +template<> +const bool Sub_Data_Files>::implemented[N_DTYPE] = + { false, false, false, false, false, false } +; + const int DataPositions::tuple_size[N_DTYPE] = { 3, 2, 1, 2, 3, 3 }; template @@ -61,67 +89,89 @@ template map Sub_Data_Files::tuple_lengths; template<> -template<> -Preprocessing>* Preprocessing>::get_new( - Machine, Rep3Share>& machine, DataPositions& usage) +Preprocessing>* Preprocessing>::get_live_prep( + SubProcessor>* proc) { - if (machine.live_prep) - return new ReplicatedPrep>; - else - return new Sub_Data_Files>(machine.get_N(), machine.prep_dir_prefix, usage); + return new ReplicatedPrep>(proc); } template<> +Preprocessing>* Preprocessing>::get_live_prep( + SubProcessor>* proc) +{ + return new ReplicatedPrep>(proc); +} + template<> -Preprocessing>* Preprocessing>::get_new( - Machine, Rep3Share>& machine, DataPositions& usage) +Preprocessing>* Preprocessing>::get_live_prep( + SubProcessor>* proc) { - if (machine.live_prep) - return new ReplicatedPrep>; - else - return new Sub_Data_Files>(machine.get_N(), machine.prep_dir_prefix, usage); + return new ReplicatedRingPrep>(proc); } template<> +Preprocessing>* Preprocessing>::get_live_prep( + SubProcessor>* proc) +{ + (void) proc; + return new MaliciousRepPrep>(proc); +} + template<> -Preprocessing>* Preprocessing>::get_new( - Machine, Rep3Share>& machine, DataPositions& usage) +Preprocessing>* Preprocessing>::get_live_prep( + SubProcessor>* proc) { - if (machine.live_prep) - return new ReplicatedRingPrep>; - else - return new Sub_Data_Files>(machine.get_N(), machine.prep_dir_prefix, usage); + (void) proc; + return new MaliciousRepPrep>(proc); } template<> +Preprocessing>* Preprocessing>::get_live_prep( + SubProcessor>* proc) +{ + return new ReplicatedPrep>(proc); +} + template<> -Preprocessing>* Preprocessing>::get_new( - Machine, MaliciousRep3Share>& machine, DataPositions& usage) +Preprocessing>* Preprocessing>::get_live_prep( + SubProcessor>* proc) { - if (machine.live_prep) - return new MaliciousRepPrep; - else - return new Sub_Data_Files>(machine.get_N(), machine.prep_dir_prefix, usage); + return new ReplicatedPrep>(proc); } template<> +Preprocessing>* Preprocessing>::get_live_prep( + SubProcessor>* proc) +{ + (void) proc; + return new MaliciousRepPrep>(proc); +} + template<> -Preprocessing>* Preprocessing>::get_new( - Machine, MaliciousRep3Share>& machine, DataPositions& usage) +Preprocessing>* Preprocessing>::get_live_prep( + SubProcessor>* proc) { - if (machine.live_prep) - return new MaliciousRepPrep; - else - return new Sub_Data_Files>(machine.get_N(), machine.prep_dir_prefix, usage); + (void) proc; + return new MaliciousRepPrep>(proc); } +template +Preprocessing* Preprocessing::get_live_prep(SubProcessor* proc) +{ + (void) proc; + throw not_implemented(); +} template template -Preprocessing* Preprocessing::get_new(Machine& machine, - DataPositions& usage) +Preprocessing* Preprocessing::get_new( + Machine& machine, + DataPositions& usage, SubProcessor* proc) { - return new Sub_Data_Files(machine.get_N(), machine.prep_dir_prefix, usage); + if (machine.live_prep) + return get_live_prep(proc); + else + return new Sub_Data_Files(machine.get_N(), machine.prep_dir_prefix, usage); } void DataPositions::set_num_players(int num_players) @@ -246,11 +296,19 @@ Sub_Data_Files::Sub_Data_Files(int my_num, int num_players, } template -Data_Files::Data_Files(Machine& machine) : +Data_Files::Data_Files(Machine& machine, SubProcessor* procp, + SubProcessor* proc2) : usage(machine.get_N().num_players()), - DataFp(*Preprocessing::get_new(machine, usage)), - DataF2(*Preprocessing::get_new(machine, usage)) + DataFp(*Preprocessing::get_new(machine, usage, procp)), + DataF2(*Preprocessing::get_new(machine, usage, proc2)) +{ +} + +template +Data_Files::~Data_Files() { + delete &DataFp; + delete &DataF2; } template @@ -393,3 +451,5 @@ template class Data_Files>; template class Data_Files, Rep3Share>; template class Data_Files, Rep3Share>; template class Data_Files, MaliciousRep3Share>; +template class Data_Files, ShamirShare>; +template class Data_Files, MaliciousShamirShare>; diff --git a/Processor/Data_Files.h b/Processor/Data_Files.h index 3ed16f825..7186017d5 100644 --- a/Processor/Data_Files.h +++ b/Processor/Data_Files.h @@ -69,7 +69,9 @@ class Preprocessing { public: template - static Preprocessing* get_new(Machine& machine, DataPositions& usage); + static Preprocessing* get_new(Machine& machine, DataPositions& usage, + SubProcessor* proc); + static Preprocessing* get_live_prep(SubProcessor* proc); virtual ~Preprocessing() {} @@ -179,7 +181,9 @@ class Data_Files Preprocessing& DataFp; Preprocessing& DataF2; - Data_Files(Machine& machine); + Data_Files(Machine& machine, SubProcessor* procp = 0, + SubProcessor* proc2 = 0); + ~Data_Files(); DataPositions tellg(); void seekg(DataPositions& pos); diff --git a/Processor/DummyProtocol.h b/Processor/DummyProtocol.h index 2a574ba88..bf38a542e 100644 --- a/Processor/DummyProtocol.h +++ b/Processor/DummyProtocol.h @@ -6,8 +6,13 @@ #ifndef PROCESSOR_DUMMYPROTOCOL_H_ #define PROCESSOR_DUMMYPROTOCOL_H_ +#include +using namespace std; + class Player; +template class SubProcessor; + class DummyMC { public: @@ -26,4 +31,40 @@ class DummyProtocol } }; +class NotImplementedInput +{ +public: + template + NotImplementedInput(T& proc, U& MC) + { + (void) proc, (void) MC; + } + void start(int n, vector regs) + { + (void) n, (void) regs; + throw not_implemented(); + } + void stop(int n, vector regs) + { + (void) n, (void) regs; + throw not_implemented(); + } + void start(int n, int m) + { + (void) n, (void) m; + throw not_implemented(); + } + void stop(int n, int m) + { + (void) n, (void) m; + throw not_implemented(); + } + template + static void input(SubProcessor& proc, vector regs) + { + (void) proc, (void) regs; + throw not_implemented(); + } +}; + #endif /* PROCESSOR_DUMMYPROTOCOL_H_ */ diff --git a/Processor/Input.h b/Processor/Input.h index 8722daeef..5f5054846 100644 --- a/Processor/Input.h +++ b/Processor/Input.h @@ -27,7 +27,7 @@ class InputBase static void input(SubProcessor& Proc, const vector& args); - InputBase(ArithmeticProcessor& proc); + InputBase(ArithmeticProcessor* proc); ~InputBase(); }; diff --git a/Processor/Input.hpp b/Processor/Input.hpp index c6a2fbcaa..0eb98f7ae 100644 --- a/Processor/Input.hpp +++ b/Processor/Input.hpp @@ -8,15 +8,16 @@ #include "Auth/MAC_Check.h" template -InputBase::InputBase(ArithmeticProcessor& proc) : +InputBase::InputBase(ArithmeticProcessor* proc) : values_input(0) { - buffer.setup(&proc.private_input, -1, proc.private_input_filename); + if (proc) + buffer.setup(&proc->private_input, -1, proc->private_input_filename); } template Input::Input(SubProcessor>& proc, MAC_Check& mc) : - InputBase>(proc.Proc), proc(proc), MC(mc), shares(proc.P.num_players()) + InputBase>(&proc.Proc), proc(proc), MC(mc), shares(proc.P.num_players()) { } diff --git a/Processor/Instruction.cpp b/Processor/Instruction.cpp index ea0d1a6d6..a73773f29 100644 --- a/Processor/Instruction.cpp +++ b/Processor/Instruction.cpp @@ -7,12 +7,19 @@ #include "Tools/parse.h" #include "Auth/ReplicatedMC.h" #include "Math/MaliciousRep3Share.h" +#include "Math/ShamirShare.h" +#include "Auth/ShamirMC.h" +#include "Math/MaliciousShamirShare.h" #include "Processor/Processor.hpp" #include "Processor/Binary_File_IO.hpp" #include "Processor/Input.hpp" #include "Processor/Beaver.hpp" +#include "Processor/Shamir.hpp" +#include "Processor/ShamirInput.hpp" +#include "Processor/Replicated.hpp" #include "Auth/MaliciousRepMC.hpp" +#include "Auth/ShamirMC.hpp" #include #include @@ -1699,3 +1706,5 @@ template void Program::execute(Processor>& Proc) const; template void Program::execute(Processor, Rep3Share>& Proc) const; template void Program::execute(Processor, Rep3Share>& Proc) const; template void Program::execute(Processor, MaliciousRep3Share>& Proc) const; +template void Program::execute(Processor, ShamirShare>& Proc) const; +template void Program::execute(Processor, MaliciousShamirShare>& Proc) const; diff --git a/Processor/Machine.cpp b/Processor/Machine.cpp index a07bd71f3..cf64261a4 100644 --- a/Processor/Machine.cpp +++ b/Processor/Machine.cpp @@ -2,6 +2,11 @@ #include "Memory.hpp" #include "Online-Thread.hpp" +#include "ShamirInput.hpp" +#include "Shamir.hpp" +#include "Replicated.hpp" +#include "Auth/ShamirMC.hpp" +#include "Auth/MaliciousShamirMC.hpp" #include "Exceptions/Exceptions.h" @@ -9,6 +14,8 @@ #include "Math/Setup.h" #include "Math/MaliciousRep3Share.h" +#include "Math/ShamirShare.h" +#include "Math/MaliciousShamirShare.h" #include #include @@ -61,6 +68,7 @@ Machine::Machine(int my_number, Names& playerNames, int nn; sprintf(filename, (prep_dir_prefix + "Player-MAC-Keys-P%d").c_str(), my_number); + ifstream inpf; inpf.open(filename); if (inpf.fail()) { @@ -87,6 +95,10 @@ Machine::Machine(int my_number, Names& playerNames, sint::clear::init_default(opts.lgp); gf2n::init_field(gf2n::default_degree()); } + catch (end_of_file& e) + { + cerr << "End of file reading MAC key but maybe we don't need it" << endl; + } // Initialize the global memory if (memtype.compare("new")==0) @@ -438,3 +450,5 @@ template class Machine>; template class Machine, Rep3Share>; template class Machine, Rep3Share>; template class Machine, MaliciousRep3Share>; +template class Machine, ShamirShare>; +template class Machine, MaliciousShamirShare>; diff --git a/Processor/MaliciousRepPrep.h b/Processor/MaliciousRepPrep.h index 8fb40734c..d91e8b723 100644 --- a/Processor/MaliciousRepPrep.h +++ b/Processor/MaliciousRepPrep.h @@ -13,15 +13,14 @@ #include -template -class MaliciousRepPrep : public BufferPrep> +template +class MaliciousRepPrep : public BufferPrep { - typedef MaliciousRep3Share T; - typedef BufferPrep> super; + typedef BufferPrep super; - ReplicatedPrep> honest_prep; - Replicated>* replicated; - HashMaliciousRepMC MC; + ReplicatedPrep honest_prep; + typename T::Honest::Protocol* replicated; + typename T::MAC_Check MC; vector masked; vector checks; @@ -38,7 +37,7 @@ class MaliciousRepPrep : public BufferPrep> void buffer_bits(); public: - MaliciousRepPrep(); + MaliciousRepPrep(SubProcessor* proc); ~MaliciousRepPrep(); void set_protocol(Beaver& protocol); diff --git a/Processor/MaliciousRepPrep.hpp b/Processor/MaliciousRepPrep.hpp index 2f43983be..de1130693 100644 --- a/Processor/MaliciousRepPrep.hpp +++ b/Processor/MaliciousRepPrep.hpp @@ -7,9 +7,11 @@ #include "Auth/Subroutines.h" #include "Auth/MaliciousRepMC.hpp" -template -MaliciousRepPrep::MaliciousRepPrep() : replicated(0) +template +MaliciousRepPrep::MaliciousRepPrep(SubProcessor* proc) : + honest_prep(0), replicated(0) { + (void) proc; } template @@ -19,10 +21,10 @@ MaliciousRepPrep::~MaliciousRepPrep() delete replicated; } -template -void MaliciousRepPrep::set_protocol(Beaver& protocol) +template +void MaliciousRepPrep::set_protocol(Beaver& protocol) { - replicated = new Replicated>(protocol.P); + replicated = new typename T::Honest::Protocol(protocol.P); honest_prep.set_protocol(*replicated); } @@ -35,8 +37,8 @@ void MaliciousRepPrep::clear_tmp() check_squares.clear(); } -template -void MaliciousRepPrep::buffer_triples() +template +void MaliciousRepPrep::buffer_triples() { auto& triples = this->triples; auto& buffer_size = this->buffer_size; @@ -80,8 +82,8 @@ void MaliciousRepPrep::buffer_triples() MC.Check(P); } -template -void MaliciousRepPrep::buffer_squares() +template +void MaliciousRepPrep::buffer_squares() { auto& squares = this->squares; auto& buffer_size = this->buffer_size; @@ -120,14 +122,14 @@ void MaliciousRepPrep::buffer_squares() throw Offline_Check_Error("square"); } -template -void MaliciousRepPrep::buffer_inverses() +template +void MaliciousRepPrep::buffer_inverses() { BufferPrep::buffer_inverses(MC, honest_prep.protocol->P); } -template -void MaliciousRepPrep::buffer_bits() +template +void MaliciousRepPrep::buffer_bits() { auto& bits = this->bits; auto& buffer_size = this->buffer_size; diff --git a/Processor/Online-Thread.hpp b/Processor/Online-Thread.hpp index 4c1d31ef6..91b8539ac 100644 --- a/Processor/Online-Thread.hpp +++ b/Processor/Online-Thread.hpp @@ -6,6 +6,7 @@ #include "Processor/Machine.h" #include "Processor/Processor.h" #include "Auth/ReplicatedMC.h" +#include "Auth/ShamirMC.h" #include "Networking/CryptoPlayer.h" #include "Processor/Processor.hpp" @@ -49,8 +50,6 @@ void* Sub_Main_Func(void* ptr) Player& P = *player; fprintf(stderr, "\tSet up player in thread %d\n",num); - Data_Files DataF(machine); - typename sgf2n::MAC_Check* MC2; typename sint::MAC_Check* MCp; @@ -76,7 +75,7 @@ void* Sub_Main_Func(void* ptr) } // Allocate memory for first program before starting the clock - Processor Proc(tinfo->thread_num,DataF,P,*MC2,*MCp,machine,progs[0]); + Processor Proc(tinfo->thread_num,P,*MC2,*MCp,machine,progs[0]); Share a,b,c; bool flag=true; @@ -115,7 +114,7 @@ void* Sub_Main_Func(void* ptr) Proc.reset(progs[program],tinfo->arg); // Bits, Triples, Squares, and Inverses skipping - DataF.seekg(tinfo->pos); + Proc.DataF.seekg(tinfo->pos); //printf("\tExecuting program"); // Execute the program @@ -123,7 +122,7 @@ void* Sub_Main_Func(void* ptr) if (progs[program].usage_unknown()) { // communicate file positions to main thread - tinfo->pos = DataF.get_usage(); + tinfo->pos = Proc.DataF.get_usage(); } //double elapsed = timeval_diff(&startv, &endv); diff --git a/Processor/Processor.h b/Processor/Processor.h index 87df4b958..2bb739c48 100644 --- a/Processor/Processor.h +++ b/Processor/Processor.h @@ -41,7 +41,7 @@ class SubProcessor template friend class Processor; template friend class SPDZ; - template friend class Replicated; + template friend class PrepLessProtocol; template friend class Beaver; public: @@ -128,7 +128,7 @@ class Processor : public ArithmeticProcessor vector& get_PO(); public: - Data_Files& DataF; + Data_Files DataF; Player& P; typename sgf2n::MAC_Check& MC2; typename sint::MAC_Check& MCp; @@ -158,7 +158,7 @@ class Processor : public ArithmeticProcessor void reset(const Program& program,int arg); // Reset the state of the processor string get_filename(const char* basename, bool use_number); - Processor(int thread_num,Data_Files& DataF,Player& P, + Processor(int thread_num,Player& P, typename sgf2n::MAC_Check& MC2,typename sint::MAC_Check& MCp, Machine& machine, const Program& program); diff --git a/Processor/Processor.hpp b/Processor/Processor.hpp index 89985876a..6698c2190 100644 --- a/Processor/Processor.hpp +++ b/Processor/Processor.hpp @@ -20,11 +20,11 @@ SubProcessor::SubProcessor(ArithmeticProcessor& Proc, typename T::MAC_Check& } template -Processor::Processor(int thread_num,Data_Files& DataF,Player& P, +Processor::Processor(int thread_num,Player& P, typename sgf2n::MAC_Check& MC2,typename sint::MAC_Check& MCp, Machine& machine, const Program& program) -: ArithmeticProcessor(machine.opts, thread_num),DataF(DataF),P(P), +: ArithmeticProcessor(machine.opts, thread_num),DataF(machine, &Procp, &Proc2),P(P), MC2(MC2),MCp(MCp),machine(machine), Proc2(*this,MC2,DataF.DataF2,P),Procp(*this,MCp,DataF.DataFp,P), privateOutput2(Proc2),privateOutputp(Procp), diff --git a/Processor/Replicated.h b/Processor/Replicated.h index 33c27a07e..5ab70c188 100644 --- a/Processor/Replicated.h +++ b/Processor/Replicated.h @@ -20,6 +20,7 @@ template class ReplicatedInput; template class ReplicatedPrivateOutput; template class Share; template class Rep3Share; +template class MAC_Check_Base; class ReplicatedBase { @@ -32,19 +33,36 @@ class ReplicatedBase }; template -class Replicated : public ReplicatedBase +class PrepLessProtocol { - vector os; - deque add_shares; int counter; +public: + PrepLessProtocol(); + virtual ~PrepLessProtocol(); + + void muls(const vector& reg, SubProcessor& proc, MAC_Check_Base& MC, + int size); + + virtual void init_mul(SubProcessor* proc) = 0; + virtual typename T::clear prepare_mul(const T& x, const T& y) = 0; + virtual void exchange() = 0; + virtual T finalize_mul() = 0; + + virtual T get_random() = 0; +}; + +template +class Replicated : public ReplicatedBase, public PrepLessProtocol +{ + vector os; + deque add_shares; public: typedef ReplicatedMC MAC_Check; typedef ReplicatedInput Input; typedef ReplicatedPrivateOutput PrivateOutput; Replicated(Player& P); - ~Replicated(); static void assign(T& share, const typename T::clear& value, int my_num) { @@ -54,9 +72,7 @@ class Replicated : public ReplicatedBase share[my_num] = value; } - void muls(const vector& reg, SubProcessor& proc, ReplicatedMC& MC, - int size); - + void init_mul(SubProcessor* proc); void init_mul(); typename T::clear prepare_mul(const T& x, const T& y); void exchange(); diff --git a/Processor/Replicated.cpp b/Processor/Replicated.hpp similarity index 78% rename from Processor/Replicated.cpp rename to Processor/Replicated.hpp index 87314c101..10722f227 100644 --- a/Processor/Replicated.cpp +++ b/Processor/Replicated.hpp @@ -8,16 +8,22 @@ #include "Math/FixedVec.h" #include "Math/Integer.h" #include "Math/MaliciousRep3Share.h" +#include "Math/ShamirShare.h" #include "Tools/benchmarking.h" #include "GC/ReplicatedSecret.h" template -Replicated::Replicated(Player& P) : ReplicatedBase(P), counter(0) +PrepLessProtocol::PrepLessProtocol() : counter(0) +{ +} + +template +Replicated::Replicated(Player& P) : ReplicatedBase(P) { assert(T::length == 2); } -ReplicatedBase::ReplicatedBase(Player& P) : P(P) +inline ReplicatedBase::ReplicatedBase(Player& P) : P(P) { assert(P.num_players() == 3); if (not P.is_encrypted()) @@ -32,21 +38,21 @@ ReplicatedBase::ReplicatedBase(Player& P) : P(P) } template -inline Replicated::~Replicated() +PrepLessProtocol::~PrepLessProtocol() { - cerr << "Number of multiplications: " << counter << endl; + if (counter) + cerr << "Number of multiplications: " << counter << endl; } template -void Replicated::muls(const vector& reg, - SubProcessor& proc, ReplicatedMC& MC, int size) +void PrepLessProtocol::muls(const vector& reg, + SubProcessor& proc, MAC_Check_Base& MC, int size) { (void)MC; - assert(T::length == 2); assert(reg.size() % 3 == 0); int n = reg.size() / 3; - init_mul(); + init_mul(&proc); for (int i = 0; i < n; i++) for (int j = 0; j < size; j++) { @@ -64,6 +70,13 @@ void Replicated::muls(const vector& reg, counter += n * size; } +template +void Replicated::init_mul(SubProcessor* proc) +{ + (void) proc; + init_mul(); +} + template void Replicated::init_mul() { @@ -112,9 +125,3 @@ T Replicated::get_random() res[i].randomize(shared_prngs[i]); return res; } - -template class Replicated>; -template class Replicated>; -template class Replicated>; -template class Replicated>; -template class Replicated>; diff --git a/Processor/ReplicatedInput.h b/Processor/ReplicatedInput.h index e434b700f..929db4126 100644 --- a/Processor/ReplicatedInput.h +++ b/Processor/ReplicatedInput.h @@ -9,26 +9,59 @@ #include "Input.h" template -class ReplicatedInput : public InputBase +class PrepLessInput : public InputBase { - SubProcessor& proc; +protected: + SubProcessor* processor; vector shares; + size_t i_share; + +public: + PrepLessInput(SubProcessor* proc) : + InputBase(proc ? &proc->Proc : 0), processor(proc), i_share(0) {} + virtual ~PrepLessInput() {} + + void start(int player, int n_inputs); + void stop(int player, vector targets); + + virtual void reset(int player) = 0; + virtual void add_mine(const typename T::clear& input) = 0; + virtual void add_other(int player) = 0; + virtual void send_mine() = 0; + virtual void finalize_other(int player, T& target, octetStream& o) = 0; + + T finalize_mine(); +}; + +template +class ReplicatedInput : public PrepLessInput +{ + SubProcessor* proc; + Player& P; vector os; + SeededPRNG secure_prng; public: + ReplicatedInput(SubProcessor& proc) : + PrepLessInput(&proc), proc(&proc), P(proc.P) + { + assert(T::length == 2); + } ReplicatedInput(SubProcessor& proc, ReplicatedMC& MC) : - InputBase(proc.Proc), proc(proc) + ReplicatedInput(proc) { (void) MC; } + ReplicatedInput(SubProcessor* proc, Player& P) : + PrepLessInput(proc), proc(proc), P(P) + { + } void reset(int player); void add_mine(const typename T::clear& input); void add_other(int player); void send_mine(); - - void start(int player, int n_inputs); - void stop(int player, vector targets); + void finalize_other(int player, T& target, octetStream& o); }; #endif /* PROCESSOR_REPLICATEDINPUT_H_ */ diff --git a/Processor/ReplicatedInput.hpp b/Processor/ReplicatedInput.hpp index af076b02a..e7033fce9 100644 --- a/Processor/ReplicatedInput.hpp +++ b/Processor/ReplicatedInput.hpp @@ -10,9 +10,10 @@ template void ReplicatedInput::reset(int player) { - if (player == proc.P.my_num()) + if (player == P.my_num()) { - shares.clear(); + this->shares.clear(); + this->i_share = 0; os.resize(2); for (auto& o : os) o.reset_write_head(); @@ -22,9 +23,10 @@ void ReplicatedInput::reset(int player) template void ReplicatedInput::add_mine(const typename T::clear& input) { + auto& shares = this->shares; shares.push_back({}); T& my_share = shares.back(); - my_share[0].randomize(proc.Proc.secure_prng); + my_share[0].randomize(secure_prng); my_share[1] = input - my_share[0]; for (int j = 0; j < 2; j++) { @@ -42,14 +44,14 @@ void ReplicatedInput::add_other(int player) template void ReplicatedInput::send_mine() { - proc.P.send_relative(os); + P.send_relative(os); } template -void ReplicatedInput::start(int player, int n_inputs) +void PrepLessInput::start(int player, int n_inputs) { - assert(T::length == 2); - + assert(processor != 0); + auto& proc = *processor; reset(player); if (player == proc.P.my_num()) @@ -66,12 +68,14 @@ void ReplicatedInput::start(int player, int n_inputs) } template -void ReplicatedInput::stop(int player, vector targets) +void PrepLessInput::stop(int player, vector targets) { + assert(processor != 0); + auto& proc = *processor; if (proc.P.my_num() == player) { for (unsigned int i = 0; i < targets.size(); i++) - proc.get_S_ref(targets[i]) = shares[i]; + proc.get_S_ref(targets[i]) = finalize_mine(); } else { @@ -80,14 +84,25 @@ void ReplicatedInput::stop(int player, vector targets) proc.P.receive_player(player, o, true); this->timer.stop(); for (unsigned int i = 0; i < targets.size(); i++) - { - typename T::value_type t; - t.unpack(o); - int j = proc.P.get_offset(player) == 2; - T share; - share[j] = t; - share[1 - j] = 0; - this->proc.get_S_ref(targets[i]) = share; - } + finalize_other(player, proc.get_S_ref(targets[i]), o); } } + +template +void ReplicatedInput::finalize_other(int player, T& target, + octetStream& o) +{ + typename T::value_type t; + t.unpack(o); + int j = P.get_offset(player) == 2; + T share; + share[j] = t; + share[1 - j] = 0; + target = share; +} + +template +T PrepLessInput::finalize_mine() +{ + return this->shares[this->i_share++]; +} diff --git a/Processor/ReplicatedMachine.h b/Processor/ReplicatedMachine.h index a373112d0..b20530217 100644 --- a/Processor/ReplicatedMachine.h +++ b/Processor/ReplicatedMachine.h @@ -13,7 +13,8 @@ template class ReplicatedMachine { public: - ReplicatedMachine(int argc, const char** argv, string name); + ReplicatedMachine(int argc, const char** argv, string name, + ez::ezOptionParser& opt, int nplayers = 3); }; #endif /* PROCESSOR_REPLICATEDMACHINE_H_ */ diff --git a/Processor/ReplicatedMachine.hpp b/Processor/ReplicatedMachine.hpp index 1af471aef..5a8ead25c 100644 --- a/Processor/ReplicatedMachine.hpp +++ b/Processor/ReplicatedMachine.hpp @@ -12,9 +12,8 @@ template ReplicatedMachine::ReplicatedMachine(int argc, const char** argv, - string name) + string name, ez::ezOptionParser& opt, int nplayers) { - ez::ezOptionParser opt; OnlineOptions online_opts(opt, argc, argv); opt.add( "localhost", // Default. @@ -89,7 +88,7 @@ ReplicatedMachine::ReplicatedMachine(int argc, const char** argv, if (not use_encryption) insecure("unencrypted communication"); Names N; - Server* server = Server::start_networking(N, playerno, 3, hostname, pnb); + Server* server = Server::start_networking(N, playerno, nplayers, hostname, pnb); Machine(playerno, N, progname, "empty", gf2n::default_degree(), 0, 0, 0, 0, 0, use_encryption, diff --git a/Processor/ReplicatedPrep.h b/Processor/ReplicatedPrep.h index 890aa5d77..7b06c02df 100644 --- a/Processor/ReplicatedPrep.h +++ b/Processor/ReplicatedPrep.h @@ -15,8 +15,6 @@ template class BufferPrep : public Preprocessing { protected: - static const int buffer_size = 1000; - vector> triples; vector> squares; vector> inverses; @@ -30,6 +28,8 @@ class BufferPrep : public Preprocessing virtual void buffer_inverses(MAC_Check_Base& MC, Player& P); public: + static const int buffer_size = 1000; + virtual ~BufferPrep() {} void get_three(Dtype dtype, T& a, T& b, T& c); @@ -46,23 +46,31 @@ class ReplicatedRingPrep : public BufferPrep protected: template friend class MaliciousRepPrep; - Replicated* protocol; + typename T::Protocol* protocol; + SubProcessor* proc; void buffer_triples(); void buffer_squares(); void buffer_inverses() { throw runtime_error("not inverses in rings"); } - void buffer_bits(); public: - ReplicatedRingPrep(); + ReplicatedRingPrep(SubProcessor* proc); + virtual ~ReplicatedRingPrep() {} - void set_protocol(Replicated& protocol) { this->protocol = &protocol; } + void set_protocol(typename T::Protocol& protocol) { this->protocol = &protocol; } + + virtual void buffer_bits(); }; template class ReplicatedPrep: public ReplicatedRingPrep { void buffer_inverses(); + +public: + ReplicatedPrep(SubProcessor* proc = 0) : ReplicatedRingPrep(proc) {} + + void buffer_bits(); }; #endif /* PROCESSOR_REPLICATEDPREP_H_ */ diff --git a/Processor/ReplicatedPrep.cpp b/Processor/ReplicatedPrep.hpp similarity index 56% rename from Processor/ReplicatedPrep.cpp rename to Processor/ReplicatedPrep.hpp index 74070e064..19b7597b9 100644 --- a/Processor/ReplicatedPrep.cpp +++ b/Processor/ReplicatedPrep.hpp @@ -7,9 +7,11 @@ #include "Math/gfp.h" #include "Math/MaliciousRep3Share.h" #include "Auth/ReplicatedMC.h" +#include "Auth/ShamirMC.h" template -ReplicatedRingPrep::ReplicatedRingPrep() : protocol(0) +ReplicatedRingPrep::ReplicatedRingPrep(SubProcessor* proc) : + protocol(0), proc(proc) { } @@ -19,7 +21,7 @@ void ReplicatedRingPrep::buffer_triples() assert(protocol != 0); auto& triples = this->triples; triples.resize(this->buffer_size); - protocol->init_mul(); + protocol->init_mul(proc); for (size_t i = 0; i < triples.size(); i++) { auto& triple = triples[i]; @@ -53,7 +55,7 @@ void ReplicatedRingPrep::buffer_squares() assert(protocol != 0); auto& squares = this->squares; squares.resize(this->buffer_size); - protocol->init_mul(); + protocol->init_mul(proc); for (size_t i = 0; i < squares.size(); i++) { auto& square = squares[i]; @@ -70,7 +72,7 @@ void ReplicatedPrep::buffer_inverses() { auto protocol = this->protocol; assert(protocol != 0); - ReplicatedMC MC; + typename T::MAC_Check MC; BufferPrep::buffer_inverses(MC, protocol->P); } @@ -126,60 +128,96 @@ void BufferPrep::get_two(Dtype dtype, T& a, T& b) } template -void ReplicatedRingPrep::buffer_bits() +void XOR(vector& res, vector& x, vector& y, int buffer_size, + typename T::Protocol& prot, SubProcessor* proc) { - assert(protocol != 0); -#ifdef BIT_BY_SQUARE - vector, 2>> squares(buffer_size); - vector> s; + prot.init_mul(proc); for (int i = 0; i < buffer_size; i++) + prot.prepare_mul(x[i], y[i]); + prot.exchange(); + res.resize(buffer_size); + typename T::clear two = typename T::clear(1) + typename T::clear(1); + for (int i = 0; i < buffer_size; i++) + res[i] = x[i] + y[i] - prot.finalize_mul() * two; +} + +int get_n_relevant_players(Player& P) +{ + int n_relevant_players = P.num_players(); + try { - get_two(DATA_SQUARE, squares[i][0], squares[i][1]); - s.push_back(squares[i][1]); + n_relevant_players = ShamirMachine::s().threshold + 1; } - vector open; - ReplicatedMC>().POpen(open, s, protocol->P); - auto one = Rep3Share(1, protocol->P.my_num()); - for (size_t i = 0; i < s.size(); i++) - if (open[i] != 0) - bits.push_back((squares[i][0] / open[i].sqrRoot() + one) / 2); - squares.clear(); - if (bits.empty()) - throw runtime_error("squares were all zero"); -#else + catch (...) + { + } + return n_relevant_players; +} + +template class T> +void buffer_bits_spec(ReplicatedPrep>& prep, vector>& bits, + typename T::Protocol& prot) +{ + (void) bits, (void) prot; + if (get_n_relevant_players(prot.P) > 10) + { + vector, 2>> squares(prep.buffer_size); + vector> s; + for (int i = 0; i < prep.buffer_size; i++) + { + prep.get_two(DATA_SQUARE, squares[i][0], squares[i][1]); + s.push_back(squares[i][1]); + } + vector open; + typename T::MAC_Check().POpen(open, s, prot.P); + auto one = T(1, prot.P.my_num()); + for (size_t i = 0; i < s.size(); i++) + if (open[i] != 0) + bits.push_back((squares[i][0] / open[i].sqrRoot() + one) / 2); + squares.clear(); + if (bits.empty()) + throw runtime_error("squares were all zero"); + } + else + prep.ReplicatedRingPrep>::buffer_bits(); +} + +template +void ReplicatedRingPrep::buffer_bits() +{ + assert(protocol != 0); auto buffer_size = this->buffer_size; auto& bits = this->bits; - vector> player_bits(3, vector(buffer_size)); - vector os(2); - SeededPRNG G; - for (auto& share : player_bits[protocol->P.my_num()]) + auto& P = protocol->P; + int n_relevant_players = get_n_relevant_players(P); + vector> player_bits(n_relevant_players, vector(buffer_size)); + typename T::Input input(proc, P); + for (int i = 0; i < n_relevant_players; i++) + input.reset(i); + if (P.my_num() < n_relevant_players) { - share.randomize_to_sum(G.get_bit(), G); - for (int i = 0; i < 2; i++) - share[i].pack(os[i]); + SeededPRNG G; + for (int i = 0; i < buffer_size; i++) + input.add_mine(G.get_bit()); + input.send_mine(); } + for (int i = 0; i < n_relevant_players; i++) + if (i == P.my_num()) + for (auto& x : player_bits[i]) + x = input.finalize_mine(); + else + { + octetStream os; + P.receive_player(i, os, true); + for (auto& x : player_bits[i]) + input.finalize_other(i, x, os); + } auto& prot = *protocol; - prot.P.send_relative(os); - prot.P.receive_relative(os); - for (int i = 0; i < 2; i++) - for (auto& share : player_bits[prot.P.get_player(i + 1)]) - share[i].unpack(os[i]); - prot.init_mul(); - for (int i = 0; i < buffer_size; i++) - prot.prepare_mul(player_bits[0][i], player_bits[1][i]); - prot.exchange(); - vector first_xor(buffer_size); - typename T::clear two(2); - for (int i = 0; i < buffer_size; i++) - first_xor[i] = player_bits[0][i] + player_bits[1][i] - prot.finalize_mul() * two; - prot.init_mul(); - for (int i = 0; i < buffer_size; i++) - prot.prepare_mul(player_bits[2][i], first_xor[i]); - prot.exchange(); - bits.resize(buffer_size); - for (int i = 0; i < buffer_size; i++) - bits[i] = player_bits[2][i] + first_xor[i] - prot.finalize_mul() * two; -#endif + vector tmp; + XOR(tmp, player_bits[0], player_bits[1], buffer_size, prot, proc); + for (int i = 2; i < n_relevant_players - 1; i++) + XOR(tmp, tmp, player_bits[i], buffer_size, prot, proc); + XOR(bits, tmp, player_bits[n_relevant_players - 1], buffer_size, prot, proc); } template<> @@ -197,6 +235,21 @@ void ReplicatedRingPrep>::buffer_bits() } } +template class T> +void buffer_bits_spec(ReplicatedPrep>& prep, vector>& bits, + typename T::Protocol& prot) +{ + (void) bits, (void) prot; + prep.ReplicatedRingPrep>::buffer_bits(); +} + +template +void ReplicatedPrep::buffer_bits() +{ + assert(this->protocol != 0); + buffer_bits_spec(*this, this->bits, *this->protocol); +} + template void BufferPrep::get_one(Dtype dtype, T& a) { @@ -224,13 +277,3 @@ void BufferPrep::get(vector& S, DataTag tag, (void) S, (void) tag, (void) regs, (void) vector_size; throw not_implemented(); } - -template class BufferPrep>; -template class BufferPrep>; -template class BufferPrep>; -template class BufferPrep>; -template class ReplicatedPrep>; -template class ReplicatedPrep>; -template class ReplicatedRingPrep>; -template class ReplicatedRingPrep>; -template class ReplicatedRingPrep>; diff --git a/Processor/Shamir.h b/Processor/Shamir.h new file mode 100644 index 000000000..92735797f --- /dev/null +++ b/Processor/Shamir.h @@ -0,0 +1,60 @@ +/* + * Shamir.h + * + */ + +#ifndef PROCESSOR_SHAMIR_H_ +#define PROCESSOR_SHAMIR_H_ + +#include +using namespace std; + +#include "Replicated.h" + +template class SubProcessor; +template class ShamirMC; +template class ShamirShare; +template class ShamirInput; + +class Player; + +template +class Shamir : public PrepLessProtocol> +{ + typedef ShamirShare T; + + vector os; + vector reconstruction; + U rec_factor; + ShamirInput* resharing; + + SeededPRNG secure_prng; + + vector random; + + void buffer_random(); + + int threshold; + int n_mul_players; + +public: + Player& P; + + static U get_rec_factor(int i, int n); + + Shamir(Player& P); + ~Shamir(); + + void reset(); + + void init_mul(SubProcessor* proc); + U prepare_mul(const T& x, const T& y); + void exchange(); + T finalize_mul(); + + T finalize(int n_input_players); + + T get_random(); +}; + +#endif /* PROCESSOR_SHAMIR_H_ */ diff --git a/Processor/Shamir.hpp b/Processor/Shamir.hpp new file mode 100644 index 000000000..c82b7e93d --- /dev/null +++ b/Processor/Shamir.hpp @@ -0,0 +1,121 @@ +/* + * Shamir.cpp + * + */ + +#include "Shamir.h" +#include "ShamirInput.h" +#include "ShamirMachine.h" + +template +U Shamir::get_rec_factor(int i, int n) +{ + U res = 1; + for (int j = 0; j < n; j++) + if (i != j) + res *= U(j + 1) / (U(j + 1) - U(i + 1)); + return res; +} + +template +Shamir::Shamir(Player& P) : resharing(0), P(P) +{ + threshold = ShamirMachine::s().threshold; + n_mul_players = 2 * threshold + 1; +} + +template +Shamir::~Shamir() +{ + if (resharing != 0) + delete resharing; +} + +template +void Shamir::reset() +{ + os.clear(); + os.resize(P.num_players()); + + if (resharing == 0) + { + resharing = new ShamirInput(0, P); + } + + for (int i = 0; i < P.num_players(); i++) + resharing->reset(i); +} + +template +void Shamir::init_mul(SubProcessor* proc) +{ + (void) proc; + reset(); + if (rec_factor == 0 and P.my_num() < n_mul_players) + rec_factor = get_rec_factor(P.my_num(), n_mul_players); +} + +template +U Shamir::prepare_mul(const T& x, const T& y) +{ + auto add_share = x * y * rec_factor; + if (P.my_num() < n_mul_players) + resharing->add_mine(add_share); + return add_share; +} + +template +void Shamir::exchange() +{ + if (P.my_num() < n_mul_players) + resharing->send_mine(); + for (int i = 0; i < n_mul_players; i++) + if (i != P.my_num()) + P.receive_player(i, os[i], true); +} + +template +ShamirShare Shamir::finalize_mul() +{ + return finalize(n_mul_players); +} + +template +ShamirShare Shamir::finalize(int n_relevant_players) +{ + ShamirShare res = U(0); + if (P.my_num() < n_relevant_players) + res = resharing->finalize_mine(); + for (int i = 0; i < n_relevant_players; i++) + if (i != P.my_num()) + { + T tmp; + resharing->finalize_other(i, tmp, os[i]); + res += tmp; + } + return res; +} + +template +ShamirShare Shamir::get_random() +{ + if (random.empty()) + buffer_random(); + auto res = random.back(); + random.pop_back(); + return res; +} + +template +void Shamir::buffer_random() +{ + Shamir shamir(P); + shamir.reset(); + int buffer_size = 1000; + if (P.my_num() <= threshold) + for (int i = 0; i < buffer_size; i++) + shamir.resharing->add_mine(secure_prng.get()); + shamir.exchange(); + for (int i = 0; i < buffer_size; i++) + random.push_back(shamir.finalize(threshold + 1)); +} diff --git a/Processor/ShamirInput.h b/Processor/ShamirInput.h new file mode 100644 index 000000000..ce2596e26 --- /dev/null +++ b/Processor/ShamirInput.h @@ -0,0 +1,47 @@ +/* + * ShamirInput.h + * + */ + +#ifndef PROCESSOR_SHAMIRINPUT_H_ +#define PROCESSOR_SHAMIRINPUT_H_ + +#include "Input.h" +#include "Shamir.h" +#include "ReplicatedInput.h" + +template +class ShamirInput : public PrepLessInput +{ + Player& P; + vector os; + vector> vandermonde; + SeededPRNG secure_prng; + + vector randomness; + +public: + ShamirInput(SubProcessor& proc) : + PrepLessInput(&proc), P(proc.P) + { + } + + ShamirInput(SubProcessor& proc, ShamirMC& MC) : + ShamirInput(proc) + { + (void) MC; + } + + ShamirInput(SubProcessor* proc, Player& P) : + PrepLessInput(proc), P(P) + { + } + + void reset(int player); + void add_mine(const typename T::clear& input); + void add_other(int player); + void send_mine(); + void finalize_other(int player, T& target, octetStream& o); +}; + +#endif /* PROCESSOR_SHAMIRINPUT_H_ */ diff --git a/Processor/ShamirInput.hpp b/Processor/ShamirInput.hpp new file mode 100644 index 000000000..b5483836f --- /dev/null +++ b/Processor/ShamirInput.hpp @@ -0,0 +1,75 @@ +/* + * ShamirInput.cpp + * + */ + +#include "ShamirInput.h" +#include "ShamirMachine.h" + +template +void ShamirInput::reset(int player) +{ + if (player == P.my_num()) + { + this->shares.clear(); + this->i_share = 0; + os.clear(); + os.resize(P.num_players()); + } +} + +template +void ShamirInput::add_mine(const typename T::clear& input) +{ + int n = P.num_players(); + int t = ShamirMachine::s().threshold; + if (vandermonde.empty()) + { + vandermonde.resize(n, vector(t)); + for (int i = 0; i < n; i++) + { + typename T::clear x = 1; + for (int j = 0; j < t; j++) + { + x *= (i + 1); + vandermonde[i][j] = x; + } + } + } + + randomness.resize(t); + for (auto& x : randomness) + x.randomize(secure_prng); + + for (int i = 0; i < n; i++) + { + typename T::clear x = input; + for (int j = 0; j < t; j++) + x += randomness[j] * vandermonde[i][j]; + if (i == P.my_num()) + this->shares.push_back(x); + else + x.pack(os[i]); + } +} + +template +void ShamirInput::add_other(int player) +{ + (void) player; +} + +template +void ShamirInput::send_mine() +{ + for (int i = 0; i < P.num_players(); i++) + if (i != P.my_num()) + P.send_to(i, os[i], true); +} + +template +void ShamirInput::finalize_other(int player, T& target, octetStream& o) +{ + (void) player; + target.unpack(o); +} diff --git a/Processor/ShamirMachine.cpp b/Processor/ShamirMachine.cpp new file mode 100644 index 000000000..75b12f2b7 --- /dev/null +++ b/Processor/ShamirMachine.cpp @@ -0,0 +1,68 @@ +/* + * ShamirMachine.cpp + * + */ + +#include "ShamirMachine.h" +#include "Math/ShamirShare.h" +#include "Math/MaliciousShamirShare.h" +#include "Math/gfp.h" +#include "Math/gf2n.h" + +#include "ReplicatedMachine.hpp" + +ShamirMachine* ShamirMachine::singleton = 0; + +ShamirMachine& ShamirMachine::s() +{ + if (singleton) + return *singleton; + else + throw runtime_error("no singleton"); +} + +ShamirMachine::ShamirMachine(int argc, const char** argv) +{ + if (singleton) + throw runtime_error("there can only be one"); + else + singleton = this; + + opt.add( + "3", // Default. + 0, // Required? + 1, // Number of args expected. + 0, // Delimiter if expecting multiple args. + "Number of players", // Help description. + "-N", // Flag token. + "--nparties" // Flag token. + ); + opt.add( + "", // Default. + 0, // Required? + 1, // Number of args expected. + 0, // Delimiter if expecting multiple args. + "Number of corrupted parties (default: just below half)", // Help description. + "-T", // Flag token. + "--threshold" // Flag token. + ); + opt.parse(argc, argv); + opt.get("-N")->getInt(nparties); + if (opt.isSet("-T")) + opt.get("-T")->getInt(threshold); + else + threshold = (nparties - 1) / 2; + cerr << "Using threshold " << threshold << " out of " << nparties << endl; + if (2 * threshold >= nparties) + throw runtime_error("threshold too high"); +} + +template class T> +ShamirMachineSpec::ShamirMachineSpec(int argc, const char** argv) : + ShamirMachine(argc, argv) +{ + ReplicatedMachine, T>(argc, argv, "shamir", opt, nparties); +} + +template class ShamirMachineSpec; +template class ShamirMachineSpec; diff --git a/Processor/ShamirMachine.h b/Processor/ShamirMachine.h new file mode 100644 index 000000000..49990783c --- /dev/null +++ b/Processor/ShamirMachine.h @@ -0,0 +1,34 @@ +/* + * ShamirMachine.h + * + */ + +#ifndef PROCESSOR_SHAMIRMACHINE_H_ +#define PROCESSOR_SHAMIRMACHINE_H_ + +#include "Tools/ezOptionParser.h" + +class ShamirMachine +{ + static ShamirMachine* singleton; + +protected: + ez::ezOptionParser opt; + int nparties; + +public: + int threshold; + + static ShamirMachine& s(); + + ShamirMachine(int argc, const char** argv); +}; + +template class T> +class ShamirMachineSpec : ShamirMachine +{ +public: + ShamirMachineSpec(int argc, const char** argv); +}; + +#endif /* PROCESSOR_SHAMIRMACHINE_H_ */ diff --git a/README.md b/README.md index 60d0ab536..825ed8abd 100644 --- a/README.md +++ b/README.md @@ -199,6 +199,45 @@ Player-Data Programs $ ../spdz/Scripts/run-online.sh test ``` +### Honest-majority computation based on Shamir secret sharing + +Compile the virtual machines: + +`make -j 8 shamir` + +Run setup to generate SSL keys and certificates. See the section replicated secret sharing for binary circuits below for details. + +`Scripts/setup-ssl.sh ` + +In order to compile a program, use `./compile.py`, for example: + +`./compile.py tutorial` + +Running the computation is similar to SPDZ but you will need to start +at least three parties: + +`./malicious-shamir-party.x -N 3 -I 0 tutorial` + +`./malicious-shamir-party.x -N 3 -I 1 tutorial` (in a separate terminal) + +`./malicious-shamir-party.x -N 3 -I 2 tutorial` (in a separate terminal) + +The `-I` enable interactive inputs, and in the tutorial party 0 and 1 +will be asked to provide three numbers. Using +`./shamir-party.x` will provide semi-honest security instead +of malicious. + +You can run all parties at once with + +`Scripts/mal-shamir.sh tutorial` + +for malicious security or + +`Scripts/shamir.sh tutorial` + +for semi-honest security. In this case, the inputs are read from +`Player-Data/Input-P-0`. + ### Three-party honest-majority computation modulo a prime Compile the virtual machines: diff --git a/Scripts/mal-shamir.sh b/Scripts/mal-shamir.sh new file mode 100755 index 000000000..33678d7b5 --- /dev/null +++ b/Scripts/mal-shamir.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +HERE=$(cd `dirname $0`; pwd) +SPDZROOT=$HERE/.. + +export PLAYERS=${PLAYERS:-3} + +if test "$THRESHOLD"; then + t="-T $THRESHOLD" +fi + +. $HERE/run-common.sh + +run_player malicious-shamir-party.x ${1:-test_all} $t || exit 1 diff --git a/Scripts/run-common.sh b/Scripts/run-common.sh index bdbde4fc6..870cabad3 100644 --- a/Scripts/run-common.sh +++ b/Scripts/run-common.sh @@ -18,13 +18,16 @@ run_player() { fi if [[ $bin = Player-Online.x || $bin =~ 'party.x' ]]; then params="$* -pn $port -h localhost" + if [[ ! $bin =~ 'rep' ]]; then + params="$params -N $players" + fi else params="$port localhost $*" fi if test $bin = Player-KeyGen.x -a ! -e Player-Data/Params-Data; then ./Setup.x $players $size 40 fi - if [[ $bin =~ Player- ]]; then + if [[ $bin =~ Player- && ! $bin =~ Player-Online.x ]]; then >&2 echo Running $SPDZROOT/Server.x $players $port $SPDZROOT/Server.x $players $port & fi diff --git a/Scripts/shamir.sh b/Scripts/shamir.sh new file mode 100755 index 000000000..c1579a7eb --- /dev/null +++ b/Scripts/shamir.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +HERE=$(cd `dirname $0`; pwd) +SPDZROOT=$HERE/.. + +export PLAYERS=${PLAYERS:-3} + +if test "$THRESHOLD"; then + t="-T $THRESHOLD" +fi + +. $HERE/run-common.sh + +run_player shamir-party.x ${1:-test_all} $t || exit 1 diff --git a/Tools/random.h b/Tools/random.h index 83639d53c..27760c3df 100644 --- a/Tools/random.h +++ b/Tools/random.h @@ -90,6 +90,10 @@ class PRNG const octet* get_seed() const { return seed; } + + template + T get() + { T res; res.randomize(*this); return res; } }; class SeededPRNG : public PRNG diff --git a/malicious-rep-field-party.cpp b/malicious-rep-field-party.cpp index e2300519e..307bd96ee 100644 --- a/malicious-rep-field-party.cpp +++ b/malicious-rep-field-party.cpp @@ -8,5 +8,7 @@ int main(int argc, const char** argv) { - ReplicatedMachine, MaliciousRep3Share>(argc, argv, "malicious-rep-field"); + ez::ezOptionParser opt; + ReplicatedMachine, MaliciousRep3Share>(argc, + argv, "malicious-rep-field", opt); } diff --git a/malicious-shamir-party.cpp b/malicious-shamir-party.cpp new file mode 100644 index 000000000..39e785642 --- /dev/null +++ b/malicious-shamir-party.cpp @@ -0,0 +1,12 @@ +/* + * malicious-shamir-party.cpp + * + */ + +#include "Processor/ShamirMachine.h" +#include "Math/MaliciousShamirShare.h" + +int main(int argc, const char** argv) +{ + ShamirMachineSpec(argc, argv); +} diff --git a/replicated-field-party.cpp b/replicated-field-party.cpp index 9e27f5365..eab7897d0 100644 --- a/replicated-field-party.cpp +++ b/replicated-field-party.cpp @@ -8,5 +8,7 @@ int main(int argc, const char** argv) { - ReplicatedMachine, Rep3Share>(argc, argv, "replicated-field"); + ez::ezOptionParser opt; + ReplicatedMachine, Rep3Share>(argc, argv, + "replicated-field", opt); } diff --git a/replicated-ring-party.cpp b/replicated-ring-party.cpp index 9c6fe7334..8977a2c4e 100644 --- a/replicated-ring-party.cpp +++ b/replicated-ring-party.cpp @@ -8,5 +8,7 @@ int main(int argc, const char** argv) { - ReplicatedMachine, Rep3Share>(argc, argv, "replicated-ring"); + ez::ezOptionParser opt; + ReplicatedMachine, Rep3Share>(argc, argv, + "replicated-ring", opt); } diff --git a/shamir-party.cpp b/shamir-party.cpp new file mode 100644 index 000000000..db9dd4835 --- /dev/null +++ b/shamir-party.cpp @@ -0,0 +1,12 @@ +/* + * shamir-party.cpp + * + */ + +#include "Processor/ShamirMachine.h" +#include "Math/ShamirShare.h" + +int main(int argc, const char** argv) +{ + ShamirMachineSpec(argc, argv); +}