diff --git a/Auth/MAC_Check.cpp b/Auth/MAC_Check.cpp
index 0bbeb79cf41917f081f3822c5c295c5ec2696298..c2eeee85295f6d5c5b58a2d569c72579c6be7441 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 <algorithm>
 
@@ -460,3 +462,7 @@ template class MAC_Check_Base<Rep3Share<gf2n>>;
 template class MAC_Check_Base<Rep3Share<Integer>>;
 template class MAC_Check_Base<MaliciousRep3Share<gfp>>;
 template class MAC_Check_Base<MaliciousRep3Share<gf2n>>;
+template class MAC_Check_Base<ShamirShare<gfp>>;
+template class MAC_Check_Base<ShamirShare<gf2n>>;
+template class MAC_Check_Base<MaliciousShamirShare<gfp>>;
+template class MAC_Check_Base<MaliciousShamirShare<gf2n>>;
diff --git a/Auth/MaliciousShamirMC.h b/Auth/MaliciousShamirMC.h
new file mode 100644
index 0000000000000000000000000000000000000000..4fa6cec0619f68c47fd086fe44f472299ffeb4ad
--- /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 T>
+class MaliciousShamirMC : public ShamirMC<T>
+{
+    vector<vector<typename T::clear>> 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<typename T::clear>& values, const vector<T>& S,
+            const Player& P);
+};
+
+#endif /* AUTH_MALICIOUSSHAMIRMC_H_ */
diff --git a/Auth/MaliciousShamirMC.hpp b/Auth/MaliciousShamirMC.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..457a67bc5c070e642b6e6da4ed9b6855def5c65b
--- /dev/null
+++ b/Auth/MaliciousShamirMC.hpp
@@ -0,0 +1,52 @@
+/*
+ * MaliciousShamirMC.cpp
+ *
+ */
+
+#include "MaliciousShamirMC.h"
+#include "Processor/ShamirMachine.h"
+
+template<class T>
+MaliciousShamirMC<T>::MaliciousShamirMC()
+{
+    this->threshold = 2 * ShamirMachine::s().threshold;
+}
+
+template<class T>
+void MaliciousShamirMC<T>::POpen_End(vector<typename T::clear>& values,
+        const vector<T>& 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<T>::get_rec_factor(j, i);
+        }
+    }
+
+    values.clear();
+    values.resize(S.size());
+    vector<T> 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 0000000000000000000000000000000000000000..a0f1bc21b00026b0f45c8481ae9c2788c1981faf
--- /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 T>
+class ShamirMC : public MAC_Check_Base<T>
+{
+    vector<typename T::clear> reconstruction;
+
+protected:
+    vector<octetStream> 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<typename T::clear>& values,const vector<T>& S,const Player& P);
+    void POpen_End(vector<typename T::clear>& values,const vector<T>& 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 0000000000000000000000000000000000000000..41840ebfb2ad89b7911327d7846323198671bf67
--- /dev/null
+++ b/Auth/ShamirMC.hpp
@@ -0,0 +1,47 @@
+/*
+ * ShamirMC.cpp
+ *
+ */
+
+#include "ShamirMC.h"
+
+template<class T>
+void ShamirMC<T>::POpen_Begin(vector<typename T::clear>& values,
+        const vector<T>& 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<class T>
+void ShamirMC<T>::POpen_End(vector<typename T::clear>& values,
+        const vector<T>& 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<typename T::clear>::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<typename T::clear>() * reconstruction[j];
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3fc607eae7dd10ed73ff1ece368c85352c293c09..01390079a37f8284b168d651de209228a9ac3b02 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 8a5ad329ec474a25b9ac28322577ef6691b55e34..9258c38d80c821786be6b1c7ac87bcad2e379155 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 @@ class bits(Tape.Register):
         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 4d55f814a22beb0df260da22e08f77eb3fb714e5..6f12e2284363c8b6f31d9a2b82280245305c38e0 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 @@ class cfix(_number, _structure):
         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 @@ class _fix(_number, _structure):
             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 @@ class sfloat(_number, _structure):
                 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 @@ _types = {
     'ci': regint,
 }
 
+def _get_type(t):
+    if t in _types:
+        return _types[t]
+    else:
+        return t
 
 class Array(object):
     @classmethod
@@ -2566,8 +2579,7 @@ class Array(object):
         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 @@ sgf2n.dynamic_array = Array
 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 6c2bad08fb2f731c62735681d4c8f74fde9c931d..b2bcd35434b93be1f86484e45d8ef79e94986cd4 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 2c5e9f50bc349dd0bd9783ef2435b57987084a02..43ec27a6eec46e27efbf8c5b33f3ca1a1a5d20d8 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 8b482f4691fbf8c04fe3f4e4299aebde1396be38..5c7c4b13db3acc67fc58b901d6a9a4c535f7be00 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 6f0e6c4682492ab3130cf1d54f37e9308fa0f4d1..44e555ffd5c796901a0f1abc9621d0cdd857b459 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 815ef2c83c26c5aa241a1fc49bf7b068dc2f7151..4ade5c6f7becfedbf458db7bde01e5ae45e85da5 100644
--- a/Math/MaliciousRep3Share.h
+++ b/Math/MaliciousRep3Share.h
@@ -23,6 +23,7 @@ public:
     typedef MAC_Check Direct_MC;
     typedef ReplicatedInput<MaliciousRep3Share<T>> Input;
     typedef ReplicatedPrivateOutput<MaliciousRep3Share<T>> PrivateOutput;
+    typedef Rep3Share<T> Honest;
 
     static string type_short()
     {
diff --git a/Math/MaliciousShamirShare.h b/Math/MaliciousShamirShare.h
new file mode 100644
index 0000000000000000000000000000000000000000..85995ba025f7590846f5ab28ed8cf72585c29ab3
--- /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 T>
+class MaliciousShamirShare : public ShamirShare<T>
+{
+    typedef ShamirShare<T> super;
+
+public:
+    typedef Beaver<MaliciousShamirShare<T>> Protocol;
+    typedef MaliciousShamirMC<MaliciousShamirShare> MAC_Check;
+    typedef MAC_Check Direct_MC;
+    typedef ShamirInput<MaliciousShamirShare> Input;
+    typedef ReplicatedPrivateOutput<MaliciousShamirShare> PrivateOutput;
+    typedef ShamirShare<T> Honest;
+
+    static string type_short()
+    {
+        return "M" + super::type_short();
+    }
+
+    MaliciousShamirShare()
+    {
+    }
+    template<class U>
+    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 0000000000000000000000000000000000000000..ec7217cb18595afb1b39ea3457bccae8d6c806ee
--- /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 T>
+class ShamirShare : public T
+{
+public:
+    typedef T clear;
+
+    typedef Shamir<T> Protocol;
+    typedef ShamirMC<ShamirShare> MAC_Check;
+    typedef MAC_Check Direct_MC;
+    typedef ShamirInput<ShamirShare> Input;
+    typedef ReplicatedPrivateOutput<ShamirShare> PrivateOutput;
+
+    static string type_short()
+    {
+        return "S" + string(1, clear::type_char());
+    }
+    static string type_string()
+    {
+        return "Shamir " + T::type_string();
+    }
+
+    ShamirShare()
+    {
+    }
+    template<class U>
+    ShamirShare(const U& other)
+    {
+        T::operator=(other);
+    }
+    template<class U>
+    ShamirShare(const U& other, int my_num) : ShamirShare(other)
+    {
+        (void) my_num;
+    }
+
+    // Share<T> 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 dd689a9d48b4553e736db68c247f03bbad85a6d4..39786de442f0f36944aeb735c7adf4defb5aeac3 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 f4ff6bd48e6de46fdab3ee7ba3a504ee0e875001..108e7e1eb3a70b1dbe94bb0044c31a6744fcdd6e 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 7f6a46e512372633dcbbe6f00e589f87e55c5528..84f38f3ce41389a869445654051d51cf0ad19129 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 1b9d4be270e5d3191df63bdb633dc9a74cce59f9..7d556fa21b8a46aa0a90f8a3c5972ebb8b1f3fe9 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 9c0e71ac5c8b412567fc0e9142c9e71057132a48..d7051fffee5c0f200dbfee7552e975fe94854d5e 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 <nparties>`.");
+}
+
+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 <directory>` on its location." << endl;
+}
+
 CryptoPlayer::CryptoPlayer(const Names& Nms, int id_base) :
         MultiPlayer<ssl_socket*>(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 8c7cbb3f4cc250828ac35ffa0f98b1104ccf1a11..d398d824c324e10eea265910972ae3e7c5fd8e65 100644
--- a/Networking/Player.cpp
+++ b/Networking/Player.cpp
@@ -371,6 +371,8 @@ void MultiPlayer<T>::Broadcast_Receive(vector<octetStream>& o,bool donthash) con
 
 void Player::Check_Broadcast() const
 {
+  if (ctx.size == 0)
+    return;
   octet hashVal[HASH_SIZE];
   vector<octetStream> h(nplayers);
   blk_SHA1_Final(hashVal,&ctx);
diff --git a/Processor/Data_Files.cpp b/Processor/Data_Files.cpp
index 25f265bf92d9177463026f4758004d0a9eef2902..dff1c2a0bd0015b633546cfba0af9c398a7ecfeb 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 <iomanip>
 #include <numeric>
@@ -53,6 +61,26 @@ const bool Sub_Data_Files<GC::MaliciousRepSecret>::implemented[N_DTYPE] =
     { true, false, true, false, false, false }
 ;
 
+template<>
+const bool Sub_Data_Files<ShamirShare<gfp>>::implemented[N_DTYPE] =
+    { false, false, false, false, false, false }
+;
+
+template<>
+const bool Sub_Data_Files<ShamirShare<gf2n>>::implemented[N_DTYPE] =
+    { false, false, false, false, false, false }
+;
+
+template<>
+const bool Sub_Data_Files<MaliciousShamirShare<gfp>>::implemented[N_DTYPE] =
+    { false, false, false, false, false, false }
+;
+
+template<>
+const bool Sub_Data_Files<MaliciousShamirShare<gf2n>>::implemented[N_DTYPE] =
+    { false, false, false, false, false, false }
+;
+
 const int DataPositions::tuple_size[N_DTYPE] = { 3, 2, 1, 2, 3, 3 };
 
 template<class T>
@@ -61,67 +89,89 @@ template<class T>
 map<DataTag, int> Sub_Data_Files<T>::tuple_lengths;
 
 template<>
-template<>
-Preprocessing<Rep3Share<gfp>>* Preprocessing<Rep3Share<gfp>>::get_new(
-    Machine<Rep3Share<gfp>, Rep3Share<gf2n>>& machine, DataPositions& usage)
+Preprocessing<Rep3Share<gfp>>* Preprocessing<Rep3Share<gfp>>::get_live_prep(
+    SubProcessor<Rep3Share<gfp>>* proc)
 {
-  if (machine.live_prep)
-    return new ReplicatedPrep<Rep3Share<gfp>>;
-  else
-    return new Sub_Data_Files<Rep3Share<gfp>>(machine.get_N(), machine.prep_dir_prefix, usage);
+  return new ReplicatedPrep<Rep3Share<gfp>>(proc);
 }
 
 template<>
+Preprocessing<Rep3Share<gf2n>>* Preprocessing<Rep3Share<gf2n>>::get_live_prep(
+    SubProcessor<Rep3Share<gf2n>>* proc)
+{
+  return new ReplicatedPrep<Rep3Share<gf2n>>(proc);
+}
+
 template<>
-Preprocessing<Rep3Share<gf2n>>* Preprocessing<Rep3Share<gf2n>>::get_new(
-    Machine<Rep3Share<gfp>, Rep3Share<gf2n>>& machine, DataPositions& usage)
+Preprocessing<Rep3Share<Integer>>* Preprocessing<Rep3Share<Integer>>::get_live_prep(
+    SubProcessor<Rep3Share<Integer>>* proc)
 {
-  if (machine.live_prep)
-    return new ReplicatedPrep<Rep3Share<gf2n>>;
-  else
-    return new Sub_Data_Files<Rep3Share<gf2n>>(machine.get_N(), machine.prep_dir_prefix, usage);
+  return new ReplicatedRingPrep<Rep3Share<Integer>>(proc);
 }
 
 template<>
+Preprocessing<MaliciousRep3Share<gfp>>* Preprocessing<MaliciousRep3Share<gfp>>::get_live_prep(
+    SubProcessor<MaliciousRep3Share<gfp>>* proc)
+{
+  (void) proc;
+  return new MaliciousRepPrep<MaliciousRep3Share<gfp>>(proc);
+}
+
 template<>
-Preprocessing<Rep3Share<Integer>>* Preprocessing<Rep3Share<Integer>>::get_new(
-    Machine<Rep3Share<Integer>, Rep3Share<gf2n>>& machine, DataPositions& usage)
+Preprocessing<MaliciousRep3Share<gf2n>>* Preprocessing<MaliciousRep3Share<gf2n>>::get_live_prep(
+    SubProcessor<MaliciousRep3Share<gf2n>>* proc)
 {
-  if (machine.live_prep)
-    return new ReplicatedRingPrep<Rep3Share<Integer>>;
-  else
-    return new Sub_Data_Files<Rep3Share<Integer>>(machine.get_N(), machine.prep_dir_prefix, usage);
+  (void) proc;
+  return new MaliciousRepPrep<MaliciousRep3Share<gf2n>>(proc);
 }
 
 template<>
+Preprocessing<ShamirShare<gfp>>* Preprocessing<ShamirShare<gfp>>::get_live_prep(
+    SubProcessor<ShamirShare<gfp>>* proc)
+{
+  return new ReplicatedPrep<ShamirShare<gfp>>(proc);
+}
+
 template<>
-Preprocessing<MaliciousRep3Share<gfp>>* Preprocessing<MaliciousRep3Share<gfp>>::get_new(
-    Machine<MaliciousRep3Share<gfp>, MaliciousRep3Share<gf2n>>& machine, DataPositions& usage)
+Preprocessing<ShamirShare<gf2n>>* Preprocessing<ShamirShare<gf2n>>::get_live_prep(
+    SubProcessor<ShamirShare<gf2n>>* proc)
 {
-  if (machine.live_prep)
-    return new MaliciousRepPrep<gfp>;
-  else
-    return new Sub_Data_Files<MaliciousRep3Share<gfp>>(machine.get_N(), machine.prep_dir_prefix, usage);
+  return new ReplicatedPrep<ShamirShare<gf2n>>(proc);
 }
 
 template<>
+Preprocessing<MaliciousShamirShare<gfp>>* Preprocessing<MaliciousShamirShare<gfp>>::get_live_prep(
+    SubProcessor<MaliciousShamirShare<gfp>>* proc)
+{
+  (void) proc;
+  return new MaliciousRepPrep<MaliciousShamirShare<gfp>>(proc);
+}
+
 template<>
-Preprocessing<MaliciousRep3Share<gf2n>>* Preprocessing<MaliciousRep3Share<gf2n>>::get_new(
-    Machine<MaliciousRep3Share<gfp>, MaliciousRep3Share<gf2n>>& machine, DataPositions& usage)
+Preprocessing<MaliciousShamirShare<gf2n>>* Preprocessing<MaliciousShamirShare<gf2n>>::get_live_prep(
+    SubProcessor<MaliciousShamirShare<gf2n>>* proc)
 {
-  if (machine.live_prep)
-    return new MaliciousRepPrep<gf2n>;
-  else
-    return new Sub_Data_Files<MaliciousRep3Share<gf2n>>(machine.get_N(), machine.prep_dir_prefix, usage);
+  (void) proc;
+  return new MaliciousRepPrep<MaliciousShamirShare<gf2n>>(proc);
 }
 
+template<class T>
+Preprocessing<T>* Preprocessing<T>::get_live_prep(SubProcessor<T>* proc)
+{
+  (void) proc;
+  throw not_implemented();
+}
 
 template<class T>
 template<class U, class V>
-Preprocessing<T>* Preprocessing<T>::get_new(Machine<U, V>& machine,
-    DataPositions& usage)
+Preprocessing<T>* Preprocessing<T>::get_new(
+    Machine<U, V>& machine,
+    DataPositions& usage, SubProcessor<T>* proc)
 {
-  return new Sub_Data_Files<T>(machine.get_N(), machine.prep_dir_prefix, usage);
+  if (machine.live_prep)
+    return get_live_prep(proc);
+  else
+    return new Sub_Data_Files<T>(machine.get_N(), machine.prep_dir_prefix, usage);
 }
 
 void DataPositions::set_num_players(int num_players)
@@ -246,11 +296,19 @@ Sub_Data_Files<T>::Sub_Data_Files(int my_num, int num_players,
 }
 
 template<class sint, class sgf2n>
-Data_Files<sint, sgf2n>::Data_Files(Machine<sint, sgf2n>& machine) :
+Data_Files<sint, sgf2n>::Data_Files(Machine<sint, sgf2n>& machine, SubProcessor<sint>* procp,
+    SubProcessor<sgf2n>* proc2) :
     usage(machine.get_N().num_players()),
-    DataFp(*Preprocessing<sint>::get_new(machine, usage)),
-    DataF2(*Preprocessing<sgf2n>::get_new(machine, usage))
+    DataFp(*Preprocessing<sint>::get_new(machine, usage, procp)),
+    DataF2(*Preprocessing<sgf2n>::get_new(machine, usage, proc2))
+{
+}
+
+template<class sint, class sgf2n>
+Data_Files<sint, sgf2n>::~Data_Files()
 {
+  delete &DataFp;
+  delete &DataF2;
 }
 
 template<class T>
@@ -393,3 +451,5 @@ template class Data_Files<sgfp, Share<gf2n>>;
 template class Data_Files<Rep3Share<Integer>, Rep3Share<gf2n>>;
 template class Data_Files<Rep3Share<gfp>, Rep3Share<gf2n>>;
 template class Data_Files<MaliciousRep3Share<gfp>, MaliciousRep3Share<gf2n>>;
+template class Data_Files<ShamirShare<gfp>, ShamirShare<gf2n>>;
+template class Data_Files<MaliciousShamirShare<gfp>, MaliciousShamirShare<gf2n>>;
diff --git a/Processor/Data_Files.h b/Processor/Data_Files.h
index 3ed16f8259c6d542285080db84934d0f1a46df42..7186017d578e406b5fa43425a9c5f8f576b3a248 100644
--- a/Processor/Data_Files.h
+++ b/Processor/Data_Files.h
@@ -69,7 +69,9 @@ class Preprocessing
 {
 public:
   template<class U, class V>
-  static Preprocessing<T>* get_new(Machine<U, V>& machine, DataPositions& usage);
+  static Preprocessing<T>* get_new(Machine<U, V>& machine, DataPositions& usage,
+      SubProcessor<T>* proc);
+  static Preprocessing<T>* get_live_prep(SubProcessor<T>* proc);
 
   virtual ~Preprocessing() {}
 
@@ -179,7 +181,9 @@ class Data_Files
   Preprocessing<sint>& DataFp;
   Preprocessing<sgf2n>& DataF2;
 
-  Data_Files(Machine<sint, sgf2n>& machine);
+  Data_Files(Machine<sint, sgf2n>& machine, SubProcessor<sint>* procp = 0,
+      SubProcessor<sgf2n>* proc2 = 0);
+  ~Data_Files();
 
   DataPositions tellg();
   void seekg(DataPositions& pos);
diff --git a/Processor/DummyProtocol.h b/Processor/DummyProtocol.h
index 2a574ba887b71f7e7a9913b55fc7a513ab66910c..bf38a542e5cb55f66f3301ab093435aec4d915f1 100644
--- a/Processor/DummyProtocol.h
+++ b/Processor/DummyProtocol.h
@@ -6,8 +6,13 @@
 #ifndef PROCESSOR_DUMMYPROTOCOL_H_
 #define PROCESSOR_DUMMYPROTOCOL_H_
 
+#include <vector>
+using namespace std;
+
 class Player;
 
+template<class T> class SubProcessor;
+
 class DummyMC
 {
 public:
@@ -26,4 +31,40 @@ public:
     }
 };
 
+class NotImplementedInput
+{
+public:
+    template<class T, class U>
+    NotImplementedInput(T& proc, U& MC)
+    {
+        (void) proc, (void) MC;
+    }
+    void start(int n, vector<int> regs)
+    {
+        (void) n, (void) regs;
+        throw not_implemented();
+    }
+    void stop(int n, vector<int> 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<class T>
+    static void input(SubProcessor<T>& proc, vector<int> regs)
+    {
+        (void) proc, (void) regs;
+        throw not_implemented();
+    }
+};
+
 #endif /* PROCESSOR_DUMMYPROTOCOL_H_ */
diff --git a/Processor/Input.h b/Processor/Input.h
index 8722daeeffed7540908e5bfda0b6327b163c853a..5f50548462f40ed86c7b1089b2ed9a3836524f66 100644
--- a/Processor/Input.h
+++ b/Processor/Input.h
@@ -27,7 +27,7 @@ public:
 
     static void input(SubProcessor<T>& Proc, const vector<int>& args);
 
-    InputBase(ArithmeticProcessor& proc);
+    InputBase(ArithmeticProcessor* proc);
     ~InputBase();
 };
 
diff --git a/Processor/Input.hpp b/Processor/Input.hpp
index c6a2fbcaa3c8baad53e19a96b747382360fbd5ec..0eb98f7ae01016debff5aec6d747ed926424de83 100644
--- a/Processor/Input.hpp
+++ b/Processor/Input.hpp
@@ -8,15 +8,16 @@
 #include "Auth/MAC_Check.h"
 
 template<class T>
-InputBase<T>::InputBase(ArithmeticProcessor& proc) :
+InputBase<T>::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<class T>
 Input<T>::Input(SubProcessor<Share<T>>& proc, MAC_Check<T>& mc) :
-        InputBase<Share<T>>(proc.Proc), proc(proc), MC(mc), shares(proc.P.num_players())
+        InputBase<Share<T>>(&proc.Proc), proc(proc), MC(mc), shares(proc.P.num_players())
 {
 }
 
diff --git a/Processor/Instruction.cpp b/Processor/Instruction.cpp
index ea0d1a6d61cd60f0f00b09a75553ff6faf32c378..a73773f29c07dde10fccf9445a233616f5dfe54c 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 <stdlib.h>
 #include <algorithm>
@@ -1699,3 +1706,5 @@ template void Program::execute(Processor<sgfp, Share<gf2n>>& Proc) const;
 template void Program::execute(Processor<Rep3Share<Integer>, Rep3Share<gf2n>>& Proc) const;
 template void Program::execute(Processor<Rep3Share<gfp>, Rep3Share<gf2n>>& Proc) const;
 template void Program::execute(Processor<MaliciousRep3Share<gfp>, MaliciousRep3Share<gf2n>>& Proc) const;
+template void Program::execute(Processor<ShamirShare<gfp>, ShamirShare<gf2n>>& Proc) const;
+template void Program::execute(Processor<MaliciousShamirShare<gfp>, MaliciousShamirShare<gf2n>>& Proc) const;
diff --git a/Processor/Machine.cpp b/Processor/Machine.cpp
index a07bd71f3632ca9aef23b668f73fd18535975925..cf64261a40088e7a965104cfbf17b50a77ab21dc 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 <iostream>
 #include <vector>
@@ -61,6 +68,7 @@ Machine<sint, sgf2n>::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<sint, sgf2n>::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<sgfp, Share<gf2n>>;
 template class Machine<Rep3Share<Integer>, Rep3Share<gf2n>>;
 template class Machine<Rep3Share<gfp>, Rep3Share<gf2n>>;
 template class Machine<MaliciousRep3Share<gfp>, MaliciousRep3Share<gf2n>>;
+template class Machine<ShamirShare<gfp>, ShamirShare<gf2n>>;
+template class Machine<MaliciousShamirShare<gfp>, MaliciousShamirShare<gf2n>>;
diff --git a/Processor/MaliciousRepPrep.h b/Processor/MaliciousRepPrep.h
index 8fb40734cc9fc10eb57437ed9482452718006fcb..d91e8b7235a892d5f9490af16d5200b1321b74ae 100644
--- a/Processor/MaliciousRepPrep.h
+++ b/Processor/MaliciousRepPrep.h
@@ -13,15 +13,14 @@
 
 #include <array>
 
-template<class U>
-class MaliciousRepPrep : public BufferPrep<MaliciousRep3Share<U>>
+template<class T>
+class MaliciousRepPrep : public BufferPrep<T>
 {
-    typedef MaliciousRep3Share<U> T;
-    typedef BufferPrep<MaliciousRep3Share<U>> super;
+    typedef BufferPrep<T> super;
 
-    ReplicatedPrep<Rep3Share<U>> honest_prep;
-    Replicated<Rep3Share<U>>* replicated;
-    HashMaliciousRepMC<T> MC;
+    ReplicatedPrep<typename T::Honest> honest_prep;
+    typename T::Honest::Protocol* replicated;
+    typename T::MAC_Check MC;
 
     vector<T> masked;
     vector<T> checks;
@@ -38,7 +37,7 @@ class MaliciousRepPrep : public BufferPrep<MaliciousRep3Share<U>>
     void buffer_bits();
 
 public:
-    MaliciousRepPrep();
+    MaliciousRepPrep(SubProcessor<T>* proc);
     ~MaliciousRepPrep();
 
     void set_protocol(Beaver<T>& protocol);
diff --git a/Processor/MaliciousRepPrep.hpp b/Processor/MaliciousRepPrep.hpp
index 2f43983be98568adfb4ea273ae0de9e876c9a14a..de1130693a4d460d3b886d34e24d446bae286e9b 100644
--- a/Processor/MaliciousRepPrep.hpp
+++ b/Processor/MaliciousRepPrep.hpp
@@ -7,9 +7,11 @@
 #include "Auth/Subroutines.h"
 #include "Auth/MaliciousRepMC.hpp"
 
-template<class U>
-MaliciousRepPrep<U>::MaliciousRepPrep() : replicated(0)
+template<class T>
+MaliciousRepPrep<T>::MaliciousRepPrep(SubProcessor<T>* proc) :
+        honest_prep(0), replicated(0)
 {
+    (void) proc;
 }
 
 template<class U>
@@ -19,10 +21,10 @@ MaliciousRepPrep<U>::~MaliciousRepPrep()
         delete replicated;
 }
 
-template<class U>
-void MaliciousRepPrep<U>::set_protocol(Beaver<T>& protocol)
+template<class T>
+void MaliciousRepPrep<T>::set_protocol(Beaver<T>& protocol)
 {
-    replicated = new Replicated<Rep3Share<U>>(protocol.P);
+    replicated = new typename T::Honest::Protocol(protocol.P);
     honest_prep.set_protocol(*replicated);
 }
 
@@ -35,8 +37,8 @@ void MaliciousRepPrep<U>::clear_tmp()
     check_squares.clear();
 }
 
-template<class U>
-void MaliciousRepPrep<U>::buffer_triples()
+template<class T>
+void MaliciousRepPrep<T>::buffer_triples()
 {
     auto& triples = this->triples;
     auto& buffer_size = this->buffer_size;
@@ -80,8 +82,8 @@ void MaliciousRepPrep<U>::buffer_triples()
     MC.Check(P);
 }
 
-template<class U>
-void MaliciousRepPrep<U>::buffer_squares()
+template<class T>
+void MaliciousRepPrep<T>::buffer_squares()
 {
     auto& squares = this->squares;
     auto& buffer_size = this->buffer_size;
@@ -120,14 +122,14 @@ void MaliciousRepPrep<U>::buffer_squares()
             throw Offline_Check_Error("square");
 }
 
-template<class U>
-void MaliciousRepPrep<U>::buffer_inverses()
+template<class T>
+void MaliciousRepPrep<T>::buffer_inverses()
 {
     BufferPrep<T>::buffer_inverses(MC, honest_prep.protocol->P);
 }
 
-template<class U>
-void MaliciousRepPrep<U>::buffer_bits()
+template<class T>
+void MaliciousRepPrep<T>::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 4c1d31ef6dd55aa237383f8a56cc13b6ccc41b49..91b8539acf50700641143eae2a85552e0fe7a2ae 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<sint, sgf2n> 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<sint, sgf2n> Proc(tinfo->thread_num,DataF,P,*MC2,*MCp,machine,progs[0]);
+  Processor<sint, sgf2n> Proc(tinfo->thread_num,P,*MC2,*MCp,machine,progs[0]);
   Share<gf2n> 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 87df4b95816ca79ff63b47a13661100b1b5ad09d..2bb739c48466e785a590d0ba65d85b5e3bcedbc6 100644
--- a/Processor/Processor.h
+++ b/Processor/Processor.h
@@ -41,7 +41,7 @@ class SubProcessor
 
   template<class sint, class sgf2n> friend class Processor;
   template<class U> friend class SPDZ;
-  template<class U> friend class Replicated;
+  template<class U> friend class PrepLessProtocol;
   template<class U> friend class Beaver;
 
 public:
@@ -128,7 +128,7 @@ class Processor : public ArithmeticProcessor
   vector<typename T::clear>& get_PO();
 
   public:
-  Data_Files<sint, sgf2n>& DataF;
+  Data_Files<sint, sgf2n> 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<sint, sgf2n>& DataF,Player& P,
+  Processor(int thread_num,Player& P,
           typename sgf2n::MAC_Check& MC2,typename sint::MAC_Check& MCp,
           Machine<sint, sgf2n>& machine,
           const Program& program);
diff --git a/Processor/Processor.hpp b/Processor/Processor.hpp
index 89985876a38350114b2d2184fbbfa4994232d680..6698c219058148fd99e8b252c64ab164b9b84191 100644
--- a/Processor/Processor.hpp
+++ b/Processor/Processor.hpp
@@ -20,11 +20,11 @@ SubProcessor<T>::SubProcessor(ArithmeticProcessor& Proc, typename T::MAC_Check&
 }
 
 template<class sint, class sgf2n>
-Processor<sint, sgf2n>::Processor(int thread_num,Data_Files<sint, sgf2n>& DataF,Player& P,
+Processor<sint, sgf2n>::Processor(int thread_num,Player& P,
         typename sgf2n::MAC_Check& MC2,typename sint::MAC_Check& MCp,
         Machine<sint, sgf2n>& 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 33c27a07e759da61d129dc25433893943121104b..5ab70c188e07c7373339a6ec22a32543342d1177 100644
--- a/Processor/Replicated.h
+++ b/Processor/Replicated.h
@@ -20,6 +20,7 @@ template<class T> class ReplicatedInput;
 template<class T> class ReplicatedPrivateOutput;
 template<class T> class Share;
 template<class T> class Rep3Share;
+template<class T> class MAC_Check_Base;
 
 class ReplicatedBase
 {
@@ -32,19 +33,36 @@ public:
 };
 
 template <class T>
-class Replicated : public ReplicatedBase
+class PrepLessProtocol
 {
-    vector<octetStream> os;
-    deque<typename T::clear> add_shares;
     int counter;
 
+public:
+    PrepLessProtocol();
+    virtual ~PrepLessProtocol();
+
+    void muls(const vector<int>& reg, SubProcessor<T>& proc, MAC_Check_Base<T>& MC,
+            int size);
+
+    virtual void init_mul(SubProcessor<T>* 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 T>
+class Replicated : public ReplicatedBase, public PrepLessProtocol<T>
+{
+    vector<octetStream> os;
+    deque<typename T::clear> add_shares;
 public:
     typedef ReplicatedMC<T> MAC_Check;
     typedef ReplicatedInput<T> Input;
     typedef ReplicatedPrivateOutput<T> PrivateOutput;
 
     Replicated(Player& P);
-    ~Replicated();
 
     static void assign(T& share, const typename T::clear& value, int my_num)
     {
@@ -54,9 +72,7 @@ public:
             share[my_num] = value;
     }
 
-    void muls(const vector<int>& reg, SubProcessor<T>& proc, ReplicatedMC<T>& MC,
-            int size);
-
+    void init_mul(SubProcessor<T>* 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 87314c1016c498c8a7001a4063541c779843cc30..10722f2279b8f4802f189d30a98686feb6dd2b2e 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<class T>
-Replicated<T>::Replicated(Player& P) : ReplicatedBase(P), counter(0)
+PrepLessProtocol<T>::PrepLessProtocol() : counter(0)
+{
+}
+
+template<class T>
+Replicated<T>::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<class T>
-inline Replicated<T>::~Replicated()
+PrepLessProtocol<T>::~PrepLessProtocol()
 {
-    cerr << "Number of multiplications: " << counter << endl;
+    if (counter)
+        cerr << "Number of multiplications: " << counter << endl;
 }
 
 template<class T>
-void Replicated<T>::muls(const vector<int>& reg,
-        SubProcessor<T>& proc, ReplicatedMC<T>& MC, int size)
+void PrepLessProtocol<T>::muls(const vector<int>& reg,
+        SubProcessor<T>& proc, MAC_Check_Base<T>& 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<T>::muls(const vector<int>& reg,
     counter += n * size;
 }
 
+template<class T>
+void Replicated<T>::init_mul(SubProcessor<T>* proc)
+{
+    (void) proc;
+    init_mul();
+}
+
 template<class T>
 void Replicated<T>::init_mul()
 {
@@ -112,9 +125,3 @@ T Replicated<T>::get_random()
         res[i].randomize(shared_prngs[i]);
     return res;
 }
-
-template class Replicated<Rep3Share<Integer>>;
-template class Replicated<Rep3Share<gfp>>;
-template class Replicated<Rep3Share<gf2n>>;
-template class Replicated<MaliciousRep3Share<gfp>>;
-template class Replicated<MaliciousRep3Share<gf2n>>;
diff --git a/Processor/ReplicatedInput.h b/Processor/ReplicatedInput.h
index e434b700f2f6b1d956fc81fe85d05cbf9b3ba143..929db41263ef45094d4c18535dcb4f4ea6a37f4d 100644
--- a/Processor/ReplicatedInput.h
+++ b/Processor/ReplicatedInput.h
@@ -9,26 +9,59 @@
 #include "Input.h"
 
 template <class T>
-class ReplicatedInput : public InputBase<T>
+class PrepLessInput : public InputBase<T>
 {
-    SubProcessor<T>& proc;
+protected:
+    SubProcessor<T>* processor;
     vector<T> shares;
+    size_t i_share;
+
+public:
+    PrepLessInput(SubProcessor<T>* proc) :
+            InputBase<T>(proc ? &proc->Proc : 0), processor(proc), i_share(0) {}
+    virtual ~PrepLessInput() {}
+
+    void start(int player, int n_inputs);
+    void stop(int player, vector<int> 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 T>
+class ReplicatedInput : public PrepLessInput<T>
+{
+    SubProcessor<T>* proc;
+    Player& P;
     vector<octetStream> os;
+    SeededPRNG secure_prng;
 
 public:
+    ReplicatedInput(SubProcessor<T>& proc) :
+            PrepLessInput<T>(&proc), proc(&proc), P(proc.P)
+    {
+        assert(T::length == 2);
+    }
     ReplicatedInput(SubProcessor<T>& proc, ReplicatedMC<T>& MC) :
-            InputBase<T>(proc.Proc), proc(proc)
+            ReplicatedInput(proc)
     {
         (void) MC;
     }
+    ReplicatedInput(SubProcessor<T>* proc, Player& P) :
+            PrepLessInput<T>(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<int> 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 af076b02a525704e441fcfc56eadaa511f266d69..e7033fce924def3da9c10960cc1acd914ee516c5 100644
--- a/Processor/ReplicatedInput.hpp
+++ b/Processor/ReplicatedInput.hpp
@@ -10,9 +10,10 @@
 template<class T>
 void ReplicatedInput<T>::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<T>::reset(int player)
 template<class T>
 void ReplicatedInput<T>::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<T>::add_other(int player)
 template<class T>
 void ReplicatedInput<T>::send_mine()
 {
-    proc.P.send_relative(os);
+    P.send_relative(os);
 }
 
 template<class T>
-void ReplicatedInput<T>::start(int player, int n_inputs)
+void PrepLessInput<T>::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<T>::start(int player, int n_inputs)
 }
 
 template<class T>
-void ReplicatedInput<T>::stop(int player, vector<int> targets)
+void PrepLessInput<T>::stop(int player, vector<int> 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<T>::stop(int player, vector<int> 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<class T>
+void ReplicatedInput<T>::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<class T>
+T PrepLessInput<T>::finalize_mine()
+{
+    return this->shares[this->i_share++];
+}
diff --git a/Processor/ReplicatedMachine.h b/Processor/ReplicatedMachine.h
index a373112d0286f13f13e8a63ca5da5256557af7d2..b2053021778c8d5618c0476dc3929bfd75ab4ff2 100644
--- a/Processor/ReplicatedMachine.h
+++ b/Processor/ReplicatedMachine.h
@@ -13,7 +13,8 @@ template<class T, class U>
 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 1af471aef2fa94eaf2b3d44834866b53ee276ab5..5a8ead25ceb775ca22e732e5013a525c77140ce9 100644
--- a/Processor/ReplicatedMachine.hpp
+++ b/Processor/ReplicatedMachine.hpp
@@ -12,9 +12,8 @@
 
 template<class T, class U>
 ReplicatedMachine<T, U>::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<T, U>::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<T, U>(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 890aa5d77e4c96141c4dee964d52e8f6b409a627..7b06c02df1b907caece7d0f66509aa0d3e217812 100644
--- a/Processor/ReplicatedPrep.h
+++ b/Processor/ReplicatedPrep.h
@@ -15,8 +15,6 @@ template<class T>
 class BufferPrep : public Preprocessing<T>
 {
 protected:
-    static const int buffer_size = 1000;
-
     vector<array<T, 3>> triples;
     vector<array<T, 2>> squares;
     vector<array<T, 2>> inverses;
@@ -30,6 +28,8 @@ protected:
     virtual void buffer_inverses(MAC_Check_Base<T>& 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<T>
 protected:
     template<class U> friend class MaliciousRepPrep;
 
-    Replicated<T>* protocol;
+    typename T::Protocol* protocol;
+    SubProcessor<T>* proc;
 
     void buffer_triples();
     void buffer_squares();
     void buffer_inverses() { throw runtime_error("not inverses in rings"); }
-    void buffer_bits();
 
 public:
-    ReplicatedRingPrep();
+    ReplicatedRingPrep(SubProcessor<T>* proc);
+    virtual ~ReplicatedRingPrep() {}
 
-    void set_protocol(Replicated<T>& protocol) { this->protocol = &protocol; }
+    void set_protocol(typename T::Protocol& protocol) { this->protocol = &protocol; }
+
+    virtual void buffer_bits();
 };
 
 template<class T>
 class ReplicatedPrep: public ReplicatedRingPrep<T>
 {
     void buffer_inverses();
+
+public:
+    ReplicatedPrep(SubProcessor<T>* proc = 0) : ReplicatedRingPrep<T>(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 74070e064a71d5072ba5968d4b9b73d5b228bac5..19b7597b95840543b941f6febd30d37d9309de04 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<class T>
-ReplicatedRingPrep<T>::ReplicatedRingPrep() : protocol(0)
+ReplicatedRingPrep<T>::ReplicatedRingPrep(SubProcessor<T>* proc) :
+        protocol(0), proc(proc)
 {
 }
 
@@ -19,7 +21,7 @@ void ReplicatedRingPrep<T>::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<T>::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<T>::buffer_inverses()
 {
 	auto protocol = this->protocol;
     assert(protocol != 0);
-    ReplicatedMC<T> MC;
+    typename T::MAC_Check MC;
     BufferPrep<T>::buffer_inverses(MC, protocol->P);
 }
 
@@ -126,60 +128,96 @@ void BufferPrep<T>::get_two(Dtype dtype, T& a, T& b)
 }
 
 template<class T>
-void ReplicatedRingPrep<T>::buffer_bits()
+void XOR(vector<T>& res, vector<T>& x, vector<T>& y, int buffer_size,
+		typename T::Protocol& prot, SubProcessor<T>* proc)
 {
-    assert(protocol != 0);
-#ifdef BIT_BY_SQUARE
-    vector<array<Rep3Share<gfp>, 2>> squares(buffer_size);
-    vector<Rep3Share<gfp>> 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<gfp> open;
-    ReplicatedMC<Rep3Share<gfp>>().POpen(open, s, protocol->P);
-    auto one = Rep3Share<gfp>(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<template<class U> class T>
+void buffer_bits_spec(ReplicatedPrep<T<gfp>>& prep, vector<T<gfp>>& bits,
+    typename T<gfp>::Protocol& prot)
+{
+    (void) bits, (void) prot;
+    if (get_n_relevant_players(prot.P) > 10)
+    {
+        vector<array<T<gfp>, 2>> squares(prep.buffer_size);
+        vector<T<gfp>> 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<gfp> open;
+        typename T<gfp>::MAC_Check().POpen(open, s, prot.P);
+        auto one = T<gfp>(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<T<gfp>>::buffer_bits();
+}
+
+template<class T>
+void ReplicatedRingPrep<T>::buffer_bits()
+{
+    assert(protocol != 0);
     auto buffer_size = this->buffer_size;
     auto& bits = this->bits;
-    vector<vector<T>> player_bits(3, vector<T>(buffer_size));
-    vector<octetStream> 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<vector<T>> player_bits(n_relevant_players, vector<T>(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<T> 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<T> 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<Rep3Share<gf2n>>::buffer_bits()
     }
 }
 
+template<template<class U> class T>
+void buffer_bits_spec(ReplicatedPrep<T<gf2n>>& prep, vector<T<gf2n>>& bits,
+    typename T<gf2n>::Protocol& prot)
+{
+    (void) bits, (void) prot;
+    prep.ReplicatedRingPrep<T<gf2n>>::buffer_bits();
+}
+
+template<class T>
+void ReplicatedPrep<T>::buffer_bits()
+{
+    assert(this->protocol != 0);
+    buffer_bits_spec(*this, this->bits, *this->protocol);
+}
+
 template<class T>
 void BufferPrep<T>::get_one(Dtype dtype, T& a)
 {
@@ -224,13 +277,3 @@ void BufferPrep<T>::get(vector<T>& S, DataTag tag,
     (void) S, (void) tag, (void) regs, (void) vector_size;
     throw not_implemented();
 }
-
-template class BufferPrep<Rep3Share<gfp>>;
-template class BufferPrep<Rep3Share<gf2n>>;
-template class BufferPrep<MaliciousRep3Share<gfp>>;
-template class BufferPrep<MaliciousRep3Share<gf2n>>;
-template class ReplicatedPrep<Rep3Share<gfp>>;
-template class ReplicatedPrep<Rep3Share<gf2n>>;
-template class ReplicatedRingPrep<Rep3Share<Integer>>;
-template class ReplicatedRingPrep<Rep3Share<gfp>>;
-template class ReplicatedRingPrep<Rep3Share<gf2n>>;
diff --git a/Processor/Shamir.h b/Processor/Shamir.h
new file mode 100644
index 0000000000000000000000000000000000000000..92735797f83f3f664fb5e6e9800eb80fc933092c
--- /dev/null
+++ b/Processor/Shamir.h
@@ -0,0 +1,60 @@
+/*
+ * Shamir.h
+ *
+ */
+
+#ifndef PROCESSOR_SHAMIR_H_
+#define PROCESSOR_SHAMIR_H_
+
+#include <vector>
+using namespace std;
+
+#include "Replicated.h"
+
+template<class T> class SubProcessor;
+template<class T> class ShamirMC;
+template<class T> class ShamirShare;
+template<class T> class ShamirInput;
+
+class Player;
+
+template<class U>
+class Shamir : public PrepLessProtocol<ShamirShare<U>>
+{
+    typedef ShamirShare<U> T;
+
+    vector<octetStream> os;
+    vector<U> reconstruction;
+    U rec_factor;
+    ShamirInput<T>* resharing;
+
+    SeededPRNG secure_prng;
+
+    vector<T> 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<T>* 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 0000000000000000000000000000000000000000..c82b7e93d037fa2b9a2e8eaf3c432d9d0daacba1
--- /dev/null
+++ b/Processor/Shamir.hpp
@@ -0,0 +1,121 @@
+/*
+ * Shamir.cpp
+ *
+ */
+
+#include "Shamir.h"
+#include "ShamirInput.h"
+#include "ShamirMachine.h"
+
+template<class U>
+U Shamir<U>::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<class U>
+Shamir<U>::Shamir(Player& P) : resharing(0), P(P)
+{
+    threshold = ShamirMachine::s().threshold;
+    n_mul_players = 2 * threshold + 1;
+}
+
+template<class U>
+Shamir<U>::~Shamir()
+{
+    if (resharing != 0)
+        delete resharing;
+}
+
+template<class U>
+void Shamir<U>::reset()
+{
+    os.clear();
+    os.resize(P.num_players());
+
+    if (resharing == 0)
+    {
+        resharing = new ShamirInput<T>(0, P);
+    }
+
+    for (int i = 0; i < P.num_players(); i++)
+        resharing->reset(i);
+}
+
+template<class U>
+void Shamir<U>::init_mul(SubProcessor<T>* 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<class U>
+U Shamir<U>::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<class U>
+void Shamir<U>::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<class U>
+ShamirShare<U> Shamir<U>::finalize_mul()
+{
+    return finalize(n_mul_players);
+}
+
+template<class U>
+ShamirShare<U> Shamir<U>::finalize(int n_relevant_players)
+{
+    ShamirShare<U> 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<class U>
+ShamirShare<U> Shamir<U>::get_random()
+{
+    if (random.empty())
+        buffer_random();
+    auto res = random.back();
+    random.pop_back();
+    return res;
+}
+
+template<class U>
+void Shamir<U>::buffer_random()
+{
+    Shamir<U> 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<U>());
+    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 0000000000000000000000000000000000000000..ce2596e26d495814c59fb3c3e744da000065b306
--- /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 T>
+class ShamirInput : public PrepLessInput<T>
+{
+    Player& P;
+    vector<octetStream> os;
+    vector<vector<typename T::clear>> vandermonde;
+    SeededPRNG secure_prng;
+
+    vector<T> randomness;
+
+public:
+    ShamirInput(SubProcessor<T>& proc) :
+            PrepLessInput<T>(&proc), P(proc.P)
+    {
+    }
+
+    ShamirInput(SubProcessor<T>& proc, ShamirMC<T>& MC) :
+            ShamirInput(proc)
+    {
+        (void) MC;
+    }
+
+    ShamirInput(SubProcessor<T>* proc, Player& P) :
+            PrepLessInput<T>(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 0000000000000000000000000000000000000000..b5483836fe3a37bbfb7bd1b206ddf7403c86b015
--- /dev/null
+++ b/Processor/ShamirInput.hpp
@@ -0,0 +1,75 @@
+/*
+ * ShamirInput.cpp
+ *
+ */
+
+#include "ShamirInput.h"
+#include "ShamirMachine.h"
+
+template<class U>
+void ShamirInput<U>::reset(int player)
+{
+    if (player == P.my_num())
+    {
+        this->shares.clear();
+        this->i_share = 0;
+        os.clear();
+        os.resize(P.num_players());
+    }
+}
+
+template<class T>
+void ShamirInput<T>::add_mine(const typename T::clear& input)
+{
+    int n = P.num_players();
+    int t = ShamirMachine::s().threshold;
+    if (vandermonde.empty())
+    {
+        vandermonde.resize(n, vector<typename T::clear>(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<class U>
+void ShamirInput<U>::add_other(int player)
+{
+    (void) player;
+}
+
+template<class U>
+void ShamirInput<U>::send_mine()
+{
+    for (int i = 0; i < P.num_players(); i++)
+        if (i != P.my_num())
+            P.send_to(i, os[i], true);
+}
+
+template<class T>
+void ShamirInput<T>::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 0000000000000000000000000000000000000000..75b12f2b785b39c9fcaf56af8f13fe7c97c6d799
--- /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<template<class U> class T>
+ShamirMachineSpec<T>::ShamirMachineSpec(int argc, const char** argv) :
+        ShamirMachine(argc, argv)
+{
+    ReplicatedMachine<T<gfp>, T<gf2n>>(argc, argv, "shamir", opt, nparties);
+}
+
+template class ShamirMachineSpec<ShamirShare>;
+template class ShamirMachineSpec<MaliciousShamirShare>;
diff --git a/Processor/ShamirMachine.h b/Processor/ShamirMachine.h
new file mode 100644
index 0000000000000000000000000000000000000000..49990783c1fe0c3fce83144aceb0b3cddf6493bd
--- /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<template<class U> 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 60d0ab536d2d264c088b75578a4eca891f43e042..825ed8abd4f46125eba8731e13e80e8b851e22f9 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 <nparties>`
+
+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<playerno>-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 0000000000000000000000000000000000000000..33678d7b57edd73b7656dd4ebb717d6cdeb49178
--- /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 bdbde4fc6c21889171145ab64d8d38383a3d89ef..870cabad369c17c7ed0b22ea4bdaa2942aef12fd 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 0000000000000000000000000000000000000000..c1579a7ebdc308e1e94eaaba1ffd8114e37a5871
--- /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 83639d53cf64ea3fb72d543335ce8d028470041c..27760c3df13b2c8fccc460d1873ad9979996daf7 100644
--- a/Tools/random.h
+++ b/Tools/random.h
@@ -90,6 +90,10 @@ class PRNG
 
    const octet* get_seed() const
      { return seed; }
+
+   template<class T>
+   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 e2300519e6d7cdf85c84d72799235eeb3c664bdd..307bd96eef39d6d3b67e7916f09d08bd84384dbb 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<gfp>, MaliciousRep3Share<gf2n>>(argc, argv, "malicious-rep-field");
+    ez::ezOptionParser opt;
+    ReplicatedMachine<MaliciousRep3Share<gfp>, MaliciousRep3Share<gf2n>>(argc,
+            argv, "malicious-rep-field", opt);
 }
diff --git a/malicious-shamir-party.cpp b/malicious-shamir-party.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..39e785642cfa02b70284b335d44552a24d084eda
--- /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<MaliciousShamirShare>(argc, argv);
+}
diff --git a/replicated-field-party.cpp b/replicated-field-party.cpp
index 9e27f5365c0e228d2a344200e2d991cb030cf88a..eab7897d0f5ffbcfbc3de1bf81e64a3ccb07cd4d 100644
--- a/replicated-field-party.cpp
+++ b/replicated-field-party.cpp
@@ -8,5 +8,7 @@
 
 int main(int argc, const char** argv)
 {
-    ReplicatedMachine<Rep3Share<gfp>, Rep3Share<gf2n>>(argc, argv, "replicated-field");
+    ez::ezOptionParser opt;
+    ReplicatedMachine<Rep3Share<gfp>, Rep3Share<gf2n>>(argc, argv,
+            "replicated-field", opt);
 }
diff --git a/replicated-ring-party.cpp b/replicated-ring-party.cpp
index 9c6fe733433a18b16c3a99487659d75680846155..8977a2c4ed6e7451bee74465d51a4de973502887 100644
--- a/replicated-ring-party.cpp
+++ b/replicated-ring-party.cpp
@@ -8,5 +8,7 @@
 
 int main(int argc, const char** argv)
 {
-    ReplicatedMachine<Rep3Share<Integer>, Rep3Share<gf2n>>(argc, argv, "replicated-ring");
+    ez::ezOptionParser opt;
+    ReplicatedMachine<Rep3Share<Integer>, Rep3Share<gf2n>>(argc, argv,
+            "replicated-ring", opt);
 }
diff --git a/shamir-party.cpp b/shamir-party.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..db9dd4835645b1771f3645ac6df6b9c4104da99e
--- /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<ShamirShare>(argc, argv);
+}