/*
 * 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.hadoop.crypto.key;

import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.log4j.Logger;
import org.apache.ranger.kms.dao.DaoManager;
import org.apache.ranger.kms.dao.RangerMasterKeyDao;
import org.apache.ranger.entity.XXRangerMasterKey;

import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
import com.sun.org.apache.xml.internal.security.utils.Base64;

public class RangerMasterKey implements RangerKMSMKI{
	
	private static final Logger logger = Logger.getLogger(RangerMasterKey.class);
	
	private static final String MK_CIPHER = "AES";
	private static final int MK_KeySize = 256;
	private static final int SALT_SIZE = 8;
	private static final String PBE_ALGO = "PBEWithMD5AndTripleDES";
	private static final String MD_ALGO = "MD5";
	
	private DaoManager daoManager;
	
	public RangerMasterKey() {		
	}
	
	public RangerMasterKey(DaoManager daoManager) {
		this.daoManager = daoManager;
	}
	
	/**
	 * To get Master Key
	 * @param password password to be used for decryption
	 * @return Decrypted Master Key
	 * @throws Throwable
	 */
	@Override
	public String getMasterKey(String password) throws Throwable{		
		logger.info("Getting Master Key");
		byte masterKeyByte[] = getEncryptedMK();
		if(masterKeyByte != null && masterKeyByte.length > 0){
			return decryptMasterKey(masterKeyByte, password);		
		}else{
			throw new Exception("No Master Key Found");
		}			
	}
	
	public SecretKey getMasterSecretKey(String password) throws Throwable{		
		logger.info("Getting Master Key");
		byte masterKeyByte[] = getEncryptedMK();
		if(masterKeyByte != null && masterKeyByte.length > 0){
			return decryptMasterKeySK(masterKeyByte, password);		
		}else{
			throw new Exception("No Master Key Found");
		}			
	}
	
	/**
	 * Generate the master key, encrypt it and save it in the database
	 * @param password password to be used for encryption
	 * @return true if the master key was successfully created
	 * 		   false if master key generation was unsuccessful or the master key already exists
	 * @throws Throwable
	 */
	@Override
	public boolean generateMasterKey(String password) throws Throwable{
		logger.info("Generating Master Key");
		String encryptedMasterKey = encryptMasterKey(password);		
		String savedKey = saveEncryptedMK(encryptedMasterKey, daoManager);
		if(savedKey != null && !savedKey.trim().equals("")){
			logger.debug("Master Key Created with id = "+savedKey);
			return true;
		}
		return false;
	}
	
	public boolean generateMKFromHSMMK(String password, byte[] key) throws Throwable{
		logger.info("Generating Master Key");
		String encryptedMasterKey = encryptMasterKey(password, key);		
		String savedKey = saveEncryptedMK(encryptedMasterKey, daoManager);
		if(savedKey != null && !savedKey.trim().equals("")){
			logger.debug("Master Key Created with id = "+savedKey);
			return true;
		}
		return false;
	}

	private String decryptMasterKey(byte masterKey[], String password) throws Throwable {
		logger.debug("Decrypting Master Key");
		PBEKeySpec pbeKeyspec = getPBEParameterSpec(password);
		byte[] masterKeyFromDBDecrypted = decryptKey(masterKey, pbeKeyspec);
		SecretKey masterKeyFromDB = getMasterKeyFromBytes(masterKeyFromDBDecrypted);
		return Base64.encode(masterKeyFromDB.getEncoded());
	}
	
	private SecretKey decryptMasterKeySK(byte masterKey[], String password) throws Throwable {
		logger.debug("Decrypting Master Key");
		PBEKeySpec pbeKeyspec = getPBEParameterSpec(password);
		byte[] masterKeyFromDBDecrypted = decryptKey(masterKey, pbeKeyspec);
		return getMasterKeyFromBytes(masterKeyFromDBDecrypted);		
	}

	private byte[] getEncryptedMK() throws Base64DecodingException {
		logger.debug("Retrieving Encrypted Master Key from database");
		try{
			  if(daoManager != null){
				  RangerMasterKeyDao rangerKMSDao = new RangerMasterKeyDao(daoManager);
				  List<XXRangerMasterKey> lstRangerMasterKey = rangerKMSDao.getAll();
				  if(lstRangerMasterKey.size() < 1){
					  throw new Exception("No Master Key exists");
				  }else if(lstRangerMasterKey.size() > 1){
					  throw new Exception("More than one Master Key exists");
				  }else {
					  XXRangerMasterKey rangerMasterKey = rangerKMSDao.getById(lstRangerMasterKey.get(0).getId());
					  String masterKeyStr = rangerMasterKey.getMasterKey();
					  return Base64.decode(masterKeyStr);
				  }
			  }			
		  }catch(Exception e){
			  e.printStackTrace();
		  }
		  return null;
	}

	private String saveEncryptedMK(String encryptedMasterKey, DaoManager daoManager) {
		  logger.debug("Saving Encrypted Master Key to database");
		  XXRangerMasterKey xxRangerMasterKey = new XXRangerMasterKey();
		  xxRangerMasterKey.setCipher(MK_CIPHER);
		  xxRangerMasterKey.setBitLength(MK_KeySize);
		  xxRangerMasterKey.setMasterKey(encryptedMasterKey);
		  try{
			  if(daoManager != null){
				  RangerMasterKeyDao rangerKMSDao = new RangerMasterKeyDao(daoManager);
				  Long l = rangerKMSDao.getAllCount();
				  if(l < 1){
					  XXRangerMasterKey rangerMasterKey = rangerKMSDao.create(xxRangerMasterKey);
					  return rangerMasterKey.getId().toString();
				  }
			  }			
		  }catch(Exception e){
			  e.printStackTrace();
		  }
		  return null;
	}

	private String encryptMasterKey(String password) throws Throwable {
			logger.debug("Encrypting Master Key");
			Key secretKey = generateMasterKey();
			PBEKeySpec pbeKeySpec = getPBEParameterSpec(password);
			byte[] masterKeyToDB = encryptKey(secretKey.getEncoded(), pbeKeySpec);
			return Base64.encode(masterKeyToDB);
	}
	
	private String encryptMasterKey(String password, byte[] secretKey) throws Throwable {
		logger.debug("Encrypting Master Key");
		PBEKeySpec pbeKeySpec = getPBEParameterSpec(password);
		byte[] masterKeyToDB = encryptKey(secretKey, pbeKeySpec);
		return Base64.encode(masterKeyToDB);
	}
	
	private Key generateMasterKey() throws NoSuchAlgorithmException{
		KeyGenerator kg = KeyGenerator.getInstance(MK_CIPHER);
		kg.init(MK_KeySize);
		return kg.generateKey();
	}
	
	private PBEKeySpec getPBEParameterSpec(String password) throws Throwable {
		MessageDigest md = MessageDigest.getInstance(MD_ALGO);
		byte[] saltGen = md.digest(password.getBytes());		
		byte[] salt = new byte[SALT_SIZE];		
		System.arraycopy(saltGen, 0, salt, 0, SALT_SIZE);		
		int iteration = password.toCharArray().length + 1;
		return new PBEKeySpec(password.toCharArray(), salt, iteration);		
	}
	private byte[] encryptKey(byte[] data, PBEKeySpec keyspec) throws Throwable {
		SecretKey key = getPasswordKey(keyspec);
		if(keyspec.getSalt() != null) {
			PBEParameterSpec paramSpec = new PBEParameterSpec(keyspec.getSalt(), keyspec.getIterationCount());
			Cipher c = Cipher.getInstance(key.getAlgorithm());
			c.init(Cipher.ENCRYPT_MODE, key,paramSpec);
			return c.doFinal(data);
		}
		return null;
	}
	private SecretKey getPasswordKey(PBEKeySpec keyspec) throws Throwable {
		SecretKeyFactory factory = SecretKeyFactory.getInstance(PBE_ALGO);
		return factory.generateSecret(keyspec);
	}
	private byte[] decryptKey(byte[] encrypted, PBEKeySpec keyspec) throws Throwable {
		SecretKey key = getPasswordKey(keyspec);
		if(keyspec.getSalt() != null) {
			PBEParameterSpec paramSpec = new PBEParameterSpec(keyspec.getSalt(), keyspec.getIterationCount());
			Cipher c = Cipher.getInstance(key.getAlgorithm());
			c.init(Cipher.DECRYPT_MODE, key, paramSpec);
			return c.doFinal(encrypted);
		}
		return null;
	}
	private SecretKey getMasterKeyFromBytes(byte[] keyData) throws Throwable {
		return new SecretKeySpec(keyData, MK_CIPHER);
	}
	
	public Map<String, String> getPropertiesWithPrefix(Properties props, String prefix) {
		Map<String, String> prefixedProperties = new HashMap<String, String>();

		if(props != null && prefix != null) {
			for(String key : props.stringPropertyNames()) {
				if(key == null) {
					continue;
				}

				String val = props.getProperty(key);

				if(key.startsWith(prefix)) {
					key = key.substring(prefix.length());

					if(key != null) {
					    prefixedProperties.put(key, val);
                    }
				}
			}
		}

		return prefixedProperties;
	}
}
