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);
        }
Example #2
0
        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);
        }
Example #6
0
        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);
        }