Browse Source

first commit

Boyoung- 8 years ago
commit
4b9a8eeed0
65 changed files with 3797 additions and 0 deletions
  1. 7 0
      .classpath
  2. 1 0
      .gitignore
  3. 17 0
      .project
  4. 11 0
      .settings/org.eclipse.jdt.core.prefs
  5. 27 0
      build.xml
  6. 6 0
      config/config.yaml
  7. 144 0
      fastergc/Cipher/Cipher.java
  8. 110 0
      fastergc/YaoGC/AND_2_1.java
  9. 154 0
      fastergc/YaoGC/Circuit.java
  10. 43 0
      fastergc/YaoGC/CompositeCircuit.java
  11. 40 0
      fastergc/YaoGC/E_AND_2_1.java
  12. 45 0
      fastergc/YaoGC/E_FF10_1_SC_2_2.java
  13. 45 0
      fastergc/YaoGC/E_FF10_2_SC_2_2.java
  14. 45 0
      fastergc/YaoGC/E_FF10_3_SC_2_2.java
  15. 41 0
      fastergc/YaoGC/E_OR_2_1.java
  16. 40 0
      fastergc/YaoGC/E_T1_FF0_O_2_1.java
  17. 40 0
      fastergc/YaoGC/E_T1_FF0_S_2_1.java
  18. 40 0
      fastergc/YaoGC/E_T1_FF1_O_2_1.java
  19. 40 0
      fastergc/YaoGC/E_T1_FF1_S_2_1.java
  20. 40 0
      fastergc/YaoGC/E_T2_FF10_O_2_1.java
  21. 40 0
      fastergc/YaoGC/E_T2_FF10_S_2_1.java
  22. 24 0
      fastergc/YaoGC/E_XOR_2_1.java
  23. 55 0
      fastergc/YaoGC/F2ET_Wplus2_Wplus2.java
  24. 83 0
      fastergc/YaoGC/F2FT_2Wplus2_Wplus2.java
  25. 128 0
      fastergc/YaoGC/FF10_1_SC_2_2.java
  26. 78 0
      fastergc/YaoGC/FF10_2_2.java
  27. 128 0
      fastergc/YaoGC/FF10_2_SC_2_2.java
  28. 128 0
      fastergc/YaoGC/FF10_3_SC_2_2.java
  29. 65 0
      fastergc/YaoGC/FF10_Wplus1_Wplus1.java
  30. 24 0
      fastergc/YaoGC/G_AND_2_1.java
  31. 24 0
      fastergc/YaoGC/G_FF10_1_SC_2_2.java
  32. 24 0
      fastergc/YaoGC/G_FF10_2_SC_2_2.java
  33. 24 0
      fastergc/YaoGC/G_FF10_3_SC_2_2.java
  34. 24 0
      fastergc/YaoGC/G_OR_2_1.java
  35. 24 0
      fastergc/YaoGC/G_T1_FF0_O_2_1.java
  36. 24 0
      fastergc/YaoGC/G_T1_FF0_S_2_1.java
  37. 24 0
      fastergc/YaoGC/G_T1_FF1_O_2_1.java
  38. 24 0
      fastergc/YaoGC/G_T1_FF1_S_2_1.java
  39. 24 0
      fastergc/YaoGC/G_T2_FF10_O_2_1.java
  40. 24 0
      fastergc/YaoGC/G_T2_FF10_S_2_1.java
  41. 36 0
      fastergc/YaoGC/G_XOR_2_1.java
  42. 112 0
      fastergc/YaoGC/OR_2_1.java
  43. 163 0
      fastergc/YaoGC/SimpleCircuit_2_1.java
  44. 180 0
      fastergc/YaoGC/SimpleCircuit_2_2.java
  45. 164 0
      fastergc/YaoGC/State.java
  46. 126 0
      fastergc/YaoGC/T1_FF0_O_2_1.java
  47. 126 0
      fastergc/YaoGC/T1_FF0_S_2_1.java
  48. 126 0
      fastergc/YaoGC/T1_FF1_O_2_1.java
  49. 126 0
      fastergc/YaoGC/T1_FF1_S_2_1.java
  50. 126 0
      fastergc/YaoGC/T2_FF10_O_2_1.java
  51. 121 0
      fastergc/YaoGC/T2_FF10_S_2_1.java
  52. 33 0
      fastergc/YaoGC/TestCircuit.java
  53. 185 0
      fastergc/YaoGC/TransitiveObservable.java
  54. 39 0
      fastergc/YaoGC/TransitiveObserver.java
  55. 87 0
      fastergc/YaoGC/Wire.java
  56. 109 0
      fastergc/YaoGC/XOR_2_1.java
  57. BIN
      lib/bcprov-jdk15on-151.jar
  58. BIN
      lib/commons-cli-1.2.jar
  59. BIN
      lib/commons-io-2.4.jar
  60. BIN
      lib/commons-lang3-3.3.2.jar
  61. BIN
      lib/jargs.jar
  62. BIN
      lib/junit-4.10.jar
  63. BIN
      lib/snakeyaml-1.11.jar
  64. 1 0
      readmd.txt
  65. 8 0
      src/HelloWorld.java

+ 7 - 0
.classpath

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+	<classpathentry excluding="LookupTable/|Program/|YaoGC/AESComponents/|Test/|OT/|Utils/" kind="src" path="fastergc"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+bin/

+ 17 - 0
.project

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>CORAM3P</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>

+ 11 - 0
.settings/org.eclipse.jdt.core.prefs

@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8

+ 27 - 0
build.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" ?>
+<project name="CORAM3P" default="compile">
+
+  <target name="init" >
+    <mkdir dir="bin" />
+  </target>
+
+  <target name="compile" depends="init" >
+    <javac srcdir="src:fastergc" destdir="bin" debug="on" debuglevel="lines,vars,source" source="1.8" includeantruntime="false">
+      <classpath>
+        <pathelement location="lib/bcprov-jdk15on-151.jar"/>
+        <pathelement location="lib/commons-cli-1.2.jar"/>
+        <pathelement location="lib/commons-io-2.4.jar"/>
+        <pathelement location="lib/commons-lang3-3.3.2.jar"/>
+        <pathelement location="lib/jargs.jar"/>
+        <pathelement location="lib/junit-4.10.jar"/>
+        <pathelement location="lib/snakeyaml-1.11.jar"/>
+        <pathelement path="bin"/>
+      </classpath>
+    </javac>
+  </target>
+
+  <target name="clean" depends="init" >
+    <delete dir="bin" />
+  </target>
+
+</project>

+ 6 - 0
config/config.yaml

@@ -0,0 +1,6 @@
+tau: 3					# tau in the write-up
+nBits: 12				# bits of N in the record
+w: 4					# number of tuples in each bucket
+e: 4 					# number of buckets contained in each leaf
+dBytes: 4 				# record D bytes in the last tree
+insert: 1000			# number of records to be initially inserted (-1 means insert max number)

+ 144 - 0
fastergc/Cipher/Cipher.java

@@ -0,0 +1,144 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package Cipher;
+
+import java.security.*;
+import java.math.*;
+
+import sprout.crypto.SR;
+import YaoGC.Wire;
+
+public final class Cipher {
+	private static final int unitLength = 160; // SHA-1 has 160-bit output.
+
+	public static final BigInteger mask = BigInteger.ONE.shiftLeft(
+			Wire.labelBitLength).subtract(BigInteger.ONE);
+
+	private static final BigInteger mask128 = BigInteger.ONE.shiftLeft(128)
+			.subtract(BigInteger.ONE);
+	
+	private static final BigInteger mask160 = BigInteger.ONE.shiftLeft(160)
+			.subtract(BigInteger.ONE);
+
+	private static MessageDigest sha1 = SR.digest;
+	
+	public static synchronized BigInteger encrypt(BigInteger lp0,
+			BigInteger lp1, int k0, int k1, BigInteger m) {
+		BigInteger ret = getPadding(lp0, lp1, k0, k1);
+		ret = ret.xor(m);
+
+		return ret;
+	}
+
+	public static synchronized BigInteger encrypt(BigInteger lp0,
+			BigInteger lp1, int k, BigInteger m) {
+		BigInteger ret = getPadding(lp0, lp1, k);
+		ret = ret.xor(m);
+
+		return ret;
+	}
+	
+	public static synchronized BigInteger decrypt(BigInteger lp0,
+			BigInteger lp1, int k0, int k1, BigInteger c) {
+		BigInteger ret = getPadding(lp0, lp1, k0, k1);
+		ret = ret.xor(c);
+
+		return ret;
+	}
+
+	public static synchronized BigInteger decrypt(BigInteger lp0,
+			BigInteger lp1, int k, BigInteger c) {
+		BigInteger ret = getPadding(lp0, lp1, k);
+		ret = ret.xor(c);
+
+		return ret;
+	}
+
+	public static synchronized BigInteger encrypt(int w, BigInteger key,
+			int outBit) {
+		sha1.update(BigInteger.valueOf(w).toByteArray());
+		sha1.update(key.toByteArray());
+		return new BigInteger(sha1.digest()).and(mask128).xor(
+				BigInteger.valueOf(outBit));
+	}
+
+	public static synchronized int decrypt(int w, BigInteger key, BigInteger c) {
+		sha1.update(BigInteger.valueOf(w).toByteArray());
+		sha1.update(key.toByteArray());
+		return new BigInteger(sha1.digest()).and(mask128).xor(c).intValue();
+	}
+
+	// this padding generation function is dedicated for encrypting garbled
+	// tables.
+	private static synchronized BigInteger getPadding(BigInteger lp0,
+			BigInteger lp1, int k) {
+		sha1.update(lp0.toByteArray());
+		sha1.update(lp1.toByteArray());
+		sha1.update(BigInteger.valueOf(k).toByteArray());
+		return (new BigInteger(sha1.digest())).and(mask);
+	}
+	
+	private static synchronized BigInteger getPadding(BigInteger lp0,
+			BigInteger lp1, int k0, int k1) {
+		sha1.update(lp0.toByteArray());
+		sha1.update(lp1.toByteArray());
+		sha1.update(BigInteger.valueOf(k0).toByteArray());
+		sha1.update(BigInteger.valueOf(k1).toByteArray());
+		return (new BigInteger(sha1.digest())).and(mask160);
+	}
+
+	public static synchronized BigInteger encrypt(BigInteger key,
+			BigInteger msg, int msgLength) {
+		return msg.xor(getPaddingOfLength(key, msgLength));
+	}
+
+	public static synchronized BigInteger decrypt(BigInteger key,
+			BigInteger cph, int cphLength) {
+		return cph.xor(getPaddingOfLength(key, cphLength));
+	}
+
+	private static synchronized BigInteger getPaddingOfLength(BigInteger key,
+			int padLength) {
+		sha1.update(key.toByteArray());
+		BigInteger pad = BigInteger.ZERO;
+		byte[] tmp = new byte[unitLength / 8];
+		for (int i = 0; i < padLength / unitLength; i++) {
+			System.arraycopy(sha1.digest(), 0, tmp, 0, unitLength / 8);
+			pad = pad.shiftLeft(unitLength).xor(new BigInteger(1, tmp));
+			sha1.update(tmp);
+		}
+		System.arraycopy(sha1.digest(), 0, tmp, 0, unitLength / 8);
+		pad = pad.shiftLeft(padLength % unitLength).xor(
+				(new BigInteger(1, tmp)).shiftRight(unitLength
+						- (padLength % unitLength)));
+		return pad;
+	}
+
+	public static synchronized BigInteger encrypt(int j, BigInteger key,
+			BigInteger msg, int msgLength) {
+		return msg.xor(getPaddingOfLength(j, key, msgLength));
+	}
+
+	public static synchronized BigInteger decrypt(int j, BigInteger key,
+			BigInteger cph, int cphLength) {
+		return cph.xor(getPaddingOfLength(j, key, cphLength));
+	}
+
+	private static synchronized BigInteger getPaddingOfLength(int j,
+			BigInteger key, int padLength) {
+		sha1.update(BigInteger.valueOf(j).toByteArray());
+		sha1.update(key.toByteArray());
+		BigInteger pad = BigInteger.ZERO;
+		byte[] tmp = new byte[unitLength / 8];
+		for (int i = 0; i < padLength / unitLength; i++) {
+			System.arraycopy(sha1.digest(), 0, tmp, 0, unitLength / 8);
+			pad = pad.shiftLeft(unitLength).xor(new BigInteger(1, tmp));
+			sha1.update(tmp);
+		}
+		System.arraycopy(sha1.digest(), 0, tmp, 0, unitLength / 8);
+		pad = pad.shiftLeft(padLength % unitLength).xor(
+				(new BigInteger(1, tmp)).shiftRight(unitLength
+						- (padLength % unitLength)));
+		return pad;
+	}
+}

+ 110 - 0
fastergc/YaoGC/AND_2_1.java

@@ -0,0 +1,110 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+import java.math.*;
+
+import Cipher.*;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+public abstract class AND_2_1 extends SimpleCircuit_2_1 {
+	public AND_2_1() {
+		super("AND_2_1");
+	}
+
+	public static AND_2_1 newInstance() {
+		if (Circuit.isForGarbling)
+			return new G_AND_2_1();
+		else
+			return new E_AND_2_1();
+	}
+
+	protected void compute() {
+		int left = inputWires[0].value;
+		int right = inputWires[1].value;
+
+		outputWires[0].value = left & right;
+	}
+
+	protected void fillTruthTable() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		BigInteger[] labelL = { inWireL.lbl, Wire.conjugate(inWireL.lbl) };
+		if (inWireL.invd == true) {
+			BigInteger tmp = labelL[0];
+			labelL[0] = labelL[1];
+			labelL[1] = tmp;
+		}
+
+		BigInteger[] labelR = { inWireR.lbl, Wire.conjugate(inWireR.lbl) };
+		if (inWireR.invd == true) {
+			BigInteger tmp = labelR[0];
+			labelR[0] = labelR[1];
+			labelR[1] = tmp;
+		}
+
+		int k = outWire.serialNum;
+
+		gtt = new BigInteger[2][2];
+
+		int cL = inWireL.lbl.testBit(0) ? 1 : 0;
+		int cR = inWireR.lbl.testBit(0) ? 1 : 0;
+
+		BigInteger[] lb = new BigInteger[2];
+		timing.stopwatch[PID.sha1][TID.offline].start();
+		lb[cL & cR] = Cipher.encrypt(labelL[cL], labelR[cR], k, BigInteger.ZERO);
+		timing.stopwatch[PID.sha1][TID.offline].stop();
+		lb[1 - (cL & cR)] = Wire.conjugate(lb[cL & cR]);
+		outWire.lbl = lb[0];
+
+		gtt[0 ^ cL][0 ^ cR] = lb[0];
+		gtt[0 ^ cL][1 ^ cR] = lb[0];
+		gtt[1 ^ cL][0 ^ cR] = lb[0];
+		gtt[1 ^ cL][1 ^ cR] = lb[1];
+
+		int lsb = lb[0].testBit(0) ? 1 : 0;
+		if (outputWires[0].outBitEncPair != null) {
+			timing.stopwatch[PID.sha1][TID.offline].start();
+			outputWires[0].outBitEncPair[lsb] = Cipher.encrypt(k, lb[0], 0);
+			outputWires[0].outBitEncPair[1 - lsb] = Cipher.encrypt(k, lb[1], 1);
+			timing.stopwatch[PID.sha1][TID.offline].stop();
+		}
+	}
+
+	protected boolean shortCut() {
+		if (inputWires[0].value == 0) {
+			outputWires[0].value = 0;
+			return true;
+		}
+
+		if (inputWires[1].value == 0) {
+			outputWires[0].value = 0;
+			return true;
+		}
+
+		return false;
+	}
+
+	protected boolean collapse() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		if (inWireL.lbl.equals(inWireR.lbl)) {
+			if (inWireL.invd == inWireR.invd) {
+				outWire.invd = inWireL.invd;
+				outWire.setLabel(inWireL.lbl);
+			} else {
+				outWire.invd = false;
+				outWire.value = 0;
+			}
+
+			return true;
+		}
+
+		return false;
+	}
+}

+ 154 - 0
fastergc/YaoGC/Circuit.java

@@ -0,0 +1,154 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+import java.math.*;
+import java.io.*;
+
+import sprout.communication.Communication;
+import sprout.util.Timing;
+
+abstract public class Circuit implements TransitiveObserver {
+	public static boolean isForGarbling;
+
+	public Wire[] inputWires;
+	public Wire[] outputWires;
+
+	protected int inDegree, outDegree;
+	protected String name;
+
+	public static ObjectOutputStream oos = null;
+	public static ObjectInputStream ois = null;
+
+	public static Communication sender = null;
+	public static Communication receiver = null;
+
+	public static Timing timing = null;
+
+	// public boolean sendOutBitsLookup = false;
+
+	public static void setSender(Communication s) {
+		sender = s;
+	}
+
+	public static void setReceiver(Communication r) {
+		receiver = r;
+	}
+
+	private int inputWireCount = 0;
+
+	public Circuit(int inDegree, int outDegree, String name) {
+		this.inDegree = inDegree;
+		this.outDegree = outDegree;
+		this.name = name;
+
+		inputWires = new Wire[inDegree];
+		outputWires = new Wire[outDegree];
+	}
+
+	public static void setIOStream(ObjectInputStream ois, ObjectOutputStream oos) {
+		Circuit.ois = ois;
+		Circuit.oos = oos;
+	}
+
+	abstract public void build() throws Exception;
+
+	protected void createInputWires() {
+		for (int i = 0; i < inDegree; i++) {
+			inputWires[i] = new Wire();
+		}
+	}
+
+	public void startExecuting(int[] vals, boolean[] invd, BigInteger[] glbs)
+			throws Exception {
+		if (vals.length != invd.length || invd.length != glbs.length
+				|| glbs.length != this.inDegree)
+			throw new Exception("Unmatched number of input labels.");
+
+		for (int i = 0; i < this.inDegree; i++) {
+			inputWires[i].value = vals[i];
+			inputWires[i].invd = invd[i];
+			inputWires[i].setLabel(glbs[i]);
+			inputWires[i].setReady(true);
+		}
+	}
+
+	public void receiveTruthTables() {
+		for (int i = 0; i < this.inDegree; i++) {
+			inputWires[i].setReady(false);
+		}
+	}
+
+	public void sendTruthTables(State s) {
+		if (s.getWidth() != this.inDegree) {
+			Exception e = new Exception("Unmatched number of input labels."
+					+ s.getWidth() + " != " + inDegree);
+			e.printStackTrace();
+			System.exit(1);
+		}
+
+		for (int i = 0; i < this.inDegree; i++) {
+			inputWires[i].value = s.wires[i].value;
+			inputWires[i].invd = s.wires[i].invd;
+			inputWires[i].setLabel(s.wires[i].lbl);
+			inputWires[i].setReady(false);
+		}
+	}
+
+	public State startExecuting(State s) {
+		if (s.getWidth() != this.inDegree) {
+			Exception e = new Exception("Unmatched number of input labels."
+					+ s.getWidth() + " != " + inDegree);
+			e.printStackTrace();
+			System.exit(1);
+		}
+
+		for (int i = 0; i < this.inDegree; i++) {
+			inputWires[i].value = s.wires[i].value;
+			inputWires[i].invd = s.wires[i].invd;
+			inputWires[i].setLabel(s.wires[i].lbl);
+			inputWires[i].setReady(true);
+		}
+
+		return State.fromWires(this.outputWires);
+	}
+
+	public BigInteger interpretOutputELabels(BigInteger[] eLabels)
+			throws Exception {
+		if (eLabels.length != outDegree)
+			throw new Exception("Length Error.");
+
+		BigInteger output = BigInteger.ZERO;
+		for (int i = 0; i < this.outDegree; i++) {
+			if (outputWires[i].value != Wire.UNKNOWN_SIG) {
+				if (outputWires[i].value == 1)
+					output = output.setBit(i);
+			} else if (eLabels[i]
+					.equals(outputWires[i].invd ? outputWires[i].lbl
+							: outputWires[i].lbl.xor(Wire.R.shiftLeft(1)
+									.setBit(0)))) {
+				output = output.setBit(i);
+			} else if (!eLabels[i]
+					.equals(outputWires[i].invd ? outputWires[i].lbl.xor(Wire.R
+							.shiftLeft(1).setBit(0)) : outputWires[i].lbl))
+				throw new Exception("Bad Label encountered at ouputWire[" + i
+						+ "]:\n" + eLabels[i] + " is neither "
+						+ outputWires[i].lbl + " nor "
+						+ outputWires[i].lbl.xor(Wire.R.shiftLeft(1).setBit(0)));
+		}
+
+		return output;
+	}
+
+	public void update(boolean evaluate, TransitiveObservable o, Object arg) {
+		inputWireCount++;
+		if (inputWireCount % inDegree == 0)
+			execute(evaluate);
+	}
+
+	abstract protected void compute();
+
+	abstract protected void execute(boolean evaluate);
+
+	// abstract public void sendOutBitsLookup(boolean send);
+}

+ 43 - 0
fastergc/YaoGC/CompositeCircuit.java

@@ -0,0 +1,43 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+public abstract class CompositeCircuit extends Circuit {
+	protected Circuit[] subCircuits;
+	protected int nSubCircuits;
+
+	public CompositeCircuit(int inDegree, int outDegree, int nSubCircuits,
+			String name) {
+		super(inDegree, outDegree, name);
+
+		this.nSubCircuits = nSubCircuits;
+
+		subCircuits = new Circuit[nSubCircuits];
+	}
+
+	public void build() throws Exception {
+		createInputWires();
+		createSubCircuits();
+		connectWires();
+		defineOutputWires();
+		fixInternalWires();
+	}
+
+	protected void createSubCircuits() throws Exception {
+		for (int i = 0; i < nSubCircuits; i++)
+			subCircuits[i].build();
+	}
+
+	abstract protected void connectWires() throws Exception;
+
+	abstract protected void defineOutputWires();
+
+	protected void fixInternalWires() {
+	}
+
+	protected void compute() {
+	}
+
+	protected void execute(boolean evaluate) {
+	}
+}

+ 40 - 0
fastergc/YaoGC/E_AND_2_1.java

@@ -0,0 +1,40 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+import java.math.*;
+
+import Cipher.*;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+class E_AND_2_1 extends AND_2_1 {
+	public E_AND_2_1() {
+		super();
+	}
+
+	protected void execYao() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		// receiveGTT();
+
+		int i0 = Wire.getLSB(inWireL.lbl);
+		i0 = inWireL.invd ? (1 - i0) : i0;
+		int i1 = Wire.getLSB(inWireR.lbl);
+		i1 = inWireR.invd ? (1 - i1) : i1;
+
+		timing.stopwatch[PID.sha1][TID.online].start();
+		BigInteger out = Cipher.decrypt(inWireL.lbl, inWireR.lbl,
+				outWire.serialNum, gtt[i0][i1]);
+		timing.stopwatch[PID.sha1][TID.online].stop();
+
+		outWire.setLabel(out);
+	}
+
+	@Override
+	protected void passTruthTable() {
+		receiveGTT();
+	}
+}

+ 45 - 0
fastergc/YaoGC/E_FF10_1_SC_2_2.java

@@ -0,0 +1,45 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+import java.math.BigInteger;
+
+import Cipher.Cipher;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+class E_FF10_1_SC_2_2 extends FF10_1_SC_2_2 {
+	public E_FF10_1_SC_2_2() {
+		super();
+	}
+
+	protected void execYao() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire0 = outputWires[0];
+		Wire outWire1 = outputWires[1];
+
+		// receiveGTT();
+
+		int i0 = Wire.getLSB(inWireL.lbl);
+		i0 = inWireL.invd ? (1 - i0) : i0;
+		int i1 = Wire.getLSB(inWireR.lbl);
+		i1 = inWireR.invd ? (1 - i1) : i1;
+		
+		int k0 = outWire0.serialNum;
+		int k1 = outWire1.serialNum;
+
+		timing.stopwatch[PID.sha1][TID.online].start();
+		BigInteger out = Cipher.decrypt(inWireL.lbl, inWireR.lbl,
+				k0, k1, gtt[i0][i1]);
+		timing.stopwatch[PID.sha1][TID.online].stop();
+
+		outWire0.setLabel(out.shiftRight(Wire.labelBitLength));
+		outWire1.setLabel(out.and(Cipher.mask));
+	}
+
+	@Override
+	protected void passTruthTable() {
+		receiveGTT();
+	}
+}

+ 45 - 0
fastergc/YaoGC/E_FF10_2_SC_2_2.java

@@ -0,0 +1,45 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+import java.math.BigInteger;
+
+import Cipher.Cipher;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+class E_FF10_2_SC_2_2 extends FF10_2_SC_2_2 {
+	public E_FF10_2_SC_2_2() {
+		super();
+	}
+
+	protected void execYao() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire0 = outputWires[0];
+		Wire outWire1 = outputWires[1];
+
+		// receiveGTT();
+
+		int i0 = Wire.getLSB(inWireL.lbl);
+		i0 = inWireL.invd ? (1 - i0) : i0;
+		int i1 = Wire.getLSB(inWireR.lbl);
+		i1 = inWireR.invd ? (1 - i1) : i1;
+		
+		int k0 = outWire0.serialNum;
+		int k1 = outWire1.serialNum;
+
+		timing.stopwatch[PID.sha1][TID.online].start();
+		BigInteger out = Cipher.decrypt(inWireL.lbl, inWireR.lbl,
+				k0, k1, gtt[i0][i1]);
+		timing.stopwatch[PID.sha1][TID.online].stop();
+
+		outWire0.setLabel(out.shiftRight(Wire.labelBitLength));
+		outWire1.setLabel(out.and(Cipher.mask));
+	}
+
+	@Override
+	protected void passTruthTable() {
+		receiveGTT();
+	}
+}

+ 45 - 0
fastergc/YaoGC/E_FF10_3_SC_2_2.java

@@ -0,0 +1,45 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+import java.math.BigInteger;
+
+import Cipher.Cipher;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+class E_FF10_3_SC_2_2 extends FF10_3_SC_2_2 {
+	public E_FF10_3_SC_2_2() {
+		super();
+	}
+
+	protected void execYao() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire0 = outputWires[0];
+		Wire outWire1 = outputWires[1];
+
+		// receiveGTT();
+
+		int i0 = Wire.getLSB(inWireL.lbl);
+		i0 = inWireL.invd ? (1 - i0) : i0;
+		int i1 = Wire.getLSB(inWireR.lbl);
+		i1 = inWireR.invd ? (1 - i1) : i1;
+		
+		int k0 = outWire0.serialNum;
+		int k1 = outWire1.serialNum;
+
+		timing.stopwatch[PID.sha1][TID.online].start();
+		BigInteger out = Cipher.decrypt(inWireL.lbl, inWireR.lbl,
+				k0, k1, gtt[i0][i1]);
+		timing.stopwatch[PID.sha1][TID.online].stop();
+
+		outWire0.setLabel(out.shiftRight(Wire.labelBitLength));
+		outWire1.setLabel(out.and(Cipher.mask));
+	}
+
+	@Override
+	protected void passTruthTable() {
+		receiveGTT();
+	}
+}

+ 41 - 0
fastergc/YaoGC/E_OR_2_1.java

@@ -0,0 +1,41 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+import java.math.*;
+
+import Cipher.*;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+class E_OR_2_1 extends OR_2_1 {
+	public E_OR_2_1() {
+		super();
+	}
+
+	protected void execYao() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		// receiveGTT();
+
+		int i0 = Wire.getLSB(inWireL.lbl);
+		i0 = inWireL.invd ? (1 - i0) : i0;
+		int i1 = Wire.getLSB(inWireR.lbl);
+		i1 = inWireR.invd ? (1 - i1) : i1;
+
+		timing.stopwatch[PID.sha1][TID.online].start();
+		BigInteger out = Cipher.decrypt(inWireL.lbl, inWireR.lbl,
+				outWire.serialNum, gtt[i0][i1]);
+		timing.stopwatch[PID.sha1][TID.online].stop();
+
+		outWire.setLabel(out);
+
+	}
+
+	@Override
+	protected void passTruthTable() {
+		receiveGTT();
+	}
+}

+ 40 - 0
fastergc/YaoGC/E_T1_FF0_O_2_1.java

@@ -0,0 +1,40 @@
+// by Boyang Wei
+
+package YaoGC;
+
+import java.math.*;
+
+import Cipher.*;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+class E_T1_FF0_O_2_1 extends T1_FF0_O_2_1 {
+	public E_T1_FF0_O_2_1() {
+		super();
+	}
+
+	protected void execYao() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		// receiveGTT();
+
+		int i0 = Wire.getLSB(inWireL.lbl);
+		i0 = inWireL.invd ? (1 - i0) : i0;
+		int i1 = Wire.getLSB(inWireR.lbl);
+		i1 = inWireR.invd ? (1 - i1) : i1;
+
+		timing.stopwatch[PID.sha1][TID.online].start();
+		BigInteger out = Cipher.decrypt(inWireL.lbl, inWireR.lbl,
+				outWire.serialNum, gtt[i0][i1]);
+		timing.stopwatch[PID.sha1][TID.online].stop();
+
+		outWire.setLabel(out);
+	}
+
+	@Override
+	protected void passTruthTable() {
+		receiveGTT();
+	}
+}

+ 40 - 0
fastergc/YaoGC/E_T1_FF0_S_2_1.java

@@ -0,0 +1,40 @@
+// by Boyang Wei
+
+package YaoGC;
+
+import java.math.*;
+
+import Cipher.*;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+class E_T1_FF0_S_2_1 extends T1_FF0_S_2_1 {
+	public E_T1_FF0_S_2_1() {
+		super();
+	}
+
+	protected void execYao() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		// receiveGTT();
+
+		int i0 = Wire.getLSB(inWireL.lbl);
+		i0 = inWireL.invd ? (1 - i0) : i0;
+		int i1 = Wire.getLSB(inWireR.lbl);
+		i1 = inWireR.invd ? (1 - i1) : i1;
+
+		timing.stopwatch[PID.sha1][TID.online].start();
+		BigInteger out = Cipher.decrypt(inWireL.lbl, inWireR.lbl,
+				outWire.serialNum, gtt[i0][i1]);
+		timing.stopwatch[PID.sha1][TID.online].stop();
+
+		outWire.setLabel(out);
+	}
+
+	@Override
+	protected void passTruthTable() {
+		receiveGTT();
+	}
+}

+ 40 - 0
fastergc/YaoGC/E_T1_FF1_O_2_1.java

@@ -0,0 +1,40 @@
+// by Boyang Wei
+
+package YaoGC;
+
+import java.math.*;
+
+import Cipher.*;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+class E_T1_FF1_O_2_1 extends T1_FF1_O_2_1 {
+	public E_T1_FF1_O_2_1() {
+		super();
+	}
+
+	protected void execYao() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		// receiveGTT();
+
+		int i0 = Wire.getLSB(inWireL.lbl);
+		i0 = inWireL.invd ? (1 - i0) : i0;
+		int i1 = Wire.getLSB(inWireR.lbl);
+		i1 = inWireR.invd ? (1 - i1) : i1;
+
+		timing.stopwatch[PID.sha1][TID.online].start();
+		BigInteger out = Cipher.decrypt(inWireL.lbl, inWireR.lbl,
+				outWire.serialNum, gtt[i0][i1]);
+		timing.stopwatch[PID.sha1][TID.online].stop();
+
+		outWire.setLabel(out);
+	}
+
+	@Override
+	protected void passTruthTable() {
+		receiveGTT();
+	}
+}

+ 40 - 0
fastergc/YaoGC/E_T1_FF1_S_2_1.java

@@ -0,0 +1,40 @@
+// by Boyang Wei
+
+package YaoGC;
+
+import java.math.*;
+
+import Cipher.*;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+class E_T1_FF1_S_2_1 extends T1_FF1_S_2_1 {
+	public E_T1_FF1_S_2_1() {
+		super();
+	}
+
+	protected void execYao() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		// receiveGTT();
+
+		int i0 = Wire.getLSB(inWireL.lbl);
+		i0 = inWireL.invd ? (1 - i0) : i0;
+		int i1 = Wire.getLSB(inWireR.lbl);
+		i1 = inWireR.invd ? (1 - i1) : i1;
+
+		timing.stopwatch[PID.sha1][TID.online].start();
+		BigInteger out = Cipher.decrypt(inWireL.lbl, inWireR.lbl,
+				outWire.serialNum, gtt[i0][i1]);
+		timing.stopwatch[PID.sha1][TID.online].stop();
+
+		outWire.setLabel(out);
+	}
+
+	@Override
+	protected void passTruthTable() {
+		receiveGTT();
+	}
+}

+ 40 - 0
fastergc/YaoGC/E_T2_FF10_O_2_1.java

@@ -0,0 +1,40 @@
+// by Boyang Wei
+
+package YaoGC;
+
+import java.math.*;
+
+import Cipher.*;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+class E_T2_FF10_O_2_1 extends T2_FF10_O_2_1 {
+	public E_T2_FF10_O_2_1() {
+		super();
+	}
+
+	protected void execYao() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		// receiveGTT();
+
+		int i0 = Wire.getLSB(inWireL.lbl);
+		i0 = inWireL.invd ? (1 - i0) : i0;
+		int i1 = Wire.getLSB(inWireR.lbl);
+		i1 = inWireR.invd ? (1 - i1) : i1;
+
+		timing.stopwatch[PID.sha1][TID.online].start();
+		BigInteger out = Cipher.decrypt(inWireL.lbl, inWireR.lbl,
+				outWire.serialNum, gtt[i0][i1]);
+		timing.stopwatch[PID.sha1][TID.online].stop();
+
+		outWire.setLabel(out);
+	}
+
+	@Override
+	protected void passTruthTable() {
+		receiveGTT();
+	}
+}

+ 40 - 0
fastergc/YaoGC/E_T2_FF10_S_2_1.java

@@ -0,0 +1,40 @@
+// by Boyang Wei
+
+package YaoGC;
+
+import java.math.*;
+
+import Cipher.*;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+class E_T2_FF10_S_2_1 extends T2_FF10_S_2_1 {
+	public E_T2_FF10_S_2_1() {
+		super();
+	}
+
+	protected void execYao() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		// receiveGTT();
+
+		int i0 = Wire.getLSB(inWireL.lbl);
+		i0 = inWireL.invd ? (1 - i0) : i0;
+		int i1 = Wire.getLSB(inWireR.lbl);
+		i1 = inWireR.invd ? (1 - i1) : i1;
+
+		timing.stopwatch[PID.sha1][TID.online].start();
+		BigInteger out = Cipher.decrypt(inWireL.lbl, inWireR.lbl,
+				outWire.serialNum, gtt[i0][i1]);
+		timing.stopwatch[PID.sha1][TID.online].stop();
+
+		outWire.setLabel(out);
+	}
+
+	@Override
+	protected void passTruthTable() {
+		receiveGTT();
+	}
+}

+ 24 - 0
fastergc/YaoGC/E_XOR_2_1.java

@@ -0,0 +1,24 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+class E_XOR_2_1 extends XOR_2_1 {
+	public E_XOR_2_1() {
+		super();
+	}
+
+	protected void sendOutBitEncPair() {
+		if (outputWires[0].outBitEncPair != null) {
+			timing.stopwatch[PID.gcf][TID.offline].stop();
+
+			timing.stopwatch[PID.gcf][TID.offline_read].start();
+			outputWires[0].outBitEncPair = sender.readBigIntegerArray();
+			timing.stopwatch[PID.gcf][TID.offline_read].stop();
+
+			timing.stopwatch[PID.gcf][TID.offline].start();
+		}
+	}
+}

+ 55 - 0
fastergc/YaoGC/F2ET_Wplus2_Wplus2.java

@@ -0,0 +1,55 @@
+// by Boyang Wei
+
+package YaoGC;
+
+public class F2ET_Wplus2_Wplus2 extends CompositeCircuit {
+	private final int w;
+	private int s1; // sigmas
+	private int s2;
+
+	public F2ET_Wplus2_Wplus2(int w, int s1, int s2) {
+		super(w + 2, w + 2, 2 * w + 2, "F2ET_" + (w + 2) + "_" + w + 2);
+
+		this.w = w;
+		this.s1 = s1;
+		this.s2 = s2;
+	}
+
+	protected void createSubCircuits() throws Exception {
+		for (int i = 0; i < 2 * w; i++)
+			subCircuits[i] = XOR_2_1.newInstance();
+		subCircuits[2 * w] = new FF10_Wplus1_Wplus1(w, false, s1);
+		subCircuits[2 * w + 1] = new FF10_Wplus1_Wplus1(w, false, s2);
+
+		s1 = s2 = 0;
+
+		super.createSubCircuits();
+	}
+
+	protected void connectWires() throws Exception {
+		// Enable wires
+		inputWires[0].connectTo(subCircuits[2 * w].inputWires, 0);
+		inputWires[1].connectTo(subCircuits[2 * w + 1].inputWires, 0);
+
+		for (int i = 0; i < w; i++) {
+			inputWires[i + 2].connectTo(subCircuits[2 * w].inputWires, i + 1);
+			inputWires[i + 2].connectTo(subCircuits[i].inputWires, 1);
+			subCircuits[2 * w].outputWires[i].connectTo(
+					subCircuits[i].inputWires, 0);
+			subCircuits[2 * w].outputWires[i].connectTo(
+					subCircuits[i + w].inputWires, 1);
+			subCircuits[i].outputWires[0].connectTo(
+					subCircuits[2 * w + 1].inputWires, i + 1);
+			subCircuits[2 * w + 1].outputWires[i].connectTo(
+					subCircuits[i + w].inputWires, 0);
+		}
+	}
+
+	protected void defineOutputWires() {
+		outputWires[0] = subCircuits[2 * w].outputWires[w];
+		outputWires[1] = subCircuits[2 * w + 1].outputWires[w];
+
+		for (int i = 0; i < w; i++)
+			outputWires[i + 2] = subCircuits[i + w].outputWires[0];
+	}
+}

+ 83 - 0
fastergc/YaoGC/F2FT_2Wplus2_Wplus2.java

@@ -0,0 +1,83 @@
+// by Boyang Wei
+
+package YaoGC;
+
+public class F2FT_2Wplus2_Wplus2 extends CompositeCircuit {
+	private final int w;
+	private int s1; // sigma
+	private int s2;
+
+	public F2FT_2Wplus2_Wplus2(int w, int s1, int s2) {
+		super(2 * w + 2, w + 2, 6 * w + 4, "F2FT_" + (2 * w + 2) + "_" + w + 2);
+
+		this.w = w;
+		this.s1 = s1;
+		this.s2 = s2;
+	}
+
+	protected void createSubCircuits() throws Exception {
+		for (int i = 0; i < w; i++)
+			subCircuits[i] = AND_2_1.newInstance();
+		for (int i = w; i < 6 * w; i++)
+			subCircuits[i] = XOR_2_1.newInstance();
+
+		subCircuits[6 * w] = new FF10_Wplus1_Wplus1(w, true, s1);
+		subCircuits[6 * w + 1] = new FF10_Wplus1_Wplus1(w, false, s1);
+		subCircuits[6 * w + 2] = new FF10_Wplus1_Wplus1(w, true, s2);
+		subCircuits[6 * w + 3] = new FF10_Wplus1_Wplus1(w, false, s2);
+
+		s1 = s2 = 0;
+
+		super.createSubCircuits();
+	}
+
+	protected void connectWires() throws Exception {
+		inputWires[0].connectTo(subCircuits[6 * w].inputWires, 0);
+		inputWires[1].connectTo(subCircuits[6 * w + 2].inputWires, 0);
+		subCircuits[6 * w].outputWires[w].connectTo(
+				subCircuits[6 * w + 1].inputWires, 0);
+		subCircuits[6 * w + 2].outputWires[w].connectTo(
+				subCircuits[6 * w + 3].inputWires, 0);
+
+		for (int i = 0; i < w; i++) {
+			inputWires[i + 2].connectTo(subCircuits[i].inputWires, 0);
+			inputWires[i + w + 2].connectTo(subCircuits[i].inputWires, 1);
+			inputWires[i + w + 2].connectTo(subCircuits[6 * w + 1].inputWires,
+					i + 1);
+			inputWires[i + w + 2].connectTo(subCircuits[i + 2 * w].inputWires,
+					1);
+			subCircuits[i].outputWires[0].connectTo(
+					subCircuits[6 * w].inputWires, i + 1);
+			subCircuits[i].outputWires[0].connectTo(
+					subCircuits[i + w].inputWires, 1);
+			subCircuits[6 * w].outputWires[i].connectTo(
+					subCircuits[i + w].inputWires, 0);
+			subCircuits[6 * w].outputWires[i].connectTo(
+					subCircuits[i + 3 * w].inputWires, 1);
+			subCircuits[6 * w + 1].outputWires[i].connectTo(subCircuits[i + 2
+					* w].inputWires, 0);
+			subCircuits[6 * w + 1].outputWires[i].connectTo(subCircuits[i + 3
+					* w].inputWires, 0);
+			subCircuits[i + w].outputWires[0].connectTo(
+					subCircuits[6 * w + 2].inputWires, i + 1);
+			subCircuits[i + 2 * w].outputWires[0].connectTo(
+					subCircuits[6 * w + 3].inputWires, i + 1);
+			subCircuits[6 * w + 2].outputWires[i].connectTo(subCircuits[i + 4
+					* w].inputWires, 0);
+			subCircuits[6 * w + 3].outputWires[i].connectTo(subCircuits[i + 4
+					* w].inputWires, 1);
+			subCircuits[i + 3 * w].outputWires[0].connectTo(subCircuits[i + 5
+					* w].inputWires, 1);
+			subCircuits[i + 4 * w].outputWires[0].connectTo(subCircuits[i + 5
+					* w].inputWires, 0);
+		}
+	}
+
+	protected void defineOutputWires() {
+		outputWires[0] = subCircuits[6 * w + 1].outputWires[w];
+		outputWires[1] = subCircuits[6 * w + 3].outputWires[w];
+
+		for (int i = 0; i < w; i++)
+			outputWires[i + 2] = subCircuits[i + 5 * w].outputWires[0];
+	}
+}

+ 128 - 0
fastergc/YaoGC/FF10_1_SC_2_2.java

@@ -0,0 +1,128 @@
+// by Boyang Wei
+
+package YaoGC;
+
+import java.math.*;
+
+import Cipher.*;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+public abstract class FF10_1_SC_2_2 extends SimpleCircuit_2_2 {
+	public FF10_1_SC_2_2() {
+		super("FF10_1_SC_2_2");
+	}
+
+	public static FF10_1_SC_2_2 newInstance() {
+		if (Circuit.isForGarbling)
+			return new G_FF10_1_SC_2_2();
+		else
+			return new E_FF10_1_SC_2_2();
+	}
+
+	protected void compute() {}
+	
+	private int outS(int l, int r) {
+		int o;
+		if (l == 0) {
+			if (r == 0)
+				o = 0;
+			else
+				o = 1;
+		} else {
+			if (r == 0)
+				o = 1;
+			else
+				o = 1;
+		}
+		return o;
+	}
+	
+	private int outO(int l, int r) {
+		int o;
+		if (l == 0) {
+			if (r == 0)
+				o = 0;
+			else
+				o = 1;
+		} else {
+			if (r == 0)
+				o = 0;
+			else
+				o = 0;
+		}
+		return o;
+	}
+
+	protected void fillTruthTable() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire0 = outputWires[0];
+		Wire outWire1 = outputWires[1];
+
+		BigInteger[] labelL = { inWireL.lbl, Wire.conjugate(inWireL.lbl) };
+		if (inWireL.invd == true) {
+			BigInteger tmp = labelL[0];
+			labelL[0] = labelL[1];
+			labelL[1] = tmp;
+		}
+
+		BigInteger[] labelR = { inWireR.lbl, Wire.conjugate(inWireR.lbl) };
+		if (inWireR.invd == true) {
+			BigInteger tmp = labelR[0];
+			labelR[0] = labelR[1];
+			labelR[1] = tmp;
+		}
+
+		int k0 = outWire0.serialNum;
+		int k1 = outWire1.serialNum;
+
+		gtt = new BigInteger[2][2];
+
+		int cL = inWireL.lbl.testBit(0) ? 1 : 0;
+		int cR = inWireR.lbl.testBit(0) ? 1 : 0;
+
+		timing.stopwatch[PID.sha1][TID.offline].start();
+		BigInteger lb = Cipher.encrypt(labelL[cL], labelR[cR], k0, k1, BigInteger.ZERO);
+		timing.stopwatch[PID.sha1][TID.offline].stop();
+		BigInteger[] lbS = new BigInteger[2];
+		BigInteger[] lbO = new BigInteger[2];
+		
+		lbS[outS(cL, cR)] = lb.shiftRight(Wire.labelBitLength);
+		lbO[outO(cL, cR)] = lb.and(Cipher.mask);
+		lbS[1 - outS(cL, cR)] = Wire.conjugate(lbS[outS(cL, cR)]);
+		lbO[1 - outO(cL, cR)] = Wire.conjugate(lbO[outO(cL, cR)]);
+		
+		outWire0.lbl = lbS[0];
+		outWire1.lbl = lbO[0];
+
+		gtt[0 ^ cL][0 ^ cR] = lbS[outS(0, 0)].shiftLeft(Wire.labelBitLength).xor(lbO[outO(0, 0)]);
+		gtt[0 ^ cL][1 ^ cR] = lbS[outS(0, 1)].shiftLeft(Wire.labelBitLength).xor(lbO[outO(0, 1)]);
+		gtt[1 ^ cL][0 ^ cR] = lbS[outS(1, 0)].shiftLeft(Wire.labelBitLength).xor(lbO[outO(1, 0)]);
+		gtt[1 ^ cL][1 ^ cR] = lbS[outS(1, 1)].shiftLeft(Wire.labelBitLength).xor(lbO[outO(1, 1)]);
+
+		int lsb = lbS[0].testBit(0) ? 1 : 0;
+		if (outputWires[0].outBitEncPair != null) {
+			timing.stopwatch[PID.sha1][TID.offline].start();
+			outputWires[0].outBitEncPair[lsb] = Cipher.encrypt(k0, lbS[0], 0);
+			outputWires[0].outBitEncPair[1 - lsb] = Cipher.encrypt(k0, lbS[1], 1);
+			timing.stopwatch[PID.sha1][TID.offline].stop();
+		}
+		
+		lsb = lbO[0].testBit(0) ? 1 : 0;
+		if (outputWires[1].outBitEncPair != null) {
+			timing.stopwatch[PID.sha1][TID.offline].start();
+			outputWires[1].outBitEncPair[lsb] = Cipher.encrypt(k1, lbO[0], 0);
+			outputWires[1].outBitEncPair[1 - lsb] = Cipher.encrypt(k1, lbO[1], 1);
+			timing.stopwatch[PID.sha1][TID.offline].stop();
+		}
+	}
+
+	protected boolean shortCut() {
+		return false;
+	}
+
+	protected boolean collapse() {
+		return false;
+	}
+}

+ 78 - 0
fastergc/YaoGC/FF10_2_2.java

@@ -0,0 +1,78 @@
+// by Boyang Wei
+// FindFirst1 Garbled Gate of Table 1
+
+package YaoGC;
+
+public class FF10_2_2 extends CompositeCircuit {
+	private int id; // 1, 2, or 3
+	
+	public FF10_2_2(int id) {
+		super(2, 2, 1, "FF10_2_2");
+
+		this.id = id;
+	}
+
+	protected void createSubCircuits() throws Exception {
+		if (id == 1) {
+			subCircuits[0] = FF10_1_SC_2_2.newInstance();
+		} else if (id == 2) {
+			subCircuits[0] = FF10_2_SC_2_2.newInstance();
+		} else {
+			subCircuits[0] = FF10_3_SC_2_2.newInstance();
+		}
+		
+		id = -1;
+
+		super.createSubCircuits();
+	}
+
+	protected void connectWires() throws Exception {
+		inputWires[0].connectTo(subCircuits[0].inputWires, 0);
+		inputWires[1].connectTo(subCircuits[0].inputWires, 1);
+	}
+
+	protected void defineOutputWires() {
+		outputWires[0] = subCircuits[0].outputWires[0];
+		outputWires[1] = subCircuits[0].outputWires[1];
+	}
+
+	/*
+	public FF10_2_2(int id) {
+		super(2, 2, 2, "FF10_2_2");
+
+		this.id = id;
+	}
+
+	protected void createSubCircuits() throws Exception {
+		if (id == 1) {
+			subCircuits[0] = T1_FF1_S_2_1.newInstance();
+			subCircuits[1] = T1_FF1_O_2_1.newInstance();
+		} else if (id == 2) {
+			subCircuits[0] = T1_FF0_S_2_1.newInstance();
+			subCircuits[1] = T1_FF0_O_2_1.newInstance();
+		} else {
+			subCircuits[0] = T2_FF10_S_2_1.newInstance();
+			subCircuits[1] = T2_FF10_O_2_1.newInstance();
+		}
+		
+		id = -1;
+
+		super.createSubCircuits();
+	}
+
+	protected void connectWires() throws Exception {
+		inputWires[0].connectTo(subCircuits[0].inputWires, 0);
+		inputWires[0].connectTo(subCircuits[1].inputWires, 0);
+		inputWires[1].connectTo(subCircuits[0].inputWires, 1);
+		inputWires[1].connectTo(subCircuits[1].inputWires, 1);
+	}
+
+	protected void defineOutputWires() {
+		outputWires[0] = subCircuits[0].outputWires[0];
+		outputWires[1] = subCircuits[1].outputWires[0];
+	}
+	*/
+
+	protected void fixInternalWires() {
+	}
+}

+ 128 - 0
fastergc/YaoGC/FF10_2_SC_2_2.java

@@ -0,0 +1,128 @@
+// by Boyang Wei
+
+package YaoGC;
+
+import java.math.*;
+
+import Cipher.*;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+public abstract class FF10_2_SC_2_2 extends SimpleCircuit_2_2 {
+	public FF10_2_SC_2_2() {
+		super("FF10_2_SC_2_2");
+	}
+
+	public static FF10_2_SC_2_2 newInstance() {
+		if (Circuit.isForGarbling)
+			return new G_FF10_2_SC_2_2();
+		else
+			return new E_FF10_2_SC_2_2();
+	}
+
+	protected void compute() {}
+	
+	private int outS(int l, int r) {
+		int o;
+		if (l == 0) {
+			if (r == 0)
+				o = 1;
+			else
+				o = 0;
+		} else {
+			if (r == 0)
+				o = 1;
+			else
+				o = 1;
+		}
+		return o;
+	}
+	
+	private int outO(int l, int r) {
+		int o;
+		if (l == 0) {
+			if (r == 0)
+				o = 1;
+			else
+				o = 0;
+		} else {
+			if (r == 0)
+				o = 0;
+			else
+				o = 0;
+		}
+		return o;
+	}
+
+	protected void fillTruthTable() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire0 = outputWires[0];
+		Wire outWire1 = outputWires[1];
+
+		BigInteger[] labelL = { inWireL.lbl, Wire.conjugate(inWireL.lbl) };
+		if (inWireL.invd == true) {
+			BigInteger tmp = labelL[0];
+			labelL[0] = labelL[1];
+			labelL[1] = tmp;
+		}
+
+		BigInteger[] labelR = { inWireR.lbl, Wire.conjugate(inWireR.lbl) };
+		if (inWireR.invd == true) {
+			BigInteger tmp = labelR[0];
+			labelR[0] = labelR[1];
+			labelR[1] = tmp;
+		}
+
+		int k0 = outWire0.serialNum;
+		int k1 = outWire1.serialNum;
+
+		gtt = new BigInteger[2][2];
+
+		int cL = inWireL.lbl.testBit(0) ? 1 : 0;
+		int cR = inWireR.lbl.testBit(0) ? 1 : 0;
+
+		timing.stopwatch[PID.sha1][TID.offline].start();
+		BigInteger lb = Cipher.encrypt(labelL[cL], labelR[cR], k0, k1, BigInteger.ZERO);
+		timing.stopwatch[PID.sha1][TID.offline].stop();
+		BigInteger[] lbS = new BigInteger[2];
+		BigInteger[] lbO = new BigInteger[2];
+		
+		lbS[outS(cL, cR)] = lb.shiftRight(Wire.labelBitLength);
+		lbO[outO(cL, cR)] = lb.and(Cipher.mask);
+		lbS[1 - outS(cL, cR)] = Wire.conjugate(lbS[outS(cL, cR)]);
+		lbO[1 - outO(cL, cR)] = Wire.conjugate(lbO[outO(cL, cR)]);
+		
+		outWire0.lbl = lbS[0];
+		outWire1.lbl = lbO[0];
+
+		gtt[0 ^ cL][0 ^ cR] = lbS[outS(0, 0)].shiftLeft(Wire.labelBitLength).xor(lbO[outO(0, 0)]);
+		gtt[0 ^ cL][1 ^ cR] = lbS[outS(0, 1)].shiftLeft(Wire.labelBitLength).xor(lbO[outO(0, 1)]);
+		gtt[1 ^ cL][0 ^ cR] = lbS[outS(1, 0)].shiftLeft(Wire.labelBitLength).xor(lbO[outO(1, 0)]);
+		gtt[1 ^ cL][1 ^ cR] = lbS[outS(1, 1)].shiftLeft(Wire.labelBitLength).xor(lbO[outO(1, 1)]);
+
+		int lsb = lbS[0].testBit(0) ? 1 : 0;
+		if (outputWires[0].outBitEncPair != null) {
+			timing.stopwatch[PID.sha1][TID.offline].start();
+			outputWires[0].outBitEncPair[lsb] = Cipher.encrypt(k0, lbS[0], 0);
+			outputWires[0].outBitEncPair[1 - lsb] = Cipher.encrypt(k0, lbS[1], 1);
+			timing.stopwatch[PID.sha1][TID.offline].stop();
+		}
+		
+		lsb = lbO[0].testBit(0) ? 1 : 0;
+		if (outputWires[1].outBitEncPair != null) {
+			timing.stopwatch[PID.sha1][TID.offline].start();
+			outputWires[1].outBitEncPair[lsb] = Cipher.encrypt(k1, lbO[0], 0);
+			outputWires[1].outBitEncPair[1 - lsb] = Cipher.encrypt(k1, lbO[1], 1);
+			timing.stopwatch[PID.sha1][TID.offline].stop();
+		}
+	}
+
+	protected boolean shortCut() {
+		return false;
+	}
+
+	protected boolean collapse() {
+		return false;
+	}
+}

+ 128 - 0
fastergc/YaoGC/FF10_3_SC_2_2.java

@@ -0,0 +1,128 @@
+// by Boyang Wei
+
+package YaoGC;
+
+import java.math.*;
+
+import Cipher.*;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+public abstract class FF10_3_SC_2_2 extends SimpleCircuit_2_2 {
+	public FF10_3_SC_2_2() {
+		super("FF10_3_SC_2_2");
+	}
+
+	public static FF10_3_SC_2_2 newInstance() {
+		if (Circuit.isForGarbling)
+			return new G_FF10_3_SC_2_2();
+		else
+			return new E_FF10_3_SC_2_2();
+	}
+
+	protected void compute() {}
+	
+	private int outS(int l, int r) {
+		int o;
+		if (l == 0) {
+			if (r == 0)
+				o = 0;
+			else
+				o = 0;
+		} else {
+			if (r == 0)
+				o = 1;
+			else
+				o = 1;
+		}
+		return o;
+	}
+	
+	private int outO(int l, int r) {
+		int o;
+		if (l == 0) {
+			if (r == 0)
+				o = 0;
+			else
+				o = 0;
+		} else {
+			if (r == 0)
+				o = 0;
+			else
+				o = 0;
+		}
+		return o;
+	}
+
+	protected void fillTruthTable() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire0 = outputWires[0];
+		Wire outWire1 = outputWires[1];
+
+		BigInteger[] labelL = { inWireL.lbl, Wire.conjugate(inWireL.lbl) };
+		if (inWireL.invd == true) {
+			BigInteger tmp = labelL[0];
+			labelL[0] = labelL[1];
+			labelL[1] = tmp;
+		}
+
+		BigInteger[] labelR = { inWireR.lbl, Wire.conjugate(inWireR.lbl) };
+		if (inWireR.invd == true) {
+			BigInteger tmp = labelR[0];
+			labelR[0] = labelR[1];
+			labelR[1] = tmp;
+		}
+
+		int k0 = outWire0.serialNum;
+		int k1 = outWire1.serialNum;
+
+		gtt = new BigInteger[2][2];
+
+		int cL = inWireL.lbl.testBit(0) ? 1 : 0;
+		int cR = inWireR.lbl.testBit(0) ? 1 : 0;
+
+		timing.stopwatch[PID.sha1][TID.offline].start();
+		BigInteger lb = Cipher.encrypt(labelL[cL], labelR[cR], k0, k1, BigInteger.ZERO);
+		timing.stopwatch[PID.sha1][TID.offline].stop();
+		BigInteger[] lbS = new BigInteger[2];
+		BigInteger[] lbO = new BigInteger[2];
+		
+		lbS[outS(cL, cR)] = lb.shiftRight(Wire.labelBitLength);
+		lbO[outO(cL, cR)] = lb.and(Cipher.mask);
+		lbS[1 - outS(cL, cR)] = Wire.conjugate(lbS[outS(cL, cR)]);
+		lbO[1 - outO(cL, cR)] = Wire.conjugate(lbO[outO(cL, cR)]);
+		
+		outWire0.lbl = lbS[0];
+		outWire1.lbl = lbO[0];
+
+		gtt[0 ^ cL][0 ^ cR] = lbS[outS(0, 0)].shiftLeft(Wire.labelBitLength).xor(lbO[outO(0, 0)]);
+		gtt[0 ^ cL][1 ^ cR] = lbS[outS(0, 1)].shiftLeft(Wire.labelBitLength).xor(lbO[outO(0, 1)]);
+		gtt[1 ^ cL][0 ^ cR] = lbS[outS(1, 0)].shiftLeft(Wire.labelBitLength).xor(lbO[outO(1, 0)]);
+		gtt[1 ^ cL][1 ^ cR] = lbS[outS(1, 1)].shiftLeft(Wire.labelBitLength).xor(lbO[outO(1, 1)]);
+
+		int lsb = lbS[0].testBit(0) ? 1 : 0;
+		if (outputWires[0].outBitEncPair != null) {
+			timing.stopwatch[PID.sha1][TID.offline].start();
+			outputWires[0].outBitEncPair[lsb] = Cipher.encrypt(k0, lbS[0], 0);
+			outputWires[0].outBitEncPair[1 - lsb] = Cipher.encrypt(k0, lbS[1], 1);
+			timing.stopwatch[PID.sha1][TID.offline].stop();
+		}
+		
+		lsb = lbO[0].testBit(0) ? 1 : 0;
+		if (outputWires[1].outBitEncPair != null) {
+			timing.stopwatch[PID.sha1][TID.offline].start();
+			outputWires[1].outBitEncPair[lsb] = Cipher.encrypt(k1, lbO[0], 0);
+			outputWires[1].outBitEncPair[1 - lsb] = Cipher.encrypt(k1, lbO[1], 1);
+			timing.stopwatch[PID.sha1][TID.offline].stop();
+		}
+	}
+
+	protected boolean shortCut() {
+		return false;
+	}
+
+	protected boolean collapse() {
+		return false;
+	}
+}

+ 65 - 0
fastergc/YaoGC/FF10_Wplus1_Wplus1.java

@@ -0,0 +1,65 @@
+// by Boyang Wei
+
+package YaoGC;
+
+public class FF10_Wplus1_Wplus1 extends CompositeCircuit {
+	private final int w;
+	private final boolean b; // find 1 or find 0
+	private int s; // sigma
+
+	public FF10_Wplus1_Wplus1(int w, boolean b, int s) {
+		super(w + 1, w + 1, w * 3, "FindFirstZeroOrOne_" + (w + 1) + "_" + w
+				+ 1);
+
+		this.w = w;
+		this.b = b;
+		this.s = s;
+	}
+
+	protected void createSubCircuits() throws Exception {
+		for (int i = 0; i < w * 2; i++) {
+			if (s <= i && i <= w + s - 1) {
+				if (b)
+					subCircuits[i] = new FF10_2_2(1);
+				else
+					subCircuits[i] = new FF10_2_2(2);
+			} else { // i < s || w+s-1 < i
+				subCircuits[i] = new FF10_2_2(3);
+			}
+		}
+
+		for (int i = 2 * w; i < w * 3; i++)
+			subCircuits[i] = XOR_2_1.newInstance();
+
+		s = 0;
+
+		super.createSubCircuits();
+	}
+
+	protected void connectWires() throws Exception {
+		inputWires[0].connectTo(subCircuits[0].inputWires, 0); // Enable wire
+
+		for (int i = 0; i < w; i++) {
+			inputWires[i + 1].connectTo(subCircuits[i].inputWires, 1); // green
+																		// wire
+			inputWires[i + 1].connectTo(subCircuits[i + w].inputWires, 1); // green
+																			// wire
+			subCircuits[i].outputWires[1].connectTo(
+					subCircuits[i + 2 * w].inputWires, 0); // orange wire
+			subCircuits[i + w].outputWires[1].connectTo(
+					subCircuits[i + 2 * w].inputWires, 1); // orange wire
+		}
+
+		for (int i = 0; i < 2 * w - 1; i++)
+			subCircuits[i].outputWires[0].connectTo(
+					subCircuits[i + 1].inputWires, 0); // blue wire
+	}
+
+	protected void defineOutputWires() {
+		for (int i = 0; i < w; i++)
+			outputWires[i] = subCircuits[i + 2 * w].outputWires[0]; // orange
+																	// wire
+
+		outputWires[w] = subCircuits[2 * w - 1].outputWires[0]; // Success wire
+	}
+}

+ 24 - 0
fastergc/YaoGC/G_AND_2_1.java

@@ -0,0 +1,24 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+class G_AND_2_1 extends AND_2_1 {
+	public G_AND_2_1() {
+		super();
+	}
+
+	protected void execYao() {
+		// fillTruthTable();
+		// encryptTruthTable();
+		// sendGTT();
+		// gtt = null;
+	}
+
+	@Override
+	protected void passTruthTable() {
+		fillTruthTable();
+		encryptTruthTable();
+		sendGTT();
+		gtt = null;
+	}
+}

+ 24 - 0
fastergc/YaoGC/G_FF10_1_SC_2_2.java

@@ -0,0 +1,24 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+class G_FF10_1_SC_2_2 extends FF10_1_SC_2_2 {
+	public G_FF10_1_SC_2_2() {
+		super();
+	}
+
+	protected void execYao() {
+		// fillTruthTable();
+		// encryptTruthTable();
+		// sendGTT();
+		// gtt = null;
+	}
+
+	@Override
+	protected void passTruthTable() {
+		fillTruthTable();
+		encryptTruthTable();
+		sendGTT();
+		gtt = null;
+	}
+}

+ 24 - 0
fastergc/YaoGC/G_FF10_2_SC_2_2.java

@@ -0,0 +1,24 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+class G_FF10_2_SC_2_2 extends FF10_2_SC_2_2 {
+	public G_FF10_2_SC_2_2() {
+		super();
+	}
+
+	protected void execYao() {
+		// fillTruthTable();
+		// encryptTruthTable();
+		// sendGTT();
+		// gtt = null;
+	}
+
+	@Override
+	protected void passTruthTable() {
+		fillTruthTable();
+		encryptTruthTable();
+		sendGTT();
+		gtt = null;
+	}
+}

+ 24 - 0
fastergc/YaoGC/G_FF10_3_SC_2_2.java

@@ -0,0 +1,24 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+class G_FF10_3_SC_2_2 extends FF10_3_SC_2_2 {
+	public G_FF10_3_SC_2_2() {
+		super();
+	}
+
+	protected void execYao() {
+		// fillTruthTable();
+		// encryptTruthTable();
+		// sendGTT();
+		// gtt = null;
+	}
+
+	@Override
+	protected void passTruthTable() {
+		fillTruthTable();
+		encryptTruthTable();
+		sendGTT();
+		gtt = null;
+	}
+}

+ 24 - 0
fastergc/YaoGC/G_OR_2_1.java

@@ -0,0 +1,24 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+class G_OR_2_1 extends OR_2_1 {
+	public G_OR_2_1() {
+		super();
+	}
+
+	protected void execYao() {
+		// fillTruthTable();
+		// encryptTruthTable();
+		// sendGTT();
+		// gtt = null;
+	}
+
+	@Override
+	protected void passTruthTable() {
+		fillTruthTable();
+		encryptTruthTable();
+		sendGTT();
+		gtt = null;
+	}
+}

+ 24 - 0
fastergc/YaoGC/G_T1_FF0_O_2_1.java

@@ -0,0 +1,24 @@
+// by Boyang Wei
+
+package YaoGC;
+
+class G_T1_FF0_O_2_1 extends T1_FF0_O_2_1 {
+	public G_T1_FF0_O_2_1() {
+		super();
+	}
+
+	protected void execYao() {
+		// fillTruthTable();
+		// encryptTruthTable();
+		// sendGTT();
+		// gtt = null;
+	}
+
+	@Override
+	protected void passTruthTable() {
+		fillTruthTable();
+		encryptTruthTable();
+		sendGTT();
+		gtt = null;
+	}
+}

+ 24 - 0
fastergc/YaoGC/G_T1_FF0_S_2_1.java

@@ -0,0 +1,24 @@
+// by Boyang Wei
+
+package YaoGC;
+
+class G_T1_FF0_S_2_1 extends T1_FF0_S_2_1 {
+	public G_T1_FF0_S_2_1() {
+		super();
+	}
+
+	protected void execYao() {
+		// fillTruthTable();
+		// encryptTruthTable();
+		// sendGTT();
+		// gtt = null;
+	}
+
+	@Override
+	protected void passTruthTable() {
+		fillTruthTable();
+		encryptTruthTable();
+		sendGTT();
+		gtt = null;
+	}
+}

+ 24 - 0
fastergc/YaoGC/G_T1_FF1_O_2_1.java

@@ -0,0 +1,24 @@
+// by Boyang Wei
+
+package YaoGC;
+
+class G_T1_FF1_O_2_1 extends T1_FF1_O_2_1 {
+	public G_T1_FF1_O_2_1() {
+		super();
+	}
+
+	protected void execYao() {
+		// fillTruthTable();
+		// encryptTruthTable();
+		// sendGTT();
+		// gtt = null;
+	}
+
+	@Override
+	protected void passTruthTable() {
+		fillTruthTable();
+		encryptTruthTable();
+		sendGTT();
+		gtt = null;
+	}
+}

+ 24 - 0
fastergc/YaoGC/G_T1_FF1_S_2_1.java

@@ -0,0 +1,24 @@
+// by Boyang Wei
+
+package YaoGC;
+
+class G_T1_FF1_S_2_1 extends T1_FF1_S_2_1 {
+	public G_T1_FF1_S_2_1() {
+		super();
+	}
+
+	protected void execYao() {
+		// fillTruthTable();
+		// encryptTruthTable();
+		// sendGTT();
+		// gtt = null;
+	}
+
+	@Override
+	protected void passTruthTable() {
+		fillTruthTable();
+		encryptTruthTable();
+		sendGTT();
+		gtt = null;
+	}
+}

+ 24 - 0
fastergc/YaoGC/G_T2_FF10_O_2_1.java

@@ -0,0 +1,24 @@
+// by Boyang Wei
+
+package YaoGC;
+
+class G_T2_FF10_O_2_1 extends T2_FF10_O_2_1 {
+	public G_T2_FF10_O_2_1() {
+		super();
+	}
+
+	protected void execYao() {
+		// fillTruthTable();
+		// encryptTruthTable();
+		// sendGTT();
+		// gtt = null;
+	}
+
+	@Override
+	protected void passTruthTable() {
+		fillTruthTable();
+		encryptTruthTable();
+		sendGTT();
+		gtt = null;
+	}
+}

+ 24 - 0
fastergc/YaoGC/G_T2_FF10_S_2_1.java

@@ -0,0 +1,24 @@
+// by Boyang Wei
+
+package YaoGC;
+
+class G_T2_FF10_S_2_1 extends T2_FF10_S_2_1 {
+	public G_T2_FF10_S_2_1() {
+		super();
+	}
+
+	protected void execYao() {
+		// fillTruthTable();
+		// encryptTruthTable();
+		// sendGTT();
+		// gtt = null;
+	}
+
+	@Override
+	protected void passTruthTable() {
+		fillTruthTable();
+		encryptTruthTable();
+		sendGTT();
+		gtt = null;
+	}
+}

+ 36 - 0
fastergc/YaoGC/G_XOR_2_1.java

@@ -0,0 +1,36 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+import java.math.BigInteger;
+
+import sprout.oram.PID;
+import sprout.oram.TID;
+import Cipher.Cipher;
+
+class G_XOR_2_1 extends XOR_2_1 {
+	public G_XOR_2_1() {
+		super();
+	}
+
+	protected void sendOutBitEncPair() {
+		if (outputWires[0].outBitEncPair != null) {
+			BigInteger[] lb = new BigInteger[2];
+			lb[0] = outputWires[0].lbl;
+			lb[1] = Wire.conjugate(lb[0]);
+			int lsb = lb[0].testBit(0) ? 1 : 0;
+			int k = outputWires[0].serialNum;
+			timing.stopwatch[PID.sha1][TID.offline].start();
+			outputWires[0].outBitEncPair[lsb] = Cipher.encrypt(k, lb[0], 0);
+			outputWires[0].outBitEncPair[1 - lsb] = Cipher.encrypt(k, lb[1], 1);
+			timing.stopwatch[PID.sha1][TID.offline].stop();
+			timing.stopwatch[PID.gcf][TID.offline].stop();
+
+			timing.stopwatch[PID.gcf][TID.offline_write].start();
+			receiver.write(outputWires[0].outBitEncPair);
+			timing.stopwatch[PID.gcf][TID.offline_write].stop();
+
+			timing.stopwatch[PID.gcf][TID.offline].start();
+		}
+	}
+}

+ 112 - 0
fastergc/YaoGC/OR_2_1.java

@@ -0,0 +1,112 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+import java.math.*;
+
+import Cipher.*;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+public abstract class OR_2_1 extends SimpleCircuit_2_1 {
+	public OR_2_1() {
+		super("OR_2_1");
+	}
+
+	public static OR_2_1 newInstance() {
+		if (Circuit.isForGarbling)
+			return new G_OR_2_1();
+		else
+			return new E_OR_2_1();
+	}
+
+	protected void compute() {
+		int left = inputWires[0].value;
+		int right = inputWires[1].value;
+
+		outputWires[0].value = left | right;
+	}
+
+	protected void fillTruthTable() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		BigInteger[] labelL = { inWireL.lbl, Wire.conjugate(inWireL.lbl) };
+		if (inWireL.invd == true) {
+			BigInteger tmp = labelL[0];
+			labelL[0] = labelL[1];
+			labelL[1] = tmp;
+		}
+
+		BigInteger[] labelR = { inWireR.lbl, Wire.conjugate(inWireR.lbl) };
+		if (inWireR.invd == true) {
+			BigInteger tmp = labelR[0];
+			labelR[0] = labelR[1];
+			labelR[1] = tmp;
+		}
+
+		int k = outWire.serialNum;
+
+		gtt = new BigInteger[2][2];
+
+		int cL = inWireL.lbl.testBit(0) ? 1 : 0;
+		int cR = inWireR.lbl.testBit(0) ? 1 : 0;
+
+		BigInteger[] lb = new BigInteger[2];
+		timing.stopwatch[PID.sha1][TID.offline].start();
+		lb[cL | cR] = Cipher.encrypt(labelL[cL], labelR[cR], k, BigInteger.ZERO);
+		timing.stopwatch[PID.sha1][TID.offline].stop();
+		lb[1 - (cL | cR)] = Wire.conjugate(lb[cL | cR]);
+		outWire.lbl = lb[0];
+
+		gtt[0 ^ cL][0 ^ cR] = lb[0];
+		gtt[0 ^ cL][1 ^ cR] = lb[1];
+		gtt[1 ^ cL][0 ^ cR] = lb[1];
+		gtt[1 ^ cL][1 ^ cR] = lb[1];
+
+		int lsb = lb[0].testBit(0) ? 1 : 0;
+		if (outputWires[0].outBitEncPair != null) {
+			timing.stopwatch[PID.sha1][TID.offline].start();
+			outputWires[0].outBitEncPair[lsb] = Cipher.encrypt(k, lb[0], 0);
+			outputWires[0].outBitEncPair[1 - lsb] = Cipher.encrypt(k, lb[1], 1);
+			timing.stopwatch[PID.sha1][TID.offline].stop();
+		}
+	}
+
+	protected boolean shortCut() {
+		if (inputWires[0].value == 1) {
+			inputWires[0].value = Wire.UNKNOWN_SIG;
+			outputWires[0].value = 1;
+			return true;
+		}
+
+		if (inputWires[1].value == 1) {
+			inputWires[1].value = Wire.UNKNOWN_SIG;
+			outputWires[0].value = 1;
+			return true;
+		}
+
+		return false;
+	}
+
+	protected boolean collapse() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		if (inWireL.lbl.equals(inWireR.lbl)) {
+			if (inWireL.invd == inWireR.invd) {
+				outWire.invd = inWireL.invd;
+				outWire.setLabel(inWireL.lbl);
+			} else {
+				outWire.invd = false;
+				outWire.value = 1;
+			}
+
+			return true;
+		}
+
+		return false;
+	}
+}

+ 163 - 0
fastergc/YaoGC/SimpleCircuit_2_1.java

@@ -0,0 +1,163 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+import java.math.*;
+
+import sprout.oram.PID;
+import sprout.oram.TID;
+import Cipher.Cipher;
+
+public abstract class SimpleCircuit_2_1 extends Circuit {
+
+	protected BigInteger[][] gtt;
+
+	public SimpleCircuit_2_1(String name) {
+		super(2, 1, name);
+	}
+
+	public void build() throws Exception {
+		createInputWires();
+		createOutputWires();
+	}
+
+	protected void createInputWires() {
+		super.createInputWires();
+
+		for (int i = 0; i < inDegree; i++)
+			inputWires[i].addObserver(this, new TransitiveObservable.Socket(
+					inputWires, i));
+	}
+
+	protected void createOutputWires() {
+		outputWires[0] = new Wire();
+	}
+
+	protected void execute(boolean evaluate) {
+
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		if (evaluate) {
+			if (inWireL.value != Wire.UNKNOWN_SIG
+					&& inWireR.value != Wire.UNKNOWN_SIG) {
+				compute();
+			} else if (inWireL.value != Wire.UNKNOWN_SIG) {
+				if (shortCut())
+					outWire.invd = false;
+				else {
+					outWire.value = Wire.UNKNOWN_SIG;
+					outWire.invd = inWireR.invd;
+					outWire.setLabel(inWireR.lbl);
+				}
+			} else if (inWireR.value != Wire.UNKNOWN_SIG) {
+				if (shortCut())
+					outWire.invd = false;
+				else {
+					outWire.value = Wire.UNKNOWN_SIG;
+					outWire.invd = inWireL.invd;
+					outWire.setLabel(inWireL.lbl);
+				}
+			} else {
+				outWire.value = Wire.UNKNOWN_SIG;
+				outWire.invd = false;
+
+				if (collapse()) {
+					System.err
+							.println("Same labels detected! Please check label generation.");
+				} else {
+					execYao();
+				}
+			}
+		} else
+			passTruthTable();
+
+		outWire.setReady(evaluate);
+	}
+
+	protected abstract void execYao();
+
+	protected abstract void passTruthTable();
+
+	protected abstract boolean shortCut();
+
+	protected abstract boolean collapse();
+
+	protected void sendGTT() {
+		timing.stopwatch[PID.gcf][TID.offline].stop();
+
+		timing.stopwatch[PID.gcf][TID.offline_write].start();
+		receiver.write(gtt[0][1]);
+		receiver.write(gtt[1][0]);
+		receiver.write(gtt[1][1]);
+
+		if (outputWires[0].outBitEncPair != null)
+			receiver.write(outputWires[0].outBitEncPair);
+		timing.stopwatch[PID.gcf][TID.offline_write].stop();
+
+		timing.stopwatch[PID.gcf][TID.offline].start();
+	}
+
+	protected void receiveGTT() {
+		try {
+			gtt = new BigInteger[2][2];
+			gtt[0][0] = BigInteger.ZERO;
+			timing.stopwatch[PID.gcf][TID.offline].stop();
+
+			timing.stopwatch[PID.gcf][TID.offline_read].start();
+			gtt[0][1] = sender.readBigInteger();
+			gtt[1][0] = sender.readBigInteger();
+			gtt[1][1] = sender.readBigInteger();
+
+			if (outputWires[0].outBitEncPair != null)
+				outputWires[0].outBitEncPair = sender.readBigIntegerArray();
+			timing.stopwatch[PID.gcf][TID.offline_read].stop();
+
+			timing.stopwatch[PID.gcf][TID.offline].start();
+		} catch (Exception e) {
+			e.printStackTrace();
+			System.exit(1);
+		}
+	}
+
+	protected void encryptTruthTable() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		BigInteger[] labelL = { inWireL.lbl, Wire.conjugate(inWireL.lbl) };
+		if (inWireL.invd == true) {
+			BigInteger tmp = labelL[0];
+			labelL[0] = labelL[1];
+			labelL[1] = tmp;
+		}
+
+		BigInteger[] labelR = { inWireR.lbl, Wire.conjugate(inWireR.lbl) };
+		if (inWireR.invd == true) {
+			BigInteger tmp = labelR[0];
+			labelR[0] = labelR[1];
+			labelR[1] = tmp;
+		}
+
+		int k = outWire.serialNum;
+
+		int cL = inWireL.lbl.testBit(0) ? 1 : 0;
+		int cR = inWireR.lbl.testBit(0) ? 1 : 0;
+
+		timing.stopwatch[PID.sha1][TID.offline].start();
+		if (cL != 0 || cR != 0)
+			gtt[0 ^ cL][0 ^ cR] = Cipher.encrypt(labelL[0], labelR[0], k,
+					gtt[0 ^ cL][0 ^ cR]);
+		if (cL != 0 || cR != 1)
+			gtt[0 ^ cL][1 ^ cR] = Cipher.encrypt(labelL[0], labelR[1], k,
+					gtt[0 ^ cL][1 ^ cR]);
+		if (cL != 1 || cR != 0)
+			gtt[1 ^ cL][0 ^ cR] = Cipher.encrypt(labelL[1], labelR[0], k,
+					gtt[1 ^ cL][0 ^ cR]);
+		if (cL != 1 || cR != 1)
+			gtt[1 ^ cL][1 ^ cR] = Cipher.encrypt(labelL[1], labelR[1], k,
+					gtt[1 ^ cL][1 ^ cR]);
+		timing.stopwatch[PID.sha1][TID.offline].stop();
+	}
+}

+ 180 - 0
fastergc/YaoGC/SimpleCircuit_2_2.java

@@ -0,0 +1,180 @@
+// by Boyang Wei
+package YaoGC;
+
+import java.math.*;
+
+import sprout.oram.PID;
+import sprout.oram.TID;
+import Cipher.Cipher;
+
+public abstract class SimpleCircuit_2_2 extends Circuit {
+
+	protected BigInteger[][] gtt;
+
+	public SimpleCircuit_2_2(String name) {
+		super(2, 2, name);
+	}
+
+	public void build() throws Exception {
+		createInputWires();
+		createOutputWires();
+	}
+
+	protected void createInputWires() {
+		super.createInputWires();
+
+		for (int i = 0; i < inDegree; i++)
+			inputWires[i].addObserver(this, new TransitiveObservable.Socket(
+					inputWires, i));
+	}
+
+	protected void createOutputWires() {
+		outputWires[0] = new Wire();
+		outputWires[1] = new Wire();
+	}
+
+	protected void execute(boolean evaluate) {
+		if (evaluate) {
+			execYao();
+		} else {
+			passTruthTable();
+		}
+
+		outputWires[0].setReady(evaluate);
+		outputWires[1].setReady(evaluate);
+		
+		/*
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		if (evaluate) {
+			if (inWireL.value != Wire.UNKNOWN_SIG
+					&& inWireR.value != Wire.UNKNOWN_SIG) {
+				compute();
+			} else if (inWireL.value != Wire.UNKNOWN_SIG) {
+				if (shortCut())
+					outWire.invd = false;
+				else {
+					outWire.value = Wire.UNKNOWN_SIG;
+					outWire.invd = inWireR.invd;
+					outWire.setLabel(inWireR.lbl);
+				}
+			} else if (inWireR.value != Wire.UNKNOWN_SIG) {
+				if (shortCut())
+					outWire.invd = false;
+				else {
+					outWire.value = Wire.UNKNOWN_SIG;
+					outWire.invd = inWireL.invd;
+					outWire.setLabel(inWireL.lbl);
+				}
+			} else {
+				outWire.value = Wire.UNKNOWN_SIG;
+				outWire.invd = false;
+
+				if (collapse()) {
+					System.err
+							.println("Same labels detected! Please check label generation.");
+				} else {
+					execYao();
+				}
+			}
+		} else
+			passTruthTable();
+
+		outWire.setReady(evaluate);
+		*/
+		
+	}
+
+	protected abstract void execYao();
+
+	protected abstract void passTruthTable();
+
+	protected abstract boolean shortCut();
+
+	protected abstract boolean collapse();
+
+	protected void sendGTT() {
+		timing.stopwatch[PID.gcf][TID.offline].stop();
+
+		timing.stopwatch[PID.gcf][TID.offline_write].start();
+		receiver.write(gtt[0][1]);
+		receiver.write(gtt[1][0]);
+		receiver.write(gtt[1][1]);
+
+		if (outputWires[0].outBitEncPair != null)
+			receiver.write(outputWires[0].outBitEncPair);
+		if (outputWires[1].outBitEncPair != null)
+			receiver.write(outputWires[1].outBitEncPair);
+		timing.stopwatch[PID.gcf][TID.offline_write].stop();
+
+		timing.stopwatch[PID.gcf][TID.offline].start();
+	}
+
+	protected void receiveGTT() {
+		try {
+			gtt = new BigInteger[2][2];
+			gtt[0][0] = BigInteger.ZERO;
+			timing.stopwatch[PID.gcf][TID.offline].stop();
+
+			timing.stopwatch[PID.gcf][TID.offline_read].start();
+			gtt[0][1] = sender.readBigInteger();
+			gtt[1][0] = sender.readBigInteger();
+			gtt[1][1] = sender.readBigInteger();
+
+			if (outputWires[0].outBitEncPair != null)
+				outputWires[0].outBitEncPair = sender.readBigIntegerArray();
+			if (outputWires[1].outBitEncPair != null)
+				outputWires[1].outBitEncPair = sender.readBigIntegerArray();
+			timing.stopwatch[PID.gcf][TID.offline_read].stop();
+
+			timing.stopwatch[PID.gcf][TID.offline].start();
+		} catch (Exception e) {
+			e.printStackTrace();
+			System.exit(1);
+		}
+	}
+
+	protected void encryptTruthTable() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire0 = outputWires[0];
+		Wire outWire1 = outputWires[1];
+
+		BigInteger[] labelL = { inWireL.lbl, Wire.conjugate(inWireL.lbl) };
+		if (inWireL.invd == true) {
+			BigInteger tmp = labelL[0];
+			labelL[0] = labelL[1];
+			labelL[1] = tmp;
+		}
+
+		BigInteger[] labelR = { inWireR.lbl, Wire.conjugate(inWireR.lbl) };
+		if (inWireR.invd == true) {
+			BigInteger tmp = labelR[0];
+			labelR[0] = labelR[1];
+			labelR[1] = tmp;
+		}
+
+		int k0 = outWire0.serialNum;
+		int k1 = outWire1.serialNum;
+
+		int cL = inWireL.lbl.testBit(0) ? 1 : 0;
+		int cR = inWireR.lbl.testBit(0) ? 1 : 0;
+
+		timing.stopwatch[PID.sha1][TID.offline].start();
+		if (cL != 0 || cR != 0)
+			gtt[0 ^ cL][0 ^ cR] = Cipher.encrypt(labelL[0], labelR[0], k0, k1,
+					gtt[0 ^ cL][0 ^ cR]);
+		if (cL != 0 || cR != 1)
+			gtt[0 ^ cL][1 ^ cR] = Cipher.encrypt(labelL[0], labelR[1], k0, k1,
+					gtt[0 ^ cL][1 ^ cR]);
+		if (cL != 1 || cR != 0)
+			gtt[1 ^ cL][0 ^ cR] = Cipher.encrypt(labelL[1], labelR[0], k0, k1,
+					gtt[1 ^ cL][0 ^ cR]);
+		if (cL != 1 || cR != 1)
+			gtt[1 ^ cL][1 ^ cR] = Cipher.encrypt(labelL[1], labelR[1], k0, k1,
+					gtt[1 ^ cL][1 ^ cR]);
+		timing.stopwatch[PID.sha1][TID.offline].stop();
+	}
+}

+ 164 - 0
fastergc/YaoGC/State.java

@@ -0,0 +1,164 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+import java.math.*;
+
+public class State {
+
+	public static class StaticWire {
+		public int value = Wire.UNKNOWN_SIG;
+		public BigInteger lbl = null;
+		public boolean invd = false;
+
+		StaticWire() {
+		}
+
+		public StaticWire(int v) {
+			value = v;
+		}
+
+		public StaticWire(BigInteger label) {
+			lbl = label;
+		}
+	}
+
+	public StaticWire wires[];
+	public BigInteger plainValue = null; // The non-negative integer the state
+											// object represents.
+
+	public State(StaticWire[] ws) {
+		wires = ws;
+
+		for (int i = 0; i < ws.length; i++) {
+			if (ws[i].value == Wire.UNKNOWN_SIG) {
+				plainValue = null;
+				return;
+			}
+		}
+
+		plainValue = BigInteger.ZERO;
+		for (int i = 0; i < ws.length; i++) {
+			if (ws[i].value == 1)
+				plainValue = plainValue.setBit(i);
+		}
+	}
+
+	public State(BigInteger v, int length) {
+		wires = new StaticWire[length];
+		for (int i = 0; i < length; i++) {
+			wires[i] = new StaticWire();
+			wires[i].value = v.testBit(i) ? 1 : 0;
+		}
+
+		plainValue = v;
+	}
+
+	private State(int length) {
+		wires = new StaticWire[length];
+		plainValue = null;
+	}
+
+	public static State flattenStateArray(State[] as) {
+		State res = new State(as.length * as[0].wires.length);
+		for (int i = 0; i < as.length; i++)
+			for (int j = 0; j < as[0].wires.length; j++) {
+				res.wires[i * 8 + j] = new StaticWire();
+				res.wires[i * 8 + j].value = as[i].wires[j].value;
+				res.wires[i * 8 + j].lbl = as[i].wires[j].lbl;
+				res.wires[i * 8 + j].invd = as[i].wires[j].invd;
+			}
+
+		return res;
+	}
+
+	public static State extractState(State s, int start, int end) {
+		State res = new State(end - start);
+		for (int i = 0; i < end - start; i++) {
+			res.wires[i] = new StaticWire();
+			res.wires[i].value = s.wires[i + start].value;
+			res.wires[i].lbl = s.wires[i + start].lbl;
+			res.wires[i].invd = s.wires[i + start].invd;
+		}
+
+		return res;
+	}
+
+	public static State fromWires(Wire[] ws) {
+		State.StaticWire[] swires = new State.StaticWire[ws.length];
+		for (int i = 0; i < ws.length; i++) {
+			swires[i] = new StaticWire();
+			swires[i].value = ws[i].value;
+			swires[i].lbl = ws[i].lbl;
+			swires[i].invd = ws[i].invd;
+		}
+
+		return new State(swires);
+	}
+
+	public static State fromLabels(BigInteger[] lbs) {
+		State res = new State(lbs.length);
+		for (int i = 0; i < lbs.length; i++)
+			res.wires[i] = new StaticWire(lbs[i]);
+
+		return res;
+	}
+
+	public int getWidth() {
+		return wires.length;
+	}
+
+	/*
+	 * Return "true" ONLY IF it is CERTAIN that the value denoted by "this"
+	 * object is larger than that denoted by "s". Namely, if "false" is
+	 * returned, it is still possible that ("this" > "s").
+	 */
+	public boolean largerThan(State s) {
+		if (plainValue != null && s.plainValue != null)
+			return plainValue.compareTo(s.plainValue) > 0;
+
+		return false; // this line should never be reached.
+	}
+
+	public static State signExtend(State s, int width) {
+		if (s.getWidth() > width) {
+			(new Exception("s is already wider than width.")).printStackTrace();
+			System.exit(1);
+		} else if (s.getWidth() == width)
+			return s;
+
+		State res = new State(width);
+		for (int i = 0; i < width; i++)
+			if (i < s.wires.length)
+				res.wires[i] = s.wires[i];
+			else
+				res.wires[i] = s.wires[s.wires.length - 1];
+
+		res.plainValue = s.plainValue;
+		return res;
+	}
+
+	public static State concatenate(State s1, State s2) {
+		int width = s1.getWidth() + s2.getWidth();
+		State res = new State(width);
+		for (int i = 0; i < width; i++)
+			if (i < s2.wires.length)
+				res.wires[i] = s2.wires[i];
+			else
+				res.wires[i] = s1.wires[i - s2.wires.length];
+
+		if (s1.plainValue == null || s2.plainValue == null)
+			res.plainValue = null;
+		else
+			res.plainValue = s1.plainValue.shiftLeft(s2.getWidth()).xor(
+					s2.plainValue);
+		return res;
+	}
+
+	public BigInteger[] toLabels() {
+		BigInteger[] res = new BigInteger[getWidth()];
+		for (int i = 0; i < res.length; i++)
+			res[i] = wires[i].lbl;
+		return res;
+	}
+}

+ 126 - 0
fastergc/YaoGC/T1_FF0_O_2_1.java

@@ -0,0 +1,126 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+import java.math.*;
+
+import Cipher.*;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+public abstract class T1_FF0_O_2_1 extends SimpleCircuit_2_1 {
+	public T1_FF0_O_2_1() {
+		super("T1_FF0_O_2_1");
+	}
+
+	public static T1_FF0_O_2_1 newInstance() {
+		if (Circuit.isForGarbling)
+			return new G_T1_FF0_O_2_1();
+		else
+			return new E_T1_FF0_O_2_1();
+	}
+
+	private int output(int l, int r) {
+		int o;
+		if (l == 0) {
+			if (r == 0)
+				o = 1;
+			else
+				o = 0;
+		} else {
+			if (r == 0)
+				o = 0;
+			else
+				o = 0;
+		}
+		return o;
+	}
+
+	protected void compute() {
+		int left = inputWires[0].value;
+		int right = inputWires[1].value;
+
+		outputWires[0].value = output(left, right);
+	}
+
+	protected void fillTruthTable() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		BigInteger[] labelL = { inWireL.lbl, Wire.conjugate(inWireL.lbl) };
+		if (inWireL.invd == true) {
+			BigInteger tmp = labelL[0];
+			labelL[0] = labelL[1];
+			labelL[1] = tmp;
+		}
+
+		BigInteger[] labelR = { inWireR.lbl, Wire.conjugate(inWireR.lbl) };
+		if (inWireR.invd == true) {
+			BigInteger tmp = labelR[0];
+			labelR[0] = labelR[1];
+			labelR[1] = tmp;
+		}
+
+		int k = outWire.serialNum;
+
+		gtt = new BigInteger[2][2];
+
+		int cL = inWireL.lbl.testBit(0) ? 1 : 0;
+		int cR = inWireR.lbl.testBit(0) ? 1 : 0;
+
+		BigInteger[] lb = new BigInteger[2];
+		timing.stopwatch[PID.sha1][TID.offline].start();
+		lb[output(cL, cR)] = Cipher.encrypt(labelL[cL], labelR[cR], k, BigInteger.ZERO);
+		timing.stopwatch[PID.sha1][TID.offline].stop();
+		lb[1 - output(cL, cR)] = Wire.conjugate(lb[output(cL, cR)]);
+		outWire.lbl = lb[0];
+
+		gtt[0 ^ cL][0 ^ cR] = lb[1];
+		gtt[0 ^ cL][1 ^ cR] = lb[0];
+		gtt[1 ^ cL][0 ^ cR] = lb[0];
+		gtt[1 ^ cL][1 ^ cR] = lb[0];
+
+		int lsb = lb[0].testBit(0) ? 1 : 0;
+		if (outputWires[0].outBitEncPair != null) {
+			timing.stopwatch[PID.sha1][TID.offline].start();
+			outputWires[0].outBitEncPair[lsb] = Cipher.encrypt(k, lb[0], 0);
+			outputWires[0].outBitEncPair[1 - lsb] = Cipher.encrypt(k, lb[1], 1);
+			timing.stopwatch[PID.sha1][TID.offline].stop();
+		}
+	}
+
+	protected boolean shortCut() {
+		if (inputWires[0].value == 1) {
+			outputWires[0].value = 0;
+			return true;
+		}
+
+		if (inputWires[1].value == 1) {
+			outputWires[0].value = 0;
+			return true;
+		}
+
+		return false;
+	}
+
+	protected boolean collapse() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		if (inWireL.lbl.equals(inWireR.lbl)) {
+			if (inWireL.invd == inWireR.invd) {
+				outWire.invd = inWireL.invd;
+				outWire.setLabel(inWireL.lbl);
+			} else {
+				outWire.invd = false;
+				outWire.value = 0;
+			}
+
+			return true;
+		}
+
+		return false;
+	}
+}

+ 126 - 0
fastergc/YaoGC/T1_FF0_S_2_1.java

@@ -0,0 +1,126 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+import java.math.*;
+
+import Cipher.*;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+public abstract class T1_FF0_S_2_1 extends SimpleCircuit_2_1 {
+	public T1_FF0_S_2_1() {
+		super("T1_FF0_S_2_1");
+	}
+
+	public static T1_FF0_S_2_1 newInstance() {
+		if (Circuit.isForGarbling)
+			return new G_T1_FF0_S_2_1();
+		else
+			return new E_T1_FF0_S_2_1();
+	}
+
+	private int output(int l, int r) {
+		int o;
+		if (l == 0) {
+			if (r == 0)
+				o = 1;
+			else
+				o = 0;
+		} else {
+			if (r == 0)
+				o = 1;
+			else
+				o = 1;
+		}
+		return o;
+	}
+
+	protected void compute() {
+		int left = inputWires[0].value;
+		int right = inputWires[1].value;
+
+		outputWires[0].value = output(left, right);
+	}
+
+	protected void fillTruthTable() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		BigInteger[] labelL = { inWireL.lbl, Wire.conjugate(inWireL.lbl) };
+		if (inWireL.invd == true) {
+			BigInteger tmp = labelL[0];
+			labelL[0] = labelL[1];
+			labelL[1] = tmp;
+		}
+
+		BigInteger[] labelR = { inWireR.lbl, Wire.conjugate(inWireR.lbl) };
+		if (inWireR.invd == true) {
+			BigInteger tmp = labelR[0];
+			labelR[0] = labelR[1];
+			labelR[1] = tmp;
+		}
+
+		int k = outWire.serialNum;
+
+		gtt = new BigInteger[2][2];
+
+		int cL = inWireL.lbl.testBit(0) ? 1 : 0;
+		int cR = inWireR.lbl.testBit(0) ? 1 : 0;
+
+		BigInteger[] lb = new BigInteger[2];
+		timing.stopwatch[PID.sha1][TID.offline].start();
+		lb[output(cL, cR)] = Cipher.encrypt(labelL[cL], labelR[cR], k, BigInteger.ZERO);
+		timing.stopwatch[PID.sha1][TID.offline].stop();
+		lb[1 - output(cL, cR)] = Wire.conjugate(lb[output(cL, cR)]);
+		outWire.lbl = lb[0];
+
+		gtt[0 ^ cL][0 ^ cR] = lb[1];
+		gtt[0 ^ cL][1 ^ cR] = lb[0];
+		gtt[1 ^ cL][0 ^ cR] = lb[1];
+		gtt[1 ^ cL][1 ^ cR] = lb[1];
+
+		int lsb = lb[0].testBit(0) ? 1 : 0;
+		if (outputWires[0].outBitEncPair != null) {
+			timing.stopwatch[PID.sha1][TID.offline].start();
+			outputWires[0].outBitEncPair[lsb] = Cipher.encrypt(k, lb[0], 0);
+			outputWires[0].outBitEncPair[1 - lsb] = Cipher.encrypt(k, lb[1], 1);
+			timing.stopwatch[PID.sha1][TID.offline].stop();
+		}
+	}
+
+	protected boolean shortCut() {
+		if (inputWires[0].value == 1) {
+			outputWires[0].value = 1;
+			return true;
+		}
+
+		if (inputWires[1].value == 0) {
+			outputWires[0].value = 1;
+			return true;
+		}
+
+		return false;
+	}
+
+	protected boolean collapse() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		if (inWireL.lbl.equals(inWireR.lbl)) {
+			if (inWireL.invd == inWireR.invd) {
+				outWire.invd = inWireL.invd;
+				outWire.setLabel(inWireL.lbl);
+			} else {
+				outWire.invd = false;
+				outWire.value = 0;
+			}
+
+			return true;
+		}
+
+		return false;
+	}
+}

+ 126 - 0
fastergc/YaoGC/T1_FF1_O_2_1.java

@@ -0,0 +1,126 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+import java.math.*;
+
+import Cipher.*;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+public abstract class T1_FF1_O_2_1 extends SimpleCircuit_2_1 {
+	public T1_FF1_O_2_1() {
+		super("T1_FF1_O_2_1");
+	}
+
+	public static T1_FF1_O_2_1 newInstance() {
+		if (Circuit.isForGarbling)
+			return new G_T1_FF1_O_2_1();
+		else
+			return new E_T1_FF1_O_2_1();
+	}
+
+	private int output(int l, int r) {
+		int o;
+		if (l == 0) {
+			if (r == 0)
+				o = 0;
+			else
+				o = 1;
+		} else {
+			if (r == 0)
+				o = 0;
+			else
+				o = 0;
+		}
+		return o;
+	}
+
+	protected void compute() {
+		int left = inputWires[0].value;
+		int right = inputWires[1].value;
+
+		outputWires[0].value = output(left, right);
+	}
+
+	protected void fillTruthTable() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		BigInteger[] labelL = { inWireL.lbl, Wire.conjugate(inWireL.lbl) };
+		if (inWireL.invd == true) {
+			BigInteger tmp = labelL[0];
+			labelL[0] = labelL[1];
+			labelL[1] = tmp;
+		}
+
+		BigInteger[] labelR = { inWireR.lbl, Wire.conjugate(inWireR.lbl) };
+		if (inWireR.invd == true) {
+			BigInteger tmp = labelR[0];
+			labelR[0] = labelR[1];
+			labelR[1] = tmp;
+		}
+
+		int k = outWire.serialNum;
+
+		gtt = new BigInteger[2][2];
+
+		int cL = inWireL.lbl.testBit(0) ? 1 : 0;
+		int cR = inWireR.lbl.testBit(0) ? 1 : 0;
+
+		BigInteger[] lb = new BigInteger[2];
+		timing.stopwatch[PID.sha1][TID.offline].start();
+		lb[output(cL, cR)] = Cipher.encrypt(labelL[cL], labelR[cR], k, BigInteger.ZERO);
+		timing.stopwatch[PID.sha1][TID.offline].stop();
+		lb[1 - output(cL, cR)] = Wire.conjugate(lb[output(cL, cR)]);
+		outWire.lbl = lb[0];
+
+		gtt[0 ^ cL][0 ^ cR] = lb[0];
+		gtt[0 ^ cL][1 ^ cR] = lb[1];
+		gtt[1 ^ cL][0 ^ cR] = lb[0];
+		gtt[1 ^ cL][1 ^ cR] = lb[0];
+
+		int lsb = lb[0].testBit(0) ? 1 : 0;
+		if (outputWires[0].outBitEncPair != null) {
+			timing.stopwatch[PID.sha1][TID.offline].start();
+			outputWires[0].outBitEncPair[lsb] = Cipher.encrypt(k, lb[0], 0);
+			outputWires[0].outBitEncPair[1 - lsb] = Cipher.encrypt(k, lb[1], 1);
+			timing.stopwatch[PID.sha1][TID.offline].stop();
+		}
+	}
+
+	protected boolean shortCut() {
+		if (inputWires[0].value == 1) {
+			outputWires[0].value = 0;
+			return true;
+		}
+
+		if (inputWires[1].value == 0) {
+			outputWires[0].value = 0;
+			return true;
+		}
+
+		return false;
+	}
+
+	protected boolean collapse() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		if (inWireL.lbl.equals(inWireR.lbl)) {
+			if (inWireL.invd == inWireR.invd) {
+				outWire.invd = inWireL.invd;
+				outWire.setLabel(inWireL.lbl);
+			} else {
+				outWire.invd = false;
+				outWire.value = 0;
+			}
+
+			return true;
+		}
+
+		return false;
+	}
+}

+ 126 - 0
fastergc/YaoGC/T1_FF1_S_2_1.java

@@ -0,0 +1,126 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+import java.math.*;
+
+import Cipher.*;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+public abstract class T1_FF1_S_2_1 extends SimpleCircuit_2_1 {
+	public T1_FF1_S_2_1() {
+		super("T1_FF1_S_2_1");
+	}
+
+	public static T1_FF1_S_2_1 newInstance() {
+		if (Circuit.isForGarbling)
+			return new G_T1_FF1_S_2_1();
+		else
+			return new E_T1_FF1_S_2_1();
+	}
+
+	private int output(int l, int r) {
+		int o;
+		if (l == 0) {
+			if (r == 0)
+				o = 0;
+			else
+				o = 1;
+		} else {
+			if (r == 0)
+				o = 1;
+			else
+				o = 1;
+		}
+		return o;
+	}
+
+	protected void compute() {
+		int left = inputWires[0].value;
+		int right = inputWires[1].value;
+
+		outputWires[0].value = output(left, right);
+	}
+
+	protected void fillTruthTable() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		BigInteger[] labelL = { inWireL.lbl, Wire.conjugate(inWireL.lbl) };
+		if (inWireL.invd == true) {
+			BigInteger tmp = labelL[0];
+			labelL[0] = labelL[1];
+			labelL[1] = tmp;
+		}
+
+		BigInteger[] labelR = { inWireR.lbl, Wire.conjugate(inWireR.lbl) };
+		if (inWireR.invd == true) {
+			BigInteger tmp = labelR[0];
+			labelR[0] = labelR[1];
+			labelR[1] = tmp;
+		}
+
+		int k = outWire.serialNum;
+
+		gtt = new BigInteger[2][2];
+
+		int cL = inWireL.lbl.testBit(0) ? 1 : 0;
+		int cR = inWireR.lbl.testBit(0) ? 1 : 0;
+
+		BigInteger[] lb = new BigInteger[2];
+		timing.stopwatch[PID.sha1][TID.offline].start();
+		lb[output(cL, cR)] = Cipher.encrypt(labelL[cL], labelR[cR], k, BigInteger.ZERO);
+		timing.stopwatch[PID.sha1][TID.offline].stop();
+		lb[1 - output(cL, cR)] = Wire.conjugate(lb[output(cL, cR)]);
+		outWire.lbl = lb[0];
+
+		gtt[0 ^ cL][0 ^ cR] = lb[0];
+		gtt[0 ^ cL][1 ^ cR] = lb[1];
+		gtt[1 ^ cL][0 ^ cR] = lb[1];
+		gtt[1 ^ cL][1 ^ cR] = lb[1];
+
+		int lsb = lb[0].testBit(0) ? 1 : 0;
+		if (outputWires[0].outBitEncPair != null) {
+			timing.stopwatch[PID.sha1][TID.offline].start();
+			outputWires[0].outBitEncPair[lsb] = Cipher.encrypt(k, lb[0], 0);
+			outputWires[0].outBitEncPair[1 - lsb] = Cipher.encrypt(k, lb[1], 1);
+			timing.stopwatch[PID.sha1][TID.offline].stop();
+		}
+	}
+
+	protected boolean shortCut() {
+		if (inputWires[0].value == 1) {
+			outputWires[0].value = 1;
+			return true;
+		}
+
+		if (inputWires[1].value == 1) {
+			outputWires[0].value = 1;
+			return true;
+		}
+
+		return false;
+	}
+
+	protected boolean collapse() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		if (inWireL.lbl.equals(inWireR.lbl)) {
+			if (inWireL.invd == inWireR.invd) {
+				outWire.invd = inWireL.invd;
+				outWire.setLabel(inWireL.lbl);
+			} else {
+				outWire.invd = false;
+				outWire.value = 0;
+			}
+
+			return true;
+		}
+
+		return false;
+	}
+}

+ 126 - 0
fastergc/YaoGC/T2_FF10_O_2_1.java

@@ -0,0 +1,126 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+import java.math.*;
+
+import Cipher.*;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+public abstract class T2_FF10_O_2_1 extends SimpleCircuit_2_1 {
+	public T2_FF10_O_2_1() {
+		super("T2_FF10_O_2_1");
+	}
+
+	public static T2_FF10_O_2_1 newInstance() {
+		if (Circuit.isForGarbling)
+			return new G_T2_FF10_O_2_1();
+		else
+			return new E_T2_FF10_O_2_1();
+	}
+
+	private int output(int l, int r) {
+		int o;
+		if (l == 0) {
+			if (r == 0)
+				o = 0;
+			else
+				o = 0;
+		} else {
+			if (r == 0)
+				o = 0;
+			else
+				o = 0;
+		}
+		return o;
+	}
+
+	protected void compute() {
+		int left = inputWires[0].value;
+		int right = inputWires[1].value;
+
+		outputWires[0].value = output(left, right);
+	}
+
+	protected void fillTruthTable() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		BigInteger[] labelL = { inWireL.lbl, Wire.conjugate(inWireL.lbl) };
+		if (inWireL.invd == true) {
+			BigInteger tmp = labelL[0];
+			labelL[0] = labelL[1];
+			labelL[1] = tmp;
+		}
+
+		BigInteger[] labelR = { inWireR.lbl, Wire.conjugate(inWireR.lbl) };
+		if (inWireR.invd == true) {
+			BigInteger tmp = labelR[0];
+			labelR[0] = labelR[1];
+			labelR[1] = tmp;
+		}
+
+		int k = outWire.serialNum;
+
+		gtt = new BigInteger[2][2];
+
+		int cL = inWireL.lbl.testBit(0) ? 1 : 0;
+		int cR = inWireR.lbl.testBit(0) ? 1 : 0;
+
+		BigInteger[] lb = new BigInteger[2];
+		timing.stopwatch[PID.sha1][TID.offline].start();
+		lb[output(cL, cR)] = Cipher.encrypt(labelL[cL], labelR[cR], k, BigInteger.ZERO);
+		timing.stopwatch[PID.sha1][TID.offline].stop();
+		lb[1 - output(cL, cR)] = Wire.conjugate(lb[output(cL, cR)]);
+		outWire.lbl = lb[0];
+
+		gtt[0 ^ cL][0 ^ cR] = lb[0];
+		gtt[0 ^ cL][1 ^ cR] = lb[0];
+		gtt[1 ^ cL][0 ^ cR] = lb[0];
+		gtt[1 ^ cL][1 ^ cR] = lb[0];
+
+		int lsb = lb[0].testBit(0) ? 1 : 0;
+		if (outputWires[0].outBitEncPair != null) {
+			timing.stopwatch[PID.sha1][TID.offline].start();
+			outputWires[0].outBitEncPair[lsb] = Cipher.encrypt(k, lb[0], 0);
+			outputWires[0].outBitEncPair[1 - lsb] = Cipher.encrypt(k, lb[1], 1);
+			timing.stopwatch[PID.sha1][TID.offline].stop();
+		}
+	}
+
+	protected boolean shortCut() {
+		if (inputWires[0].value == 0 || inputWires[0].value == 1) {
+			outputWires[0].value = 0;
+			return true;
+		}
+
+		if (inputWires[1].value == 0 || inputWires[1].value == 1) {
+			outputWires[0].value = 0;
+			return true;
+		}
+
+		return false;
+	}
+
+	protected boolean collapse() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		if (inWireL.lbl.equals(inWireR.lbl)) {
+			if (inWireL.invd == inWireR.invd) {
+				outWire.invd = inWireL.invd;
+				outWire.setLabel(inWireL.lbl);
+			} else {
+				outWire.invd = false;
+				outWire.value = 0;
+			}
+
+			return true;
+		}
+
+		return false;
+	}
+}

+ 121 - 0
fastergc/YaoGC/T2_FF10_S_2_1.java

@@ -0,0 +1,121 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+import java.math.*;
+
+import Cipher.*;
+import sprout.oram.PID;
+import sprout.oram.TID;
+
+public abstract class T2_FF10_S_2_1 extends SimpleCircuit_2_1 {
+	public T2_FF10_S_2_1() {
+		super("T2_FF10_S_2_1");
+	}
+
+	public static T2_FF10_S_2_1 newInstance() {
+		if (Circuit.isForGarbling)
+			return new G_T2_FF10_S_2_1();
+		else
+			return new E_T2_FF10_S_2_1();
+	}
+
+	private int output(int l, int r) {
+		int o;
+		if (l == 0) {
+			if (r == 0)
+				o = 0;
+			else
+				o = 0;
+		} else {
+			if (r == 0)
+				o = 1;
+			else
+				o = 1;
+		}
+		return o;
+	}
+
+	protected void compute() {
+		int left = inputWires[0].value;
+		int right = inputWires[1].value;
+
+		outputWires[0].value = output(left, right);
+	}
+
+	protected void fillTruthTable() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		BigInteger[] labelL = { inWireL.lbl, Wire.conjugate(inWireL.lbl) };
+		if (inWireL.invd == true) {
+			BigInteger tmp = labelL[0];
+			labelL[0] = labelL[1];
+			labelL[1] = tmp;
+		}
+
+		BigInteger[] labelR = { inWireR.lbl, Wire.conjugate(inWireR.lbl) };
+		if (inWireR.invd == true) {
+			BigInteger tmp = labelR[0];
+			labelR[0] = labelR[1];
+			labelR[1] = tmp;
+		}
+
+		int k = outWire.serialNum;
+
+		gtt = new BigInteger[2][2];
+
+		int cL = inWireL.lbl.testBit(0) ? 1 : 0;
+		int cR = inWireR.lbl.testBit(0) ? 1 : 0;
+
+		BigInteger[] lb = new BigInteger[2];
+		timing.stopwatch[PID.sha1][TID.offline].start();
+		lb[output(cL, cR)] = Cipher.encrypt(labelL[cL], labelR[cR], k, BigInteger.ZERO);
+		timing.stopwatch[PID.sha1][TID.offline].stop();
+		lb[1 - output(cL, cR)] = Wire.conjugate(lb[output(cL, cR)]);
+		outWire.lbl = lb[0];
+
+		gtt[0 ^ cL][0 ^ cR] = lb[0];
+		gtt[0 ^ cL][1 ^ cR] = lb[0];
+		gtt[1 ^ cL][0 ^ cR] = lb[1];
+		gtt[1 ^ cL][1 ^ cR] = lb[1];
+
+		int lsb = lb[0].testBit(0) ? 1 : 0;
+		if (outputWires[0].outBitEncPair != null) {
+			timing.stopwatch[PID.sha1][TID.offline].start();
+			outputWires[0].outBitEncPair[lsb] = Cipher.encrypt(k, lb[0], 0);
+			outputWires[0].outBitEncPair[1 - lsb] = Cipher.encrypt(k, lb[1], 1);
+			timing.stopwatch[PID.sha1][TID.offline].stop();
+		}
+	}
+
+	protected boolean shortCut() {
+		if (inputWires[0].value == 0 || inputWires[0].value == 1) {
+			outputWires[0].value = inputWires[0].value;
+			return true;
+		}
+
+		return false;
+	}
+
+	protected boolean collapse() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		if (inWireL.lbl.equals(inWireR.lbl)) {
+			if (inWireL.invd == inWireR.invd) {
+				outWire.invd = inWireL.invd;
+				outWire.setLabel(inWireL.lbl);
+			} else {
+				outWire.invd = false;
+				outWire.value = 0;
+			}
+
+			return true;
+		}
+
+		return false;
+	}
+}

+ 33 - 0
fastergc/YaoGC/TestCircuit.java

@@ -0,0 +1,33 @@
+// by Boyang Wei
+
+package YaoGC;
+
+public class TestCircuit extends CompositeCircuit {
+	public TestCircuit() {
+		super(2, 2, 1, "TestCircuit");
+	}
+
+	protected void createSubCircuits() throws Exception {
+		subCircuits[0] = new FF10_2_2(1);
+
+		super.createSubCircuits();
+	}
+
+	protected void connectWires() throws Exception {
+		// Enable wires
+		inputWires[0].connectTo(subCircuits[0].inputWires, 0);
+		inputWires[1].connectTo(subCircuits[0].inputWires, 1);
+	}
+
+	protected void defineOutputWires() {
+		outputWires[0] = subCircuits[0].outputWires[0];
+		outputWires[1] = subCircuits[0].outputWires[1];
+	}
+
+	/*
+	 * public void sendOutBitsLookup(boolean send) { //sendOutBitsLookup = send;
+	 * if (send) for (int i=0; i<outputWires.length; i++)
+	 * outputWires[i].outBitEncPair = new BigInteger[2]; else for (int i=0;
+	 * i<outputWires.length; i++) outputWires[i].outBitEncPair = null; }
+	 */
+}

+ 185 - 0
fastergc/YaoGC/TransitiveObservable.java

@@ -0,0 +1,185 @@
+/*
+ Modified by Yan Huang <yhuang@virginia.edu>
+
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package YaoGC;
+
+import java.util.*;
+
+/**
+ * Observable is used to notify a group of Observer objects when a change
+ * occurs. On creation, the set of observers is empty. After a change occurred,
+ * the application can call the {@link #notifyObservers()} method. This will
+ * cause the invocation of the {@code update()} method of all registered
+ * Observers. The order of invocation is not specified. This implementation will
+ * call the Observers in the order they registered. Subclasses are completely
+ * free in what order they call the update methods.
+ *
+ * @see Observer
+ */
+public class TransitiveObservable {
+
+	List<TransitiveObserver> observers = new ArrayList<TransitiveObserver>();
+
+	boolean changed = false;
+
+	List<Socket> exports = new ArrayList<Socket>();
+
+	static class Socket {
+		Wire[] wires;
+		int idx;
+
+		public Socket(Wire[] ws, int i) {
+			wires = ws;
+			idx = i;
+		}
+
+		public void updateSocket(Wire w) {
+			wires[idx] = w;
+		}
+
+		public boolean equals(Socket sock) {
+			if (this == sock)
+				return true;
+
+			if (sock != null) {
+				return (wires == sock.wires) && (idx == sock.idx);
+			}
+
+			return false;
+		}
+	}
+
+	/**
+	 * Constructs a new {@code Observable} object.
+	 */
+	public TransitiveObservable() {
+		super();
+	}
+
+	/**
+	 * Adds the specified observer to the list of observers. If it is already
+	 * registered, it is not added a second time.
+	 * 
+	 * @param observer
+	 *            the Observer to add.
+	 */
+	public void addObserver(TransitiveObserver observer, Socket sock) {
+		if (observer == null) {
+			throw new NullPointerException();
+		}
+		synchronized (this) {
+			// if (!observers.contains(observer))
+			observers.add(observer);
+			exports.add(sock);
+		}
+	}
+
+	/**
+	 * Clears the changed flag for this {@code Observable}. After calling
+	 * {@code clearChanged()}, {@code hasChanged()} will return {@code false}.
+	 */
+	protected void clearChanged() {
+		changed = false;
+	}
+
+	/**
+	 * Returns the number of observers registered to this {@code Observable}.
+	 * 
+	 * @return the number of observers.
+	 */
+	public int countObservers() {
+		return observers.size();
+	}
+
+	/**
+	 * Removes the specified observer from the list of observers. Passing null
+	 * won't do anything.
+	 * 
+	 * @param observer
+	 *            the observer to remove.
+	 */
+	public synchronized void deleteObserver(TransitiveObserver observer,
+			Socket sock) {
+		observers.remove(observer);
+		exports.remove(sock);
+	}
+
+	/**
+	 * Removes all observers from the list of observers.
+	 */
+	public synchronized void deleteObservers() {
+		observers.clear();
+		exports.clear();
+	}
+
+	/**
+	 * Returns the changed flag for this {@code Observable}.
+	 * 
+	 * @return {@code true} when the changed flag for this {@code Observable} is
+	 *         set, {@code false} otherwise.
+	 */
+	public boolean hasChanged() {
+		return changed;
+	}
+
+	/**
+	 * If {@code hasChanged()} returns {@code true}, calls the {@code update()}
+	 * method for every observer in the list of observers using null as the
+	 * argument. Afterwards, calls {@code clearChanged()}.
+	 * <p>
+	 * Equivalent to calling {@code notifyObservers(null)}.
+	 */
+	public void notifyObservers(boolean evaluate) {
+		notifyObservers(evaluate, null);
+	}
+
+	/**
+	 * If {@code hasChanged()} returns {@code true}, calls the {@code update()}
+	 * method for every Observer in the list of observers using the specified
+	 * argument. Afterwards calls {@code clearChanged()}.
+	 * 
+	 * @param data
+	 *            the argument passed to {@code update()}.
+	 */
+	public void notifyObservers(boolean evaluate, Object data) {
+		int size = 0;
+		TransitiveObserver[] arrays = null;
+		synchronized (this) {
+			if (hasChanged()) {
+				clearChanged();
+				size = observers.size();
+				arrays = new TransitiveObserver[size];
+				observers.toArray(arrays);
+			}
+		}
+		if (arrays != null) {
+			for (TransitiveObserver observer : arrays) {
+				observer.update(evaluate, this, data);
+			}
+		}
+	}
+
+	/**
+	 * Sets the changed flag for this {@code Observable}. After calling
+	 * {@code setChanged()}, {@code hasChanged()} will return {@code true}.
+	 */
+	protected void setChanged() {
+		changed = true;
+	}
+}

+ 39 - 0
fastergc/YaoGC/TransitiveObserver.java

@@ -0,0 +1,39 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package YaoGC;
+
+/**
+ * {@code Observer} is the interface to be implemented by objects that receive
+ * notification of updates on an {@code Observable} object.
+ * 
+ * @see Observable
+ */
+public interface TransitiveObserver {
+
+	/**
+	 * This method is called if the specified {@code Observable} object's
+	 * {@code notifyObservers} method is called (because the {@code Observable}
+	 * object has been updated.
+	 * 
+	 * @param observable
+	 *            the {@link Observable} object.
+	 * @param data
+	 *            the data passed to {@link Observable#notifyObservers(Object)}.
+	 */
+	void update(boolean evaluate, TransitiveObservable observable, Object data);
+}

+ 87 - 0
fastergc/YaoGC/Wire.java

@@ -0,0 +1,87 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+import java.math.*;
+import java.security.SecureRandom;
+
+import sprout.crypto.SR;
+
+public class Wire extends TransitiveObservable {
+	public static final int UNKNOWN_SIG = -1;
+
+	// These four fields are for garbling
+	public static int K = 0;
+	private static SecureRandom rnd = SR.rand;
+	public static final int labelBitLength = 80;
+	public static final int labelBytes = (labelBitLength + 7) / 8;
+
+	public static final BigInteger R = new BigInteger(labelBitLength - 1, rnd);
+
+	public final int serialNum;
+	public int value = UNKNOWN_SIG;
+	public BigInteger lbl;
+	public boolean invd = false;
+
+	public BigInteger[] outBitEncPair = null;
+
+	public Wire() {
+		serialNum = K++;
+		lbl = new BigInteger(labelBitLength, rnd);
+	}
+
+	public static BigInteger[] newLabelPair() {
+		BigInteger[] res = new BigInteger[2];
+		res[0] = new BigInteger(labelBitLength, rnd);
+		res[1] = conjugate(res[0]);
+		return res;
+	}
+
+	public static BigInteger conjugate(BigInteger label) {
+		if (label == null)
+			return null;
+
+		return label.xor(R.shiftLeft(1).setBit(0));
+	}
+
+	public void setLabel(BigInteger label) {
+		lbl = label;
+	}
+
+	public void setReady(boolean evaluate) {
+		setChanged();
+		notifyObservers(evaluate);
+	}
+
+	public void connectTo(Wire[] ws, int idx) {
+		Wire w = ws[idx];
+
+		for (int i = 0; i < w.observers.size(); i++) {
+			TransitiveObserver ob = w.observers.get(i);
+			TransitiveObservable.Socket s = w.exports.get(i);
+			this.addObserver(ob, s);
+			s.updateSocket(this);
+		}
+
+		w.deleteObservers();
+		ws[idx] = this;
+	}
+
+	public void fixWire(int v) {
+		this.value = v;
+
+		for (int i = 0; i < this.observers.size(); i++) {
+			Circuit c = (Circuit) this.observers.get(i);
+			c.inDegree--;
+			if (c.inDegree == 0) {
+				c.compute();
+				for (int j = 0; j < c.outDegree; j++)
+					c.outputWires[j].fixWire(c.outputWires[j].value);
+			}
+		}
+	}
+
+	protected static int getLSB(BigInteger lp) {
+		return lp.testBit(0) ? 1 : 0;
+	}
+}

+ 109 - 0
fastergc/YaoGC/XOR_2_1.java

@@ -0,0 +1,109 @@
+// Copyright (C) 2010 by Yan Huang <yhuang@virginia.edu>
+
+package YaoGC;
+
+import java.math.*;
+
+public abstract class XOR_2_1 extends SimpleCircuit_2_1 {
+	public XOR_2_1() {
+		super("XOR_2_1");
+	}
+
+	public static XOR_2_1 newInstance() {
+		if (Circuit.isForGarbling)
+			return new G_XOR_2_1();
+		else
+			return new E_XOR_2_1();
+	}
+
+	protected void compute() {
+		int left = inputWires[0].value;
+		int right = inputWires[1].value;
+
+		outputWires[0].value = left ^ right;
+	}
+
+	public void execute(boolean evaluate) {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		if (inWireL.value != Wire.UNKNOWN_SIG
+				&& inWireR.value != Wire.UNKNOWN_SIG) {
+			compute();
+		} else if (inWireL.value != Wire.UNKNOWN_SIG) {
+			if (inWireL.value == 0)
+				outWire.invd = inWireR.invd;
+			else
+				outWire.invd = !inWireR.invd;
+
+			outWire.value = Wire.UNKNOWN_SIG;
+			outWire.setLabel(inWireR.lbl);
+		} else if (inWireR.value != Wire.UNKNOWN_SIG) {
+			if (inWireR.value == 0)
+				outWire.invd = inWireL.invd;
+			else
+				outWire.invd = !inWireL.invd;
+
+			outWire.value = Wire.UNKNOWN_SIG;
+			outWire.setLabel(inWireL.lbl);
+		} else {
+			if (collapse()) {
+				System.err
+						.println("Same labels detected! Please check label generation.");
+			} else {
+				BigInteger l = inWireL.lbl;
+				BigInteger r = inWireR.lbl;
+
+				BigInteger out = l.xor(r);
+
+				outWire.invd = inWireL.invd ^ inWireR.invd;
+				outWire.value = Wire.UNKNOWN_SIG;
+				outWire.setLabel(out);
+			}
+		}
+
+		if (!evaluate)
+			sendOutBitEncPair();
+
+		outWire.setReady(evaluate);
+	}
+
+	protected boolean collapse() {
+		Wire inWireL = inputWires[0];
+		Wire inWireR = inputWires[1];
+		Wire outWire = outputWires[0];
+
+		if (inWireL.lbl.equals(inWireR.lbl)) {
+			if (inWireL.invd == inWireR.invd) {
+				outWire.invd = false;
+				outWire.value = 0;
+			} else {
+				outWire.invd = false;
+				outWire.value = 1;
+			}
+
+			return true;
+		}
+
+		return false;
+	}
+
+	protected void sendOutBitEncPair() {
+	}
+
+	// Never used for XOR gate.
+	protected boolean shortCut() {
+		return false;
+	}
+
+	// Never used for XOR gate.
+	protected void fillTruthTable() {
+	}
+
+	protected void execYao() {
+	}
+
+	protected void passTruthTable() {
+	}
+}

BIN
lib/bcprov-jdk15on-151.jar


BIN
lib/commons-cli-1.2.jar


BIN
lib/commons-io-2.4.jar


BIN
lib/commons-lang3-3.3.2.jar


BIN
lib/jargs.jar


BIN
lib/junit-4.10.jar


BIN
lib/snakeyaml-1.11.jar


+ 1 - 0
readmd.txt

@@ -0,0 +1 @@
+Three-Party Circuit-ORAM Implementation

+ 8 - 0
src/HelloWorld.java

@@ -0,0 +1,8 @@
+
+public class HelloWorld {
+
+	public static void main(String[] args) {
+		System.out.println("HelloWorld!");
+	}
+
+}