protected override async Task <byte[][]> ReceiveMaskedOptionsAsync(BitArray selectionIndices, BitMatrix tTransposed, int numberOfInvocations, int numberOfMessageBytes) { Debug.Assert(selectionIndices.Length == numberOfInvocations); Debug.Assert(tTransposed.Rows == SecurityParameter); Debug.Assert(tTransposed.Cols == numberOfInvocations); // retrieve the masked options from the sender and unmask the one indicated by the // corresponding selection indices byte[][][] maskedOptions = await CommunicationTools.ReadOptionsAsync(Channel, 1, numberOfInvocations, numberOfMessageBytes); Debug.Assert(maskedOptions.Length == numberOfInvocations); byte[][] results = new byte[numberOfInvocations][]; Parallel.For(0, numberOfInvocations, i => { Debug.Assert(maskedOptions[i].Length == 1); Debug.Assert(maskedOptions[i][0].Length == numberOfMessageBytes); RandomOracle randomOracle = RandomOracleProvider.Create(); int s = Convert.ToInt32(selectionIndices[i].Value); byte[] query = tTransposed.GetColumn((uint)i).ToBytes(); if (s == 0) { results[i] = randomOracle.Invoke(query).Take(numberOfMessageBytes).ToArray(); } else { results[i] = randomOracle.Mask(maskedOptions[i][0], query); } }); return(results); }
protected override async Task <byte[][]> ReceiveMaskedOptionsAsync(BitArray selectionIndices, BitMatrix tTransposed, int numberOfInvocations, int numberOfMessageBytes) { Debug.Assert(selectionIndices.Length == numberOfInvocations); Debug.Assert(tTransposed.Rows == SecurityParameter); Debug.Assert(tTransposed.Cols == numberOfInvocations); // note(lumip): could precompute the masks for the response to have only cheap Xor after // waiting for the message, but not sure if it really is a significant performance issue // retrieve the masked options from the sender and unmask the one indicated by the // corresponding selection indices byte[][][] maskedOptions = await CommunicationTools.ReadOptionsAsync(Channel, 2, numberOfInvocations, numberOfMessageBytes); Debug.Assert(maskedOptions.Length == numberOfInvocations); byte[][] results = new byte[numberOfInvocations][]; Parallel.For(0, numberOfInvocations, i => { int s = Convert.ToInt32(selectionIndices[i].Value); Debug.Assert(maskedOptions[i][s].Length == numberOfMessageBytes); byte[] query = tTransposed.GetColumn((uint)i).ToBytes(); results[i] = RandomOracleProvider.Create().Mask(maskedOptions[i][s], query); }); return(results); }
public async Task <byte[][]> ReceiveAsync(BitArray selectionIndices, int numberOfInvocations, int numberOfMessageBytes) { if (selectionIndices.Length != numberOfInvocations) { throw new ArgumentException("Amount of selection indices must match the specified number of invocations.", nameof(selectionIndices)); } if (_receiverState.SeededRandomOracles == null) { await ExecuteReceiverBaseOTAsync(); } // note(lumip): we need a random bit matrix t as per the construction // of Ishai et al. and we use the trick of Asharov et al. and populate it with the random // expansion of the base OT seeds, i.e., t_k = H(seed_0). Since these are calculated later, // we only set up the matrix structure here. BitMatrix tTransposed = new BitMatrix((uint)SecurityParameter, (uint)numberOfInvocations); // "perform" _securityParams many 1-out-of-2 OTs with numberOfInvocations bits message length // by extending the _securityParams many 1-out-of-2 OTs with _securityParams bits message length // (using the seeded random oracles) // the purpose of these OTs is to offer to the _sender_ either a column of t or the column xor'ed with // the selection bits of the receiver // todo(lumip): should try-catch in case random oracle runs out // and ideally performs new base OTs and repeat int numberOfRandomBytes = BitArray.RequiredBytes(numberOfInvocations); byte[][][] sendBuffer = new byte[SecurityParameter][][]; Parallel.For(0, SecurityParameter, k => { BitArray tColumn = BitArray.FromBytes( _receiverState.SeededRandomOracles[k][0].Take(numberOfRandomBytes).ToArray(), numberOfInvocations ); tTransposed.SetRow((uint)k, tColumn); BitArray mask = BitArray.FromBytes( _receiverState.SeededRandomOracles[k][1].Take(numberOfRandomBytes).ToArray(), numberOfInvocations ); BitArray maskedSecondOption = tColumn ^ mask ^ selectionIndices; sendBuffer[k] = new byte[1][] { maskedSecondOption.ToBytes() }; }); await CommunicationTools.WriteOptionsAsync(Channel, sendBuffer, 1, SecurityParameter, numberOfRandomBytes); return(await ReceiveMaskedOptionsAsync(selectionIndices, tTransposed, numberOfInvocations, numberOfMessageBytes)); }
public async Task <Pair <byte[]>[]> SendAsync(byte[][] correlationStrings, int numberOfInvocations, int numberOfMessageBytes) { if (correlationStrings.Length != numberOfInvocations) { throw new ArgumentException("Amount of provided correlation strings must match the specified number of invocations.", nameof(correlationStrings)); } foreach (byte[] message in correlationStrings) { if (message.Length != numberOfMessageBytes) { throw new ArgumentException("The length of of at least one correlation string does not match the specified message length.", nameof(correlationStrings)); } } BitMatrix q = await ReceiveQMatrix(numberOfInvocations); Debug.Assert(q.Rows == numberOfInvocations); Debug.Assert(q.Cols == SecurityParameter); Pair <byte[]>[] options = new Pair <byte[]> [numberOfInvocations]; byte[][][] maskedOptions = new byte[numberOfInvocations][][]; Parallel.For(0, numberOfInvocations, i => { Debug.Assert(correlationStrings[i].Length == numberOfMessageBytes); RandomOracle randomOracle = RandomOracleProvider.Create(); options[i] = new Pair <byte[]>(); BitArray qRow = q.GetRow((uint)i); byte[] query = qRow.ToBytes(); options[i][0] = randomOracle.Invoke(query).Take(numberOfMessageBytes).ToArray(); options[i][1] = ByteBuffer.Xor(correlationStrings[i], options[i][0]); query = (qRow ^ SenderChoices).ToBytes(); maskedOptions[i] = new[] { randomOracle.Mask(options[i][1], query) }; Debug.Assert(maskedOptions[i][0].Length == numberOfMessageBytes); }); await CommunicationTools.WriteOptionsAsync(Channel, maskedOptions, 1, numberOfInvocations, numberOfMessageBytes); return(options); }
/// <summary> /// Receives and returns the matrix Q as specified in the OT extension protocol of Ishai et al. /// /// This is involves the preprocessing (expanding the base OTs for the number of invocations, etc..) /// for all variants of the OT extension. This method should be called is the first step by /// subclasses implementing the OT extension variants. /// </summary> /// <param name="numberOfInvocations">The number of invocations/instances of OT.</param> /// <returns>The matrix Q of correlated randomness.</returns> protected async Task <BitMatrix> ReceiveQMatrix(int numberOfInvocations) { if (_senderState.SeededRandomOracles == null) { await ExecuteSenderBaseOTAsync(); } int numberOfRandomBytes = BitArray.RequiredBytes(numberOfInvocations); BitMatrix q = new BitMatrix((uint)numberOfInvocations, (uint)SecurityParameter); // note(lumip): could precompute the masks for the response to have only cheap Xor after // waiting for the message, but not sure if it really is a significant performance issue // todo(lumip): should try-catch in case random oracle runs out // and ideally performs new base OTs and repeat byte[][][] qOTResult = await CommunicationTools.ReadOptionsAsync(Channel, 1, SecurityParameter, numberOfRandomBytes); Debug.Assert(qOTResult.Length == SecurityParameter); PairIndexArray randomChoiceInts = _senderState.RandomChoices.ToPairIndexArray(); Parallel.For(0, SecurityParameter, k => { Debug.Assert(qOTResult[k].Length == 1); Debug.Assert(qOTResult[k][0].Length == numberOfRandomBytes); BitArray mask = BitArray.FromBytes( _senderState.SeededRandomOracles[k].Take(numberOfRandomBytes).ToArray(), numberOfInvocations ); int s = randomChoiceInts[k]; BitArray qColumn = mask; if (s == 1) { qColumn.Xor(BitArray.FromBytes(qOTResult[k][0], numberOfInvocations)); } q.SetColumn((uint)k, qColumn); }); return(q); }
public async Task SendAsync(Pair <byte[]>[] options, int numberOfInvocations, int numberOfMessageBytes) { if (options.Length != numberOfInvocations) { throw new ArgumentException("Amount of provided option pairs must match the specified number of invocations.", nameof(options)); } for (int j = 0; j < options.Length; ++j) { foreach (byte[] message in options[j]) { if (message.Length != numberOfMessageBytes) { throw new ArgumentException("The length of of at least one option does not match the specified message length.", nameof(options)); } } } BitMatrix q = await ReceiveQMatrix(numberOfInvocations); Debug.Assert(q.Rows == numberOfInvocations); Debug.Assert(q.Cols == SecurityParameter); byte[][][] maskedOptions = new byte[numberOfInvocations][][]; Parallel.For(0, numberOfInvocations, i => { maskedOptions[i] = new byte[2][]; BitArray qRow = q.GetRow((uint)i); for (int j = 0; j < 2; ++j) { Debug.Assert(options[i][j].Length == numberOfMessageBytes); if (j == 1) { qRow.Xor(SenderChoices); } byte[] query = qRow.ToBytes(); maskedOptions[i][j] = RandomOracleProvider.Create().Mask(options[i][j], query); } }); await CommunicationTools.WriteOptionsAsync(Channel, maskedOptions, 2, numberOfInvocations, numberOfMessageBytes); }