package com.nifty.cloud.ncs.encrypt;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Properties;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import com.nifty.cloud.ncs.NiftyCloudClientException;

/**
 * 秘密鍵生成用のクラスです。
 *
 */
public class PrivateKeyGenerator
{
	private static final String ENCRYPTION_KEY_NAME = "privateKeyphrase";
	private static final String MESSAGE_DIGEST_ALGORITHM = "SHA-256";
	private static final String DEFAULT_ENCODING = "UTF-8";

	private final String privateKeyphrase;

	/**
	 * ファイルを指定して新しいPrivateKeyGeneratorを構築します。
	 *
	 * @param file
	 *  秘密鍵生成に使用するキーフレーズの情報を持つファイル
	 *
	 * @throws FileNotFoundException
	 * @throws IOException
	 * @throws IllegalArgumentException
	 */
	public PrivateKeyGenerator(File file) throws FileNotFoundException, IOException, IllegalArgumentException
	{
		if (file.exists() == false) {
			throw (new FileNotFoundException("File not found: " + file.getAbsolutePath()));
		}

		Properties properties = new Properties();
		properties.load(new FileInputStream(file));

		String propPrivateKeyphrase = properties.getProperty(ENCRYPTION_KEY_NAME);
		if (propPrivateKeyphrase == null) {
			throw (new IllegalArgumentException("The specified file [" + file.getAbsolutePath() + "] " + "does not contain the expected property " + "'" + ENCRYPTION_KEY_NAME + "'"));
		}
		else if (propPrivateKeyphrase.isEmpty()) {
			throw (new IllegalArgumentException("The specified file [" + file.getAbsolutePath() + "] " + "contains the expected property " + "'" + ENCRYPTION_KEY_NAME + "', but the value is empty"));
		}

		this.privateKeyphrase = properties.getProperty(ENCRYPTION_KEY_NAME);
	}

	/**
	 * キーフレーズを指定して新しいPrivateKeyGeneratorを構築します。
	 *
	 * @param privateKeyphrase
	 *  秘密鍵のキーフレーズ
	 */
	public PrivateKeyGenerator(String privateKeyphrase)
	{
		if (privateKeyphrase == null || privateKeyphrase.isEmpty()) {
			throw (new IllegalArgumentException("The parameter " + ENCRYPTION_KEY_NAME + " must not be null or empty."));
		}

		this.privateKeyphrase = privateKeyphrase;
	}

	/**
	 * 暗号化に使用する秘密鍵を生成します。
	 *
	 * @return 秘密鍵
	 * @throws NiftyCloudClientException
	 */
	public SecretKey generatePrivateKey() throws NiftyCloudClientException
	{
		try {
			MessageDigest digest = MessageDigest.getInstance(MESSAGE_DIGEST_ALGORITHM);
			try {
				digest.update(privateKeyphrase.getBytes(DEFAULT_ENCODING));
			} catch (UnsupportedEncodingException e) {
				digest.update(privateKeyphrase.getBytes());
			}

			return (new SecretKeySpec(digest.digest(), EncryptionConstants.SYMMETRIC_KEY_ALGORITHM_AES));

		} catch (NoSuchAlgorithmException e) {
			throw (new NiftyCloudClientException(e.getMessage(), e.getCause()));
		}
	}
}
