/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

package org.apache.druid.crypto;

import com.google.common.base.Preconditions;
import org.apache.druid.java.util.common.StringUtils;

import javax.annotation.Nullable;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.ByteBuffer;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.KeySpec;

/**
 * Utility class for symmetric key encryption (i.e. same secret is used for encryption and decryption) of byte[]
 * using javax.crypto package.
 *
 * To learn about possible algorithms supported and their names,
 * See https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html
 */
public class CryptoService
{
  // Based on Javadocs on SecureRandom, It is threadsafe as well.
  private static final SecureRandom SECURE_RANDOM_INSTANCE = new SecureRandom();

  // User provided secret phrase used for encrypting data
  private final char[] passPhrase;

  // Variables for algorithm used to generate a SecretKey based on user provided passPhrase
  private final String secretKeyFactoryAlg;
  private final int saltSize;
  private final int iterationCount;
  private final int keyLength;

  // Cipher algorithm information
  private final String cipherAlgName;
  private final String cipherAlgMode;
  private final String cipherAlgPadding;

  // transformation =  "cipherAlgName/cipherAlgMode/cipherAlgPadding" used in Cipher.getInstance(transformation)
  private final String transformation;

  public CryptoService(
      String passPhrase,
      @Nullable String cipherAlgName,
      @Nullable String cipherAlgMode,
      @Nullable String cipherAlgPadding,
      @Nullable String secretKeyFactoryAlg,
      @Nullable Integer saltSize,
      @Nullable Integer iterationCount,
      @Nullable Integer keyLength
  )
  {
    Preconditions.checkArgument(
        passPhrase != null && !passPhrase.isEmpty(),
        "null/empty passPhrase"
    );
    this.passPhrase = passPhrase.toCharArray();

    this.cipherAlgName = cipherAlgName == null ? "AES" : cipherAlgName;
    this.cipherAlgMode = cipherAlgMode == null ? "CBC" : cipherAlgMode;
    this.cipherAlgPadding = cipherAlgPadding == null ? "PKCS5Padding" : cipherAlgPadding;
    this.transformation = StringUtils.format("%s/%s/%s", this.cipherAlgName, this.cipherAlgMode, this.cipherAlgPadding);

    this.secretKeyFactoryAlg = secretKeyFactoryAlg == null ? "PBKDF2WithHmacSHA256" : secretKeyFactoryAlg;
    this.saltSize = saltSize == null ? 8 : saltSize;
    this.iterationCount = iterationCount == null ? 65536 : iterationCount;
    this.keyLength = keyLength == null ? 128 : keyLength;

    // encrypt/decrypt a test string to ensure all params are valid
    String testString = "duh! !! !!!";
    Preconditions.checkState(
        testString.equals(StringUtils.fromUtf8(decrypt(encrypt(StringUtils.toUtf8(testString))))),
        "decrypt(encrypt(testString)) failed"
    );
  }

  public byte[] encrypt(byte[] plain)
  {
    try {
      byte[] salt = new byte[saltSize];
      SECURE_RANDOM_INSTANCE.nextBytes(salt);

      SecretKey tmp = getKeyFromPassword(passPhrase, salt);
      SecretKey secret = new SecretKeySpec(tmp.getEncoded(), cipherAlgName);

      // error-prone warns if the transformation is not a compile-time constant
      // since it cannot check it for insecure combinations.
      @SuppressWarnings("InsecureCryptoUsage")
      Cipher ecipher = Cipher.getInstance(transformation);
      ecipher.init(Cipher.ENCRYPT_MODE, secret);
      return new EncryptedData(
          salt,
          ecipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV(),
          ecipher.doFinal(plain)
      ).toByteAray();
    }
    catch (InvalidKeySpecException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidParameterSpecException | IllegalBlockSizeException | BadPaddingException ex) {
      throw new RuntimeException(ex);
    }
  }

  public byte[] decrypt(byte[] data)
  {
    try {
      EncryptedData encryptedData = EncryptedData.fromByteArray(data);

      SecretKey tmp = getKeyFromPassword(passPhrase, encryptedData.getSalt());
      SecretKey secret = new SecretKeySpec(tmp.getEncoded(), cipherAlgName);

      // error-prone warns if the transformation is not a compile-time constant
      // since it cannot check it for insecure combinations.
      @SuppressWarnings("InsecureCryptoUsage")
      Cipher dcipher = Cipher.getInstance(transformation);
      dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(encryptedData.getIv()));
      return dcipher.doFinal(encryptedData.getCipher());
    }
    catch (InvalidKeySpecException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException ex) {
      throw new RuntimeException(ex);
    }
  }

  private SecretKey getKeyFromPassword(char[] passPhrase, byte[] salt)
      throws NoSuchAlgorithmException, InvalidKeySpecException
  {
    SecretKeyFactory factory = SecretKeyFactory.getInstance(secretKeyFactoryAlg);
    KeySpec spec = new PBEKeySpec(passPhrase, salt, iterationCount, keyLength);
    return factory.generateSecret(spec);
  }

  private static class EncryptedData
  {
    private final byte[] salt;
    private final byte[] iv;
    private final byte[] cipher;

    public EncryptedData(byte[] salt, byte[] iv, byte[] cipher)
    {
      this.salt = salt;
      this.iv = iv;
      this.cipher = cipher;
    }

    public byte[] getSalt()
    {
      return salt;
    }

    public byte[] getIv()
    {
      return iv;
    }

    public byte[] getCipher()
    {
      return cipher;
    }

    public byte[] toByteAray()
    {
      int headerLength = 12;
      ByteBuffer bb = ByteBuffer.allocate(salt.length + iv.length + cipher.length + headerLength);
      bb.putInt(salt.length)
        .putInt(iv.length)
        .putInt(cipher.length)
        .put(salt)
        .put(iv)
        .put(cipher);
      bb.flip();

      return bb.array();
    }

    public static EncryptedData fromByteArray(byte[] array)
    {
      ByteBuffer bb = ByteBuffer.wrap(array);

      int saltSize = bb.getInt();
      int ivSize = bb.getInt();
      int cipherSize = bb.getInt();

      byte[] salt = new byte[saltSize];
      bb.get(salt);

      byte[] iv = new byte[ivSize];
      bb.get(iv);

      byte[] cipher = new byte[cipherSize];
      bb.get(cipher);

      return new EncryptedData(salt, iv, cipher);
    }
  }
}
