Adding a Protocol

In order to illustrate how to create a virtual machine for a new protocol, we have created one with blanks to be filled in. It is defined in the following files:

Machines/no-party.cpp

Contains the main function.

Protocols/NoShare.h

Contains the NoShare class, which is supposed to hold one share. NoShare takes the cleartext type as a template parameter.

Protocols/NoProtocol.h

Contains a number of classes representing instances of protocols:

NoInput

Private input.

NoProtocol

Multiplication protocol.

NoOutput

Public output.

Protocols/NoLivePrep.h

Contains the NoLivePrep class, representing a preprocessing instance.

The number of blanks can be overwhelming. We therefore recommend the following approach to get started. If the desired protocol resembles one that is already implemented, you can check its code for inspiration. The main function of <protocol>-party.x can be found in Machines/<protocol>-party.cpp, which in turns contains the name of the share class. For example replicated-ring-party.x is implemented in Machines/replicated-ring-party.cpp, which refers to Rep3Share2() in Protocols/Rep3Share2.h. There you will find that it uses Replicated() for multiplication, which is found in Protocols/Replicated.h. You can also consult the tutorial for the lowest-level interface.

  1. Fill in the constant() static member function of NoShare as well as the exchange() member function of NoOutput. Check out DirectSemiMC<T>::exchange_() in Protocols/SemiMC.hpp for a simple example. It opens an additive secret sharing by sending all shares to all other parties and then summing up the received. See this reference for documentation on the necessary infrastructure. Constant sharing and public output allows to execute the following program:

    print_ln('result: %s', sint(123).reveal())
    

    This allows to check the correct execution of further functionality.

    Put the above code in Programs/Source/test.mpc and run the following if your protocol works for two parties (otherwise add more parties and change the -N argument accordingly):

    make no-party.x
    ./compile.py test
    ./no-party.x 0 test -N 2 & ./no-party.1 test -N 2
    

    This should output result: 123.

  2. Fill in the operator functions in NoShare and check them:

    print_ln('%s', (sint(2) + sint(3)).reveal())
    print_ln('%s', (sint(2) - sint(3)).reveal())
    print_ln('%s', (sint(2) * cint(3)).reveal())
    

    Many protocols use these basic operations, which makes it beneficial to check the correctness

  3. Fill in NoProtocol. Alternatively, if the desired protocol is based on Beaver multiplication, you can specify the following in NoShare:

    typedef Beaver<This> Protocol;
    

    Then add the desired triple generation to NoLivePrep::buffer_triples(). In any case you should then be able to execute:

    print_ln('%s', (sint(2) * sint(3)).reveal())
    
  4. In order to execute many kinds of non-linear computation, random bits are needed. After filling in NoLivePrep::buffer_bits(), you should be able to execute:

    print_ln('%s', (sint(2) < sint(3)).reveal()
    

Reference

The following classes are fundamental building blocks in protocols. See also the this reference for networking-related classes.

class PRNG

Pseudo-random number generator. This uses counter-mode AES by default, which can be changed libsodium’s expansion by undefining USE_AES.

Subclassed by ElementPRNG< T >, GlobalPRNG, SeededPRNG

Public Functions

PRNG()

Construction without initialization. Usage without initialization will fail.

PRNG(octetStream &seed)

Initialize with SEED_SIZE bytes from buffer.

void ReSeed()

Initialize from local randomness.

void SeedGlobally(const Player &P, bool secure = true)

Coordinate random seed

Parameters
  • P – communication instances

  • secure – seeding prevents tampering at higher cost

void SetSeed(const unsigned char*)

Initialize with SEED_SIZE bytes from pointer.

void SetSeed(PRNG &G)

Initialize with seed from another instance.

inline bool get_bit()

Random bit.

inline unsigned char get_uchar()

Random bytes.

unsigned int get_uint()

Random 32-bit integer.

unsigned int get_uint(int upper)

Random 32-bit integer between 0 and upper

template<class T>
void randomBnd(T &res, const bigint &B, bool positive = true)

Random integer in [0, B-1]

Parameters
  • res – result

  • B – bound

  • positive – positive result (random sign otherwise)

inline word get_word()

Random 64-bit integer.

inline __m128i get_doubleword()

Random 128-bit integer.

inline void get_octets(octet *ans, int len)

Fill array with random data

Parameters
  • ans – result

  • len – byte length

template<int L>
inline void get_octets(octet *ans)

Fill array with random data (compile-time length)

Parameters

ans – result

template<class T>
inline T get()

Random instance of any supported class.

class SeededPRNG : public PRNG

Randomly seeded pseudo-random number generator.

class GlobalPRNG : public PRNG

Coordinated pseudo-random number with secure seeding.