Forráskód Böngészése

mpc_and, mpc_or for bit shares

Ian Goldberg 1 éve
szülő
commit
bc5dc4a257
5 módosított fájl, 110 hozzáadás és 5 törlés
  1. 17 0
      mpcio.cpp
  2. 6 0
      mpcio.hpp
  3. 52 5
      mpcops.cpp
  4. 16 0
      mpcops.hpp
  5. 19 0
      online.cpp

+ 17 - 0
mpcio.cpp

@@ -433,6 +433,7 @@ MPCTIO::MPCTIO(MPCIO &mpcio, int thread_num, int num_threads) :
 #ifdef VERBOSE_COMMS
         , round_num(0)
 #endif
+        , last_andtriple_bits_remaining(0)
 {
     if (mpcio.player < 2) {
         MPCPeerIO &mpcpio = static_cast<MPCPeerIO&>(mpcio);
@@ -783,6 +784,22 @@ SelectTriple<value_t> MPCTIO::valselecttriple(yield_t &yield)
     return val;
 }
 
+SelectTriple<bit_t> MPCTIO::bitselecttriple(yield_t &yield)
+{
+    // Do we need to fetch a new AND triple?
+    if (last_andtriple_bits_remaining == 0) {
+        last_andtriple = andtriple(yield);
+        last_andtriple_bits_remaining = 8*sizeof(value_t);
+    }
+    --last_andtriple_bits_remaining;
+    value_t mask = value_t(1) << last_andtriple_bits_remaining;
+    SelectTriple<bit_t> val;
+    val.X = !!(std::get<0>(last_andtriple) & mask);
+    val.Y = !!(std::get<1>(last_andtriple) & mask);
+    val.Z = !!(std::get<2>(last_andtriple) & mask);
+    return val;
+}
+
 // Only computational peers call this; the server should be calling
 // rdpfpair() at the same time
 RDPFTriple MPCTIO::rdpftriple(yield_t &yield, nbits_t depth,

+ 6 - 0
mpcio.hpp

@@ -304,6 +304,11 @@ class MPCTIO {
     size_t round_num;
 #endif
 
+    // We implement SelectTriple<bit_t> by fetching a single AndTriple
+    // and using it for producing 64 bitwise SelectTriple<bit_t>s.
+    AndTriple last_andtriple;
+    nbits_t last_andtriple_bits_remaining;
+
 public:
     MPCTIO(MPCIO &mpcio, int thread_num, int num_threads = 1);
 
@@ -378,6 +383,7 @@ public:
     AndTriple andtriple(yield_t &yield);
     SelectTriple<DPFnode> nodeselecttriple(yield_t &yield);
     SelectTriple<value_t> valselecttriple(yield_t &yield);
+    SelectTriple<bit_t> bitselecttriple(yield_t &yield);
 
     // These ones only work during the online phase
     // Computational peers call:

+ 52 - 5
mpcops.cpp

@@ -174,11 +174,8 @@ void mpc_select(MPCTIO &tio, yield_t &yield,
 
     // Compute our share of f ? x : y = (f * (x ^ y))^x
     value_t peer_blind_fext = -value_t(peer_blind_f);
-    value_t zshare =
-            (fext & peer_blind_d) ^ (Y & peer_blind_fext) ^
-            (fext & d) ^ (Z ^ x.xshare);
-
-    z.set(zshare & mask);
+    z.xshare = ((fext & peer_blind_d) ^ (Y & peer_blind_fext) ^
+            (fext & d) ^ (Z ^ x.xshare)) & mask;
 }
 
 // P0 and P1 hold bit shares f0 and f1 of the single bit f, and additive
@@ -300,3 +297,53 @@ void mpc_reconstruct_choice(MPCTIO &tio, yield_t &yield,
 
     z = zshare ^ peer_zshare;
 }
+
+// P0 and P1 hold bit shares of x and y.  Set z to bit shares of x & y.
+//
+// Cost:
+// 1 byte sent in 1 message
+// consumes 1/64 AndTriple
+void mpc_and(MPCTIO &tio, yield_t &yield,
+    RegBS &z, RegBS x, RegBS y)
+{
+    // Compute XOR shares of x & y
+    auto T = tio.bitselecttriple(yield);
+    bit_t blind_x = x.bshare ^ T.X;
+    bit_t blind_y = y.bshare ^ T.Y;
+
+    // Send the blinded values
+    uint8_t v = (blind_x << 1) | blind_y;
+    tio.queue_peer(&v, sizeof(v));
+
+    yield();
+
+    // Read the peer's values
+    bit_t peer_blind_x = 0;
+    bit_t peer_blind_y = 0;
+    uint8_t peer_v = 0;
+    tio.recv_peer(&peer_v, sizeof(peer_v));
+    peer_blind_x = (peer_v >> 1) & 1;
+    peer_blind_y = peer_v & 1;
+
+    // Compute our share of x & y
+    z.bshare = (x.bshare & peer_blind_y) ^ (T.Y & peer_blind_x) ^
+        (x.bshare & y.bshare) ^ T.Z;
+}
+
+// P0 and P1 hold bit shares of x and y.  Set z to bit shares of x | y.
+//
+// Cost:
+// 1 byte sent in 1 message
+// consumes 1/64 AndTriple
+void mpc_or(MPCTIO &tio, yield_t &yield,
+    RegBS &z, RegBS x, RegBS y)
+{
+    if (tio.player() == 0) {
+        x.bshare = !x.bshare;
+        y.bshare = !y.bshare;
+    }
+    mpc_and(tio, yield, z, x, y);
+    if (tio.player() == 0) {
+        z.bshare = !z.bshare;
+    }
+}

+ 16 - 0
mpcops.hpp

@@ -110,4 +110,20 @@ void mpc_xs_to_as(MPCTIO &tio, yield_t &yield,
 void mpc_reconstruct_choice(MPCTIO &tio, yield_t &yield,
     DPFnode &z, RegBS f, DPFnode x, DPFnode y);
 
+// P0 and P1 hold bit shares of x and y.  Set z to bit shares of x & y.
+//
+// Cost:
+// 1 byte sent in 1 message
+// consumes 1/64 AndTriple
+void mpc_and(MPCTIO &tio, yield_t &yield,
+    RegBS &z, RegBS x, RegBS y);
+
+// P0 and P1 hold bit shares of x and y.  Set z to bit shares of x | y.
+//
+// Cost:
+// 1 byte sent in 1 message
+// consumes 1/64 AndTriple
+void mpc_or(MPCTIO &tio, yield_t &yield,
+    RegBS &z, RegBS x, RegBS y);
+
 #endif

+ 19 - 0
online.cpp

@@ -27,6 +27,7 @@ static void online_test(MPCIO &mpcio,
     RegXS *AX = new RegXS[xs_memsize];
     value_t V;
     RegBS F0, F1;
+    RegBS FA, FO;
     RegXS X;
 
     if (!is_server) {
@@ -73,6 +74,14 @@ static void online_test(MPCIO &mpcio,
         [&tio, &AX, &F0, nbits](yield_t &yield) {
             mpc_select(tio, yield, AX[2], F0, AX[0], AX[1], nbits);
         });
+    coroutines.emplace_back(
+        [&tio, &FA, &F0, &F1, nbits](yield_t &yield) {
+            mpc_and(tio, yield, FA, F0, F1);
+        });
+    coroutines.emplace_back(
+        [&tio, &FO, &F0, &F1, nbits](yield_t &yield) {
+            mpc_or(tio, yield, FO, F0, F1);
+        });
     run_coroutines(tio, coroutines);
     if (!is_server) {
         printf("\n");
@@ -87,33 +96,43 @@ static void online_test(MPCIO &mpcio,
         tio.queue_peer(&V, sizeof(V));
         tio.queue_peer(&F0, sizeof(RegBS));
         tio.queue_peer(&F1, sizeof(RegBS));
+        tio.queue_peer(&FA, sizeof(RegBS));
+        tio.queue_peer(&FO, sizeof(RegBS));
         tio.queue_peer(&X, sizeof(RegXS));
         tio.send();
     } else if (mpcio.player == 0) {
         RegAS *B = new RegAS[as_memsize];
         RegXS *BAX = new RegXS[xs_memsize];
         RegBS BF0, BF1;
+        RegBS BFA, BFO;
         RegXS BX;
         value_t BV;
         value_t *S = new value_t[as_memsize];
         value_t *Y = new value_t[xs_memsize];
         bit_t SF0, SF1;
+        bit_t SFA, SFO;
         value_t SX;
         tio.recv_peer(B, as_memsize*sizeof(RegAS));
         tio.recv_peer(BAX, xs_memsize*sizeof(RegXS));
         tio.recv_peer(&BV, sizeof(BV));
         tio.recv_peer(&BF0, sizeof(RegBS));
         tio.recv_peer(&BF1, sizeof(RegBS));
+        tio.recv_peer(&BFA, sizeof(RegBS));
+        tio.recv_peer(&BFO, sizeof(RegBS));
         tio.recv_peer(&BX, sizeof(RegXS));
         for(size_t i=0; i<as_memsize; ++i) S[i] = A[i].ashare+B[i].ashare;
         for(size_t i=0; i<xs_memsize; ++i) Y[i] = AX[i].xshare^BAX[i].xshare;
         SF0 = F0.bshare ^ BF0.bshare;
         SF1 = F1.bshare ^ BF1.bshare;
+        SFA = FA.bshare ^ BFA.bshare;
+        SFO = FO.bshare ^ BFO.bshare;
         SX = X.xshare ^ BX.xshare;
         printf("S:\n"); for (size_t i=0; i<as_memsize; ++i) printf("%3lu: %016lX\n", i, S[i]);
         printf("Y:\n"); for (size_t i=0; i<xs_memsize; ++i) printf("%3lu: %016lX\n", i, Y[i]);
         printf("SF0: %01X\n", SF0);
         printf("SF1: %01X\n", SF1);
+        printf("SFA: %01X\n", SFA);
+        printf("SFO: %01X\n", SFO);
         printf("SX : %016lX\n", SX);
         printf("\n%016lx\n", S[0]*S[1]-S[2]);
         printf("%016lx\n", (V*BV)-S[3]);