@Override public byte[] receive(int id) { ByteArrayInputStream byteInputStream = input.get(id); if (byteInputStream == null) { byte[] partyData = network.receive(id); byteInputStream = new ByteArrayInputStream(partyData); input.put(id, byteInputStream); } int count = byteInputStream.read(); byte[] bytes = new byte[count]; byteInputStream.read(bytes, 0, count); return bytes; }
@Override public StrictBitVector receive(boolean choiceBit) { byte[] seed = receiveRandomOt(choiceBit); byte[] encryptedZeroMessage = network.receive(otherId); byte[] encryptedOneMessage = network.receive(otherId); return recoverTrueMessage(encryptedZeroMessage, encryptedOneMessage, seed, choiceBit); }
/** * Runs broadcast validation upon receiving messages to ensure consistency. */ @Override public byte[] receive(int partyId) { byte[] received = network.receive(partyId); validator.validate(Arrays.asList(received)); return received; }
/** * Retrieves input from all players (including yourself) * * @return A list of byte buffers where the data from party 1 resides at * index 0 and so forth. */ default List<byte[]> receiveFromAll() { List<byte[]> res = new ArrayList<>(); for (int i = 1; i <= getNoOfParties(); i++) { res.add(receive(i)); } return res; }
@Override public byte[] receive(int partyId) { byte[] res = this.delegate.receive(partyId); int noBytes = res.length; partyStatsMap.computeIfAbsent(partyId, (i) -> new PartyStats()).recordTransmission(noBytes); 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; } }
/** * Completes the receiver's part of the Naor-Pinkas OT in order to receive a random message of the * length of hash digest. * * @return The random message received */ private byte[] receiveRandomOt(boolean choiceBit) { BigInteger c = new BigInteger(network.receive(otherId)); BigInteger privateKey = randNum.nextBigInteger(dhModulus); BigInteger publicKeySigma = dhGenerator.modPow(privateKey, dhModulus); BigInteger publicKeyNotSigma = publicKeySigma.modInverse(dhModulus).multiply(c); if (choiceBit == false) { network.send(otherId, publicKeySigma.toByteArray()); } else { network.send(otherId, publicKeyNotSigma.toByteArray()); } BigInteger encZero = new BigInteger(network.receive(otherId)); BigInteger encOne = new BigInteger(network.receive(otherId)); byte[] message; if (choiceBit == false) { message = decryptRandomMessage(encZero, privateKey); } else { message = decryptRandomMessage(encOne, privateKey); } return message; }
/** * Computes shares of product of this party's mac key share and other party's inputs. * * @param numInputs number of other party's inputs * @return shares of product */ public List<FieldElement> extend(int numInputs) { // compute chosen masks List<FieldElement> chosenMasks = generateMasks(numInputs); // use mac share for each input List<FieldElement> macKeyShares = IntStream.range(0, numInputs).mapToObj(idx -> macKeyShare).collect(Collectors.toList()); // receive diffs from other party List<FieldElement> diffs = resourcePool.getFieldDefinition().deserializeList(network.receive(otherId)); // compute product shares return multiplier.computeProductShares(macKeyShares, chosenMasks, diffs); }
/** * Retrieves shares for epsilon and delta and reconstructs each. */ private Pair<PlainT, PlainT> receiveAndReconstruct(Network network, CompUIntFactory<PlainT> factory, int noOfParties) { PlainT e = factory.zero(); PlainT d = factory.zero(); for (int i = 1; i <= noOfParties; i++) { e = e.add(factory.deserialize(network.receive(i))); d = d.add(factory.deserialize(network.receive(i))); } return new Pair<>(e, d); }
/** * Exchange the seed with the other party using a commitment protocol. * * @param seed * The current party's seed * @param network * The network instance * @return The other party's seed */ private byte[] exchangeSeeds(byte[] seed, Network network) { // Let the party with the smallest id be the party receiving a commitment if (myId < otherId) { byte[] serializedComm = network.receive(otherId); HashBasedCommitment comm = serializer.deserialize(serializedComm); network.send(otherId, seed.clone()); byte[] opening = network.receive(otherId); return comm.open(opening); } else { HashBasedCommitment comm = new HashBasedCommitment(); byte[] openInfo = comm.commit(rand, seed); network.send(otherId, serializer.serialize(comm)); byte[] otherSeed = network.receive(otherId); network.send(otherId, openInfo); return otherSeed; } } }
/** * Completes the sender's part of the Naor-Pinkas OT in order to send two random messages of the * length of hash digest. * * @return The two random messages sent by the sender. */ private Pair<byte[], byte[]> sendRandomOt() { BigInteger c = randNum.nextBigInteger(dhModulus); network.send(otherId, c.toByteArray()); BigInteger publicKeyZero = new BigInteger(network.receive(otherId)); BigInteger publicKeyOne = publicKeyZero.modInverse(dhModulus).multiply(c); Pair<BigInteger, byte[]> zeroChoiceData = encryptRandomMessage(publicKeyZero); Pair<BigInteger, byte[]> oneChoiceData = encryptRandomMessage(publicKeyOne); network.send(otherId, zeroChoiceData.getFirst().toByteArray()); network.send(otherId, oneChoiceData.getFirst().toByteArray()); return new Pair<>(zeroChoiceData.getSecond(), oneChoiceData.getSecond()); }
/** * 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; }
@Override public EvaluationStatus evaluate(int round, ResourcePool resourcePool, Network network) { if (round == 0) { if (resourcePool.getMyId() == sender) { network.sendToAll(new byte[]{BooleanSerializer.toBytes(input.out())}); } return EvaluationStatus.HAS_MORE_ROUNDS; } else { boolean r = BooleanSerializer.fromBytes(network.receive(sender)[0]); this.output = new DummyBooleanSBool(r); return EvaluationStatus.IS_DONE; } }
@Override public EvaluationStatus evaluate(int round, DummyArithmeticResourcePool rp, Network network) { if (round == 0) { if (targetId == rp.getMyId()) { network.sendToAll(rp.getFieldDefinition().serialize(open)); } return EvaluationStatus.HAS_MORE_ROUNDS; } else { //if (round == 1) { byte[] bin = network.receive(targetId); closed = new DummyArithmeticSInt(rp.getFieldDefinition().deserialize(bin)); return EvaluationStatus.IS_DONE; } }
/** * Runs a batch of the entry wise product protocol with a given of left hand vector. * * <p> For right vector <i><b>b</b>= b<sub>0</sub>, b<sub>1</sub>, ...)</i> and left vector * <i><b>a</b> = (a<sub>0</sub>, a<sub>1</sub>, ...)</i>, the protocol computes secret shares of * entry wise product <i>(a<sub>0</sub>b<sub>0</sub>, a<sub>1</sub>b<sub>1</sub>, ... </i>). </p> * * @param leftFactors this party's vector <i>a<sub>0</sub>, a<sub>1</sub> ...</i> * @return shares of the products <i>a<sub>0</sub>b<sub>0</sub>, a<sub>1</sub>b<sub>1</sub> * ...</i> */ public List<FieldElement> multiply(List<FieldElement> leftFactors) { List<StrictBitVector> seeds = multiplyLeftHelper.generateSeeds(leftFactors, resourcePool.getModBitLength()); List<FieldElement> feSeeds = seedsToFieldElements(seeds); // receive diffs from other party List<FieldElement> diffs = resourcePool.getFieldDefinition().deserializeList(network.receive(otherId)); return multiplyLeftHelper.computeProductShares(leftFactors, feSeeds, diffs); }
/** * 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)); } } }
@Override public EvaluationStatus evaluate(int round, ResourcePoolImpl resourcePool, Network network) { TinyTablesProtocolSuite ps = TinyTablesProtocolSuite.getInstance(resourcePool.getMyId()); if (round == 0) { if (resourcePool.getMyId() == this.inputter) { TinyTablesElement r = ps.getStorage().getMaskShare(id); TinyTablesElement e = TinyTablesElement.getInstance(this.in ^ r.getShare()); network.sendToAll(new byte[]{BooleanSerializer.toBytes(e.getShare())}); } return EvaluationStatus.HAS_MORE_ROUNDS; } else { TinyTablesElement share = TinyTablesElement.getInstance(BooleanSerializer.fromBytes(network.receive(this.inputter)[0])); out = TinyTablesSBool.getInstance(share); return EvaluationStatus.IS_DONE; } }
@Override public EvaluationStatus evaluate(int round, Spdz2kResourcePool<PlainT> resourcePool, Network network) { CompUIntFactory<PlainT> factory = resourcePool.getFactory(); int myId = resourcePool.getMyId(); Spdz2kDataSupplier<PlainT> dataSupplier = resourcePool.getDataSupplier(); if (round == 0) { inputMask = dataSupplier.getNextInputMask(inputPartyId); if (myId == inputPartyId) { PlainT bcValue = this.input.subtract(inputMask.getOpenValue()); network.sendToAll(factory.serialize(bcValue)); } return EvaluationStatus.HAS_MORE_ROUNDS; } else { byte[] inputMaskBytes = network.receive(inputPartyId); PlainT macKeyShare = dataSupplier.getSecretSharedKey(); Spdz2kSInt<PlainT> maskShare = inputMask.getMaskShare(); Spdz2kSInt<PlainT> out = maskShare.addConstant( factory.deserialize(inputMaskBytes), macKeyShare, factory.zero(), myId == 1); this.shareAndMaskBytes = new Pair<>(out, inputMaskBytes); return EvaluationStatus.IS_DONE; } }
@Override public EvaluationStatus evaluate(int round, SpdzResourcePool spdzResourcePool, Network network) { int myId = spdzResourcePool.getMyId(); SpdzDataSupplier dataSupplier = spdzResourcePool.getDataSupplier(); FieldDefinition definition = spdzResourcePool.getFieldDefinition(); if (round == 0) { this.inputMask = dataSupplier.getNextInputMask(this.inputter); if (myId == this.inputter) { FieldElement inputElement = spdzResourcePool.getFieldDefinition().createElement(this.input); FieldElement bcValue = inputElement.subtract(this.inputMask.getRealValue()); network.sendToAll(definition.serialize(bcValue)); } return EvaluationStatus.HAS_MORE_ROUNDS; } else if (round == 1) { this.valueMasked = definition.deserialize(network.receive(inputter)); this.digest = sendMaliciousBroadcastValidation(spdzResourcePool.getMessageDigest(), network, valueMasked, spdzResourcePool.getFieldDefinition()); return EvaluationStatus.HAS_MORE_ROUNDS; } else { boolean validated = receiveMaliciousBroadcastValidation(network, digest); if (!validated) { throw new MaliciousException("Broadcast digests did not match"); } FieldElement maskedValue = dataSupplier.getSecretSharedKey().multiply(valueMasked); SpdzSInt valueMaskedElm = new SpdzSInt(valueMasked, maskedValue); this.out = this.inputMask.getMask().add(valueMaskedElm, myId); return EvaluationStatus.IS_DONE; } }