public RotReceiver createReceiver() { CoteReceiver receiver = new CoteReceiver(resources, network); return new RotReceiverImpl(receiver, resources, network); } }
public RotSender createSender() { CoteSender sender = new CoteSender(resources, network); return new RotSenderImpl(sender, resources, network); }
/** * Returns the receiver object for the protocol. * * @return Returns the receiver object for the protocol */ public CoteReceiver getReceiver() { if (receiver == null) { this.receiver = new CoteReceiver(resources, network); } return receiver; } }
@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; }
/** * 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; }
/** * 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; }
/** * 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; }
@Override public RotBatch createRot(int otherId, Network network) { if (getMyId() == otherId) { throw new IllegalArgumentException("Cannot initialize with self"); } CoinTossing ct = new CoinTossing(getMyId(), otherId, getRandomGenerator()); ct.initialize(network); OtExtensionResourcePool otResources = new OtExtensionResourcePoolImpl(getMyId(), otherId, getPrgSeedLength(), getLambdaSecurityParam(), getInstanceId(), getRandomGenerator(), ct, seedOts.get(otherId)); return new BristolRotBatch(new RotFactory(otResources, network), getPrgSeedLength(), getLambdaSecurityParam()); }
@Override public List<StrictBitVector> receive(StrictBitVector choiceBits, int sizeOfEachMessage) { if (this.receiver == null) { this.receiver = rot.createReceiver(); } int amountToPreprocess = computeExtensionSize(choiceBits.getSize(), comSecParam, statSecParam); byte[] extraByteChoices = Arrays.copyOf(choiceBits.toByteArray(), amountToPreprocess / Byte.SIZE); List<StrictBitVector> messages = receiver.extend(new StrictBitVector(extraByteChoices)); return messages.parallelStream().limit(choiceBits.getSize()) .map(m -> LengthAdjustment.adjust(m.toByteArray(), sizeOfEachMessage / Byte.SIZE)) .map(StrictBitVector::new) .collect(Collectors.toList()); }
@Override public List<Pair<StrictBitVector, StrictBitVector>> send(int numMessages, int sizeOfEachMessage) { if (this.sender == null) { this.sender = rot.createSender(); } int amountToPreprocess = computeExtensionSize(numMessages, comSecParam, statSecParam); Pair<List<StrictBitVector>, List<StrictBitVector>> messages = sender.extend(amountToPreprocess); List<StrictBitVector> zeroMessages = messages.getFirst().parallelStream().limit(numMessages) .map(m -> LengthAdjustment.adjust(m.toByteArray(), sizeOfEachMessage / Byte.SIZE)) .map(StrictBitVector::new) .collect(Collectors.toList()); List<StrictBitVector> oneMessages = messages.getSecond().parallelStream().limit(numMessages) .map(m -> LengthAdjustment.adjust(m.toByteArray(), sizeOfEachMessage / Byte.SIZE)) .map(StrictBitVector::new) .collect(Collectors.toList()); return IntStream.range(0, numMessages).parallel() .mapToObj(i -> new Pair<>(zeroMessages.get(i), oneMessages.get(i))) .collect(Collectors.toList()); }
/** * 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; }
/** * Act as receiver in a 1-out-of-2 OT. * * @param choiceBit * The bit representing choice of message. False represents 0 and * true represents 1. */ @Override public StrictBitVector receive(boolean choiceBit) { if (this.receiver == null) { RotReceiver receiver = rot.createReceiver(); this.receiver = new BristolOtReceiver(receiver, resources, network, batchSize); } byte[] res = receiver.receive(choiceBit); return new StrictBitVector(res); } }
/** * Act as sender in a 1-out-of-2 OT. * * @param messageZero * The zero-choice message * @param messageOne * the one-choice message */ @Override public void send(StrictBitVector messageZero, StrictBitVector messageOne) { if (this.sender == null) { RotSender sender = rot.createSender(); this.sender = new BristolOtSender(sender, resources, network, batchSize); } this.sender.send(messageZero.toByteArray(), messageOne.toByteArray()); }
/** * Send the serialized message from the current 1-out-of-2 OT. * * @param messageZero The message to send for choice zero * @param messageOne The message to send for choice one */ public void send(byte[] messageZero, byte[] messageOne) { // Check if there is still an unused random OT stored, if not, execute a // random OT extension if (offset < 0 || offset >= batchSize) { randomMessages = sender.extend(batchSize); offset = 0; } doActualSend(messageZero, messageOne); offset++; }
/** * Returns the sender object for the protocol. * * @return Returns the sender object for the protocol */ public CoteSender getSender() { if (sender == null) { this.sender = new CoteSender(resources, network); } return sender; }
/** * Given a candidate key OTP encrypts a message using either using the key directly or a key * pseudo randomly derived from the candidate, in order to match the length of the message. * * <p> * The key candidate is assumed to be uniformly random. Thus, if its size is longer or equal to * the message, the candidate key will be used directly as a OTP key. Otherwise, the key will be * deterministically <i>stretched</i> to match the length of the message in some secure way (e.g., * using a hash function). * </p> * * @param message the message to be encrypted * @param keyCandidate the candidate key * @return the resulting cipher text */ public static byte[] encrypt(byte[] message, byte[] keyCandidate) { return encrypt(message, keyCandidate, message.length); }
/** * Given a candidate key OTP decrypts a cipher text using either the key directly or a key pseudo * randomly derived from the candidate, in order to match the length of the cipher text. * * <p> * The key candidate is assumed to be uniformly random. Thus, if its size longer or equal to the * cipher text, the candidate key will be used directly as a OTP key. Otherwise, the key will be * deterministically <i>stretched</i> to match the length of the cipher text in some secure way * (e.g., using a hash function). * </p> * * @param cipherText the cipher text to be decrypted * @param keyCandidate the candidate key for OTP decryption * @return the resulting message */ public static byte[] decrypt(byte[] cipherText, byte[] keyCandidate) { return decrypt(cipherText, keyCandidate, cipherText.length); }
/** * Transpose all 8 bit squares in a square matrix, in-place. * * @param input The input */ private static void transposeAllByteBlocks(List<byte[]> input) { // Start by transposing one byte and 8 rows at a time using the trivial // O(n^2) algorithm for (int i = 0; i < input.size(); i = i + Byte.SIZE) { for (int j = 0; j < input.get(0).length * Byte.SIZE; j = j + Byte.SIZE) { transposeByteBlock(input, i, j); } } }
/** * Complete the Eklundh algorithm for transposing with initial blocks of 8 bits. That is, assuming * all blocks of 8 bits have already been transposed * * @param input The matrix to transpose. Represented in row-major */ private static void doEklundh(List<byte[]> input) { int rows = input.size(); int byteColumns = input.get(0).length; for (int blockSize = 1; blockSize <= byteColumns / 2; blockSize = blockSize * 2) { for (int i = 0; i < rows; i = i + 2 * Byte.SIZE * blockSize) { for (int j = 0; j < byteColumns; j = j + 2 * blockSize) { // swap the blocks swap(input, i, j, blockSize); } } } }
/** * 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; }