Beispiel #1
0
        public byte[] HandleQueryRequest(QueryRequest request)
        {
            if (request.row_min > request.row_max)
            {
                Console.Error.WriteLine("Row value range empty");
                return DiffPrivSrvResponse.EncodeQueryResponse(1, 0);
            }
            if (request.answer_min > request.answer_max)
            {
                Console.Error.WriteLine("Answer range empty");
                return DiffPrivSrvResponse.EncodeQueryResponse(2, 0);
            }
            if (request.answer_units <= 0)
            {
                Console.Error.WriteLine("Answer units not positive");
                return DiffPrivSrvResponse.EncodeQueryResponse(3, 0);
            }
            if (request.alpha_num <= request.alpha_den)
            {
                Console.Error.WriteLine("Alpha not greater than 1");
                return DiffPrivSrvResponse.EncodeQueryResponse(6, 0);
            }
            if (request.beta_num <= request.beta_den)
            {
                Console.Error.WriteLine("Beta not greater than 1");
                return DiffPrivSrvResponse.EncodeQueryResponse(13, 0);
            }

            UInt32[] program_words = CommonRoutines.BEByteSeqToWordSeq(request.program_encoding);
            MapperProgram program = new MapperProgram(program_words);
            if (!program.IsValid())
            {
                Console.Error.WriteLine("Invalid program provided for query");
                return DiffPrivSrvResponse.EncodeQueryResponse(4, 0);
            }

            if (request.answer_units >= 0x80000000)
            {
                Console.Error.WriteLine("Answer granularity too high");
                return DiffPrivSrvResponse.EncodeQueryResponse(17, 0);
            }

            BigRational alpha = new BigRational(request.alpha_num, request.alpha_den);
            BigRational beta = new BigRational(request.beta_num, request.beta_den);
            UInt32 delta = DivideRoundingUp(request.row_max - request.row_min, request.answer_units);
            UInt32 B = request.answer_max - request.answer_min;

            if (B <= 0)
            {
                Console.Error.WriteLine("Answer range empty");
                return DiffPrivSrvResponse.EncodeQueryResponse(5, 0);
            }
            if (alpha <= new BigRational(1))
            {
                return DiffPrivSrvResponse.EncodeQueryResponse(6, 0);
            }
            BigRational alpha_to_delta = BigRational.Power(alpha, delta);
            if (beta <= alpha_to_delta)
            {
                Console.Error.WriteLine("Beta not greater than alpha to the power of delta");
                return DiffPrivSrvResponse.EncodeQueryResponse(7, 0);
            }

            if (beta > budget)
            {
                Console.Error.WriteLine("Not enough budget for request");
                return DiffPrivSrvResponse.EncodeQueryResponse(11, 0);
            }

            BigRational one = new BigRational(1);
            BigRational two = new BigRational(2);
            BigRational min_alpha_minus_1_and_2 = alpha - one;
            if (min_alpha_minus_1_and_2 > two)
            {
                min_alpha_minus_1_and_2 = two;
            }
            BigRational noiseEntropyPart1 = (alpha + one) * (beta + one) / ((beta - alpha_to_delta) * min_alpha_minus_1_and_2);

            UInt32 r1;
            if (!FindHigherPowerOfTwo(noiseEntropyPart1, out r1) || r1 >= 0xFFFFFFE0)
            {
                Console.Error.WriteLine("Requires too many bits of randomness due to noise entropy part 1");
                return DiffPrivSrvResponse.EncodeQueryResponse(8, 0);
            }

            UInt32 log_alpha;
            if (!FindHigherPowerOfTwo(alpha, out log_alpha) || log_alpha > 0xFFFFFFFFUL / B)
            {
                Console.Error.WriteLine("Requires too many bits of randomness due to alpha");
                return DiffPrivSrvResponse.EncodeQueryResponse(8, 0);
            }

            UInt32 r2 = log_alpha * (B-1);
            if (r2 >= 0xFFFFFFC8 - r1)
            {
                Console.Error.WriteLine("Requires too many bits of randomness due to r2");
                return DiffPrivSrvResponse.EncodeQueryResponse(8, 0);
            }

            UInt32 r = RoundUpToMultiple(r1 + r2 + 7, 8);
            UInt32 num_randoms_needed = RoundUpToMultiple(r / 8, 4) + 1;

            bool negate_noise = (rng.Next() % 2 == 0);
            byte[] randoms = new byte[num_randoms_needed];
            rng.NextBytes(randoms);
            randoms[num_randoms_needed - 1] = 0;
            BigInteger U = new BigInteger(randoms);

            BigRational one_half = new BigRational(1, 2);
            BigRational numerator = new BigRational(U) + one_half;
            BigRational denominator = BigRational.Power(two, (num_randoms_needed - 1) * 8);
            BigRational u = numerator / denominator;

            BigRational threshold = (two * alpha) / (u * (alpha + one));
            UInt32 absolute_noise = FindHighestPowerLeThreshold(alpha, threshold, B);

            UInt32 answer = ComputeSum(program, request.row_min, request.row_max, request.answer_units, request.answer_min, request.answer_max);
            UInt32 noised_answer = AddNoise(answer, absolute_noise, negate_noise);
            UInt32 response = ClipWord32(noised_answer, request.answer_min, request.answer_max);

            budget = budget / beta;
            return DiffPrivSrvResponse.EncodeQueryResponse(0, response);
        }
Beispiel #2
0
        private UInt32 ComputeSum (MapperProgram program, UInt32 row_min, UInt32 row_max, UInt32 answer_units,
                                   UInt32 answer_min, UInt32 answer_max)
        {
            UInt32 clipped_scaled_sum = 0;
            UInt32 total_remainder = 0;

            foreach (DiffPrivRow row in rows)
            {
                UInt32 row_value =  program.Run(row.data);
                UInt32 clipped_value = ClipWord32(row_value, row_min, row_max);
                UInt32 scaled_value = clipped_value / answer_units;
                UInt32 scaling_remainder = clipped_value % answer_units;

                clipped_scaled_sum = SaturatingAdd(clipped_scaled_sum, scaled_value);
                total_remainder = total_remainder + scaling_remainder;
                if (total_remainder >= answer_units)
                {
                    clipped_scaled_sum = SaturatingAdd(clipped_scaled_sum, 1);
                    total_remainder -= answer_units;
                }
            }

            UInt32 extra = (UInt32)(total_remainder * 2 >= answer_units ? 1 : 0);
            clipped_scaled_sum = SaturatingAdd(clipped_scaled_sum, extra);
            return ClipWord32(clipped_scaled_sum, answer_min, answer_max);
        }