package test.util;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPrivateKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import javax.crypto.spec.DHPrivateKeySpec;


public class DHUtil {

public static final String PUBLIC_KEY = "DHPublicKey";
public static final String PRIVATE_KEY = "DHPrivateKey";
/**
* 甲方初始化并返回密钥对
* @return
* @throws Exception
*/
public static Map<String,Object> initKey() throws Exception{
// 实例化密钥对生成器
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH");
// 初始化密钥对生成器
keyPairGenerator.initialize(1024);
// 生成密钥对
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// 得到甲方公钥
DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic();
// 得到甲方私钥
DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate();
// 将公钥和私钥封装在Map 中
Map<String,Object> map = new HashMap<String,Object>();
map.put(PUBLIC_KEY, publicKey);
map.put(PRIVATE_KEY, privateKey);
return map;
}

/**
* 乙方根据甲方公钥初始化并返回密钥对
* @param key
* @return
* @throws Exception
*/
public static Map<String,Object> initKey(byte[] key) throws Exception{
// 将甲方公钥从字节类型转换为 DHPublicKey
X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(key);
// 实例化密钥工厂
KeyFactory keyFactory = KeyFactory.getInstance("DH");
// 产生甲方公钥publicKey
DHPublicKey publicKey = (DHPublicKey) keyFactory.generatePublic(encodedKeySpec);
// 解剖甲方公钥,得到其参数
DHParameterSpec dhPrivateKeySpec = publicKey.getParams();
// 实例化密钥对生成器
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH");
// 用甲方公钥初始化密钥生成器
keyPairGenerator.initialize(dhPrivateKeySpec);
// 产生密钥对
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// 得到公钥
DHPublicKey dhpublicKey = (DHPublicKey) keyPair.getPublic();
// 得到私钥
DHPrivateKey dhprivateKey = (DHPrivateKey) keyPair.getPrivate();
// 将公钥和私钥封装在Map 中
Map<String,Object> map = new HashMap<String,Object>();
map.put(PUBLIC_KEY, dhpublicKey);
map.put(PRIVATE_KEY, dhprivateKey);
return map;
}


/**
* 根据对方公钥和自己私钥生成本地密钥
* @param publickey
* @param privatekey
* @return
* @throws NoSuchAlgorithmException
*/
public static byte[] getSecretKey(byte[] publickey,byte[] privatekey) throws Exception{
// 实例化密钥工厂
KeyFactory keyFactory = KeyFactory.getInstance("DH");
// 将公钥从字节类型转换为 PublicKey
X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(publickey);
PublicKey publicKey = keyFactory.generatePublic(encodedKeySpec);
// 将私钥从字节类型转换为 PrivateKey
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privatekey);
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
// 先实例化KeyAgreement
KeyAgreement keyAgreement = KeyAgreement.getInstance("DH");
// 用自己的密钥初始化KeyAgreement
keyAgreement.init(privateKey);
// 结合对方的公钥进行计算
keyAgreement.doPhase(publicKey, true);
// 开始生成本地密钥,密钥算法为对称算法
SecretKey secretKey = keyAgreement.generateSecret("AES");
return secretKey.getEncoded();
}

/**
* 从 Map 中得到公钥
* @param key
* @return
*/
public static byte[] getPublicKey(Map<String,Object> key){
DHPublicKey publicKey = (DHPublicKey) key.get(PUBLIC_KEY);
return publicKey.getEncoded();
}

/**
* 从 Map 中得到私钥
* @param key
* @return
*/
public static byte[] getPrivateKey(Map<String,Object> key){
DHPrivateKey privateKey = (DHPrivateKey) key.get(PRIVATE_KEY);
return privateKey.getEncoded();
}

/*
* 公钥加密
*/
public static byte[] encrypt(byte[] data,DHPublicKey key) throws Exception{
Cipher cipher = Cipher.getInstance("DH");
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(data);
}

/*
* 私钥解密
*/
public static byte[] decrypt(byte[] data,DHPrivateKey key) throws Exception{
Cipher cipher = Cipher.getInstance("DH");
cipher.init(Cipher.DECRYPT_MODE, key);
return cipher.doFinal(data);
}

}