// Copyright (C) 2013 by Yan Huang package com.oblivm.backend.ot; import java.io.IOException; import java.math.BigInteger; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.Security; import com.oblivm.backend.flexsc.Flag; import com.oblivm.backend.gc.GCSignal; import com.oblivm.backend.network.Network; import com.oblivm.backend.rand.ISAACProvider; public class NPOTReceiver extends OTReceiver { static SecureRandom rnd; static { Security.addProvider(new ISAACProvider()); try { rnd = SecureRandom.getInstance("ISAACRandom"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } private BigInteger p, q, g, C; private BigInteger gr; private BigInteger[][] pk; private BigInteger[] keys; Cipher cipher; public NPOTReceiver(Network channel) throws Exception { super(channel); cipher = new Cipher(); initialize(); } @Override public GCSignal receive(boolean c) throws IOException { return receive(new boolean[] { c })[0]; } public GCSignal[] receive(boolean[] choices) throws IOException { step1(choices); return step2(choices); } private void initialize() throws Exception { Flag.sw.startOTIO(); C = channel.readBI(); p = channel.readBI(); q = channel.readBI(); g = channel.readBI(); gr = channel.readBI(); msgBitLength = channel.readInt(); Flag.sw.stopOTIO(); } private void step1(boolean[] choices) throws IOException { keys = new BigInteger[choices.length]; pk = new BigInteger[choices.length][2]; BigInteger[] pk0 = new BigInteger[choices.length]; for (int i = 0; i < choices.length; i++) { BigInteger k = (new BigInteger(q.bitLength(), rnd)).mod(q); BigInteger gk = g.modPow(k, p); BigInteger C_over_gk = C.multiply(gk.modInverse(p)).mod(p); keys[i] = gr.modPow(k, p); int sigma = choices[i] ? 1 : 0; pk[i][sigma] = gk; pk[i][1 - sigma] = C_over_gk; pk0[i] = pk[i][0]; } Flag.sw.startOTIO(); for (int i = 0; i < choices.length; i++) channel.writeBI(pk0[i]); channel.flush(); Flag.sw.stopOTIO(); } private GCSignal[] step2(boolean[] choices) { BigInteger[][] msg = new BigInteger[choices.length][2]; Flag.sw.startOTIO(); for (int i = 0; i < choices.length; i++) { msg[i][0] = channel.readBI(); msg[i][1] = channel.readBI(); } Flag.sw.stopOTIO(); GCSignal[] data = new GCSignal[choices.length]; for (int i = 0; i < choices.length; i++) { int sigma = choices[i] ? 1 : 0; data[i] = GCSignal .newInstance(cipher.decrypt(keys[i].toByteArray(), msg[i][sigma], msgBitLength).toByteArray()); } return data; } }