Low-Level Interface

In the following we will explain the basic of the C++ interface by walking trough Utils/paper-example.cpp.

template<class T>
void run(char** argv, int prime_length);

MP-SPDZ heavily uses templating to allow to reuse code between different protocols. run() is a simple example of this. The entire virtual machine in the Processor directory is built on the same principle. The central type is a type representing a share in a particular type.

// bit length of prime
const int prime_length = 128;

// compute number of 64-bit words needed
const int n_limbs = (prime_length + 63) / 64;

Computation modulo a prime requires to fix the number of limbs (64-bit words) at compile time. This allows for optimal memory usage and computation.

if (protocol == "MASCOT")
    run<Share<gfp_<0, n_limbs>>>(argv, prime_length);
else if (protocol == "CowGear")
    run<CowGearShare<gfp_<0, n_limbs>>>(argv, prime_length);

Share types for computation module a prime (and in \(\mathrm{GF}(2^n)\)) generally take one parameter for the computation domain. gfp_ in turn takes two parameters, a counter and the number of limbs. The counter allows to use several instances with different parameters. It can be chosen freely, but the convention is to use 0 for the online phase and 1 for the offline phase where required.

else if (protocol == "SPDZ2k")
    run<Spdz2kShare<64, 64>>(argv, 0);

Share types for computation modulo a power of two simply take the exponent as parameter, and some take an additional security parameter.

int my_number = atoi(argv[1]);
int n_parties = atoi(argv[2]);
int port_base = 9999;
Names N(my_number, n_parties, "localhost", port_base);

All implemented protocols require point-to-point connections between all parties. Names objects represent a setup of hostnames and IPs used to set up the actual connections. The chosen initialization provides a way where every party connects to party 0 on a specified location (localhost in this case), which then broadcasts the locations of all parties. The base port number is used to derive the port numbers for the parties to listen on (base + party number). See the the Names class for other possibilities such as a text file containing hostname and port number for each party.

CryptoPlayer P(N);

The networking setup is used to set up the actual connections. CryptoPlayer uses encrypted connection while PlainPlayer does not. If you use several instances (for several threads for example), you must use an integer identifier as the second parameter, which must differ from any other by at least the number of parties.

ProtocolSetup<T> setup(P, prime_length);

We have to use a specific prime for computation modulo a prime. This deterministically generates one of the desired length if necessary. For computation modulo a power of two, this does not do anything. Some protocols use an information-theoretic tag that is constant throughout the protocol. This code reads it from storage if available or generates a fresh one otherwise.

ProtocolSet<T> set(P, setup);
auto& input = set.input;
auto& protocol = set.protocol;
auto& output = set.output;

The ProtocolSet contains one instance for every essential protocol step.

int n = 1000;
vector<T> a(n), b(n);
T c;
typename T::clear result;

Remember that T stands for a share in the protocol. The derived type T::clear stands for the cleartext domain. Share types support linear operations such as addition, subtraction, and multiplication with a constant. Use T::constant() to convert a constant to a share type.

input.reset_all(P);
for (int i = 0; i < n; i++)
    input.add_from_all(i);
input.exchange();
for (int i = 0; i < n; i++)
{
    a[i] = input.finalize(0);
    b[i] = input.finalize(1);
}

The interface for all protocols proceeds in four stages:

  1. Initialization. This is required to initialize and reset data structures in consecutive use.

  2. Local data preparation

  3. Communication

  4. Output extraction

This blueprint allows for a minimal number of communication rounds.

protocol.init_dotprod(&processor);
for (int i = 0; i < n; i++)
    protocol.prepare_dotprod(a[i], b[i]);
protocol.next_dotprod();
protocol.exchange();
c = protocol.finalize_dotprod(n);

The initialization of the multiplication sets the preprocessing and output instances to use in Beaver multiplication. next_dotprod() separates dot products in the data preparation phase.

protocol.check();

Some protocols require a check of all multiplications up to a certain point. To guarantee that outputs do not reveal secret information, it has to be run before using the output protocol.

output.init_open(P);
output.prepare_open(c);
output.exchange(P);
result = output.finalize_open();

cout << "result: " << result << endl;
output.Check(P);

The output protocol follows the same blueprint as the multiplication protocol.

T::LivePrep::teardown();

This frees the memory used for global key material when using homomorphic encryption. Otherwise, this does not do anything.

Domain Types

gfp_<X, L>

Computation modulo a prime. L is the number of 64-bit limbs, that is, it covers primes of bit length \(64(L-1)+1\) to \(64L\). The type has to be initialized using init_field() or init_default(). The latter picks a prime given a bit length.

SignedZ2<K> / Z2<K>

Computation modulo \(2^K\). This is not a field.

gf2n_short / gf2n_long / gf2n_<T>

\(GF(2^n)\). T denotes a type that is used to store the values. It must support a variety of integer operations. The type has to be initialized using init_field(). The choice of degrees is limited. At the time of writing, 4, 8, 28, 40, 63, and 128 are supported if the storage type is large enough.

Share Types

Type

Protocol

AtlasShare<T>

Semi-honest version of ATLAS (Section 4.2). T must represent a field.

ChaiGearShare<T>

HighGear with covert key setup. T must be gfp_<X, L> or gf2n_short.

CowGearShare<T>

LowGear with covert key setup. T must be gfp_<X, L> or gf2n_short.

HemiShare<T>

Semi-honest protocol with Beaver multiplication based on semi-homomorphic encryption. T must be gfp_<X, L> or gf2n_short.

HighGearShare<T>

HighGear. T must be gfp_<X, L> or gf2n_short.

LowGearShare<T>

LowGear. T must be gfp_<X, L> or gf2n_short.

MaliciousShamirShare<T>

Shamir secret sharing with Beaver multiplication and sacrifice. T must represent a field.

MamaShare<T, N>

MASCOT with multiple MACs. T must represent a field, N is the number of MACs.

PostSacriRepFieldShare<T>

Post-sacrifice protocol using three-party replicated secret sharing with T representing a field.

PostSacriRepRingShare<K, S>

Post-sacrifice protocol using replicated three-party secret sharing modulo \(2^K\) with security parameter S.

Rep3Share2<K>

Three-party semi-honest protocol using replicated secret sharing modulo \(2^K\).

Rep4Share<T>

Four-party malicious protocol using replicated secret sharing over a field.

Rep4Share2<K>

Four-party malicious protocol using replicated secret sharing modulo \(2^K\).

SemiShare2<K>

Semi-honest dishonest-majority protocol using Beaver multiplication based on oblivious transfer modulo \(2^K\).

SemiShare<T>

Semi-honest dishonest-majority protocol using Beaver multiplication based on oblivious transfer in a field.

ShamirShare<T>

Semi-honest protocol based on Shamir’s secret sharing. T must represent a field.

Share<T>

MASCOT. T must represent a field.

SohoShare<T>

Semi-honest protocol with Beaver multiplication based on somewhat homomorphic encryption. T must be gfp_<X, L> or gf2n_short.

Spdz2kShare<K, S>

SPDZ2k computing modulo \(2^K\) with security parameter S.

SpdzWiseShare<K, S>

SPDZ-wise computing modulo \(2^K\) with security parameter S.

SpdzWiseShare<T>

SPDZ-wise. T must be MaliciousShamirShare or MaliciousRep3Share.

TemiShare<T>

Semi-honest protocol with Beaver multiplication based on threshold semi-homomorphic encryption. T must be gfp_<X, L> or gf2n_short.

Protocol Setup

template<class T>
class ProtocolSetup

Global setup for an arithmetic share type

Subclassed by MixedProtocolSetup< T >

Public Functions

inline ProtocolSetup(Player &P, int prime_length = 0, string directory = "")
Parameters
  • P – communication instance (used for MAC generation if needed)

  • prime_length – length of prime if computing modulo a prime

  • directory – location to read MAC if needed

template<class T>
class ProtocolSet

Input, multiplication, and output protocol instance for an arithmetic share type

Public Functions

inline ProtocolSet(Player &P, const ProtocolSetup<T> &setup)
Parameters
  • P – communication instance

  • setup – one-time setup instance

inline void check()

Run all protocol checks

template<class T>
class BinaryProtocolSetup

Global setup for a binary share type

Public Functions

inline BinaryProtocolSetup(Player &P, string directory = "")
Parameters
  • P – communication instance (used for MAC generation if needed)

  • directory – location to read MAC if needed

template<class T>
class BinaryProtocolSet

Input, multiplication, and output protocol instance for a binary share type

Public Functions

inline BinaryProtocolSet(Player &P, const BinaryProtocolSetup<T> &setup)
Parameters
  • P – communication instance

  • setup – one-time setup instance

inline void check()

Run all protocol checks

template<class T>
class MixedProtocolSetup : public ProtocolSetup<T>

Global setup for an arithmetic share type and the corresponding binary one

Public Functions

inline MixedProtocolSetup(Player &P, int prime_length = 0, string directory = "")
Parameters
  • P – communication instance (used for MAC generation if needed)

  • prime_length – length of prime if computing modulo a prime

  • directory – location to read MAC if needed

template<class T>
class MixedProtocolSet

Input, multiplication, and output protocol instance for an arithmetic share type and the corresponding binary one

Public Functions

inline MixedProtocolSet(Player &P, const MixedProtocolSetup<T> &setup)
Parameters
  • P – communication instance

  • setup – one-time setup instance

inline void check()

Run all protocol checks

Protocol Interfaces

template<class T>
class ProtocolBase

Abstract base class for multiplication protocols

Subclassed by Replicated< T >

Public Functions

T mul(const T &x, const T &y)

Single multiplication.

inline virtual void init(Preprocessing<T>&, typename T::MAC_Check&)

Initialize protocol if needed (repeated call possible)

virtual void init_mul() = 0

Initialize multiplication round.

virtual void prepare_mul(const T &x, const T &y, int n = -1) = 0

Schedule multiplication of operand pair.

virtual void exchange() = 0

Run multiplication protocol.

virtual T finalize_mul(int n = -1) = 0

Get next multiplication result.

virtual void finalize_mult(T &res, int n = -1)

Store next multiplication result in res

inline void init_dotprod()

Initialize dot product round.

inline void prepare_dotprod(const T &x, const T &y)

Add operand pair to current dot product.

inline void next_dotprod()

Finish dot product.

T finalize_dotprod(int length)

Get next dot product result.

template<class T>
class InputBase

Abstract base for input protocols

Subclassed by Input< T >

Public Functions

virtual void reset(int player) = 0

Initialize input round for player

void reset_all(Player &P)

Initialize input round for all players.

virtual void add_mine(const typename T::open_type &input, int n_bits = -1) = 0

Schedule input from me.

virtual void add_other(int player, int n_bits = -1) = 0

Schedule input from other player.

void add_from_all(const typename T::open_type &input, int n_bits = -1)

Schedule input from all players.

virtual void exchange()

Run input protocol for all players.

virtual T finalize(int player, int n_bits = -1)

Get share for next input from player

template<class T>
class MAC_Check_Base

Abstract base class for opening protocols

Public Functions

inline virtual void Check(const Player &P)

Run checking protocol.

inline const T::mac_key_type::Scalar &get_alphai() const

Get MAC key.

virtual void POpen(vector<typename T::open_type> &values, const vector<T> &S, const Player &P)

Open values in S and store results in values

inline T::open_type open(const T &secret, const Player &P)

Open single value.

virtual void init_open(const Player &P, int n = 0)

Initialize opening round.

virtual void prepare_open(const T &secret)

Add value to be opened.

virtual void exchange(const Player &P) = 0

Run opening protocol.

virtual T::open_type finalize_open()

Get next opened value.

virtual void CheckFor(const typename T::open_type &value, const vector<T> &shares, const Player &P)

Check whether all shares are value

template<class T>
class Preprocessing : public PrepBase

Abstract base class for preprocessing

Subclassed by BufferPrep< T >, Sub_Data_Files< T >

Public Functions

virtual array<T, 3> get_triple(int n_bits)

Get fresh random multiplication triple.

virtual T get_bit()

Get fresh random bit.

virtual T get_random()

Get fresh random value in domain.

virtual void get_dabit(T &a, typename T::bit_type &b)

Store fresh daBit in a (arithmetic part) and b (binary part)

template<int>
edabitvec<T> get_edabitvec(bool strict, int n_bits)

Get fresh edaBit chunk.

template<class T>
class BufferPrep : public Preprocessing<T>

Abstract base class for live preprocessing

Subclassed by BitPrep< T >

Public Functions

virtual T get_random()

Get fresh random value.

Public Static Functions

static inline void basic_setup(Player &P)

Key-independent setup if necessary (cryptosystem parameters)

static inline void setup(Player &P, typename T::mac_key_type alphai)

Generate keys if necessary.

static inline void teardown()

Free memory of global cryptosystem parameters.