/** * Construct a sending party for an instance of the random OT extension protocol. * * @param snd * The correlated OT with error sender this protocol will use * @param resources * The common OT extension resources * @param network * The network to use */ public RotSenderImpl(CoteSender snd, OtExtensionResourcePool resources, Network network) { super(resources.getCoinTossing(), resources.getDigest(), resources .getComputationalSecurityParameter()); this.sender = snd; this.resources = resources; this.network = network; }
/** * Construct a sending party for an instance of the correlated OT protocol. * * @param resources The common resource pool needed for OT extension * @param network The network interface. Must not be null and must be initialized. */ public CoteSender(OtExtensionResourcePool resources, Network network) { super(resources.getInstanceId()); this.prgs = new ArrayList<>(resources.getComputationalSecurityParameter()); for (StrictBitVector message : resources.getSeedOts().getLearnedMessages()) { // Initialize the PRGs with the random messages prgs.add(initPrg(message)); } otChoices = resources.getSeedOts().getChoices(); this.resources = resources; this.network = network; }
@Override public List<StrictBitVector> extend(StrictBitVector choices) { // The underlying scheme requires computational security parameter plus lambda security // parameter extra OTs int minOts = choices.getSize() + resources.getComputationalSecurityParameter() + resources .getLambdaSecurityParam(); // Round up to nearest two-power, which is required by the underlying scheme int ellPrime = (int) Math.pow(2, Math.ceil(Math.log(minOts) / Math.log(2))); // Extend the choices with random choices for padding StrictBitVector paddingChoices = new StrictBitVector(ellPrime - choices.getSize(), resources .getRandomGenerator()); StrictBitVector extendedChoices = StrictBitVector.concat(choices, paddingChoices); // Use the choices along with the random padding uses for correlated OT with // errors List<StrictBitVector> tlist = receiver.extend(extendedChoices); // Agree on challenges for linear combination test List<StrictBitVector> chiList = getChallenges(ellPrime); StrictBitVector xvec = computeBitLinearCombination(extendedChoices, chiList); network.send(resources.getOtherId(), xvec.toByteArray()); StrictBitVector tvec = computeInnerProduct(chiList, tlist); network.send(resources.getOtherId(), tvec.toByteArray()); // Remove the correlation of the OTs by hashing List<StrictBitVector> vvec = hashBitVector(tlist, choices.getSize()); return vvec; }
int minOts = size + resources.getComputationalSecurityParameter() + resources .getLambdaSecurityParam(); byte[] xvecBytes = network.receive(resources.getOtherId()); byte[] tvecBytes = network.receive(resources.getOtherId()); StrictBitVector xvec = new StrictBitVector(xvecBytes); StrictBitVector tvec = new StrictBitVector(tvecBytes);
/** * Receive the serialized message from the current 1-out-of-2 OT. * * @param choiceBit * Choice-bit. False for message 0, true for message 1. * @return The serialized message from the OT */ public byte[] receive(boolean choiceBit) { // Check if there is still an unused random OT stored, if not, execute a // random OT extension if (offset < 0 || offset >= batchSize) { choices = new StrictBitVector(batchSize, resources.getRandomGenerator()); randomMessages = receiver.extend(choices); offset = 0; } // Notify the sender if it should switch the 0 and 1 messages around (s.t. // the random choice bit in the preprocessed random OTs matches the true // choice bit sendSwitchBit(choiceBit); // Receive the serialized adjusted messages byte[] zeroAdjustment = network.receive(resources.getOtherId()); byte[] oneAdjustment = network.receive(resources.getOtherId()); byte[] res = doActualReceive(zeroAdjustment, oneAdjustment); offset++; return res; }
/** * Receives a list of StrictBitVectors from the default (0) channel. * * @param size Amount of elements in vector to receive. All of which must be of equal size. * @return The list of received elements, or null in case an error occurred. */ private List<StrictBitVector> receiveList(int size) { List<StrictBitVector> list = new ArrayList<>(size); byte[] byteBuffer = network.receive(resources.getOtherId()); int elementLength = byteBuffer.length / size; for (int i = 0; i < size; i++) { byte[] currentVector = new byte[elementLength]; System.arraycopy(byteBuffer, i * elementLength, currentVector, 0, elementLength); StrictBitVector currentArr = new StrictBitVector(currentVector); list.add(currentArr); } return list; } }
/** * Constructs a new batch of correlated OTs with errors. * * @param size Amount of OTs to construct */ public List<StrictBitVector> extend(int size) { if (size < 1) { throw new IllegalArgumentException("The amount of OTs must be a positive integer"); } if (size % Byte.SIZE != 0) { throw new IllegalArgumentException( "The amount of OTs must be a positive integer divisible by 8"); } int bytesNeeded = size / Byte.SIZE; final List<StrictBitVector> tlist = prgs.parallelStream() .limit(resources.getComputationalSecurityParameter()) .map(drbg -> { byte[] bytes = new byte[bytesNeeded]; drbg.nextBytes(bytes); return bytes; }) .map(StrictBitVector::new) .collect(Collectors.toList()); final List<StrictBitVector> ulist = receiveList(resources.getComputationalSecurityParameter()); IntStream.range(0, resources.getComputationalSecurityParameter()).parallel() .filter(i -> otChoices.getBit(i, false)) .forEach(i -> tlist.get(i).xor(ulist.get(i))); return Transpose.transpose(tlist); }
/** * Sends a list of StrictBitVectors to the default (0) channel. * * @param list * List to send, where all elements are required to have the same * length. */ private void sendList(List<StrictBitVector> list) { // Find the amount of bytes needed for each bitvector in the list int elementLength = list.get(0).getSize() / 8; // Allocate space for all elements in the list. byte[] toSend = new byte[(list.get(0).getSize() / 8) * list.size()]; for (int i = 0; i < list.size(); i++) { System.arraycopy(list.get(i).toByteArray(), 0, toSend, i * elementLength, elementLength); } network.send(resources.getOtherId(), toSend); } }
.limit(resources.getComputationalSecurityParameter()) .map(p -> p.getFirst()) .map(drbg -> { .collect(Collectors.toList()); final List<StrictBitVector> ulist = prgs.parallelStream() .limit(resources.getComputationalSecurityParameter()) .map(p -> p.getSecond()) .map(drbg -> { .collect(Collectors.toList()); ulist.parallelStream().forEach(u -> u.xor(choices)); IntStream.range(0, resources.getComputationalSecurityParameter()).parallel() .forEach(i -> ulist.get(i).xor(tlistZero.get(i))); sendList(ulist);
/** * Construct a receiving party for an instance of the random OT extension protocol. * * @param rec * The correlated OT with error receiver this protocol will use * @param resources * The common OT extension resources * @param network * The network to use */ public RotReceiverImpl(CoteReceiver rec, OtExtensionResourcePool resources, Network network) { super(resources.getCoinTossing(), resources.getDigest(), resources .getComputationalSecurityParameter()); this.receiver = rec; this.resources = resources; this.network = network; }
/** * Constructs a correlated OT extension with errors receiver instance. * * @param resources * The common resource pool needed for OT extension * @param network * The network object used to communicate with the other party */ public CoteReceiver(OtExtensionResourcePool resources, Network network) { super(resources.getInstanceId()); this.prgs = new ArrayList<>(resources.getComputationalSecurityParameter()); for (Pair<StrictBitVector, StrictBitVector> pair : resources.getSeedOts() .getSentMessages()) { Drbg prgZero = initPrg(pair.getFirst()); Drbg prgOne = initPrg(pair.getSecond()); prgs.add(new Pair<>(prgZero, prgOne)); } this.resources = resources; this.network = network; }
/** * Compute and send a bit indicating whether the sender should switch the zero * and one message around. * * @param choiceBit * The actual choice bit of the receiver */ private void sendSwitchBit(boolean choiceBit) { // Since we can only send a byte array we use 0x00 to indicate a 0-choice // and 0x01 to indicate a 1-choice byte[] switchBit = new byte[] { 0x00 }; // Set the choice to 0x01 if the sender should switch the 0 and 1 messages if (choiceBit ^ choices.getBit(offset, false) == true) { switchBit[0] = 0x01; } network.send(resources.getOtherId(), switchBit); } }
/** * Adjust the random, preprocessed message, to fit the specific messages to send. * * @param messageZero The actual zero message to send * @param messageOne The actual one message to send */ private void doActualSend(byte[] messageZero, byte[] messageOne) { // Find the correct preprocessed random OT messages StrictBitVector randomZero = randomMessages.getFirst().get(offset); StrictBitVector randomOne = randomMessages.getSecond().get(offset); int maxLength = Math.max(messageZero.length, messageOne.length); // Receive a bit from the receiver indicating whether the zero and one // messages should be switched around byte[] switchBit = network.receive(resources.getOtherId()); // If false (indicated by byte 0x00), then don't switch around if (switchBit[0] == 0x00) { network.send(resources.getOtherId(), PseudoOtp.encrypt(messageZero, randomZero.toByteArray(), maxLength)); network.send(resources.getOtherId(), PseudoOtp.encrypt(messageOne, randomOne.toByteArray(), maxLength)); } else { network.send(resources.getOtherId(), PseudoOtp.encrypt(messageOne, randomZero.toByteArray(), maxLength)); network.send(resources.getOtherId(), PseudoOtp.encrypt(messageZero, randomOne.toByteArray(), maxLength)); } } }