|
@@ -0,0 +1,199 @@
|
|
|
+package protocols;
|
|
|
+
|
|
|
+import java.math.BigInteger;
|
|
|
+
|
|
|
+import com.oblivm.backend.flexsc.CompEnv;
|
|
|
+import com.oblivm.backend.gc.GCGenComp;
|
|
|
+import com.oblivm.backend.gc.GCSignal;
|
|
|
+import com.oblivm.backend.gc.regular.GCEva;
|
|
|
+import com.oblivm.backend.gc.regular.GCGen;
|
|
|
+import com.oblivm.backend.network.Network;
|
|
|
+
|
|
|
+import communication.Communication;
|
|
|
+import crypto.Crypto;
|
|
|
+import exceptions.NoSuchPartyException;
|
|
|
+import gc.GCLib;
|
|
|
+import oram.Forest;
|
|
|
+import oram.Metadata;
|
|
|
+import util.Util;
|
|
|
+
|
|
|
+public class DeepestAndEmpty extends Protocol {
|
|
|
+
|
|
|
+ private int d = 10;
|
|
|
+ private int w = 8;
|
|
|
+
|
|
|
+ public DeepestAndEmpty(Communication con1, Communication con2) {
|
|
|
+ super(con1, con2);
|
|
|
+ }
|
|
|
+
|
|
|
+ private GCSignal[] revSelectKeys(GCSignal[][] pairs, byte[] input) {
|
|
|
+ BigInteger in = new BigInteger(1, input);
|
|
|
+ GCSignal[] out = new GCSignal[pairs.length];
|
|
|
+ for (int i = 0; i < pairs.length; i++)
|
|
|
+ out[i] = pairs[i][in.testBit(i) ? 1 : 0];
|
|
|
+ return out;
|
|
|
+ }
|
|
|
+
|
|
|
+ private GCSignal[] selectKeys(GCSignal[][] pairs, byte[] input) {
|
|
|
+ BigInteger in = new BigInteger(1, input);
|
|
|
+ GCSignal[] out = new GCSignal[pairs.length];
|
|
|
+ for (int i = 0; i < pairs.length; i++)
|
|
|
+ out[i] = pairs[i][in.testBit(pairs.length - 1 - i) ? 1 : 0];
|
|
|
+ return out;
|
|
|
+ }
|
|
|
+
|
|
|
+ private GCSignal[][] genKeyPairs(int n) {
|
|
|
+ GCSignal[][] pairs = new GCSignal[n][];
|
|
|
+ for (int i = 0; i < n; i++)
|
|
|
+ pairs[i] = GCGenComp.genPair();
|
|
|
+ return pairs;
|
|
|
+ }
|
|
|
+
|
|
|
+ private GCSignal[] getZeroKeys(GCSignal[][] pairs) {
|
|
|
+ GCSignal[] keys = new GCSignal[pairs.length];
|
|
|
+ for (int i = 0; i < keys.length; i++)
|
|
|
+ keys[i] = pairs[i][0];
|
|
|
+ return keys;
|
|
|
+ }
|
|
|
+
|
|
|
+ private BigInteger decodeOutput(GCSignal[] out1, GCSignal[] out2) {
|
|
|
+ BigInteger output = BigInteger.ZERO;
|
|
|
+ for (int i = 0; i < out1.length; i++) {
|
|
|
+ if (out2[i].isPublic()) {
|
|
|
+ if (out2[i].v)
|
|
|
+ output = output.setBit(i);
|
|
|
+ } else if (out1[i].equals(out2[i])) {
|
|
|
+ ;
|
|
|
+ } else if (out1[i].equals(GCGenComp.R.xor(out2[i]))) {
|
|
|
+ output = output.setBit(i);
|
|
|
+ } else {
|
|
|
+ System.err.println("ERROR on GC output!");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return output;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String addZeros(String a, int n) {
|
|
|
+ String out = a;
|
|
|
+ for (int i = 0; i < n - a.length(); i++)
|
|
|
+ out = "0" + out;
|
|
|
+ return out;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void runE() {
|
|
|
+ int i = Crypto.sr.nextInt(d);
|
|
|
+ byte[] Li = Util.nextBytes((d - 1 + 7) / 8, Crypto.sr);
|
|
|
+ byte[] feBits = Util.nextBytes((w + 7) / 8, Crypto.sr);
|
|
|
+ byte[][] tupleLabels = new byte[w][];
|
|
|
+ for (int j = 0; j < w; j++)
|
|
|
+ tupleLabels[j] = Util.nextBytes((d - 1 + 7) / 8, Crypto.sr);
|
|
|
+
|
|
|
+ GCSignal[][] E_feKeyPairs = genKeyPairs(w);
|
|
|
+ GCSignal[][] C_feKeyPairs = genKeyPairs(w);
|
|
|
+ GCSignal[] E_feZeroKeys = getZeroKeys(E_feKeyPairs);
|
|
|
+ GCSignal[] C_feZeroKeys = getZeroKeys(C_feKeyPairs);
|
|
|
+ GCSignal[] E_feKeyInput = selectKeys(E_feKeyPairs, feBits);
|
|
|
+
|
|
|
+ GCSignal[][][] E_labelKeyPairs = new GCSignal[w][][];
|
|
|
+ GCSignal[][][] C_labelKeyPairs = new GCSignal[w][][];
|
|
|
+ GCSignal[][] E_labelZeroKeys = new GCSignal[w][];
|
|
|
+ GCSignal[][] C_labelZeroKeys = new GCSignal[w][];
|
|
|
+ GCSignal[][] E_labelKeyInput = new GCSignal[w][];
|
|
|
+ for (int j = 0; j < w; j++) {
|
|
|
+ E_labelKeyPairs[j] = genKeyPairs(d - 1);
|
|
|
+ C_labelKeyPairs[j] = genKeyPairs(d - 1);
|
|
|
+ E_labelZeroKeys[j] = getZeroKeys(E_labelKeyPairs[j]);
|
|
|
+ C_labelZeroKeys[j] = getZeroKeys(C_labelKeyPairs[j]);
|
|
|
+ E_labelKeyInput[j] = revSelectKeys(E_labelKeyPairs[j], tupleLabels[j]);
|
|
|
+ }
|
|
|
+
|
|
|
+ con1.write(i);
|
|
|
+ con1.write(Li);
|
|
|
+ con1.write(E_feKeyInput);
|
|
|
+ con1.write(C_feZeroKeys);
|
|
|
+ con1.write(E_labelKeyInput);
|
|
|
+ con1.write(C_labelZeroKeys);
|
|
|
+
|
|
|
+ Network channel = new Network(null, con1);
|
|
|
+ CompEnv<GCSignal> gen = new GCGen(channel);
|
|
|
+ GCSignal[][] E_out = new GCLib<GCSignal>(gen, d, w).deepestAndEmptyTuples(i, Li, E_feZeroKeys, C_feZeroKeys,
|
|
|
+ E_labelZeroKeys, C_labelZeroKeys);
|
|
|
+
|
|
|
+ GCSignal[][] D_out = con1.readObject();
|
|
|
+
|
|
|
+ int l = decodeOutput(E_out[0], D_out[0]).intValue();
|
|
|
+ int j1 = decodeOutput(E_out[1], D_out[1]).intValue();
|
|
|
+ int j2 = decodeOutput(E_out[2], D_out[2]).intValue();
|
|
|
+ int et = decodeOutput(E_out[3], D_out[3]).intValue();
|
|
|
+
|
|
|
+ System.out.println("i=" + i);
|
|
|
+
|
|
|
+ System.out.print("full tuples: ");
|
|
|
+ BigInteger fe = new BigInteger(1, feBits);
|
|
|
+ for (int j = 0; j < w; j++)
|
|
|
+ if (fe.testBit(w - 1 - j))
|
|
|
+ System.out.print(j + " ");
|
|
|
+ System.out.println();
|
|
|
+ System.out.print("empty tuples: ");
|
|
|
+ for (int j = 0; j < w; j++)
|
|
|
+ if (!fe.testBit(w - 1 - j))
|
|
|
+ System.out.print(j + " ");
|
|
|
+ System.out.println();
|
|
|
+
|
|
|
+ System.out.println("tuple labels xor path label:");
|
|
|
+ BigInteger pathLabel = new BigInteger(1, Li);
|
|
|
+ for (int j = 0; j < w; j++) {
|
|
|
+ BigInteger xor = Util.getSubBits(new BigInteger(1, tupleLabels[j]).xor(pathLabel), d - 1, 0);
|
|
|
+ System.out.println(j + ": " + addZeros(xor.toString(2), d - 1));
|
|
|
+ }
|
|
|
+
|
|
|
+ System.out.println();
|
|
|
+ System.out.println("deepest level: " + l);
|
|
|
+ System.out.println("deepest tuple index: " + j1);
|
|
|
+ System.out.println("empty tuple index: " + j2);
|
|
|
+ System.out.println("empty tuple exists: " + et);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void runD() {
|
|
|
+ int i = con1.readObject();
|
|
|
+ byte[] Li = con1.read();
|
|
|
+ GCSignal[] E_feKeyInput = con1.readObject();
|
|
|
+ GCSignal[] C_feZeroKeys = con1.readObject();
|
|
|
+ GCSignal[][] E_labelKeyInput = con1.readObject();
|
|
|
+ GCSignal[][] C_labelZeroKeys = con1.readObject();
|
|
|
+
|
|
|
+ Network channel = new Network(con1, null);
|
|
|
+ CompEnv<GCSignal> gen = new GCEva(channel);
|
|
|
+ GCLib<GCSignal> dae = new GCLib<GCSignal>(gen, d, w);
|
|
|
+ dae.deepestAndEmptyTuples(i, Li, E_feKeyInput, C_feZeroKeys, E_labelKeyInput, C_labelZeroKeys);
|
|
|
+
|
|
|
+ gen.setEvaluate();
|
|
|
+ GCSignal[][] D_out = dae.deepestAndEmptyTuples(i, Li, E_feKeyInput, C_feZeroKeys, E_labelKeyInput,
|
|
|
+ C_labelZeroKeys);
|
|
|
+
|
|
|
+ con1.write(D_out);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void runC() {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // for testing correctness
|
|
|
+ @Override
|
|
|
+ public void run(Party party, Metadata md, Forest forest) {
|
|
|
+
|
|
|
+ if (party == Party.Eddie) {
|
|
|
+ runE();
|
|
|
+
|
|
|
+ } else if (party == Party.Debbie) {
|
|
|
+ runD();
|
|
|
+
|
|
|
+ } else if (party == Party.Charlie) {
|
|
|
+ runC();
|
|
|
+
|
|
|
+ } else {
|
|
|
+ throw new NoSuchPartyException(party + "");
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|