// Copyright 2016 The Fuchsia Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef COBALT_ALGORITHMS_RAPPOR_RAPPOR_ENCODER_H_
#define COBALT_ALGORITHMS_RAPPOR_RAPPOR_ENCODER_H_

#include <memory>
#include <string>
#include <utility>

#include "./observation.pb.h"
#include "algorithms/rappor/rappor_config_validator.h"
#include "config/encodings.pb.h"
#include "encoder/client_secret.h"
#include "util/crypto_util/hash.h"
#include "util/crypto_util/random.h"

namespace cobalt {
namespace rappor {

enum Status {
  kOK = 0,
  kInvalidConfig,
  kInvalidInput,
};

// Performs String RAPPOR encoding.
class RapporEncoder {
 public:
  // Constructor.
  // The |client_secret| is used to determine the cohort and the PRR.
  RapporEncoder(const RapporConfig& config,
                encoder::ClientSecret client_secret);
  virtual ~RapporEncoder();

  // Encodes |value| using RAPPOR encoding. Returns kOK on success, or
  // kInvalidConfig if the |config| passed to the constructor is not valid.
  Status Encode(const ValuePart& value, RapporObservation* observation_out);

  uint32_t cohort() const { return cohort_num_; }

 private:
  friend class StringRapporEncoderTest;
  friend class RapporAnalyzer;

  // Allows Friend classess to set a special RNG for use in tests.
  void SetRandomForTesting(std::unique_ptr<crypto::Random> random) {
    random_ = std::move(random);
  }

  // Computes a hash of the given |serialized value| and |cohort_num| and writes
  // the result to |hashed_value|. This plus ExtractBitIndex() are used by
  // MakeBloomBits() to form the Bloom filter. These two functions have been
  // extracted from MakeBloomBits() so that they can be shared by RaporAnalyzer.
  //
  // |num_hashes| indicates the the upper bound for the values of |hash_index|
  // that will be passed to ExtractBitIndex() after this method returns.
  //
  // Returns true for success or false if the hash operation fails for any
  // reason.
  static bool HashValueAndCohort(
      const std::string serialized_value, uint32_t cohort_num,
      uint32_t num_hashes,
      crypto::byte hashed_value[crypto::hash::DIGEST_SIZE]);

  // Extracts a bit index from the given |hashed_value| for the given
  // |hash_index|. This plus HashValueAndCohort are used by MakeBloomBits()
  // to form the Bloom filter. These two functions have been extracted from
  // MakeBloomBits() so that they can be shared by RaporAnalyzer.
  //
  // IMPORTANT: We index bits "from the right." This means that bit number zero
  // is the least significant bit of the last byte of the Bloom filter.
  static uint32_t ExtractBitIndex(
      crypto::byte hashed_value[crypto::hash::DIGEST_SIZE], size_t hash_index,
      uint32_t num_bits);

  // Generates the array of bloom bits derived from |value|. Returns the
  // empty string on error.
  std::string MakeBloomBits(const ValuePart& value);

  // Derives an integer in the range [0, config_.num_cohorts_2_power_) from
  // |client_secret_| and |attempt_number|. The distribution of values in this
  // range will be (approximately) uniform as the Client Secret and
  // |attempt_number| vary uniformly.
  //
  // This method is invoked iteratively from DeriveCohortFromSecret() with
  // increasing attempt_numbers until the returned value is less than
  // config_.num_cohorts_.
  //
  // Returns UINT32_MAX to indicate failure.
  uint32_t AttemptDeriveCohortFromSecret(size_t attempt_number);

  // Derives an integer in the range [0, config_.num_cohorts_) from
  // |client_secret_|. The distribution of values in this range will be
  // (approximately) uniform as the Client Secret varies uniformly.
  //
  // Returns UINT32_MAX to indicate failure.
  uint32_t DeriveCohortFromSecret();

  std::unique_ptr<RapporConfigValidator> config_;
  std::unique_ptr<crypto::Random> random_;
  encoder::ClientSecret client_secret_;
  uint32_t cohort_num_;
};

// Performs encoding for Basic RAPPOR, a.k.a Categorical RAPPOR. No cohorts
// are used and the list of all candidates must be pre-specified as part
// of the BasicRapporConfig.
// The |client_secret| is used to determine the PRR.
class BasicRapporEncoder {
 public:
  BasicRapporEncoder(const BasicRapporConfig& config,
                     encoder::ClientSecret client_secret);
  ~BasicRapporEncoder();

  // Encodes |value| using Basic RAPPOR encoding. |value| must be one
  // of the categories listed in the |categories| field of the |config|
  // that was passed to the constructor. Returns kOK on success, kInvalidConfig
  // if the |config| passed to the constructor is not valid, and kInvalidInput
  // if |value| is not one of the |categories|.
  Status Encode(const ValuePart& value,
                BasicRapporObservation* observation_out);

  // Applies Basic RAPPOR encoding to a sequence of 0-bits whose length is equal
  // to the number of categories in the config which was passed to the
  // constructor. Returns kOK on success and kInvalidConfig if the config that
  // was passed to the constructor is not valid.
  Status EncodeNullObservation(BasicRapporObservation* observation_out);

 private:
  friend class BasicRapporAnalyzerTest;
  friend class BasicRapporDeterministicTest;

  // Initializes |data| with a number of 0 bytes determined by the |num_bits|
  // field of |config_| and returns |kOK|. Returns |kInvalidConfig| if |config_|
  // or |client_secret_| is invalid.
  Status InitializeObservationData(std::string* data);

  // Allows Friend classess to set a special RNG for use in tests.
  void SetRandomForTesting(std::unique_ptr<crypto::Random> random) {
    random_ = std::move(random);
  }

  std::unique_ptr<RapporConfigValidator> config_;
  std::unique_ptr<crypto::Random> random_;
  encoder::ClientSecret client_secret_;
};

}  // namespace rappor
}  // namespace cobalt

#endif  // COBALT_ALGORITHMS_RAPPOR_RAPPOR_ENCODER_H_
