// 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.

#include "algorithms/forculus/forculus_decrypter.h"

#include <functional>
#include <vector>

#include "algorithms/forculus/polynomial_computations.h"
#include "util/crypto_util/cipher.h"

namespace cobalt {
namespace forculus {

using crypto::SymmetricCipher;

ForculusDecrypter::ForculusDecrypter(uint32_t threshold,
                                     std::string ciphertext) :
  threshold_(threshold), num_seen_(0), ciphertext_(std::move(ciphertext)) {}

ForculusDecrypter::Status ForculusDecrypter::AddObservation(
    const ForculusObservation& obs) {
  if (obs.ciphertext() != ciphertext_) {
    return kWrongCiphertext;
  }
  // Keep a copy of y so we can check it its the same as a previously added
  // point.
  FieldElement y(obs.point_y());
  auto result = points_.insert(std::make_pair(FieldElement(obs.point_x()), y));
  auto key_value_pair = result.first;
  auto success = result.second;
  if (!success) {
    if (key_value_pair->second != y) {
      return kInconsistentPoints;
    }
  }
  num_seen_++;
  return kOK;
}

uint32_t ForculusDecrypter::size() {
  return points_.size();
}

ForculusDecrypter::Status ForculusDecrypter::Decrypt(
    std::string *plain_text_out) {
  if (size() < threshold_) {
    return kNotEnoughPoints;
  }

  // Put pointers to the first |threshold_| x and y values into vectors.
  std::vector<const FieldElement*> x_values(threshold_);
  std::vector<const FieldElement*> y_values(threshold_);
  uint32_t point_index = 0;
  for (const auto& point : points_) {
    if (point_index >= threshold_) {
      break;
    }
    x_values[point_index] = &point.first;
    y_values[point_index++] = &point.second;
  }

  // The decryption key we need is the constant term of the unique polynomial of
  // degree (threshold_  - 1) that passes through the points given by the
  // x_values and y_values. We can find this using interpolation.
  FieldElement c0 = InterpolateConstant(x_values, y_values);

  // Now we have the key, decrypt.
  SymmetricCipher cipher;
  cipher.set_key(c0.KeyBytes());
  std::vector<byte> recoverd_text;
  // Our encryption scheme uses a zero nonce. (Note that C++11 initializes
  // the entire array to 0 with this syntax.)
  static const byte kZeroNonce[SymmetricCipher::NONCE_SIZE] = {0};
  if (!cipher.Decrypt(kZeroNonce,
                     reinterpret_cast<const byte*>(ciphertext_.data()),
                     ciphertext_.size(), &recoverd_text)) {
    // TODO(pseudorandom, rudominer) One reason that decryption might fail
    // is a ballot suppression attack. An adversary may intentionally flood
    // us with bad (x, y) values in order to keep us from decrypting a
    // ciphertext. Because we use authenticated encryption, the result of
    // invalid (x, y) values will be failure to decrypt. One way to combat
    // this attack might be to try different sets of points of size
    // |threshold| iteratively until decryption succeeds.
    return kDecryptionFailed;
  }
  plain_text_out->assign(recoverd_text.begin(), recoverd_text.end());
  return kOK;
}

}  // namespace forculus
}  // namespace cobalt

